summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/accessible/accessible.pri3
-rw-r--r--src/gui/accessible/qaccessible.cpp4
-rw-r--r--src/gui/accessible/qaccessible.h1
-rw-r--r--src/gui/accessible/qaccessible_mac.mm14
-rw-r--r--src/gui/accessible/qaccessible_mac_cocoa.mm235
-rw-r--r--src/gui/accessible/qaccessible_win.cpp46
-rw-r--r--src/gui/accessible/qaccessibleobject.cpp14
-rw-r--r--src/gui/accessible/qaccessiblewidget.cpp19
-rw-r--r--src/gui/animation/animation.pri3
-rw-r--r--src/gui/animation/qguivariantanimation.cpp99
-rw-r--r--src/gui/dialogs/dialogs.pri7
-rw-r--r--src/gui/dialogs/qabstractprintdialog.cpp11
-rw-r--r--src/gui/dialogs/qcolordialog.cpp17
-rw-r--r--src/gui/dialogs/qcolordialog_mac.mm38
-rw-r--r--src/gui/dialogs/qdialog.cpp60
-rw-r--r--src/gui/dialogs/qdialog.h4
-rw-r--r--src/gui/dialogs/qdialog_p.h2
-rw-r--r--src/gui/dialogs/qerrormessage.cpp13
-rw-r--r--src/gui/dialogs/qfiledialog.cpp137
-rw-r--r--src/gui/dialogs/qfiledialog_embedded.ui (renamed from src/gui/dialogs/qfiledialog_wince.ui)0
-rw-r--r--src/gui/dialogs/qfiledialog_mac.mm19
-rw-r--r--src/gui/dialogs/qfiledialog_p.h63
-rw-r--r--src/gui/dialogs/qfiledialog_win.cpp686
-rw-r--r--src/gui/dialogs/qfileinfogatherer.cpp37
-rw-r--r--src/gui/dialogs/qfileinfogatherer_p.h2
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp61
-rw-r--r--src/gui/dialogs/qfontdialog.cpp20
-rw-r--r--src/gui/dialogs/qfscompleter_p.h82
-rw-r--r--src/gui/dialogs/qinputdialog.cpp7
-rw-r--r--src/gui/dialogs/qmessagebox.cpp71
-rw-r--r--src/gui/dialogs/qmessagebox.h4
-rw-r--r--src/gui/dialogs/qpagesetupdialog.cpp46
-rw-r--r--src/gui/dialogs/qpagesetupdialog_win.cpp11
-rw-r--r--src/gui/dialogs/qprintdialog.qdoc (renamed from src/gui/embedded/qkbdpc101_qws.h)69
-rw-r--r--src/gui/dialogs/qprintdialog_unix.cpp13
-rw-r--r--src/gui/dialogs/qprintdialog_win.cpp117
-rw-r--r--src/gui/dialogs/qprintpreviewdialog.cpp164
-rw-r--r--src/gui/dialogs/qprintpreviewdialog.h2
-rw-r--r--src/gui/dialogs/qprogressdialog.cpp6
-rw-r--r--src/gui/dialogs/qsidebar.cpp13
-rw-r--r--src/gui/dialogs/qwizard.cpp101
-rw-r--r--src/gui/dialogs/qwizard_win.cpp8
-rw-r--r--src/gui/dialogs/qwizard_win_p.h2
-rw-r--r--src/gui/effects/effects.pri4
-rw-r--r--src/gui/effects/qgraphicseffect.cpp1142
-rw-r--r--src/gui/effects/qgraphicseffect.h307
-rw-r--r--src/gui/effects/qgraphicseffect_p.h181
-rw-r--r--src/gui/egl/egl.pri28
-rw-r--r--src/gui/egl/qegl.cpp414
-rw-r--r--src/gui/egl/qegl_p.h143
-rw-r--r--src/gui/egl/qegl_qws.cpp111
-rw-r--r--src/gui/egl/qegl_symbian.cpp109
-rw-r--r--src/gui/egl/qegl_wince.cpp116
-rw-r--r--src/gui/egl/qegl_x11.cpp157
-rw-r--r--src/gui/egl/qeglproperties.cpp533
-rw-r--r--src/gui/egl/qeglproperties_p.h141
-rw-r--r--src/gui/embedded/embedded.pri76
-rw-r--r--src/gui/embedded/qdirectpainter_qws.cpp10
-rw-r--r--src/gui/embedded/qkbd_defaultmap_qws_p.h798
-rw-r--r--src/gui/embedded/qkbd_qws.cpp479
-rw-r--r--src/gui/embedded/qkbd_qws.h22
-rw-r--r--src/gui/embedded/qkbd_qws_p.h134
-rw-r--r--src/gui/embedded/qkbddriverfactory_qws.cpp42
-rw-r--r--src/gui/embedded/qkbdlinuxinput_qws.cpp245
-rw-r--r--src/gui/embedded/qkbdlinuxinput_qws.h79
-rw-r--r--src/gui/embedded/qkbdpc101_qws.cpp485
-rw-r--r--src/gui/embedded/qkbdqnx_qws.cpp236
-rw-r--r--src/gui/embedded/qkbdqnx_qws.h (renamed from src/gui/embedded/qkbdvr41xx_qws.h)51
-rw-r--r--src/gui/embedded/qkbdsl5000_qws.cpp356
-rw-r--r--src/gui/embedded/qkbdtty_qws.cpp308
-rw-r--r--src/gui/embedded/qkbdtty_qws.h8
-rw-r--r--src/gui/embedded/qkbdum_qws.cpp9
-rw-r--r--src/gui/embedded/qkbdusb_qws.cpp401
-rw-r--r--src/gui/embedded/qkbdvfb_qws.cpp9
-rw-r--r--src/gui/embedded/qkbdvr41xx_qws.cpp185
-rw-r--r--src/gui/embedded/qkbdyopy_qws.cpp209
-rw-r--r--src/gui/embedded/qlock.cpp78
-rw-r--r--src/gui/embedded/qmouse_qws.cpp4
-rw-r--r--src/gui/embedded/qmousebus_qws.cpp238
-rw-r--r--src/gui/embedded/qmousedriverfactory_qws.cpp42
-rw-r--r--src/gui/embedded/qmouselinuxinput_qws.cpp205
-rw-r--r--src/gui/embedded/qmouselinuxinput_qws.h78
-rw-r--r--src/gui/embedded/qmouselinuxtp_qws.cpp7
-rw-r--r--src/gui/embedded/qmousepc_qws.cpp41
-rw-r--r--src/gui/embedded/qmouseqnx_qws.cpp190
-rw-r--r--src/gui/embedded/qmouseqnx_qws.h (renamed from src/gui/embedded/qmousebus_qws.h)33
-rw-r--r--src/gui/embedded/qmousetslib_qws.h2
-rw-r--r--src/gui/embedded/qmousevfb_qws.cpp9
-rw-r--r--src/gui/embedded/qmousevr41xx_qws.cpp250
-rw-r--r--src/gui/embedded/qmouseyopy_qws.cpp184
-rw-r--r--src/gui/embedded/qmouseyopy_qws.h80
-rw-r--r--src/gui/embedded/qscreen_qws.cpp37
-rw-r--r--src/gui/embedded/qscreen_qws.h4
-rw-r--r--src/gui/embedded/qscreendriverfactory_qws.cpp8
-rw-r--r--src/gui/embedded/qscreenlinuxfb_qws.cpp42
-rw-r--r--src/gui/embedded/qscreenlinuxfb_qws.h8
-rw-r--r--src/gui/embedded/qscreenmulti_qws.cpp4
-rw-r--r--src/gui/embedded/qscreenproxy_qws.cpp12
-rw-r--r--src/gui/embedded/qscreenqnx_qws.cpp450
-rw-r--r--src/gui/embedded/qscreenqnx_qws.h (renamed from src/gui/embedded/qkbdusb_qws.h)39
-rw-r--r--src/gui/embedded/qscreentransformed_qws.cpp6
-rw-r--r--src/gui/embedded/qscreenvfb_qws.cpp4
-rw-r--r--src/gui/embedded/qsoundqss_qws.cpp49
-rw-r--r--src/gui/embedded/qtransportauth_qws.cpp11
-rw-r--r--src/gui/embedded/qunixsocket.cpp50
-rw-r--r--src/gui/embedded/qunixsocketserver.cpp8
-rw-r--r--src/gui/embedded/qwindowsystem_qws.cpp93
-rw-r--r--src/gui/embedded/qwscommand_qws.cpp9
-rw-r--r--src/gui/embedded/qwscursor_qws.cpp2
-rw-r--r--src/gui/embedded/qwssignalhandler.cpp6
-rw-r--r--src/gui/embedded/qwsutils_qws.h12
-rw-r--r--src/gui/graphicsview/graphicsview.pri94
-rw-r--r--src/gui/graphicsview/qgraph_p.h296
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout.cpp477
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout.h141
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.cpp2104
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.h493
-rw-r--r--src/gui/graphicsview/qgraphicsgridlayout.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp3001
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h172
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h390
-rw-r--r--src/gui/graphicsview/qgraphicsitemanimation.cpp1
-rw-r--r--src/gui/graphicsview/qgraphicslayout.cpp5
-rw-r--r--src/gui/graphicsview/qgraphicslayout.h2
-rw-r--r--src/gui/graphicsview/qgraphicslayout_p.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicslayout_p.h4
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.cpp140
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.h5
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem_p.h12
-rw-r--r--src/gui/graphicsview/qgraphicslinearlayout.cpp20
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp36
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.h4
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget_p.h6
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp3154
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h57
-rw-r--r--src/gui/graphicsview/qgraphicsscene_bsp.cpp56
-rw-r--r--src/gui/graphicsview/qgraphicsscene_bsp_p.h9
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h208
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp783
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h208
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.cpp46
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.h7
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex.cpp647
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex_p.h182
-rw-r--r--src/gui/graphicsview/qgraphicsscenelinearindex.cpp95
-rw-r--r--src/gui/graphicsview/qgraphicsscenelinearindex_p.h109
-rw-r--r--src/gui/graphicsview/qgraphicstransform.cpp564
-rw-r--r--src/gui/graphicsview/qgraphicstransform.h154
-rw-r--r--src/gui/graphicsview/qgraphicstransform_p.h77
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp995
-rw-r--r--src/gui/graphicsview/qgraphicsview.h7
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h57
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp211
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h10
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp294
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h78
-rw-r--r--src/gui/graphicsview/qgridlayoutengine.cpp46
-rw-r--r--src/gui/graphicsview/qgridlayoutengine_p.h4
-rw-r--r--src/gui/graphicsview/qsimplex_p.cpp412
-rw-r--r--src/gui/graphicsview/qsimplex_p.h164
-rw-r--r--src/gui/gui.pro12
-rw-r--r--src/gui/image/image.pri15
-rw-r--r--src/gui/image/qbitmap.cpp16
-rw-r--r--src/gui/image/qbitmap.h2
-rw-r--r--src/gui/image/qbmphandler.cpp8
-rw-r--r--src/gui/image/qicon.cpp240
-rw-r--r--src/gui/image/qicon.h10
-rw-r--r--src/gui/image/qicon_p.h138
-rw-r--r--src/gui/image/qiconengine.cpp4
-rw-r--r--src/gui/image/qiconloader.cpp604
-rw-r--r--src/gui/image/qiconloader_p.h187
-rw-r--r--src/gui/image/qimage.cpp162
-rw-r--r--src/gui/image/qimageiohandler.cpp1
-rw-r--r--src/gui/image/qimageiohandler.h3
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks.cpp113
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks_p.h (renamed from src/gui/embedded/qkbdsl5000_qws.h)54
-rw-r--r--src/gui/image/qimagereader.cpp2
-rw-r--r--src/gui/image/qimagewriter.cpp2
-rw-r--r--src/gui/image/qmovie.cpp4
-rw-r--r--src/gui/image/qnativeimage.cpp22
-rw-r--r--src/gui/image/qnativeimage_p.h3
-rw-r--r--src/gui/image/qpicture.cpp84
-rw-r--r--src/gui/image/qpicture.h9
-rw-r--r--src/gui/image/qpicture_p.h10
-rw-r--r--src/gui/image/qpixmap.cpp277
-rw-r--r--src/gui/image/qpixmap.h31
-rw-r--r--src/gui/image/qpixmap_mac.cpp205
-rw-r--r--src/gui/image/qpixmap_mac_p.h7
-rw-r--r--src/gui/image/qpixmap_qws.cpp13
-rw-r--r--src/gui/image/qpixmap_raster.cpp64
-rw-r--r--src/gui/image/qpixmap_raster_p.h8
-rw-r--r--src/gui/image/qpixmap_s60.cpp236
-rw-r--r--src/gui/image/qpixmap_win.cpp26
-rw-r--r--src/gui/image/qpixmap_x11.cpp51
-rw-r--r--src/gui/image/qpixmap_x11_p.h15
-rw-r--r--src/gui/image/qpixmapcache.cpp435
-rw-r--r--src/gui/image/qpixmapcache.h27
-rw-r--r--src/gui/image/qpixmapcache_p.h98
-rw-r--r--src/gui/image/qpixmapdata.cpp59
-rw-r--r--src/gui/image/qpixmapdata_p.h24
-rw-r--r--src/gui/image/qpixmapdatafactory.cpp6
-rw-r--r--src/gui/image/qpixmapdatafactory_p.h2
-rw-r--r--src/gui/image/qpixmapfilter.cpp286
-rw-r--r--src/gui/image/qpixmapfilter_p.h29
-rw-r--r--src/gui/image/qpnghandler.cpp2
-rw-r--r--src/gui/image/qppmhandler.cpp2
-rw-r--r--src/gui/image/qxpmhandler.cpp6
-rw-r--r--src/gui/inputmethod/inputmethod.pri5
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_p.h154
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_s60.cpp667
-rw-r--r--src/gui/inputmethod/qinputcontext.cpp99
-rw-r--r--src/gui/inputmethod/qinputcontext.h8
-rw-r--r--src/gui/inputmethod/qinputcontext_p.h4
-rw-r--r--src/gui/inputmethod/qinputcontextfactory.cpp24
-rw-r--r--src/gui/inputmethod/qinputcontextplugin.h2
-rw-r--r--src/gui/inputmethod/qmacinputcontext_mac.cpp20
-rw-r--r--src/gui/inputmethod/qmacinputcontext_p.h5
-rw-r--r--src/gui/inputmethod/qwininputcontext_p.h2
-rw-r--r--src/gui/inputmethod/qwininputcontext_win.cpp195
-rw-r--r--src/gui/inputmethod/qwsinputcontext_p.h1
-rw-r--r--src/gui/inputmethod/qwsinputcontext_qws.cpp27
-rw-r--r--src/gui/inputmethod/qximinputcontext_x11.cpp6
-rw-r--r--src/gui/itemviews/qabstractitemdelegate.cpp2
-rw-r--r--src/gui/itemviews/qabstractitemview.cpp363
-rw-r--r--src/gui/itemviews/qabstractitemview.h1
-rw-r--r--src/gui/itemviews/qabstractitemview_p.h43
-rw-r--r--src/gui/itemviews/qcolumnview.cpp120
-rw-r--r--src/gui/itemviews/qcolumnview.h8
-rw-r--r--src/gui/itemviews/qcolumnview_p.h11
-rw-r--r--src/gui/itemviews/qdirmodel.cpp28
-rw-r--r--src/gui/itemviews/qfileiconprovider.cpp42
-rw-r--r--src/gui/itemviews/qfileiconprovider.h5
-rw-r--r--src/gui/itemviews/qheaderview.cpp100
-rw-r--r--src/gui/itemviews/qheaderview.h3
-rw-r--r--src/gui/itemviews/qheaderview_p.h9
-rw-r--r--src/gui/itemviews/qitemdelegate.cpp34
-rw-r--r--src/gui/itemviews/qitemselectionmodel.cpp412
-rw-r--r--src/gui/itemviews/qitemselectionmodel_p.h2
-rw-r--r--src/gui/itemviews/qlistview.cpp1169
-rw-r--r--src/gui/itemviews/qlistview_p.h222
-rw-r--r--src/gui/itemviews/qlistwidget.cpp532
-rw-r--r--src/gui/itemviews/qlistwidget_p.h3
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp294
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.h1
-rw-r--r--src/gui/itemviews/qstandarditemmodel.cpp78
-rw-r--r--src/gui/itemviews/qstandarditemmodel.h2
-rw-r--r--src/gui/itemviews/qstandarditemmodel_p.h5
-rw-r--r--src/gui/itemviews/qstringlistmodel.cpp2
-rw-r--r--src/gui/itemviews/qstyleditemdelegate.cpp26
-rw-r--r--src/gui/itemviews/qtableview.cpp369
-rw-r--r--src/gui/itemviews/qtableview_p.h98
-rw-r--r--src/gui/itemviews/qtablewidget.cpp160
-rw-r--r--src/gui/itemviews/qtablewidget_p.h3
-rw-r--r--src/gui/itemviews/qtreeview.cpp331
-rw-r--r--src/gui/itemviews/qtreeview.h12
-rw-r--r--src/gui/itemviews/qtreeview_p.h38
-rw-r--r--src/gui/itemviews/qtreewidget.cpp128
-rw-r--r--src/gui/itemviews/qtreewidget_p.h7
-rw-r--r--src/gui/itemviews/qtreewidgetitemiterator.cpp3
-rw-r--r--src/gui/itemviews/qtreewidgetitemiterator.h3
-rw-r--r--src/gui/itemviews/qtreewidgetitemiterator_p.h3
-rw-r--r--src/gui/kernel/kernel.pri66
-rw-r--r--src/gui/kernel/mac.pri2
-rw-r--r--src/gui/kernel/qaction.cpp110
-rw-r--r--src/gui/kernel/qaction.h47
-rw-r--r--src/gui/kernel/qaction_p.h2
-rw-r--r--src/gui/kernel/qactiongroup.cpp2
-rw-r--r--src/gui/kernel/qapplication.cpp761
-rw-r--r--src/gui/kernel/qapplication.h27
-rw-r--r--src/gui/kernel/qapplication_mac.mm123
-rw-r--r--src/gui/kernel/qapplication_p.h199
-rw-r--r--src/gui/kernel/qapplication_qws.cpp75
-rw-r--r--src/gui/kernel/qapplication_s60.cpp1212
-rw-r--r--src/gui/kernel/qapplication_win.cpp1011
-rw-r--r--src/gui/kernel/qapplication_x11.cpp755
-rw-r--r--src/gui/kernel/qboxlayout.cpp40
-rw-r--r--src/gui/kernel/qclipboard.cpp28
-rw-r--r--src/gui/kernel/qclipboard_mac.cpp14
-rw-r--r--src/gui/kernel/qclipboard_s60.cpp266
-rw-r--r--src/gui/kernel/qclipboard_win.cpp10
-rw-r--r--src/gui/kernel/qclipboard_x11.cpp2
-rw-r--r--src/gui/kernel/qcocoaapplicationdelegate_mac.mm18
-rw-r--r--src/gui/kernel/qcocoapanel_mac.mm6
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm233
-rw-r--r--src/gui/kernel/qcocoaview_mac_p.h3
-rw-r--r--src/gui/kernel/qcocoawindow_mac.mm6
-rw-r--r--src/gui/kernel/qcursor.cpp7
-rw-r--r--src/gui/kernel/qcursor_qws.cpp6
-rw-r--r--src/gui/kernel/qcursor_s60.cpp60
-rw-r--r--src/gui/kernel/qcursor_win.cpp56
-rw-r--r--src/gui/kernel/qdesktopwidget.h8
-rw-r--r--src/gui/kernel/qdesktopwidget.qdoc264
-rw-r--r--src/gui/kernel/qdesktopwidget_mac.mm64
-rw-r--r--src/gui/kernel/qdesktopwidget_mac_p.h3
-rw-r--r--src/gui/kernel/qdesktopwidget_s60.cpp201
-rw-r--r--src/gui/kernel/qdesktopwidget_win.cpp151
-rw-r--r--src/gui/kernel/qdesktopwidget_x11.cpp53
-rw-r--r--src/gui/kernel/qdnd.cpp2
-rw-r--r--src/gui/kernel/qdnd_mac.mm4
-rw-r--r--src/gui/kernel/qdnd_p.h4
-rw-r--r--src/gui/kernel/qdnd_s60.cpp395
-rw-r--r--src/gui/kernel/qdnd_win.cpp77
-rw-r--r--src/gui/kernel/qdnd_x11.cpp30
-rw-r--r--src/gui/kernel/qevent.cpp705
-rw-r--r--src/gui/kernel/qevent.h104
-rw-r--r--src/gui/kernel/qevent_p.h65
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm435
-rw-r--r--src/gui/kernel/qeventdispatcher_mac_p.h26
-rw-r--r--src/gui/kernel/qeventdispatcher_s60.cpp130
-rw-r--r--src/gui/kernel/qeventdispatcher_s60_p.h (renamed from src/gui/embedded/qmousevr41xx_qws.h)64
-rw-r--r--src/gui/kernel/qformlayout.cpp2
-rw-r--r--src/gui/kernel/qgesture.cpp308
-rw-r--r--src/gui/kernel/qgesture.h103
-rw-r--r--src/gui/kernel/qgesture_p.h88
-rw-r--r--src/gui/kernel/qgridlayout.cpp22
-rw-r--r--src/gui/kernel/qguifunctions_wince.cpp49
-rw-r--r--src/gui/kernel/qguifunctions_wince.h8
-rw-r--r--src/gui/kernel/qguivariant.cpp161
-rw-r--r--src/gui/kernel/qkde.cpp157
-rw-r--r--src/gui/kernel/qkde_p.h76
-rw-r--r--src/gui/kernel/qkeymapper.cpp3
-rw-r--r--src/gui/kernel/qkeymapper_mac.cpp46
-rw-r--r--src/gui/kernel/qkeymapper_p.h10
-rw-r--r--src/gui/kernel/qkeymapper_s60.cpp247
-rw-r--r--src/gui/kernel/qkeymapper_win.cpp139
-rw-r--r--src/gui/kernel/qkeysequence.cpp275
-rw-r--r--src/gui/kernel/qkeysequence.h4
-rw-r--r--src/gui/kernel/qlayout.cpp28
-rw-r--r--src/gui/kernel/qlayoutengine.cpp2
-rw-r--r--src/gui/kernel/qlayoutitem.cpp9
-rw-r--r--src/gui/kernel/qmime_mac.cpp172
-rw-r--r--src/gui/kernel/qmime_win.cpp160
-rw-r--r--src/gui/kernel/qmotifdnd_x11.cpp2
-rw-r--r--src/gui/kernel/qmultitouch_mac.mm219
-rw-r--r--src/gui/kernel/qmultitouch_mac_p.h102
-rw-r--r--src/gui/kernel/qpalette.cpp8
-rw-r--r--src/gui/kernel/qshortcut.cpp3
-rw-r--r--src/gui/kernel/qshortcutmap.cpp25
-rw-r--r--src/gui/kernel/qshortcutmap_p.h3
-rw-r--r--src/gui/kernel/qsizepolicy.h2
-rw-r--r--src/gui/kernel/qsizepolicy.qdoc521
-rw-r--r--src/gui/kernel/qsound.cpp5
-rw-r--r--src/gui/kernel/qsound_qws.cpp6
-rw-r--r--src/gui/kernel/qsound_s60.cpp206
-rw-r--r--src/gui/kernel/qsound_win.cpp40
-rw-r--r--src/gui/kernel/qstackedlayout.cpp2
-rw-r--r--src/gui/kernel/qstandardgestures.cpp624
-rw-r--r--src/gui/kernel/qstandardgestures.h154
-rw-r--r--src/gui/kernel/qstandardgestures_p.h129
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm233
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac_p.h12
-rw-r--r--src/gui/kernel/qt_mac.cpp19
-rw-r--r--src/gui/kernel/qt_mac_p.h15
-rw-r--r--src/gui/kernel/qt_s60_p.h291
-rw-r--r--src/gui/kernel/qt_x11_p.h26
-rw-r--r--src/gui/kernel/qtooltip.cpp23
-rw-r--r--src/gui/kernel/qwhatsthis.cpp11
-rw-r--r--src/gui/kernel/qwidget.cpp1064
-rw-r--r--src/gui/kernel/qwidget.h23
-rw-r--r--src/gui/kernel/qwidget_mac.mm582
-rw-r--r--src/gui/kernel/qwidget_p.h616
-rw-r--r--src/gui/kernel/qwidget_qws.cpp52
-rw-r--r--src/gui/kernel/qwidget_s60.cpp1206
-rw-r--r--src/gui/kernel/qwidget_win.cpp357
-rw-r--r--src/gui/kernel/qwidget_wince.cpp65
-rw-r--r--src/gui/kernel/qwidget_x11.cpp176
-rw-r--r--src/gui/kernel/qwidgetaction.cpp9
-rw-r--r--src/gui/kernel/qwindowdefs.h5
-rw-r--r--src/gui/kernel/qwindowdefs_win.h2
-rw-r--r--src/gui/kernel/qx11embed_x11.cpp26
-rw-r--r--src/gui/kernel/qx11info_x11.cpp3
-rw-r--r--src/gui/kernel/symbian.pri3
-rw-r--r--src/gui/kernel/x11.pri2
-rw-r--r--src/gui/mac/images/leopard-unified-toolbar-on.pngbin0 -> 356 bytes
-rw-r--r--src/gui/mac/macresources.qrc (renamed from src/gui/mac/maccursors.qrc)3
-rw-r--r--src/gui/math3d/math3d.pri15
-rw-r--r--src/gui/math3d/qgenericmatrix.cpp253
-rw-r--r--src/gui/math3d/qgenericmatrix.h373
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp1908
-rw-r--r--src/gui/math3d/qmatrix4x4.h1002
-rw-r--r--src/gui/math3d/qquaternion.cpp631
-rw-r--r--src/gui/math3d/qquaternion.h334
-rw-r--r--src/gui/math3d/qvector2d.cpp466
-rw-r--r--src/gui/math3d/qvector2d.h260
-rw-r--r--src/gui/math3d/qvector3d.cpp618
-rw-r--r--src/gui/math3d/qvector3d.h287
-rw-r--r--src/gui/math3d/qvector4d.cpp571
-rw-r--r--src/gui/math3d/qvector4d.h292
-rw-r--r--src/gui/painting/painting.pri59
-rw-r--r--src/gui/painting/qbackingstore.cpp53
-rw-r--r--src/gui/painting/qbackingstore_p.h8
-rw-r--r--src/gui/painting/qbezier.cpp32
-rw-r--r--src/gui/painting/qblendfunctions.cpp701
-rw-r--r--src/gui/painting/qblendfunctions_armv6_rvct.s222
-rw-r--r--src/gui/painting/qbrush.cpp123
-rw-r--r--src/gui/painting/qbrush.h17
-rw-r--r--src/gui/painting/qcolor.cpp471
-rw-r--r--src/gui/painting/qcolor.h32
-rw-r--r--src/gui/painting/qcolor_p.cpp2
-rw-r--r--src/gui/painting/qcolormap.qdoc152
-rw-r--r--src/gui/painting/qcolormap_s60.cpp107
-rw-r--r--src/gui/painting/qcolormap_win.cpp2
-rw-r--r--src/gui/painting/qcssutil.cpp8
-rw-r--r--src/gui/painting/qdrawhelper.cpp1387
-rw-r--r--src/gui/painting/qdrawhelper_armv6_p.h81
-rw-r--r--src/gui/painting/qdrawhelper_armv6_rvct.inc496
-rw-r--r--src/gui/painting/qdrawhelper_armv6_rvct.s177
-rw-r--r--src/gui/painting/qdrawhelper_p.h117
-rw-r--r--src/gui/painting/qdrawutil.cpp327
-rw-r--r--src/gui/painting/qdrawutil.h45
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp12
-rw-r--r--src/gui/painting/qfixed_p.h2
-rw-r--r--src/gui/painting/qgraphicssystem.cpp4
-rw-r--r--src/gui/painting/qgraphicssystemfactory.cpp6
-rw-r--r--src/gui/painting/qgraphicssystemfactory_p.h2
-rw-r--r--src/gui/painting/qgraphicssystemplugin_p.h2
-rw-r--r--src/gui/painting/qgrayraster.c8
-rw-r--r--src/gui/painting/qmatrix.cpp90
-rw-r--r--src/gui/painting/qmatrix.h34
-rw-r--r--src/gui/painting/qoutlinemapper.cpp28
-rw-r--r--src/gui/painting/qpaintdevice.cpp68
-rw-r--r--src/gui/painting/qpaintdevice.qdoc289
-rw-r--r--src/gui/painting/qpaintdevice_mac.cpp37
-rw-r--r--src/gui/painting/qpaintdevice_qws.cpp33
-rw-r--r--src/gui/painting/qpaintdevice_win.cpp21
-rw-r--r--src/gui/painting/qpaintdevice_x11.cpp21
-rw-r--r--src/gui/painting/qpaintengine.cpp10
-rw-r--r--src/gui/painting/qpaintengine.h4
-rw-r--r--src/gui/painting/qpaintengine_d3d.cpp4576
-rw-r--r--src/gui/painting/qpaintengine_d3d.fx608
-rw-r--r--src/gui/painting/qpaintengine_d3d.qrc5
-rw-r--r--src/gui/painting/qpaintengine_d3d_p.h120
-rw-r--r--src/gui/painting/qpaintengine_mac.cpp94
-rw-r--r--src/gui/painting/qpaintengine_mac_p.h107
-rw-r--r--src/gui/painting/qpaintengine_p.h4
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp826
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h22
-rw-r--r--src/gui/painting/qpaintengine_x11.cpp38
-rw-r--r--src/gui/painting/qpaintengineex.cpp222
-rw-r--r--src/gui/painting/qpaintengineex_p.h49
-rw-r--r--src/gui/painting/qpainter.cpp387
-rw-r--r--src/gui/painting/qpainter.h9
-rw-r--r--src/gui/painting/qpainter_p.h8
-rw-r--r--src/gui/painting/qpainterpath.cpp118
-rw-r--r--src/gui/painting/qpainterpath.h25
-rw-r--r--src/gui/painting/qpainterpath_p.h2
-rw-r--r--src/gui/painting/qpathclipper.cpp36
-rw-r--r--src/gui/painting/qpathclipper_p.h7
-rw-r--r--src/gui/painting/qpdf.cpp66
-rw-r--r--src/gui/painting/qpdf_p.h2
-rw-r--r--src/gui/painting/qpen.cpp6
-rw-r--r--src/gui/painting/qpolygon.cpp65
-rw-r--r--src/gui/painting/qpolygon.h13
-rw-r--r--src/gui/painting/qprintengine_mac.mm41
-rw-r--r--src/gui/painting/qprintengine_pdf.cpp6
-rw-r--r--src/gui/painting/qprintengine_ps.cpp24
-rw-r--r--src/gui/painting/qprintengine_win.cpp658
-rw-r--r--src/gui/painting/qprintengine_win_p.h16
-rw-r--r--src/gui/painting/qprinter.cpp39
-rw-r--r--src/gui/painting/qprinter.h5
-rw-r--r--src/gui/painting/qprinterinfo.h3
-rw-r--r--src/gui/painting/qprinterinfo.qdoc139
-rw-r--r--src/gui/painting/qprinterinfo_mac.cpp36
-rw-r--r--src/gui/painting/qprinterinfo_unix.cpp31
-rw-r--r--src/gui/painting/qprinterinfo_win.cpp124
-rw-r--r--src/gui/painting/qrasterizer.cpp5
-rw-r--r--src/gui/painting/qrasterizer_p.h2
-rw-r--r--src/gui/painting/qregion.cpp204
-rw-r--r--src/gui/painting/qregion.h5
-rw-r--r--src/gui/painting/qregion_mac.cpp37
-rw-r--r--src/gui/painting/qregion_s60.cpp (renamed from src/gui/embedded/qkbdyopy_qws.h)61
-rw-r--r--src/gui/painting/qregion_win.cpp513
-rw-r--r--src/gui/painting/qregion_wince.cpp119
-rw-r--r--src/gui/painting/qstroker.cpp12
-rw-r--r--src/gui/painting/qstylepainter.cpp2
-rw-r--r--src/gui/painting/qtessellator.cpp29
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp69
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h9
-rw-r--r--src/gui/painting/qtransform.cpp363
-rw-r--r--src/gui/painting/qtransform.h51
-rw-r--r--src/gui/painting/qvectorpath_p.h12
-rw-r--r--src/gui/painting/qwindowsurface_d3d.cpp169
-rw-r--r--src/gui/painting/qwindowsurface_raster.cpp43
-rw-r--r--src/gui/painting/qwindowsurface_raster_p.h15
-rw-r--r--src/gui/painting/qwindowsurface_s60.cpp237
-rw-r--r--src/gui/painting/qwindowsurface_s60_p.h95
-rw-r--r--src/gui/painting/qwindowsurface_x11.cpp8
-rw-r--r--src/gui/statemachine/qbasickeyeventtransition.cpp208
-rw-r--r--src/gui/statemachine/qbasickeyeventtransition_p.h98
-rw-r--r--src/gui/statemachine/qbasicmouseeventtransition.cpp213
-rw-r--r--src/gui/statemachine/qbasicmouseeventtransition_p.h101
-rw-r--r--src/gui/statemachine/qguistatemachine.cpp566
-rw-r--r--src/gui/statemachine/qkeyeventtransition.cpp178
-rw-r--r--src/gui/statemachine/qkeyeventtransition.h88
-rw-r--r--src/gui/statemachine/qmouseeventtransition.cpp206
-rw-r--r--src/gui/statemachine/qmouseeventtransition.h92
-rw-r--r--src/gui/statemachine/statemachine.pri13
-rw-r--r--src/gui/styles/gtksymbols.cpp290
-rw-r--r--src/gui/styles/gtksymbols_p.h3
-rw-r--r--src/gui/styles/images/defaults60theme.blobbin0 -> 74127 bytes
-rw-r--r--src/gui/styles/qcleanlooksstyle.cpp810
-rw-r--r--src/gui/styles/qcleanlooksstyle_p.h2
-rw-r--r--src/gui/styles/qcommonstyle.cpp1807
-rw-r--r--src/gui/styles/qcommonstyle_p.h15
-rw-r--r--src/gui/styles/qgtkstyle.cpp262
-rw-r--r--src/gui/styles/qgtkstyle.h4
-rw-r--r--src/gui/styles/qmacstyle.qdoc261
-rw-r--r--src/gui/styles/qmacstyle_mac.mm1077
-rw-r--r--src/gui/styles/qmacstylepixmaps_mac_p.h1400
-rw-r--r--src/gui/styles/qmotifstyle.cpp160
-rw-r--r--src/gui/styles/qplastiquestyle.cpp215
-rw-r--r--src/gui/styles/qproxystyle.cpp420
-rw-r--r--src/gui/styles/qproxystyle.h114
-rw-r--r--src/gui/styles/qproxystyle_p.h79
-rw-r--r--src/gui/styles/qs60style.cpp2882
-rw-r--r--src/gui/styles/qs60style.h110
-rw-r--r--src/gui/styles/qs60style_p.h508
-rw-r--r--src/gui/styles/qs60style_s60.cpp1384
-rw-r--r--src/gui/styles/qs60style_simulated.cpp448
-rw-r--r--src/gui/styles/qstyle.cpp118
-rw-r--r--src/gui/styles/qstyle.h16
-rw-r--r--src/gui/styles/qstyle_p.h17
-rw-r--r--src/gui/styles/qstyle_s60_simulated.qrc6
-rw-r--r--src/gui/styles/qstylefactory.cpp14
-rw-r--r--src/gui/styles/qstylehelper.cpp376
-rw-r--r--src/gui/styles/qstylehelper_p.h (renamed from src/gui/painting/qwindowsurface_d3d_p.h)54
-rw-r--r--src/gui/styles/qstyleoption.cpp96
-rw-r--r--src/gui/styles/qstyleoption.h1
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp350
-rw-r--r--src/gui/styles/qstylesheetstyle_default.cpp7
-rw-r--r--src/gui/styles/qstylesheetstyle_p.h2
-rw-r--r--src/gui/styles/qwindowscestyle.cpp4
-rw-r--r--src/gui/styles/qwindowsmobilestyle.cpp4449
-rw-r--r--src/gui/styles/qwindowsmobilestyle_p.h39
-rw-r--r--src/gui/styles/qwindowsstyle.cpp258
-rw-r--r--src/gui/styles/qwindowsvistastyle.cpp318
-rw-r--r--src/gui/styles/qwindowsxpstyle.cpp227
-rw-r--r--src/gui/styles/styles.pri23
-rw-r--r--src/gui/text/qabstractfontengine_p.h2
-rw-r--r--src/gui/text/qabstracttextdocumentlayout.cpp3
-rw-r--r--src/gui/text/qcssparser.cpp80
-rw-r--r--src/gui/text/qcssparser_p.h46
-rw-r--r--src/gui/text/qfont.cpp86
-rw-r--r--src/gui/text/qfont.h3
-rw-r--r--src/gui/text/qfont_s60.cpp94
-rw-r--r--src/gui/text/qfont_win.cpp8
-rw-r--r--src/gui/text/qfontdatabase.cpp281
-rw-r--r--src/gui/text/qfontdatabase.h3
-rw-r--r--src/gui/text/qfontdatabase_qws.cpp294
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp428
-rw-r--r--src/gui/text/qfontdatabase_win.cpp271
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp30
-rw-r--r--src/gui/text/qfontengine.cpp66
-rw-r--r--src/gui/text/qfontengine_ft.cpp105
-rw-r--r--src/gui/text/qfontengine_ft_p.h3
-rw-r--r--src/gui/text/qfontengine_mac.mm124
-rw-r--r--src/gui/text/qfontengine_p.h31
-rw-r--r--src/gui/text/qfontengine_qpf.cpp95
-rw-r--r--src/gui/text/qfontengine_qpf_p.h1
-rw-r--r--src/gui/text/qfontengine_qws.cpp7
-rw-r--r--src/gui/text/qfontengine_s60.cpp331
-rw-r--r--src/gui/text/qfontengine_s60_p.h148
-rw-r--r--src/gui/text/qfontengine_win.cpp500
-rw-r--r--src/gui/text/qfontengine_win_p.h18
-rw-r--r--src/gui/text/qfontengine_x11.cpp5
-rw-r--r--src/gui/text/qfontengineglyphcache_p.h4
-rw-r--r--src/gui/text/qfontmetrics.cpp50
-rw-r--r--src/gui/text/qfontsubset.cpp30
-rw-r--r--src/gui/text/qfragmentmap_p.h21
-rw-r--r--src/gui/text/qsyntaxhighlighter.cpp44
-rw-r--r--src/gui/text/qsyntaxhighlighter.h1
-rw-r--r--src/gui/text/qtextcontrol.cpp42
-rw-r--r--src/gui/text/qtextcursor.cpp90
-rw-r--r--src/gui/text/qtextdocument.cpp13
-rw-r--r--src/gui/text/qtextdocument_p.cpp188
-rw-r--r--src/gui/text/qtextdocument_p.h11
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp6
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp55
-rw-r--r--src/gui/text/qtextdocumentwriter.cpp2
-rw-r--r--src/gui/text/qtextengine.cpp16
-rw-r--r--src/gui/text/qtextengine_p.h2
-rw-r--r--src/gui/text/qtextformat.cpp180
-rw-r--r--src/gui/text/qtextformat.h6
-rw-r--r--src/gui/text/qtexthtmlparser.cpp15
-rw-r--r--src/gui/text/qtextimagehandler_p.h4
-rw-r--r--src/gui/text/qtextlayout.cpp8
-rw-r--r--src/gui/text/qtextlist.cpp53
-rw-r--r--src/gui/text/qtextobject.cpp16
-rw-r--r--src/gui/text/qtextobject_p.h3
-rw-r--r--src/gui/text/qtextodfwriter.cpp61
-rw-r--r--src/gui/text/qtextoption.cpp12
-rw-r--r--src/gui/text/qtexttable.cpp15
-rw-r--r--src/gui/text/qtexttable_p.h2
-rw-r--r--src/gui/text/qzip.cpp32
-rw-r--r--src/gui/text/text.pri35
-rw-r--r--src/gui/util/qcompleter.cpp68
-rw-r--r--src/gui/util/qcompleter.h4
-rw-r--r--src/gui/util/qcompleter_p.h4
-rw-r--r--src/gui/util/qdesktopservices.cpp8
-rw-r--r--src/gui/util/qdesktopservices_mac.cpp15
-rw-r--r--src/gui/util/qdesktopservices_s60.cpp440
-rw-r--r--src/gui/util/qdesktopservices_win.cpp95
-rw-r--r--src/gui/util/qdesktopservices_x11.cpp8
-rw-r--r--src/gui/util/qsystemtrayicon.cpp11
-rw-r--r--src/gui/util/qsystemtrayicon_win.cpp357
-rw-r--r--src/gui/util/qundogroup.cpp1
-rw-r--r--src/gui/util/qundostack.cpp2
-rw-r--r--src/gui/util/qundoview.cpp2
-rw-r--r--src/gui/util/util.pri5
-rw-r--r--src/gui/widgets/qabstractbutton.cpp43
-rw-r--r--src/gui/widgets/qabstractscrollarea.cpp97
-rw-r--r--src/gui/widgets/qabstractscrollarea.h5
-rw-r--r--src/gui/widgets/qabstractscrollarea_p.h14
-rw-r--r--src/gui/widgets/qabstractslider.cpp1
-rw-r--r--src/gui/widgets/qabstractspinbox.cpp35
-rw-r--r--src/gui/widgets/qabstractspinbox.h2
-rw-r--r--src/gui/widgets/qactiontokeyeventmapper.cpp103
-rw-r--r--src/gui/widgets/qactiontokeyeventmapper_p.h81
-rw-r--r--src/gui/widgets/qbuttongroup.cpp19
-rw-r--r--src/gui/widgets/qcalendarwidget.cpp30
-rw-r--r--src/gui/widgets/qcheckbox.cpp129
-rw-r--r--src/gui/widgets/qcocoamenu_mac.mm4
-rw-r--r--src/gui/widgets/qcocoatoolbardelegate_mac.mm12
-rw-r--r--src/gui/widgets/qcombobox.cpp67
-rw-r--r--src/gui/widgets/qcombobox_p.h3
-rw-r--r--src/gui/widgets/qcommandlinkbutton.cpp15
-rw-r--r--src/gui/widgets/qdatetimeedit.cpp51
-rw-r--r--src/gui/widgets/qdatetimeedit_p.h1
-rw-r--r--src/gui/widgets/qdial.cpp2
-rw-r--r--src/gui/widgets/qdialogbuttonbox.cpp4
-rw-r--r--src/gui/widgets/qdockarealayout.cpp311
-rw-r--r--src/gui/widgets/qdockarealayout_p.h47
-rw-r--r--src/gui/widgets/qdockwidget.cpp94
-rw-r--r--src/gui/widgets/qeffects.cpp104
-rw-r--r--src/gui/widgets/qfocusframe.cpp2
-rw-r--r--src/gui/widgets/qfontcombobox.cpp3
-rw-r--r--src/gui/widgets/qframe.cpp8
-rw-r--r--src/gui/widgets/qframe_p.h3
-rw-r--r--src/gui/widgets/qgroupbox.cpp19
-rw-r--r--src/gui/widgets/qlabel.cpp26
-rw-r--r--src/gui/widgets/qlcdnumber.cpp14
-rw-r--r--src/gui/widgets/qlinecontrol.cpp1779
-rw-r--r--src/gui/widgets/qlinecontrol_p.h744
-rw-r--r--src/gui/widgets/qlineedit.cpp1903
-rw-r--r--src/gui/widgets/qlineedit.h7
-rw-r--r--src/gui/widgets/qlineedit_p.cpp263
-rw-r--r--src/gui/widgets/qlineedit_p.h177
-rw-r--r--src/gui/widgets/qmacnativewidget_mac.h2
-rw-r--r--src/gui/widgets/qmainwindow.cpp52
-rw-r--r--src/gui/widgets/qmainwindowlayout.cpp327
-rw-r--r--src/gui/widgets/qmainwindowlayout_mac.mm51
-rw-r--r--src/gui/widgets/qmainwindowlayout_p.h62
-rw-r--r--src/gui/widgets/qmdiarea.cpp38
-rw-r--r--src/gui/widgets/qmdisubwindow.cpp79
-rw-r--r--src/gui/widgets/qmdisubwindow_p.h4
-rw-r--r--src/gui/widgets/qmenu.cpp656
-rw-r--r--src/gui/widgets/qmenu.h13
-rw-r--r--src/gui/widgets/qmenu_mac.mm240
-rw-r--r--src/gui/widgets/qmenu_p.h79
-rw-r--r--src/gui/widgets/qmenu_symbian.cpp425
-rw-r--r--src/gui/widgets/qmenu_wince.cpp4
-rw-r--r--src/gui/widgets/qmenubar.cpp437
-rw-r--r--src/gui/widgets/qmenubar.h8
-rw-r--r--src/gui/widgets/qmenubar_p.h74
-rw-r--r--src/gui/widgets/qmenudata.h2
-rw-r--r--src/gui/widgets/qplaintextedit.cpp110
-rw-r--r--src/gui/widgets/qplaintextedit.h5
-rw-r--r--src/gui/widgets/qplaintextedit_p.h15
-rw-r--r--src/gui/widgets/qprintpreviewwidget.cpp59
-rw-r--r--src/gui/widgets/qprintpreviewwidget.h2
-rw-r--r--src/gui/widgets/qprogressbar.cpp27
-rw-r--r--src/gui/widgets/qpushbutton.cpp16
-rw-r--r--src/gui/widgets/qpushbutton_p.h3
-rw-r--r--src/gui/widgets/qradiobutton.cpp2
-rw-r--r--src/gui/widgets/qrubberband.cpp3
-rw-r--r--src/gui/widgets/qscrollarea.cpp2
-rw-r--r--src/gui/widgets/qscrollbar.cpp6
-rw-r--r--src/gui/widgets/qsizegrip.cpp8
-rw-r--r--src/gui/widgets/qslider.cpp12
-rw-r--r--src/gui/widgets/qspinbox.cpp53
-rw-r--r--src/gui/widgets/qsplashscreen.cpp3
-rw-r--r--src/gui/widgets/qsplitter.cpp16
-rw-r--r--src/gui/widgets/qsplitter_p.h9
-rw-r--r--src/gui/widgets/qstackedwidget.cpp3
-rw-r--r--src/gui/widgets/qstatusbar.cpp8
-rw-r--r--src/gui/widgets/qtabbar.cpp100
-rw-r--r--src/gui/widgets/qtabbar.h2
-rw-r--r--src/gui/widgets/qtabbar_p.h68
-rw-r--r--src/gui/widgets/qtabwidget.cpp4
-rw-r--r--src/gui/widgets/qtextbrowser.cpp10
-rw-r--r--src/gui/widgets/qtextedit.cpp25
-rw-r--r--src/gui/widgets/qtextedit_p.h2
-rw-r--r--src/gui/widgets/qtoolbar.cpp109
-rw-r--r--src/gui/widgets/qtoolbar.h1
-rw-r--r--src/gui/widgets/qtoolbar_p.h8
-rw-r--r--src/gui/widgets/qtoolbararealayout.cpp139
-rw-r--r--src/gui/widgets/qtoolbararealayout_p.h77
-rw-r--r--src/gui/widgets/qtoolbarextension.cpp6
-rw-r--r--src/gui/widgets/qtoolbarlayout.cpp27
-rw-r--r--src/gui/widgets/qtoolbarlayout_p.h10
-rw-r--r--src/gui/widgets/qtoolbox.cpp2
-rw-r--r--src/gui/widgets/qtoolbutton.cpp30
-rw-r--r--src/gui/widgets/qvalidator.cpp11
-rw-r--r--src/gui/widgets/qvalidator.h4
-rw-r--r--src/gui/widgets/qwidgetanimator.cpp164
-rw-r--r--src/gui/widgets/qwidgetanimator_p.h34
-rw-r--r--src/gui/widgets/qwidgetresizehandler.cpp2
-rw-r--r--src/gui/widgets/qworkspace.cpp33
-rw-r--r--src/gui/widgets/widgets.pri17
709 files changed, 78644 insertions, 34344 deletions
diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri
index 76b6687..ad2fb4c 100644
--- a/src/gui/accessible/accessible.pri
+++ b/src/gui/accessible/accessible.pri
@@ -14,7 +14,8 @@ contains(QT_CONFIG, accessibility) {
mac:!embedded {
HEADERS += accessible/qaccessible_mac_p.h
- OBJECTIVE_SOURCES += accessible/qaccessible_mac.mm
+ OBJECTIVE_SOURCES += accessible/qaccessible_mac.mm \
+ accessible/qaccessible_mac_cocoa.mm
} else:win32 {
SOURCES += accessible/qaccessible_win.cpp
} else {
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index f911b72..30e1f46 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
relating to accessibility.
\ingroup accessibility
- \mainclass
+
Accessible applications can be used by people who are not able to
use applications by conventional means.
@@ -394,7 +394,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
(QAccessibleFactoryInterface_iid, QLatin1String("/accessible")))
#endif
-Q_GLOBAL_STATIC(QList<QAccessible::InterfaceFactory>, qAccessibleFactories);
+Q_GLOBAL_STATIC(QList<QAccessible::InterfaceFactory>, qAccessibleFactories)
QAccessible::UpdateHandler QAccessible::updateHandler = 0;
QAccessible::RootObjectHandler QAccessible::rootObjectHandler = 0;
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 75d5443..7c1793f 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -210,6 +210,7 @@ public:
PageTabList = 0x0000003C,
Clock = 0x0000003D,
Splitter = 0x0000003E,
+ // Additional Qt roles where enum value does not map directly to MSAA:
LayeredPane = 0x0000003F,
UserRole = 0x0000ffff
};
diff --git a/src/gui/accessible/qaccessible_mac.mm b/src/gui/accessible/qaccessible_mac.mm
index 3580e4e..31a20bf 100644
--- a/src/gui/accessible/qaccessible_mac.mm
+++ b/src/gui/accessible/qaccessible_mac.mm
@@ -1232,10 +1232,8 @@ static int textForRoleAndAttribute(QAccessible::Role role, CFStringRef attribute
return QAccessible::Value;
else if (CFStringCompare(attribute, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo)
return QAccessible::Help;
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
else if (CFStringCompare(attribute, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo)
return QAccessible::Description;
-#endif
else
return -1;
}
@@ -1442,17 +1440,13 @@ static OSStatus getAllAttributeNames(EventRef event, const QAInterface &interfac
qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRoleAttribute));
qt_mac_append_cf_uniq(attrs, CFStringRef(QAXEnabledAttribute));
qt_mac_append_cf_uniq(attrs, CFStringRef(QAXWindowAttribute));
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTopLevelUIElementAttribute));
-#endif
// Append these names if the QInterafceItem returns any data for them.
appendIfSupported(attrs, CFStringRef(QAXTitleAttribute), interface);
appendIfSupported(attrs, CFStringRef(QAXValueAttribute), interface);
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
appendIfSupported(attrs, CFStringRef(QAXDescriptionAttribute), interface);
appendIfSupported(attrs, CFStringRef(QAXLinkedUIElementsAttribute), interface);
-#endif
appendIfSupported(attrs, CFStringRef(QAXHelpAttribute), interface);
appendIfSupported(attrs, CFStringRef(QAXTitleUIElementAttribute), interface);
appendIfSupported(attrs, CFStringRef(QAXChildrenAttribute), interface);
@@ -1705,12 +1699,10 @@ static OSStatus handleWindowAttribute(EventHandlerCallRef next_ref, EventRef eve
Returns the top-level window for an interface, which is the closest ancestor interface that
has the Window role. (Can also be a sheet or a drawer)
*/
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
static OSStatus handleTopLevelUIElementAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
{
return navigateAncestors<IsWindowTest>(next_ref, event, interface, CFStringRef(QAXTopLevelUIElementAttribute));
}
-#endif
/*
Returns the tab buttons for an interface.
@@ -1888,10 +1880,8 @@ static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event,
if (CFStringCompare(var, CFStringRef(QAXChildrenAttribute), 0) == kCFCompareEqualTo) {
return handleChildrenAttribute(next_ref, event, interface);
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
} else if(CFStringCompare(var, CFStringRef(QAXTopLevelUIElementAttribute), 0) == kCFCompareEqualTo) {
return handleTopLevelUIElementAttribute(next_ref, event, interface);
-#endif
} else if(CFStringCompare(var, CFStringRef(QAXWindowAttribute), 0) == kCFCompareEqualTo) {
return handleWindowAttribute(next_ref, event, interface);
} else if(CFStringCompare(var, CFStringRef(QAXParentAttribute), 0) == kCFCompareEqualTo) {
@@ -1981,7 +1971,7 @@ static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event,
} else if (CFStringCompare(var, CFStringRef(QAXSubroleAttribute), 0) == kCFCompareEqualTo) {
return handleSubroleAttribute(next_ref, event, interface);
} else if (CFStringCompare(var, CFStringRef(QAXRoleDescriptionAttribute), 0) == kCFCompareEqualTo) {
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) && !defined(QT_MAC_USE_COCOA)
+#if !defined(QT_MAC_USE_COCOA)
if (HICopyAccessibilityRoleDescription) {
const CFStringRef roleDescription = HICopyAccessibilityRoleDescription(macRole(interface), 0);
SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
@@ -2005,14 +1995,12 @@ static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event,
} else {
handleStringAttribute(event, text, interface);
}
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
} else if (CFStringCompare(var, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo) {
const QAccessible::Role role = interface.role();
const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
handleStringAttribute(event, text, interface);
} else if (CFStringCompare(var, CFStringRef(QAXLinkedUIElementsAttribute), 0) == kCFCompareEqualTo) {
return CallNextEventHandler(next_ref, event);
-#endif
} else if (CFStringCompare(var, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo) {
const QAccessible::Role role = interface.role();
const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
diff --git a/src/gui/accessible/qaccessible_mac_cocoa.mm b/src/gui/accessible/qaccessible_mac_cocoa.mm
index e69de29..41a2566 100644
--- a/src/gui/accessible/qaccessible_mac_cocoa.mm
+++ b/src/gui/accessible/qaccessible_mac_cocoa.mm
@@ -0,0 +1,235 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessible.h"
+#include "qaccessible_mac_p.h"
+#include "qdebug.h"
+#include "qtabwidget.h"
+
+#include <private/qt_mac_p.h>
+#include <private/qcocoaview_mac_p.h>
+#include <private/qwidget_p.h>
+
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#ifdef QT_MAC_USE_COCOA
+
+QT_BEGIN_NAMESPACE
+
+//#define MAC_ACCESSIBILTY_DEVELOPER_MODE
+
+#ifdef MAC_ACCESSIBILTY_DEVELOPER_MODE
+#define MAC_ACCESSIBILTY_DEBUG QT_PREPEND_NAMESPACE(qDebug)
+#else
+#define MAC_ACCESSIBILTY_DEBUG if (0) QT_PREPEND_NAMESPACE(qDebug)
+#endif
+
+typedef QMap<QAccessible::Role, NSString *> QMacAccessibiltyRoleMap;
+Q_GLOBAL_STATIC(QMacAccessibiltyRoleMap, qMacAccessibiltyRoleMap);
+
+static QAInterface interfaceForView(QT_MANGLE_NAMESPACE(QCocoaView) *view)
+{
+ return QAInterface(QAccessible::queryAccessibleInterface([view qt_qwidget]));
+}
+
+/*
+ Set up mappings from Qt accessibilty roles to Mac accessibilty roles.
+*/
+static void populateRoleMap()
+{
+ QMacAccessibiltyRoleMap &roleMap = *qMacAccessibiltyRoleMap();
+ roleMap[QAccessible::MenuItem] = NSAccessibilityMenuItemRole;
+ roleMap[QAccessible::MenuBar] = NSAccessibilityMenuBarRole;
+ roleMap[QAccessible::ScrollBar] = NSAccessibilityScrollBarRole;
+ roleMap[QAccessible::Grip] = NSAccessibilityGrowAreaRole;
+ roleMap[QAccessible::Window] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::Dialog] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::AlertMessage] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::ToolTip] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::HelpBalloon] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::PopupMenu] = NSAccessibilityMenuRole;
+ roleMap[QAccessible::Application] = NSAccessibilityApplicationRole;
+ roleMap[QAccessible::Pane] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Grouping] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Separator] = NSAccessibilitySplitterRole;
+ roleMap[QAccessible::ToolBar] = NSAccessibilityToolbarRole;
+ roleMap[QAccessible::PageTab] = NSAccessibilityRadioButtonRole;
+ roleMap[QAccessible::ButtonMenu] = NSAccessibilityMenuButtonRole;
+ roleMap[QAccessible::ButtonDropDown] = NSAccessibilityPopUpButtonRole;
+ roleMap[QAccessible::SpinBox] = NSAccessibilityIncrementorRole;
+ roleMap[QAccessible::Slider] = NSAccessibilitySliderRole;
+ roleMap[QAccessible::ProgressBar] = NSAccessibilityProgressIndicatorRole;
+ roleMap[QAccessible::ComboBox] = NSAccessibilityPopUpButtonRole;
+ roleMap[QAccessible::RadioButton] = NSAccessibilityRadioButtonRole;
+ roleMap[QAccessible::CheckBox] = NSAccessibilityCheckBoxRole;
+ roleMap[QAccessible::StaticText] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Table] = NSAccessibilityTableRole;
+ roleMap[QAccessible::StatusBar] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Column] = NSAccessibilityColumnRole;
+ roleMap[QAccessible::ColumnHeader] = NSAccessibilityColumnRole;
+ roleMap[QAccessible::Row] = NSAccessibilityRowRole;
+ roleMap[QAccessible::RowHeader] = NSAccessibilityRowRole;
+ roleMap[QAccessible::Cell] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::PushButton] = NSAccessibilityButtonRole;
+ roleMap[QAccessible::EditableText] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::Link] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::Indicator] = NSAccessibilityValueIndicatorRole;
+ roleMap[QAccessible::Splitter] = NSAccessibilitySplitGroupRole;
+ roleMap[QAccessible::List] = NSAccessibilityListRole;
+ roleMap[QAccessible::ListItem] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Cell] = NSAccessibilityStaticTextRole;
+}
+
+/*
+ Returns a Mac accessibility role for the given interface, or
+ NSAccessibilityUnknownRole if no role mapping is found.
+*/
+static NSString *macRoleForInterface(QAInterface interface)
+{
+ const QAccessible::Role qtRole = interface.role();
+ QMacAccessibiltyRoleMap &roleMap = *qMacAccessibiltyRoleMap();
+
+ if (roleMap.isEmpty())
+ populateRoleMap();
+
+ MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << hex << qtRole;
+
+ if (roleMap.contains(qtRole)) {
+ MAC_ACCESSIBILTY_DEBUG() << "return" << roleMap[qtRole];
+ return roleMap[qtRole];
+ }
+
+ MAC_ACCESSIBILTY_DEBUG() << "return NSAccessibilityUnknownRole";
+ return NSAccessibilityUnknownRole;
+}
+
+/*
+ Is the interface a QTabBar embedded in a QTabWidget?
+ (as opposed to a stand-alone tab bar)
+*/
+static bool isEmbeddedTabBar(const QAInterface &interface)
+{
+ QObject *object = interface.object();
+ if (interface.role() == QAccessible::PageTabList && object)
+ return (qobject_cast<QTabWidget *>(object->parent()));
+
+ return false;
+}
+
+static bool isInterfaceIgnored(QAInterface interface)
+{
+ // Mac accessibility does not have an attribute that corresponds to the
+ // Invisible/Offscreen state. Use the ignore facility to disable them.
+ const QAccessible::State state = interface.state();
+ if (state & QAccessible::Invisible ||
+ state & QAccessible::Offscreen )
+ return false;
+
+ // Hide QTabBars that has a QTabWidget parent (the QTabWidget handles the accessibility)
+ if (isEmbeddedTabBar(interface))
+ return false;
+
+ if (QObject * const object = interface.object()) {
+ const QString className = QLatin1String(object->metaObject()->className());
+
+ // Prevent VoiceOver from focusing on tool tips by ignoring those
+ // interfaces. Shifting VoiceOver focus to the tool tip is confusing
+ // and the contents of the tool tip is avalible through the description
+ // attribute anyway.
+ if (className == QLatin1String("QTipLabel"))
+ return false;
+ }
+
+ // Hide interfaces with an unknown role. When developing it's often useful to disable
+ // this check to see all interfaces in the hierarchy.
+#ifndef MAC_ACCESSIBILTY_DEVELOPER_MODE
+ return [macRoleForInterface(interface) isEqualToString: NSAccessibilityUnknownRole];
+#else
+ return NO;
+#endif
+}
+
+QT_END_NAMESPACE
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaView) (Accessibility)
+
+- (BOOL)accessibilityIsIgnored
+{
+ QT_PREPEND_NAMESPACE(QAInterface) interface = QT_PREPEND_NAMESPACE(interfaceForView)(self);
+ return isInterfaceIgnored(interface);
+}
+
+- (NSArray *)accessibilityAttributeNames
+{
+ QT_PREPEND_NAMESPACE(QAInterface) interface = QT_PREPEND_NAMESPACE(interfaceForView)(self);
+
+ static NSArray *attributes = nil;
+ if (attributes == nil) {
+ attributes = [super accessibilityAttributeNames];
+
+ }
+ return attributes;
+}
+
+- (id)accessibilityAttributeValue:(NSString *)attribute
+{
+ MAC_ACCESSIBILTY_DEBUG() << "accessibilityAttributeValue" << self <<
+ QT_PREPEND_NAMESPACE(QCFString)::toQString(reinterpret_cast<CFStringRef>(attribute));
+
+ QT_PREPEND_NAMESPACE(QAInterface) interface = QT_PREPEND_NAMESPACE(interfaceForView)(self);
+
+ // Switch on the attribute name and call the appropriate handler function.
+ // Pass the call on to the NSView class for attributes we don't handle.
+ if ([attribute isEqualToString:@"AXRole"]) {
+ return macRoleForInterface(interface);
+ } else {
+ return [super accessibilityAttributeValue:attribute];
+ }
+}
+
+@end
+
+#endif // QT_MAC_USE_COCOA
+
+#endif // QT_NO_ACCESSIBILITY
+
diff --git a/src/gui/accessible/qaccessible_win.cpp b/src/gui/accessible/qaccessible_win.cpp
index f88f8cb..9e7cf35 100644
--- a/src/gui/accessible/qaccessible_win.cpp
+++ b/src/gui/accessible/qaccessible_win.cpp
@@ -50,7 +50,7 @@
#include <winuser.h>
#if !defined(WINABLEAPI)
-# if defined(Q_OS_WINCE)
+# if defined(Q_WS_WINCE)
# include <bldver.h>
# endif
# include <winable.h>
@@ -61,7 +61,7 @@
#include <comdef.h>
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qguifunctions_wince.h"
#endif
@@ -177,14 +177,14 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
return;
}
- QByteArray soundName;
+ QString soundName;
switch (reason) {
case PopupMenuStart:
- soundName = "MenuPopup";
+ soundName = QLatin1String("MenuPopup");
break;
case MenuCommand:
- soundName = "MenuCommand";
+ soundName = QLatin1String("MenuCommand");
break;
case Alert:
@@ -194,13 +194,13 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
if (mb) {
switch (mb->icon()) {
case QMessageBox::Warning:
- soundName = "SystemExclamation";
+ soundName = QLatin1String("SystemExclamation");
break;
case QMessageBox::Critical:
- soundName = "SystemHand";
+ soundName = QLatin1String("SystemHand");
break;
case QMessageBox::Information:
- soundName = "SystemAsterisk";
+ soundName = QLatin1String("SystemAsterisk");
break;
default:
break;
@@ -208,7 +208,7 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
} else
#endif // QT_NO_MESSAGEBOX
{
- soundName = "SystemAsterisk";
+ soundName = QLatin1String("SystemAsterisk");
}
}
@@ -219,27 +219,23 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
if (soundName.size()) {
#ifndef QT_NO_SETTINGS
- QSettings settings(QLatin1String("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\.Default\\") +
- QString::fromLatin1(soundName.constData()), QSettings::NativeFormat);
+ QSettings settings(QLatin1String("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\.Default\\") + soundName,
+ QSettings::NativeFormat);
QString file = settings.value(QLatin1String(".Current/.")).toString();
#else
- QString file;
+ QString file;
#endif
- if (!file.isEmpty()) {
- QT_WA({
- PlaySoundW(reinterpret_cast<const wchar_t *> (QString::fromLatin1(soundName).utf16()), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT );
- } , {
- PlaySoundA(soundName.constData(), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT );
- });
- }
- }
+ if (!file.isEmpty()) {
+ PlaySound(reinterpret_cast<const wchar_t *>(soundName.utf16()), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT);
+ }
+ }
if (!isActive())
return;
typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG);
-#if defined(Q_OS_WINCE) // ### TODO: check for NotifyWinEvent in CE 6.0
+#if defined(Q_WS_WINCE) // ### TODO: check for NotifyWinEvent in CE 6.0
// There is no user32.lib nor NotifyWinEvent for CE
return;
#else
@@ -270,9 +266,9 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
if (!w) {
if (reason != QAccessible::ContextHelpStart &&
reason != QAccessible::ContextHelpEnd)
- w = qApp->focusWidget();
+ w = QApplication::focusWidget();
if (!w) {
- w = qApp->activeWindow();
+ w = QApplication::activeWindow();
if (!w)
return;
@@ -289,7 +285,7 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
if (reason != MenuCommand) { // MenuCommand is faked
ptrNotifyWinEvent(reason, w->winId(), OBJID_CLIENT, who);
}
-#endif // Q_OS_WINCE
+#endif // Q_WS_WINCE
}
void QAccessible::setRootObject(QObject *o)
@@ -1055,6 +1051,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT
Role role = accessible->role(varID.lVal);
if (role != NoRole) {
+ if (role == LayeredPane)
+ role = QAccessible::Pane;
(*pvarRole).vt = VT_I4;
(*pvarRole).lVal = role;
} else {
diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp
index 133b216..aa10d17 100644
--- a/src/gui/accessible/qaccessibleobject.cpp
+++ b/src/gui/accessible/qaccessibleobject.cpp
@@ -212,7 +212,7 @@ QAccessibleApplication::QAccessibleApplication()
static QWidgetList topLevelWidgets()
{
QWidgetList list;
- const QWidgetList tlw(qApp->topLevelWidgets());
+ const QWidgetList tlw(QApplication::topLevelWidgets());
for (int i = 0; i < tlw.count(); ++i) {
QWidget *w = tlw.at(i);
if (!(w->windowType() == Qt::Popup) && !(w->windowType() == Qt::Desktop))
@@ -308,7 +308,7 @@ int QAccessibleApplication::navigate(RelationFlag relation, int entry,
}
break;
case FocusChild:
- targetObject = qApp->activeWindow();
+ targetObject = QApplication::activeWindow();
break;
default:
break;
@@ -322,11 +322,11 @@ QString QAccessibleApplication::text(Text t, int) const
{
switch (t) {
case Name:
- if (qApp->activeWindow())
- return qApp->activeWindow()->windowTitle();
+ if (QApplication::activeWindow())
+ return QApplication::activeWindow()->windowTitle();
break;
case Description:
- return qApp->applicationFilePath();
+ return QApplication::applicationFilePath();
default:
break;
}
@@ -342,7 +342,7 @@ QAccessible::Role QAccessibleApplication::role(int) const
/*! \reimp */
QAccessible::State QAccessibleApplication::state(int) const
{
- return qApp->activeWindow() ? Focused : Normal;
+ return QApplication::activeWindow() ? Focused : Normal;
}
/*! \reimp */
@@ -356,7 +356,7 @@ bool QAccessibleApplication::doAction(int action, int child, const QVariantList
{
if (action == 0 || action == 1) {
QWidget *w = 0;
- w = qApp->activeWindow();
+ w = QApplication::activeWindow();
if (!w)
w = topLevelWidgets().at(0);
if (!w)
diff --git a/src/gui/accessible/qaccessiblewidget.cpp b/src/gui/accessible/qaccessiblewidget.cpp
index 064fd4d..a934f69 100644
--- a/src/gui/accessible/qaccessiblewidget.cpp
+++ b/src/gui/accessible/qaccessiblewidget.cpp
@@ -102,24 +102,7 @@ static QString buddyString(const QWidget *widget)
QString Q_GUI_EXPORT qt_accStripAmp(const QString &text)
{
- if (text.isEmpty())
- return text;
-
- const QChar *ch = text.unicode();
- int length = text.length();
- QString str;
- while (length > 0) {
- if (*ch == QLatin1Char('&')) {
- ++ch;
- --length;
- if (!ch)
- --ch;
- }
- str += *ch;
- ++ch;
- --length;
- }
- return str;
+ return QString(text).remove(QLatin1Char('&'));
}
QString Q_GUI_EXPORT qt_accHotKey(const QString &text)
diff --git a/src/gui/animation/animation.pri b/src/gui/animation/animation.pri
new file mode 100644
index 0000000..27763ca
--- /dev/null
+++ b/src/gui/animation/animation.pri
@@ -0,0 +1,3 @@
+# Qt gui animation module
+
+SOURCES += animation/qguivariantanimation.cpp
diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp
new file mode 100644
index 0000000..de9363c
--- /dev/null
+++ b/src/gui/animation/qguivariantanimation.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_ANIMATION
+
+#include <QtCore/qvariantanimation.h>
+#include <private/qvariantanimation_p.h>
+
+#include <QtGui/qcolor.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qquaternion.h>
+
+QT_BEGIN_NAMESPACE
+
+template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor &t, qreal progress)
+{
+ return QColor(_q_interpolate(f.red(), t.red(), progress),
+ _q_interpolate(f.green(), t.green(), progress),
+ _q_interpolate(f.blue(), t.blue(), progress),
+ _q_interpolate(f.alpha(), t.alpha(), progress));
+}
+
+template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,const QQuaternion &t, qreal progress)
+{
+ return QQuaternion::slerp(f, t, progress);
+}
+
+static int qRegisterGuiGetInterpolator()
+{
+ qRegisterAnimationInterpolator<QColor>(_q_interpolateVariant<QColor>);
+ qRegisterAnimationInterpolator<QVector2D>(_q_interpolateVariant<QVector2D>);
+ qRegisterAnimationInterpolator<QVector3D>(_q_interpolateVariant<QVector3D>);
+ qRegisterAnimationInterpolator<QVector4D>(_q_interpolateVariant<QVector4D>);
+ qRegisterAnimationInterpolator<QQuaternion>(_q_interpolateVariant<QQuaternion>);
+ return 1;
+}
+Q_CONSTRUCTOR_FUNCTION(qRegisterGuiGetInterpolator)
+
+static int qUnregisterGuiGetInterpolator()
+{
+ // casts required by Sun CC 5.5
+ qRegisterAnimationInterpolator<QColor>(
+ (QVariant (*)(const QColor &, const QColor &, qreal))0);
+ qRegisterAnimationInterpolator<QVector2D>(
+ (QVariant (*)(const QVector2D &, const QVector2D &, qreal))0);
+ qRegisterAnimationInterpolator<QVector3D>(
+ (QVariant (*)(const QVector3D &, const QVector3D &, qreal))0);
+ qRegisterAnimationInterpolator<QVector4D>(
+ (QVariant (*)(const QVector4D &, const QVector4D &, qreal))0);
+ qRegisterAnimationInterpolator<QQuaternion>(
+ (QVariant (*)(const QQuaternion &, const QQuaternion &, qreal))0);
+
+ return 1;
+}
+Q_DESTRUCTOR_FUNCTION(qUnregisterGuiGetInterpolator)
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
diff --git a/src/gui/dialogs/dialogs.pri b/src/gui/dialogs/dialogs.pri
index f1ec858..b9fad41 100644
--- a/src/gui/dialogs/dialogs.pri
+++ b/src/gui/dialogs/dialogs.pri
@@ -7,6 +7,7 @@ HEADERS += \
dialogs/qabstractpagesetupdialog_p.h \
dialogs/qcolordialog.h \
dialogs/qcolordialog_p.h \
+ dialogs/qfscompleter_p.h \
dialogs/qdialog.h \
dialogs/qdialog_p.h \
dialogs/qerrormessage.h \
@@ -45,7 +46,7 @@ win32 {
!win32-borland:!wince*: LIBS += -lshell32 # the filedialog needs this library
}
-!mac:!embedded:unix {
+!mac:!embedded:!symbian:unix {
HEADERS += dialogs/qpagesetupdialog_unix_p.h
SOURCES += dialogs/qprintdialog_unix.cpp \
dialogs/qpagesetupdialog_unix.cpp
@@ -70,7 +71,7 @@ embedded {
}
}
-wince*: FORMS += dialogs/qfiledialog_wince.ui
+wince*|symbian: FORMS += dialogs/qfiledialog_embedded.ui
else: FORMS += dialogs/qfiledialog.ui
INCLUDEPATH += $$PWD
@@ -94,4 +95,4 @@ SOURCES += \
FORMS += dialogs/qpagesetupwidget.ui
RESOURCES += dialogs/qprintdialog.qrc
-RESOURCES += dialogs/qmessagebox.qrc \ No newline at end of file
+RESOURCES += dialogs/qmessagebox.qrc
diff --git a/src/gui/dialogs/qabstractprintdialog.cpp b/src/gui/dialogs/qabstractprintdialog.cpp
index 7872960..9be2d8c 100644
--- a/src/gui/dialogs/qabstractprintdialog.cpp
+++ b/src/gui/dialogs/qabstractprintdialog.cpp
@@ -59,6 +59,8 @@ class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
\brief The QAbstractPrintDialog class provides a base implementation for
print dialogs used to configure printers.
+ \ingroup printing
+
This class implements getter and setter functions that are used to
customize settings shown in print dialogs, but it is not used directly.
Use QPrintDialog to display a print dialog in your application.
@@ -357,7 +359,8 @@ void QAbstractPrintDialogPrivate::setPrinter(QPrinter *newPrinter)
\brief The QPrintDialog class provides a dialog for specifying
the printer's configuration.
- \ingroup dialogs
+ \ingroup standard-dialogs
+ \ingroup printing
The dialog allows users to change document-related settings, such
as the paper size and orientation, type of print (color or
@@ -395,10 +398,8 @@ void QAbstractPrintDialogPrivate::setPrinter(QPrinter *newPrinter)
On Windows and Mac OS X, the native print dialog is used, which means that
some QWidget and QDialog properties set on the dialog won't be respected.
- The native print dialog on
- Mac OS X does not support setting printer options, i.e.
- QAbstractPrintDialog::setEnabledOptions() and
- QAbstractPrintDialog::addEnabledOption() have no effect.
+ The native print dialog on Mac OS X does not support setting printer options,
+ i.e. setOptions() and setOption() have no effect.
In Qt 4.4, it was possible to use the static functions to show a sheet on
Mac OS X. This is no longer supported in Qt 4.5. If you want this
diff --git a/src/gui/dialogs/qcolordialog.cpp b/src/gui/dialogs/qcolordialog.cpp
index c03c47c..354de1d 100644
--- a/src/gui/dialogs/qcolordialog.cpp
+++ b/src/gui/dialogs/qcolordialog.cpp
@@ -1066,7 +1066,7 @@ QColorShower::QColorShower(QColorDialog *parent)
QGridLayout *gl = new QGridLayout(this);
gl->setMargin(gl->spacing());
lab = new QColorShowLabel(this);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
lab->setMinimumWidth(60);
#else
lab->setMinimumWidth(20);
@@ -1369,13 +1369,13 @@ void QColorDialogPrivate::init(const QColor &initial)
leftLay = 0;
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
smallDisplay = true;
const int lumSpace = 20;
#else
// small displays (e.g. PDAs) cannot fit the full color dialog,
// so just use the color picker.
- smallDisplay = (qApp->desktop()->width() < 480 || qApp->desktop()->height() < 350);
+ smallDisplay = (QApplication::desktop()->width() < 480 || QApplication::desktop()->height() < 350);
const int lumSpace = topLay->spacing() / 2;
#endif
@@ -1409,7 +1409,7 @@ void QColorDialogPrivate::init(const QColor &initial)
leftLay->addWidget(lblBasicColors);
leftLay->addWidget(standard);
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
leftLay->addStretch();
#endif
@@ -1510,9 +1510,7 @@ static const Qt::WindowFlags DefaultWindowFlags =
\class QColorDialog
\brief The QColorDialog class provides a dialog widget for specifying colors.
- \mainclass
- \ingroup dialogs
- \ingroup multimedia
+ \ingroup standard-dialogs
The color dialog's function is to allow users to choose colors.
For example, you might use this in a drawing program to allow the
@@ -1578,10 +1576,11 @@ void QColorDialog::setCurrentColor(const QColor &color)
{
Q_D(QColorDialog);
d->setCurrentColor(color.rgb());
- d->selectColor(color.rgb());
+ d->selectColor(color);
d->setCurrentAlpha(color.alpha());
#ifdef Q_WS_MAC
+ d->setCurrentQColor(color);
d->setCocoaPanelColor(color);
#endif
}
@@ -1835,8 +1834,8 @@ QRgb QColorDialog::getRgba(QRgb initial, bool *ok, QWidget *parent)
QColorDialog::~QColorDialog()
{
- Q_D(QColorDialog);
#if defined(Q_WS_MAC)
+ Q_D(QColorDialog);
if (d->delegate) {
d->releaseCocoaColorPanelDelegate();
QColorDialogPrivate::sharedColorPanelAvailable = true;
diff --git a/src/gui/dialogs/qcolordialog_mac.mm b/src/gui/dialogs/qcolordialog_mac.mm
index 248d621..71869b2 100644
--- a/src/gui/dialogs/qcolordialog_mac.mm
+++ b/src/gui/dialogs/qcolordialog_mac.mm
@@ -256,16 +256,22 @@ QT_USE_NAMESPACE
CGFloat cyan, magenta, yellow, black, alpha;
[color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha];
mQtColor->setCmykF(cyan, magenta, yellow, black, alpha);
+ } else if (colorSpace == NSCalibratedRGBColorSpace || colorSpace == NSDeviceRGBColorSpace) {
+ CGFloat red, green, blue, alpha;
+ [color getRed:&red green:&green blue:&blue alpha:&alpha];
+ mQtColor->setRgbF(red, green, blue, alpha);
} else {
- NSColor *tmpColor;
- if (colorSpace == NSCalibratedRGBColorSpace || colorSpace == NSDeviceRGBColorSpace) {
- tmpColor = color;
+ NSColorSpace *colorSpace = [color colorSpace];
+ if ([colorSpace colorSpaceModel] == NSCMYKColorSpaceModel && [color numberOfComponents] == 5){
+ CGFloat components[5];
+ [color getComponents:components];
+ mQtColor->setCmykF(components[0], components[1], components[2], components[3], components[4]);
} else {
- tmpColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ NSColor *tmpColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ CGFloat red, green, blue, alpha;
+ [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha];
+ mQtColor->setRgbF(red, green, blue, alpha);
}
- CGFloat red, green, blue, alpha;
- [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha];
- mQtColor->setRgbF(red, green, blue, alpha);
}
mPriv->setCurrentQColor(*mQtColor);
@@ -437,10 +443,20 @@ void QColorDialogPrivate::setCocoaPanelColor(const QColor &color)
{
QMacCocoaAutoReleasePool pool;
QCocoaColorPanelDelegate *theDelegate = static_cast<QCocoaColorPanelDelegate *>(delegate);
- NSColor *nsColor = [NSColor colorWithCalibratedRed:color.red() / 255.0
- green:color.green() / 255.0
- blue:color.blue() / 255.0
- alpha:color.alpha() / 255.0];
+ NSColor *nsColor;
+ const QColor::Spec spec = color.spec();
+ if (spec == QColor::Cmyk) {
+ nsColor = [NSColor colorWithDeviceCyan:color.cyanF()
+ magenta:color.magentaF()
+ yellow:color.yellowF()
+ black:color.blackF()
+ alpha:color.alphaF()];
+ } else {
+ nsColor = [NSColor colorWithCalibratedRed:color.redF()
+ green:color.greenF()
+ blue:color.blueF()
+ alpha:color.alphaF()];
+ }
[[theDelegate colorPanel] setColor:nsColor];
}
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index 30006b7..6f80046 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -55,7 +55,7 @@
#ifndef QT_NO_ACCESSIBILITY
#include "qaccessible.h"
#endif
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qt_windows.h"
#include "qmenubar.h"
#include "qpointer.h"
@@ -64,8 +64,10 @@ extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp
extern bool qt_wince_is_smartphone(); //is defined in qguifunctions_wce.cpp
#elif defined(Q_WS_X11)
# include "../kernel/qt_x11_p.h"
+#elif defined(Q_OS_SYMBIAN)
+# include "qfiledialog.h"
+# include "qmenubar.h"
#endif
-
#ifndef SPI_GETSNAPTODEFBUTTON
# define SPI_GETSNAPTODEFBUTTON 95
#endif
@@ -76,9 +78,9 @@ QT_BEGIN_NAMESPACE
\class QDialog
\brief The QDialog class is the base class of dialog windows.
- \ingroup dialogs
+ \ingroup dialog-classes
\ingroup abstractwidgets
- \mainclass
+
A dialog window is a top-level window mostly used for short-term
tasks and brief communications with the user. QDialogs may be
@@ -251,7 +253,7 @@ QDialog::QDialog(QWidget *parent, Qt::WindowFlags f)
: QWidget(*new QDialogPrivate, parent,
f | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0))
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (!qt_wince_is_smartphone())
setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint));
#endif
@@ -280,7 +282,7 @@ QDialog::QDialog(QWidget *parent, const char *name, bool modal, Qt::WindowFlags
QDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f)
: QWidget(dd, parent, f | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0))
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (!qt_wince_is_smartphone())
setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint));
#endif
@@ -292,9 +294,13 @@ QDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f)
QDialog::~QDialog()
{
- // Need to hide() here, as our (to-be) overridden hide()
- // will not be called in ~QWidget.
- hide();
+ QT_TRY {
+ // Need to hide() here, as our (to-be) overridden hide()
+ // will not be called in ~QWidget.
+ hide();
+ } QT_CATCH(...) {
+ // we're in the destructor - just swallow the exception
+ }
}
/*!
@@ -364,8 +370,8 @@ void QDialogPrivate::resetModalitySetByOpen()
resetModalityTo = -1;
}
-#ifdef Q_OS_WINCE
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE
+#ifdef Q_WS_WINCE_WM
void QDialogPrivate::_q_doneAction()
{
//Done...
@@ -473,7 +479,7 @@ int QDialog::exec()
setResult(0);
//On Windows Mobile we create an empty menu to hide the current menu
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
#ifndef QT_NO_MENUBAR
QMenuBar *menuBar = 0;
if (!findChild<QMenuBar *>())
@@ -484,9 +490,21 @@ int QDialog::exec()
connect(doneAction, SIGNAL(triggered()), this, SLOT(_q_doneAction()));
}
#endif //QT_NO_MENUBAR
-#endif //Q_OS_WINCE_WM
+#endif //Q_WS_WINCE_WM
- show();
+#ifdef Q_OS_SYMBIAN
+#ifndef QT_NO_MENUBAR
+ QMenuBar *menuBar = 0;
+ if (!findChild<QMenuBar *>())
+ menuBar = new QMenuBar(this);
+#endif
+
+ if (qobject_cast<QFileDialog *>(this))
+ showFullScreen();
+ else
+#endif // Q_OS_SYMBIAN
+
+ show();
#ifdef Q_WS_MAC
d->mac_nativeDialogModalHelp();
@@ -505,12 +523,19 @@ int QDialog::exec()
int res = result();
if (deleteOnClose)
delete this;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
+#ifndef QT_NO_MENUBAR
+ else if (menuBar)
+ delete menuBar;
+#endif //QT_NO_MENUBAR
+#endif //Q_WS_WINCE_WM
+#ifdef Q_OS_SYMBIAN
#ifndef QT_NO_MENUBAR
else if (menuBar)
delete menuBar;
#endif //QT_NO_MENUBAR
-#endif //Q_OS_WINCE_WM
+#endif //Q_OS_SYMBIAN
+
return res;
}
@@ -762,8 +787,7 @@ void QDialog::setVisible(bool visible)
#ifdef Q_WS_WIN
if (d->mainDef && isActiveWindow()) {
BOOL snapToDefault = false;
- if ( QT_WA_INLINE( SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &snapToDefault, 0) ,
- SystemParametersInfoA(SPI_GETSNAPTODEFBUTTON, 0, &snapToDefault, 0) )) {
+ if (SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &snapToDefault, 0)) {
if (snapToDefault)
QCursor::setPos(d->mainDef->mapToGlobal(d->mainDef->rect().center()));
}
diff --git a/src/gui/dialogs/qdialog.h b/src/gui/dialogs/qdialog.h
index 583b0bc..bd12006 100644
--- a/src/gui/dialogs/qdialog.h
+++ b/src/gui/dialogs/qdialog.h
@@ -107,7 +107,7 @@ public Q_SLOTS:
protected:
QDialog(QDialogPrivate &, QWidget *parent, Qt::WindowFlags f = 0);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
bool event(QEvent *e);
#endif
void keyPressEvent(QKeyEvent *);
@@ -124,7 +124,7 @@ private:
Q_DECLARE_PRIVATE(QDialog)
Q_DISABLE_COPY(QDialog)
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
Q_PRIVATE_SLOT(d_func(), void _q_doneAction())
#endif
};
diff --git a/src/gui/dialogs/qdialog_p.h b/src/gui/dialogs/qdialog_p.h
index c6b8481..5239d09 100644
--- a/src/gui/dialogs/qdialog_p.h
+++ b/src/gui/dialogs/qdialog_p.h
@@ -93,7 +93,7 @@ public:
void hideDefault();
void resetModalitySetByOpen();
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
void _q_doneAction();
#endif
diff --git a/src/gui/dialogs/qerrormessage.cpp b/src/gui/dialogs/qerrormessage.cpp
index 975844c..650599b 100644
--- a/src/gui/dialogs/qerrormessage.cpp
+++ b/src/gui/dialogs/qerrormessage.cpp
@@ -61,7 +61,7 @@
#include <stdio.h>
#include <stdlib.h>
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
@@ -100,7 +100,7 @@ public:
QSize QErrorMessageTextView::minimumSizeHint() const
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile())
if (qt_wince_is_high_dpi())
return QSize(200, 200);
@@ -115,7 +115,7 @@ QSize QErrorMessageTextView::minimumSizeHint() const
QSize QErrorMessageTextView::sizeHint() const
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile())
if (qt_wince_is_high_dpi())
return QSize(400, 200);
@@ -133,8 +133,7 @@ QSize QErrorMessageTextView::sizeHint() const
\brief The QErrorMessage class provides an error message display dialog.
- \ingroup dialogs
- \ingroup misc
+ \ingroup standard-dialog
An error message widget consists of a text label and a checkbox. The
checkbox lets the user control whether the same error message will be
@@ -240,7 +239,7 @@ QErrorMessage::QErrorMessage(QWidget * parent)
d->again->setChecked(true);
grid->addWidget(d->again, 1, 1, Qt::AlignTop);
d->ok = new QPushButton(this);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
d->ok->setFixedSize(0,0);
#endif
connect(d->ok, SIGNAL(clicked()), this, SLOT(accept()));
@@ -300,7 +299,7 @@ QErrorMessage * QErrorMessage::qtHandler()
if (!qtMessageHandler) {
qtMessageHandler = new QErrorMessage(0);
qAddPostRoutine(deleteStaticcQErrorMessage); // clean up
- qtMessageHandler->setWindowTitle(qApp->applicationName());
+ qtMessageHandler->setWindowTitle(QApplication::applicationName());
qInstallMsgHandler(jump);
}
return qtMessageHandler;
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 4363bc7..709a95a 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -58,12 +58,15 @@
#include <qdebug.h>
#include <qapplication.h>
#include <qstylepainter.h>
-#ifndef Q_OS_WINCE
+#if !defined(Q_WS_WINCE) && !defined(Q_OS_SYMBIAN)
#include "ui_qfiledialog.h"
#else
-#include "ui_qfiledialog_wince.h"
+#define Q_EMBEDDED_SMALLSCREEN
+#include "ui_qfiledialog_embedded.h"
+#if defined(Q_OS_WINCE)
extern bool qt_priv_ptr_valid;
#endif
+#endif
QT_BEGIN_NAMESPACE
@@ -89,8 +92,8 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook
/*!
\class QFileDialog
\brief The QFileDialog class provides a dialog that allow users to select files or directories.
- \ingroup dialogs
- \mainclass
+ \ingroup standard-dialogs
+
The QFileDialog class enables a user to traverse the file system in
order to select one or many files or a directory.
@@ -209,25 +212,30 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook
/*!
\enum QFileDialog::Option
- \value ShowDirsOnly Only show directories in the file dialog. By default both files and
- directories are shown. (Valid only in the \l Directory file mode.)
- \value DontResolveSymlinks Don't resolve symlinks in the file dialog. By default symlinks
- are resolved.
- \value DontConfirmOverwrite Don't ask for confirmation if an existing file is selected.
- By default confirmation is requested.
- \value DontUseNativeDialog Don't use the native file dialog. By default on Mac OS X,
- the native file dialog is used unless you use a subclass of QFileDialog that contains the
- Q_OBJECT macro.
+ \value ShowDirsOnly Only show directories in the file dialog. By
+ default both files and directories are shown. (Valid only in the
+ \l Directory file mode.)
+
+ \value DontResolveSymlinks Don't resolve symlinks in the file
+ dialog. By default symlinks are resolved.
+
+ \value DontConfirmOverwrite Don't ask for confirmation if an
+ existing file is selected. By default confirmation is requested.
+
+ \value DontUseNativeDialog Don't use the native file dialog. By
+ default, the native file dialog is used unless you use a subclass
+ of QFileDialog that contains the Q_OBJECT macro.
+
\value ReadOnly Indicates that the model is readonly.
- \value HideNameFilterDetails Indicates if the filter extension (e.g. *.bmp) is hidden or not.
+ \value HideNameFilterDetails Indicates if the is hidden or not.
This value is obsolete and does nothing since Qt 4.5:
- \value DontUseSheet In previous versions of Qt, the static functions would
- create a sheet by default if the static function was given a parent. This
- is no longer supported in Qt 4.5, The static functions will always be an
- application modal dialog. If you want to use sheets, use
- QFileDialog::open() instead.
+ \value DontUseSheet In previous versions of Qt, the static
+ functions would create a sheet by default if the static function
+ was given a parent. This is no longer supported in Qt 4.5, The
+ static functions will always be an application modal dialog. If
+ you want to use sheets, use QFileDialog::open() instead.
*/
@@ -353,7 +361,6 @@ QFileDialog::~QFileDialog()
settings.beginGroup(QLatin1String("Qt"));
settings.setValue(QLatin1String("filedialog"), saveState());
#endif
- delete d->qFileDialogUi;
d->deleteNativeDialog_sys();
}
@@ -389,6 +396,9 @@ QList<QUrl> QFileDialog::sidebarUrls() const
static const qint32 QFileDialogMagic = 0xbe;
+const char *qt_file_dialog_filter_reg_exp =
+"^(.*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
+
/*!
\since 4.3
Saves the state of the dialog's layout, history and current directory.
@@ -485,6 +495,38 @@ void QFileDialog::changeEvent(QEvent *e)
QDialog::changeEvent(e);
}
+QFileDialogPrivate::QFileDialogPrivate()
+ :
+#ifndef QT_NO_PROXYMODEL
+ proxyModel(0),
+#endif
+ model(0),
+ fileMode(QFileDialog::AnyFile),
+ acceptMode(QFileDialog::AcceptOpen),
+ currentHistoryLocation(-1),
+ renameAction(0),
+ deleteAction(0),
+ showHiddenAction(0),
+ useDefaultCaption(true),
+ defaultFileTypes(true),
+ fileNameLabelExplicitlySat(false),
+ nativeDialogInUse(false),
+#ifdef Q_WS_MAC
+ mDelegate(0),
+#ifndef QT_MAC_USE_COCOA
+ mDialog(0),
+ mDialogStarted(false),
+ mDialogClosed(true),
+#endif
+#endif
+ qFileDialogUi(0)
+{
+}
+
+QFileDialogPrivate::~QFileDialogPrivate()
+{
+}
+
void QFileDialogPrivate::retranslateWindowTitle()
{
Q_Q(QFileDialog);
@@ -840,8 +882,8 @@ QStringList QFileDialogPrivate::addDefaultSuffixToFiles(const QStringList filesT
// This check is needed since we might be at the root directory
// and on Windows it already ends with slash.
QString path = rootPath();
- if (!path.endsWith(QLatin1String("/")))
- path += QLatin1String("/");
+ if (!path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
path += name;
files.append(path);
}
@@ -979,8 +1021,13 @@ void QFileDialog::setNameFilters(const QStringList &filters)
if (testOption(HideNameFilterDetails)) {
QStringList strippedFilters;
+ QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
for (int i = 0; i < cleanedFilters.count(); ++i) {
- strippedFilters.append(cleanedFilters[i].mid(0, cleanedFilters[i].indexOf(QLatin1String(" ("))));
+ QString filterName;
+ int index = r.indexIn(cleanedFilters[i]);
+ if (index >= 0)
+ filterName = r.cap(1);
+ strippedFilters.append(filterName.simplified());
}
d->qFileDialogUi->fileTypeCombo->addItems(strippedFilters);
} else {
@@ -1849,7 +1896,7 @@ QString QFileDialog::getExistingDirectory(QWidget *parent,
#if defined(Q_WS_WIN)
if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog) && (options & ShowDirsOnly)
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
&& qt_priv_ptr_valid
#endif
) {
@@ -2063,7 +2110,7 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte
q->restoreState(settings.value(QLatin1String("filedialog")).toByteArray());
#endif
-#ifdef Q_OS_WINCE
+#if defined(Q_EMBEDDED_SMALLSCREEN)
qFileDialogUi->lookInLabel->setVisible(false);
qFileDialogUi->fileNameLabel->setVisible(false);
qFileDialogUi->fileTypeLabel->setVisible(false);
@@ -2103,7 +2150,7 @@ void QFileDialogPrivate::createWidgets()
q, SLOT(_q_rowsInserted(const QModelIndex &)));
model->setReadOnly(false);
- qFileDialogUi = new Ui_QFileDialog();
+ qFileDialogUi.reset(new Ui_QFileDialog());
qFileDialogUi->setupUi(q);
QList<QUrl> initialBookmarks;
@@ -2129,7 +2176,7 @@ void QFileDialogPrivate::createWidgets()
qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
#endif
#ifndef QT_NO_COMPLETER
- completer = new QFSCompletor(model, q);
+ completer = new QFSCompleter(model, q);
qFileDialogUi->fileNameEdit->setCompleter(completer);
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
q, SLOT(_q_autoCompleteFileName(QString)));
@@ -2187,9 +2234,9 @@ void QFileDialogPrivate::createWidgets()
treeHeader->addAction(showHeader);
}
- QItemSelectionModel *selModel = qFileDialogUi->treeView->selectionModel();
+ QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());
qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
- delete selModel;
+
QObject::connect(qFileDialogUi->treeView, SIGNAL(activated(QModelIndex)),
q, SLOT(_q_enterDirectory(QModelIndex)));
QObject::connect(qFileDialogUi->treeView, SIGNAL(customContextMenuRequested(QPoint)),
@@ -2271,9 +2318,9 @@ void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
connect(d->model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
this, SLOT(_q_rowsInserted(const QModelIndex &)));
}
- QItemSelectionModel *selModel = d->qFileDialogUi->treeView->selectionModel();
+ QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());
d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
- delete selModel;
+
d->setRootIndex(idx);
// reconnect selection
@@ -2638,7 +2685,7 @@ void QFileDialogPrivate::_q_deleteCurrent()
void QFileDialogPrivate::_q_autoCompleteFileName(const QString &text)
{
- if (text.startsWith(QLatin1String("//")) || text.startsWith(QLatin1String("\\"))) {
+ if (text.startsWith(QLatin1String("//")) || text.startsWith(QLatin1Char('\\'))) {
qFileDialogUi->listView->selectionModel()->clearSelection();
return;
}
@@ -2680,10 +2727,10 @@ void QFileDialogPrivate::_q_updateOkButton()
QStringList files = q->selectedFiles();
QString lineEditText = lineEdit()->text();
- if (lineEditText.startsWith(QLatin1String("//")) || lineEditText.startsWith(QLatin1String("\\"))) {
+ if (lineEditText.startsWith(QLatin1String("//")) || lineEditText.startsWith(QLatin1Char('\\'))) {
button->setEnabled(true);
if (acceptMode == QFileDialog::AcceptSave)
- button->setText(isOpenDirectory ? QFileDialog::tr("&Open") : acceptLabel);
+ button->setText(acceptLabel);
return;
}
@@ -2832,9 +2879,6 @@ void QFileDialogPrivate::_q_goToDirectory(const QString &path)
}
}
-const char *qt_file_dialog_filter_reg_exp =
- "^([^()]*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
-
// Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)"
QStringList qt_clean_filter_list(const QString &filter)
{
@@ -3154,7 +3198,7 @@ void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e)
#ifndef QT_NO_COMPLETER
-QString QFSCompletor::pathFromIndex(const QModelIndex &index) const
+QString QFSCompleter::pathFromIndex(const QModelIndex &index) const
{
const QFileSystemModel *dirModel;
if (proxyModel)
@@ -3169,14 +3213,17 @@ QString QFSCompletor::pathFromIndex(const QModelIndex &index) const
return index.data(QFileSystemModel::FilePathRole).toString();
}
-QStringList QFSCompletor::splitPath(const QString &path) const
+QStringList QFSCompleter::splitPath(const QString &path) const
{
if (path.isEmpty())
return QStringList(completionPrefix());
QString pathCopy = QDir::toNativeSeparators(path);
QString sep = QDir::separator();
-#ifdef Q_OS_WIN
+#if defined(Q_OS_SYMBIAN)
+ if (pathCopy == QLatin1String("\\"))
+ return QStringList(pathCopy);
+#elif defined(Q_OS_WIN)
if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\"))
return QStringList(pathCopy);
QString doubleSlash(QLatin1String("\\\\"));
@@ -3186,9 +3233,13 @@ QStringList QFSCompletor::splitPath(const QString &path) const
doubleSlash.clear();
#endif
- QRegExp re(QLatin1String("[") + QRegExp::escape(sep) + QLatin1String("]"));
+ QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']'));
-#ifdef Q_OS_WIN
+#if defined(Q_OS_SYMBIAN)
+ QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
+ if (pathCopy.endsWith(sep))
+ parts.append(QString());
+#elif defined(Q_OS_WIN)
QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
if (!doubleSlash.isEmpty() && !parts.isEmpty())
parts[0].prepend(doubleSlash);
@@ -3200,7 +3251,7 @@ QStringList QFSCompletor::splitPath(const QString &path) const
parts[0] = sep[0];
#endif
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(QLatin1Char(':'));
#else
bool startsFromRoot = path[0] == sep[0];
diff --git a/src/gui/dialogs/qfiledialog_wince.ui b/src/gui/dialogs/qfiledialog_embedded.ui
index 454af4b..454af4b 100644
--- a/src/gui/dialogs/qfiledialog_wince.ui
+++ b/src/gui/dialogs/qfiledialog_embedded.ui
diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm
index 4e03b46..e54c016 100644
--- a/src/gui/dialogs/qfiledialog_mac.mm
+++ b/src/gui/dialogs/qfiledialog_mac.mm
@@ -911,8 +911,9 @@ void QFileDialogPrivate::createNavServicesDialog()
navOptions.windowTitle = QCFString::toCFStringRef(q->windowTitle());
- static const int w = 450, h = 350;
- navOptions.location.h = navOptions.location.v = -1;
+ navOptions.location.h = -1;
+ navOptions.location.v = -1;
+
QWidget *parent = q->parentWidget();
if (parent && parent->isVisible()) {
WindowClass wclass;
@@ -920,20 +921,6 @@ void QFileDialogPrivate::createNavServicesDialog()
parent = parent->window();
QString s = parent->windowTitle();
navOptions.clientName = QCFString::toCFStringRef(s);
- navOptions.location.h = (parent->x() + (parent->width() / 2)) - (w / 2);
- navOptions.location.v = (parent->y() + (parent->height() / 2)) - (h / 2);
-
- QRect r = QApplication::desktop()->screenGeometry(
- QApplication::desktop()->screenNumber(parent));
- const int border = 10;
- if (navOptions.location.h + w > r.right())
- navOptions.location.h -= (navOptions.location.h + w) - r.right() + border;
- if (navOptions.location.v + h > r.bottom())
- navOptions.location.v -= (navOptions.location.v + h) - r.bottom() + border;
- if (navOptions.location.h < r.left())
- navOptions.location.h = r.left() + border;
- if (navOptions.location.v < r.top())
- navOptions.location.v = r.top() + border;
}
filterInfo.currentSelection = 0;
diff --git a/src/gui/dialogs/qfiledialog_p.h b/src/gui/dialogs/qfiledialog_p.h
index c8eaa0c..4482bc0 100644
--- a/src/gui/dialogs/qfiledialog_p.h
+++ b/src/gui/dialogs/qfiledialog_p.h
@@ -73,9 +73,9 @@
#include <qabstractproxymodel.h>
#include <qcompleter.h>
#include <qpointer.h>
-#include <qtimeline.h>
#include <qdebug.h>
#include "qsidebar_p.h"
+#include "qfscompleter_p.h"
#if defined (Q_OS_UNIX)
#include <unistd.h>
@@ -91,25 +91,6 @@ class QCompleter;
class QHBoxLayout;
class Ui_QFileDialog;
-#ifndef QT_NO_COMPLETER
-/*!
- QCompleter that can deal with QFileSystemModel
- */
-class QFSCompletor : public QCompleter {
-public:
- QFSCompletor(QFileSystemModel *model, QObject *parent = 0) : QCompleter(model, parent), proxyModel(0), sourceModel(model)
- {
-#ifdef Q_OS_WIN
- setCaseSensitivity(Qt::CaseInsensitive);
-#endif
- }
- QString pathFromIndex(const QModelIndex &index) const;
- QStringList splitPath(const QString& path) const;
-
- QAbstractProxyModel *proxyModel;
- QFileSystemModel *sourceModel;
-};
-#endif // QT_NO_COMPLETER
struct QFileDialogArgs
{
@@ -131,31 +112,7 @@ class Q_AUTOTEST_EXPORT QFileDialogPrivate : public QDialogPrivate
Q_DECLARE_PUBLIC(QFileDialog)
public:
- QFileDialogPrivate() :
-#ifndef QT_NO_PROXYMODEL
- proxyModel(0),
-#endif
- model(0),
- fileMode(QFileDialog::AnyFile),
- acceptMode(QFileDialog::AcceptOpen),
- currentHistoryLocation(-1),
- renameAction(0),
- deleteAction(0),
- showHiddenAction(0),
- useDefaultCaption(true),
- defaultFileTypes(true),
- fileNameLabelExplicitlySat(false),
- nativeDialogInUse(false),
-#ifdef Q_WS_MAC
- mDelegate(0),
-#ifndef QT_MAC_USE_COCOA
- mDialog(0),
- mDialogStarted(false),
- mDialogClosed(true),
-#endif
-#endif
- qFileDialogUi(0)
- {}
+ QFileDialogPrivate();
void createToolButtons();
void createMenuActions();
@@ -187,8 +144,7 @@ public:
#ifndef Q_OS_WINCE
DWORD maxLength;
QString drive = path.left(3);
- if (QT_WA_INLINE(::GetVolumeInformationW(reinterpret_cast<const WCHAR *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0),
- ::GetVolumeInformationA(drive.toLocal8Bit().constData(), NULL, 0, NULL, &maxLength, NULL, NULL, 0)) == FALSE)
+ if (::GetVolumeInformation(reinterpret_cast<const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) == FALSE)
return -1;
return maxLength;
#else
@@ -224,7 +180,7 @@ public:
static inline QString toInternal(const QString &path)
{
-#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX)
+#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) || defined(Q_OS_SYMBIAN)
QString n(path);
for (int i = 0; i < (int)n.length(); ++i)
if (n[i] == QLatin1Char('\\')) n[i] = QLatin1Char('/');
@@ -277,7 +233,7 @@ public:
QFileSystemModel *model;
#ifndef QT_NO_COMPLETER
- QFSCompletor *completer;
+ QFSCompleter *completer;
#endif //QT_NO_COMPLETER
QFileDialog::FileMode fileMode;
@@ -298,7 +254,7 @@ public:
bool defaultFileTypes;
bool fileNameLabelExplicitlySat;
QStringList nameFilters;
-
+
// Members for using native dialogs:
bool nativeDialogInUse;
// setVisible_sys returns true if it ends up showing a native
@@ -360,7 +316,7 @@ public:
void mac_nativeDialogModalHelp();
#endif
- Ui_QFileDialog *qFileDialogUi;
+ QScopedPointer<Ui_QFileDialog> qFileDialogUi;
QString acceptLabel;
@@ -369,6 +325,11 @@ public:
QByteArray signalToDisconnectOnClose;
QFileDialog::Options opts;
+
+ ~QFileDialogPrivate();
+
+private:
+ Q_DISABLE_COPY(QFileDialogPrivate)
};
class QFileDialogLineEdit : public QLineEdit
diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp
index b704639..2dfe389 100644
--- a/src/gui/dialogs/qfiledialog_win.cpp
+++ b/src/gui/dialogs/qfiledialog_win.cpp
@@ -59,8 +59,19 @@
#endif
#include <shlobj.h>
+//At some point we can hope that mingw will support that interface
+#if !defined(Q_WS_WINCE) && !defined(Q_CC_MINGW)
+#include <shobjidl.h>
+#endif
+
+#include <objbase.h>
-#ifdef Q_OS_WINCE
+#if defined(__IFileDialog_INTERFACE_DEFINED__) \
+ && defined(__IFileOpenDialog_INTERFACE_DEFINED__)
+#define USE_COMMON_ITEM_DIALOG
+#endif
+
+#ifdef Q_WS_WINCE
#include <commdlg.h>
# ifndef BFFM_SETSELECTION
# define BFFM_SETSELECTION (WM_USER + 102)
@@ -70,8 +81,8 @@
typedef struct qt_priv_browseinfo {
HWND hwndOwner;
LPCITEMIDLIST pidlRoot;
- LPTSTR pszDisplayName;
- LPCTSTR lpszTitle;
+ LPWSTR pszDisplayName;
+ LPCWSTR lpszTitle;
UINT ulFlags;
BFFCALLBACK lpfn;
LPARAM lParam;
@@ -90,6 +101,9 @@ typedef LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(BROWSEINFO*);
static PtrSHBrowseForFolder ptrSHBrowseForFolder = 0;
typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(LPITEMIDLIST,LPWSTR);
static PtrSHGetPathFromIDList ptrSHGetPathFromIDList = 0;
+typedef HRESULT (WINAPI *PtrSHGetMalloc)(LPMALLOC *);
+static PtrSHGetMalloc ptrSHGetMalloc = 0;
+
QT_BEGIN_NAMESPACE
@@ -111,20 +125,20 @@ static void qt_win_resolve_libs()
#endif
triedResolve = true;
- if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) {
-#if !defined(Q_OS_WINCE)
- QLibrary lib(QLatin1String("shell32"));
- ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW");
- ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW");
+#if !defined(Q_WS_WINCE)
+ QLibrary lib(QLatin1String("shell32"));
+ ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW");
+ ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW");
+ ptrSHGetMalloc = (PtrSHGetMalloc) lib.resolve("SHGetMalloc");
#else
- // CE stores them in a different lib and does not use unicode version
- HINSTANCE handle = LoadLibraryW(L"Ceshell");
- ptrSHBrowseForFolder = (PtrSHBrowseForFolder)GetProcAddress(handle, L"SHBrowseForFolder");
- ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)GetProcAddress(handle, L"SHGetPathFromIDList");
- if (ptrSHBrowseForFolder && ptrSHGetPathFromIDList)
- qt_priv_ptr_valid = true;
+ // CE stores them in a different lib and does not use unicode version
+ HINSTANCE handle = LoadLibraryW(L"Ceshell");
+ ptrSHBrowseForFolder = (PtrSHBrowseForFolder)GetProcAddress(handle, L"SHBrowseForFolder");
+ ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)GetProcAddress(handle, L"SHGetPathFromIDList");
+ ptrSHGetMalloc = (PtrSHGetMalloc)GetProcAddress(handle, L"SHGetMalloc");
+ if (ptrSHBrowseForFolder && ptrSHGetPathFromIDList && ptrSHGetMalloc)
+ qt_priv_ptr_valid = true;
#endif
- }
}
}
@@ -193,114 +207,34 @@ static QString qt_win_selected_filter(const QString &filter, DWORD idx)
return qt_win_make_filters_list(filter).at((int)idx - 1);
}
-#ifndef Q_OS_WINCE
-// Static vars for OFNA funcs:
-static QByteArray aInitDir;
-static QByteArray aInitSel;
-static QByteArray aTitle;
-static QByteArray aFilter;
-// Use ANSI strings and API
-
-// If you change this, then make sure you change qt_win_make_OFN (below) too
-static OPENFILENAMEA *qt_win_make_OFNA(QWidget *parent,
- const QString &initialSelection,
- const QString &initialDirectory,
- const QString &title,
- const QString &filters,
- QFileDialog::FileMode mode,
- QFileDialog::Options options)
-{
- if (parent)
- parent = parent->window();
- else
- parent = qApp->activeWindow();
-
- aTitle = title.toLocal8Bit();
- aInitDir = QDir::toNativeSeparators(initialDirectory).toLocal8Bit();
- if (initialSelection.isEmpty()) {
- aInitSel = "";
- } else {
- aInitSel = QDir::toNativeSeparators(initialSelection).toLocal8Bit();
- aInitSel.replace("<", "");
- aInitSel.replace(">", "");
- aInitSel.replace("\"", "");
- aInitSel.replace("|", "");
- }
- int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen;
- aInitSel.resize(maxLen + 1); // make room for return value
- aFilter = filters.toLocal8Bit();
-
- OPENFILENAMEA* ofn = new OPENFILENAMEA;
- memset(ofn, 0, sizeof(OPENFILENAMEA));
-
-#if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500)
- // according to the MSDN, this should also be necessary for MSVC, but
- // OPENFILENAME_SIZE_VERSION_400A is in not Microsoft header, as it seems
- if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) {
- ofn->lStructSize = OPENFILENAME_SIZE_VERSION_400A;
- } else {
- ofn->lStructSize = sizeof(OPENFILENAMEA);
- }
-#else
- ofn->lStructSize = sizeof(OPENFILENAMEA);
-#endif
- Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
- ofn->hwndOwner = parent ? parent->winId() : 0;
- ofn->lpstrFilter = aFilter;
- ofn->lpstrFile = aInitSel.data();
- ofn->nMaxFile = maxLen;
- ofn->lpstrInitialDir = aInitDir.data();
- ofn->lpstrTitle = aTitle.data();
- ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER);
-
- if (mode == QFileDialog::ExistingFile ||
- mode == QFileDialog::ExistingFiles)
- ofn->Flags |= (OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST);
- if (mode == QFileDialog::ExistingFiles)
- ofn->Flags |= (OFN_ALLOWMULTISELECT);
- if (!(options & QFileDialog::DontConfirmOverwrite))
- ofn->Flags |= OFN_OVERWRITEPROMPT;
-
- return ofn;
-}
-
-static void qt_win_clean_up_OFNA(OPENFILENAMEA **ofn)
-{
- delete *ofn;
- *ofn = 0;
-}
-#endif
-
static QString tFilters, tTitle, tInitDir;
-#ifdef UNICODE
-// If you change this, then make sure you change qt_win_make_OFNA (above) too
static OPENFILENAME* qt_win_make_OFN(QWidget *parent,
const QString& initialSelection,
const QString& initialDirectory,
const QString& title,
const QString& filters,
QFileDialog::FileMode mode,
- QFileDialog::Options options)
+ QFileDialog::Options options)
{
if (parent)
parent = parent->window();
else
- parent = qApp->activeWindow();
+ parent = QApplication::activeWindow();
tInitDir = QDir::toNativeSeparators(initialDirectory);
tFilters = filters;
tTitle = title;
QString initSel = QDir::toNativeSeparators(initialSelection);
if (!initSel.isEmpty()) {
- initSel.replace(QLatin1String("<"), QLatin1String(""));
- initSel.replace(QLatin1String(">"), QLatin1String(""));
- initSel.replace(QLatin1String("\""), QLatin1String(""));
- initSel.replace(QLatin1String("|"), QLatin1String(""));
+ initSel.remove(QLatin1Char('<'));
+ initSel.remove(QLatin1Char('>'));
+ initSel.remove(QLatin1Char('\"'));
+ initSel.remove(QLatin1Char('|'));
}
int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen;
- TCHAR *tInitSel = new TCHAR[maxLen+1];
+ wchar_t *tInitSel = new wchar_t[maxLen + 1];
if (initSel.length() > 0 && initSel.length() <= maxLen)
memcpy(tInitSel, initSel.utf16(), (initSel.length()+1)*sizeof(QChar));
else
@@ -309,24 +243,14 @@ static OPENFILENAME* qt_win_make_OFN(QWidget *parent,
OPENFILENAME* ofn = new OPENFILENAME;
memset(ofn, 0, sizeof(OPENFILENAME));
-#if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500)
- // according to the MSDN, this should also be necessary for MSVC, but
- // OPENFILENAME_SIZE_VERSION_400 is in not Microsoft header, as it seems
- if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) {
- ofn->lStructSize= OPENFILENAME_SIZE_VERSION_400;
- } else {
- ofn->lStructSize = sizeof(OPENFILENAME);
- }
-#else
ofn->lStructSize = sizeof(OPENFILENAME);
-#endif
Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
ofn->hwndOwner = parent ? parent->winId() : 0;
- ofn->lpstrFilter = (TCHAR *)tFilters.utf16();
+ ofn->lpstrFilter = (wchar_t*)tFilters.utf16();
ofn->lpstrFile = tInitSel;
ofn->nMaxFile = maxLen;
- ofn->lpstrInitialDir = (TCHAR *)tInitDir.utf16();
- ofn->lpstrTitle = (TCHAR *)tTitle.utf16();
+ ofn->lpstrInitialDir = (wchar_t*)tInitDir.utf16();
+ ofn->lpstrTitle = (wchar_t*)tTitle.utf16();
ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER);
if (mode == QFileDialog::ExistingFile ||
mode == QFileDialog::ExistingFiles)
@@ -339,7 +263,6 @@ static OPENFILENAME* qt_win_make_OFN(QWidget *parent,
return ofn;
}
-
static void qt_win_clean_up_OFN(OPENFILENAME **ofn)
{
delete [] (*ofn)->lpstrFile;
@@ -347,8 +270,6 @@ static void qt_win_clean_up_OFN(OPENFILENAME **ofn)
*ofn = 0;
}
-#endif // UNICODE
-
extern void qt_win_eatMouseMove();
QString qt_win_get_open_file_name(const QFileDialogArgs &args,
@@ -384,36 +305,21 @@ QString qt_win_get_open_file_name(const QFileDialogArgs &args,
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
modal_widget.setParent(args.parent, Qt::Window);
QApplicationPrivate::enterModal(&modal_widget);
+
bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails;
- QT_WA({
- // Use Unicode strings and API
- OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection,
- args.directory, args.caption,
- qt_win_filter(args.filter, hideFiltersDetails),
- QFileDialog::ExistingFile,
- args.options);
- if (idx)
- ofn->nFilterIndex = idx + 1;
- if (GetOpenFileName(ofn)) {
- result = QString::fromUtf16((ushort*)ofn->lpstrFile);
- selFilIdx = ofn->nFilterIndex;
- }
- qt_win_clean_up_OFN(&ofn);
- } , {
- // Use ANSI strings and API
- OPENFILENAMEA* ofn = qt_win_make_OFNA(args.parent, args.selection,
- args.directory, args.caption,
- qt_win_filter(args.filter, hideFiltersDetails),
- QFileDialog::ExistingFile,
- args.options);
- if (idx)
- ofn->nFilterIndex = idx + 1;
- if (GetOpenFileNameA(ofn)) {
- result = QString::fromLocal8Bit(ofn->lpstrFile);
- selFilIdx = ofn->nFilterIndex;
- }
- qt_win_clean_up_OFNA(&ofn);
- });
+ OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection,
+ args.directory, args.caption,
+ qt_win_filter(args.filter, hideFiltersDetails),
+ QFileDialog::ExistingFile,
+ args.options);
+ if (idx)
+ ofn->nFilterIndex = idx + 1;
+ if (GetOpenFileName(ofn)) {
+ result = QString::fromWCharArray(ofn->lpstrFile);
+ selFilIdx = ofn->nFilterIndex;
+ }
+ qt_win_clean_up_OFN(&ofn);
+
QApplicationPrivate::leaveModal(&modal_widget);
qt_win_eatMouseMove();
@@ -430,7 +336,7 @@ QString qt_win_get_open_file_name(const QFileDialogArgs &args,
QString qt_win_get_save_file_name(const QFileDialogArgs &args,
QString *initialDirectory,
- QString *selectedFilter)
+ QString *selectedFilter)
{
QString result;
@@ -477,42 +383,24 @@ QString qt_win_get_save_file_name(const QFileDialogArgs &args,
defaultSaveExt.clear();
}
}
- QT_WA({
- // Use Unicode strings and API
- OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection,
- args.directory, args.caption,
- qt_win_filter(args.filter, hideFiltersDetails),
- QFileDialog::AnyFile,
- args.options);
-
- ofn->lpstrDefExt = (TCHAR *)defaultSaveExt.utf16();
-
- if (idx)
- ofn->nFilterIndex = idx + 1;
- if (GetSaveFileName(ofn)) {
- result = QString::fromUtf16((ushort*)ofn->lpstrFile);
- selFilIdx = ofn->nFilterIndex;
- }
- qt_win_clean_up_OFN(&ofn);
- } , {
- // Use ANSI strings and API
- OPENFILENAMEA *ofn = qt_win_make_OFNA(args.parent, args.selection,
- args.directory, args.caption,
- qt_win_filter(args.filter, hideFiltersDetails),
- QFileDialog::AnyFile,
- args.options);
- QByteArray asciiExt = defaultSaveExt.toAscii();
- ofn->lpstrDefExt = asciiExt.data();
-
- if (idx)
- ofn->nFilterIndex = idx + 1;
- if (GetSaveFileNameA(ofn)) {
- result = QString::fromLocal8Bit(ofn->lpstrFile);
- selFilIdx = ofn->nFilterIndex;
- }
- qt_win_clean_up_OFNA(&ofn);
- });
-#if defined(Q_OS_WINCE)
+
+ OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection,
+ args.directory, args.caption,
+ qt_win_filter(args.filter, hideFiltersDetails),
+ QFileDialog::AnyFile,
+ args.options);
+
+ ofn->lpstrDefExt = (wchar_t*)defaultSaveExt.utf16();
+
+ if (idx)
+ ofn->nFilterIndex = idx + 1;
+ if (GetSaveFileName(ofn)) {
+ result = QString::fromWCharArray(ofn->lpstrFile);
+ selFilIdx = ofn->nFilterIndex;
+ }
+ qt_win_clean_up_OFN(&ofn);
+
+#if defined(Q_WS_WINCE)
int semIndex = result.indexOf(QLatin1Char(';'));
if (semIndex >= 0)
result = result.left(semIndex);
@@ -532,14 +420,204 @@ QString qt_win_get_save_file_name(const QFileDialogArgs &args,
return fi.absoluteFilePath();
}
+
+#if defined(USE_COMMON_ITEM_DIALOG)
+
+typedef HRESULT (WINAPI *PtrSHCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
+static PtrSHCreateItemFromParsingName pSHCreateItemFromParsingName = 0;
+
+static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd,
+ const QString& initialSelection,
+ const QString& initialDirectory,
+ const QString& title,
+ const QStringList& filterLst,
+ QFileDialog::FileMode mode,
+ QFileDialog::Options options)
+{
+ if (!pSHCreateItemFromParsingName) {
+ // This function is available only in Vista & above.
+ QLibrary shellLib(QLatin1String("Shell32"));
+ pSHCreateItemFromParsingName = (PtrSHCreateItemFromParsingName)
+ shellLib.resolve("SHCreateItemFromParsingName");
+ if (!pSHCreateItemFromParsingName)
+ return false;
+ }
+ HRESULT hr;
+ QString winfilters;
+ int numFilters = 0;
+ quint32 currentOffset = 0;
+ QList<quint32> offsets;
+ QStringList::ConstIterator it = filterLst.begin();
+ // Create the native filter string and save offset to each entry.
+ for (; it != filterLst.end(); ++it) {
+ QString subfilter = *it;
+ if (!subfilter.isEmpty()) {
+ offsets<<currentOffset;
+ //Here the COMMON_ITEM_DIALOG API always add the details for the filter (e.g. *.txt)
+ //so we don't need to handle the flag HideNameFilterDetails.
+ winfilters += subfilter; // The name of the filter.
+ winfilters += QChar();
+ currentOffset += subfilter.size()+1;
+ offsets<<currentOffset;
+ QString spec = qt_win_extract_filter(subfilter);
+ winfilters += spec; // The actual filter spec.
+ winfilters += QChar();
+ currentOffset += spec.size()+1;
+ numFilters++;
+ }
+ }
+ // Add the filters to the file dialog.
+ if (numFilters) {
+ wchar_t *szData = (wchar_t*)winfilters.utf16();
+ COMDLG_FILTERSPEC *filterSpec = new COMDLG_FILTERSPEC[numFilters];
+ for(int i = 0; i<numFilters; i++) {
+ filterSpec[i].pszName = szData+offsets[i*2];
+ filterSpec[i].pszSpec = szData+offsets[(i*2)+1];
+ }
+ hr = pfd->SetFileTypes(numFilters, filterSpec);
+ delete []filterSpec;
+ }
+ // Set the starting folder.
+ tInitDir = QDir::toNativeSeparators(initialDirectory);
+ if (!tInitDir.isEmpty()) {
+ IShellItem *psiDefaultFolder;
+ hr = pSHCreateItemFromParsingName((wchar_t*)tInitDir.utf16(),
+ NULL,
+ IID_PPV_ARGS(&psiDefaultFolder));
+
+ if (SUCCEEDED(hr)) {
+ hr = pfd->SetFolder(psiDefaultFolder);
+ psiDefaultFolder->Release();
+ }
+ }
+ // Set the currently selected file.
+ QString initSel = QDir::toNativeSeparators(initialSelection);
+ if (!initSel.isEmpty()) {
+ initSel.remove(QLatin1Char('<'));
+ initSel.remove(QLatin1Char('>'));
+ initSel.remove(QLatin1Char('\"'));
+ initSel.remove(QLatin1Char('|'));
+ }
+ if (!initSel.isEmpty()) {
+ hr = pfd->SetFileName((wchar_t*)initSel.utf16());
+ }
+ // Set the title for the file dialog.
+ if (!title.isEmpty()) {
+ hr = pfd->SetTitle((wchar_t*)title.utf16());
+ }
+ // Set other flags for the dialog.
+ DWORD newOptions;
+ hr = pfd->GetOptions(&newOptions);
+ if (SUCCEEDED(hr)) {
+ newOptions |= (FOS_NOCHANGEDIR | FOS_NOREADONLYRETURN);
+ if (mode == QFileDialog::ExistingFile ||
+ mode == QFileDialog::ExistingFiles)
+ newOptions |= (FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST);
+ if (mode == QFileDialog::ExistingFiles)
+ newOptions |= FOS_ALLOWMULTISELECT;
+ if (!(options & QFileDialog::DontConfirmOverwrite))
+ newOptions |= FOS_OVERWRITEPROMPT;
+ hr = pfd->SetOptions(newOptions);
+ }
+ return SUCCEEDED(hr);
+}
+
+QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
+ QString *initialDirectory,
+ const QStringList &filterList,
+ QString *selectedFilter,
+ int selectedFilterIndex)
+{
+ QStringList result;
+ QDialog modal_widget;
+ modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
+ modal_widget.setParent(args.parent, Qt::Window);
+ QApplicationPrivate::enterModal(&modal_widget);
+ // Multiple selection is allowed only in IFileOpenDialog.
+ IFileOpenDialog *pfd;
+ HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&pfd));
+
+ if (SUCCEEDED(hr)) {
+ qt_win_set_IFileDialogOptions(pfd, args.selection,
+ args.directory, args.caption,
+ filterList, QFileDialog::ExistingFiles,
+ args.options);
+ // Set the currently selected filter (one-based index).
+ hr = pfd->SetFileTypeIndex(selectedFilterIndex+1);
+ QWidget *parentWindow = args.parent;
+ if (parentWindow)
+ parentWindow = parentWindow->window();
+ else
+ parentWindow = QApplication::activeWindow();
+ // Show the file dialog.
+ hr = pfd->Show(parentWindow ? parentWindow->winId() : 0);
+ if (SUCCEEDED(hr)) {
+ // Retrieve the results.
+ IShellItemArray *psiaResults;
+ hr = pfd->GetResults(&psiaResults);
+ if (SUCCEEDED(hr)) {
+ DWORD numItems = 0;
+ psiaResults->GetCount(&numItems);
+ for (DWORD i = 0; i<numItems; i++) {
+ IShellItem *psi = 0;
+ hr = psiaResults->GetItemAt(i, &psi);
+ if (SUCCEEDED(hr)) {
+ // Retrieve the file name from shell item.
+ wchar_t *pszPath;
+ hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
+ if (SUCCEEDED(hr)) {
+ QString fileName = QString::fromWCharArray(pszPath);
+ result.append(fileName);
+ CoTaskMemFree(pszPath);
+ }
+ psi->Release(); // Free the current item.
+ }
+ }
+ psiaResults->Release(); // Free the array of items.
+ }
+ }
+ }
+ QApplicationPrivate::leaveModal(&modal_widget);
+
+ qt_win_eatMouseMove();
+
+ if (!result.isEmpty()) {
+ // Retrieve the current folder name.
+ IShellItem *psi = 0;
+ hr = pfd->GetFolder(&psi);
+ if (SUCCEEDED(hr)) {
+ wchar_t *pszPath;
+ hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
+ if (SUCCEEDED(hr)) {
+ *initialDirectory = QString::fromWCharArray(pszPath);
+ CoTaskMemFree(pszPath);
+ }
+ psi->Release();
+ }
+ // Retrieve the currently selected filter.
+ if (selectedFilter) {
+ quint32 filetype = 0;
+ hr = pfd->GetFileTypeIndex(&filetype);
+ if (SUCCEEDED(hr) && filetype && filetype <= (quint32)filterList.length()) {
+ // This is a one-based index, not zero-based.
+ *selectedFilter = filterList[filetype-1];
+ }
+ }
+ }
+ return result;
+}
+
+#endif
+
QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
QString *initialDirectory,
QString *selectedFilter)
{
- QStringList result;
QFileInfo fi;
QDir dir;
- QString isel;
if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:"))
initialDirectory->remove(0, 5);
@@ -547,7 +625,6 @@ QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
if (initialDirectory && !fi.isDir()) {
*initialDirectory = fi.absolutePath();
- isel = fi.fileName();
}
if (!fi.exists())
@@ -555,84 +632,60 @@ QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
DWORD selFilIdx = 0;
+ QStringList filterLst = qt_win_make_filters_list(args.filter);
int idx = 0;
if (selectedFilter) {
- QStringList filterLst = qt_win_make_filters_list(args.filter);
idx = filterLst.indexOf(*selectedFilter);
}
+ // Windows Vista (& above) allows users to search from file dialogs. If user selects
+ // multiple files belonging to different folders from these search results, the
+ // GetOpenFileName() will return only one folder name for all the files. To retrieve
+ // the correct path for all selected files, we have to use Common Item Dialog interfaces.
+#if defined(USE_COMMON_ITEM_DIALOG)
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
+ return qt_win_CID_get_open_file_names(args, initialDirectory, filterLst, selectedFilter, idx);
+#endif
+ QStringList result;
QDialog modal_widget;
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
modal_widget.setParent(args.parent, Qt::Window);
QApplicationPrivate::enterModal(&modal_widget);
+
bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails;
- QT_WA({
- OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection,
- args.directory, args.caption,
- qt_win_filter(args.filter, hideFiltersDetails),
- QFileDialog::ExistingFiles,
- args.options);
- if (idx)
- ofn->nFilterIndex = idx + 1;
- if (GetOpenFileName(ofn)) {
- QString fileOrDir = QString::fromUtf16((ushort*)ofn->lpstrFile);
- selFilIdx = ofn->nFilterIndex;
- int offset = fileOrDir.length() + 1;
- if (ofn->lpstrFile[offset] == 0) {
- // Only one file selected; has full path
- fi.setFile(fileOrDir);
- QString res = fi.absoluteFilePath();
- if (!res.isEmpty())
- result.append(res);
- }
- else {
- // Several files selected; first string is path
- dir.setPath(fileOrDir);
- QString f;
- while(!(f = QString::fromUtf16((ushort*)ofn->lpstrFile+offset)).isEmpty()) {
- fi.setFile(dir, f);
- QString res = fi.absoluteFilePath();
- if (!res.isEmpty())
- result.append(res);
- offset += f.length() + 1;
- }
- }
+ OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection,
+ args.directory, args.caption,
+ qt_win_filter(args.filter, hideFiltersDetails),
+ QFileDialog::ExistingFiles,
+ args.options);
+ if (idx)
+ ofn->nFilterIndex = idx + 1;
+ if (GetOpenFileName(ofn)) {
+ QString fileOrDir = QString::fromWCharArray(ofn->lpstrFile);
+ selFilIdx = ofn->nFilterIndex;
+ int offset = fileOrDir.length() + 1;
+ if (ofn->lpstrFile[offset] == 0) {
+ // Only one file selected; has full path
+ fi.setFile(fileOrDir);
+ QString res = fi.absoluteFilePath();
+ if (!res.isEmpty())
+ result.append(res);
}
- qt_win_clean_up_OFN(&ofn);
- } , {
- OPENFILENAMEA* ofn = qt_win_make_OFNA(args.parent, args.selection,
- args.directory, args.caption,
- qt_win_filter(args.filter, hideFiltersDetails),
- QFileDialog::ExistingFiles,
- args.options);
- if (idx)
- ofn->nFilterIndex = idx + 1;
- if (GetOpenFileNameA(ofn)) {
- QByteArray fileOrDir(ofn->lpstrFile);
- selFilIdx = ofn->nFilterIndex;
- int offset = fileOrDir.length() + 1;
- if (ofn->lpstrFile[offset] == '\0') {
- // Only one file selected; has full path
- fi.setFile(QString::fromLocal8Bit(fileOrDir));
+ else {
+ // Several files selected; first string is path
+ dir.setPath(fileOrDir);
+ QString f;
+ while(!(f = QString::fromWCharArray(ofn->lpstrFile + offset)).isEmpty()) {
+ fi.setFile(dir, f);
QString res = fi.absoluteFilePath();
if (!res.isEmpty())
result.append(res);
+ offset += f.length() + 1;
}
- else {
- // Several files selected; first string is path
- dir.setPath(QString::fromLocal8Bit(fileOrDir));
- QByteArray f;
- while (!(f = QByteArray(ofn->lpstrFile + offset)).isEmpty()) {
- fi.setFile(dir, QString::fromLocal8Bit(f));
- QString res = fi.absoluteFilePath();
- if (!res.isEmpty())
- result.append(res);
- offset += f.length() + 1;
- }
- }
- qt_win_clean_up_OFNA(&ofn);
}
- });
+ }
+ qt_win_clean_up_OFN(&ofn);
+
QApplicationPrivate::leaveModal(&modal_widget);
qt_win_eatMouseMove();
@@ -655,34 +708,20 @@ static int __stdcall winGetExistDirCallbackProc(HWND hwnd,
if (uMsg == BFFM_INITIALIZED && lpData != 0) {
QString *initDir = (QString *)(lpData);
if (!initDir->isEmpty()) {
- // ### Lars asks: is this correct for the A version????
- QT_WA({
- SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16()));
- } , {
- SendMessageA(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16()));
- });
+ SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16()));
}
} else if (uMsg == BFFM_SELCHANGED) {
- QT_WA({
- qt_win_resolve_libs();
- TCHAR path[MAX_PATH];
+ qt_win_resolve_libs();
+ if (ptrSHGetPathFromIDList) {
+ wchar_t path[MAX_PATH];
ptrSHGetPathFromIDList(LPITEMIDLIST(lParam), path);
- QString tmpStr = QString::fromUtf16((ushort*)path);
+ QString tmpStr = QString::fromWCharArray(path);
if (!tmpStr.isEmpty())
SendMessage(hwnd, BFFM_ENABLEOK, 1, 1);
else
SendMessage(hwnd, BFFM_ENABLEOK, 0, 0);
SendMessage(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path));
- } , {
- char path[MAX_PATH];
- SHGetPathFromIDListA(LPITEMIDLIST(lParam), path);
- QString tmpStr = QString::fromLocal8Bit(path);
- if (!tmpStr.isEmpty())
- SendMessageA(hwnd, BFFM_ENABLEOK, 1, 1);
- else
- SendMessageA(hwnd, BFFM_ENABLEOK, 0, 0);
- SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path));
- });
+ }
}
return 0;
}
@@ -700,7 +739,7 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args)
if (parent)
parent = parent->window();
else
- parent = qApp->activeWindow();
+ parent = QApplication::activeWindow();
if (parent)
parent->createWinId();
@@ -708,118 +747,51 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args)
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
modal_widget.setParent(parent, Qt::Window);
QApplicationPrivate::enterModal(&modal_widget);
-#if !defined(Q_OS_WINCE)
- QT_WA({
- qt_win_resolve_libs();
- QString initDir = QDir::toNativeSeparators(args.directory);
- TCHAR path[MAX_PATH];
- TCHAR initPath[MAX_PATH];
- initPath[0] = 0;
- path[0] = 0;
- tTitle = args.caption;
- BROWSEINFO bi;
- Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
- bi.hwndOwner = (parent ? parent->winId() : 0);
- bi.pidlRoot = NULL;
- //### This does not seem to be respected? - the dialog always displays "Browse for folder"
- bi.lpszTitle = (TCHAR*)tTitle.utf16();
- bi.pszDisplayName = initPath;
- bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE;
- bi.lpfn = winGetExistDirCallbackProc;
- bi.lParam = LPARAM(&initDir);
- if (ptrSHBrowseForFolder) {
- LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder(&bi);
- if (pItemIDList && ptrSHGetPathFromIDList) {
- ptrSHGetPathFromIDList(pItemIDList, path);
- IMalloc *pMalloc;
- if (SHGetMalloc(&pMalloc) != NOERROR)
- result = QString();
- else {
- pMalloc->Free(pItemIDList);
- pMalloc->Release();
- result = QString::fromUtf16((ushort*)path);
- }
- } else
- result = QString();
- }
- tTitle = QString();
- } , {
- QString initDir = QDir::toNativeSeparators(args.directory);
- char path[MAX_PATH];
- char initPath[MAX_PATH];
- QByteArray ctitle = args.caption.toLocal8Bit();
- initPath[0]=0;
- path[0]=0;
- BROWSEINFOA bi;
- Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
- bi.hwndOwner = (parent ? parent->winId() : 0);
- bi.pidlRoot = NULL;
- bi.lpszTitle = ctitle;
- bi.pszDisplayName = initPath;
- bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE;
- bi.lpfn = winGetExistDirCallbackProc;
- bi.lParam = LPARAM(&initDir);
- LPITEMIDLIST pItemIDList = SHBrowseForFolderA(&bi);
- if (pItemIDList) {
- SHGetPathFromIDListA(pItemIDList, path);
- IMalloc *pMalloc;
- if (SHGetMalloc(&pMalloc) != NOERROR)
- result = QString();
- else {
- pMalloc->Free(pItemIDList);
- pMalloc->Release();
- result = QString::fromLocal8Bit(path);
- }
- } else
- result = QString();
- });
-#else
- qt_win_resolve_libs();
+
QString initDir = QDir::toNativeSeparators(args.directory);
- TCHAR path[MAX_PATH];
- TCHAR initPath[MAX_PATH];
- memset(initPath, 0 , MAX_PATH*sizeof(TCHAR));
- memset(path, 0, MAX_PATH*sizeof(TCHAR));
+ wchar_t path[MAX_PATH];
+ wchar_t initPath[MAX_PATH];
+ initPath[0] = 0;
+ path[0] = 0;
tTitle = args.caption;
+
+#if !defined(Q_WS_WINCE)
+ BROWSEINFO bi;
+#else
qt_BROWSEINFO bi;
+#endif
+
Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
bi.hwndOwner = (parent ? parent->winId() : 0);
bi.pidlRoot = NULL;
- bi.lpszTitle = (TCHAR*)tTitle.utf16();
+ //### This does not seem to be respected? - the dialog always displays "Browse for folder"
+ bi.lpszTitle = (wchar_t*)tTitle.utf16();
bi.pszDisplayName = initPath;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE;
bi.lpfn = winGetExistDirCallbackProc;
bi.lParam = LPARAM(&initDir);
+
+ qt_win_resolve_libs();
if (ptrSHBrowseForFolder) {
LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder((BROWSEINFO*)&bi);
- if (pItemIDList && ptrSHGetPathFromIDList) {
+ if (pItemIDList) {
ptrSHGetPathFromIDList(pItemIDList, path);
IMalloc *pMalloc;
- if (SHGetMalloc(&pMalloc) != NOERROR)
- result = QString();
- else {
+ if (ptrSHGetMalloc(&pMalloc) == NOERROR) {
pMalloc->Free(pItemIDList);
pMalloc->Release();
- result = QString::fromUtf16((ushort*)path);
+ result = QString::fromWCharArray(path);
}
- } else
- result = QString();
+ }
}
tTitle = QString();
-#endif
QApplicationPrivate::leaveModal(&modal_widget);
qt_win_eatMouseMove();
- // Due to a bug on Windows Me, we need to reset the current
- // directory
- if ((QSysInfo::WindowsVersion == QSysInfo::WV_98 || QSysInfo::WindowsVersion == QSysInfo::WV_Me)
- && QDir::currentPath() != currentDir)
- QDir::setCurrent(currentDir);
-
if (!result.isEmpty())
- result.replace(QLatin1String("\\"), QLatin1String("/"));
+ result.replace(QLatin1Char('\\'), QLatin1Char('/'));
return result;
}
diff --git a/src/gui/dialogs/qfileinfogatherer.cpp b/src/gui/dialogs/qfileinfogatherer.cpp
index 58658f3..6b8cfea 100644
--- a/src/gui/dialogs/qfileinfogatherer.cpp
+++ b/src/gui/dialogs/qfileinfogatherer.cpp
@@ -44,8 +44,11 @@
#include <qfsfileengine.h>
#include <qdiriterator.h>
#ifndef Q_OS_WIN
-#include <unistd.h>
-#include <sys/types.h>
+# include <unistd.h>
+# include <sys/types.h>
+#endif
+#if defined(Q_OS_VXWORKS)
+# include "qplatformdefs.h"
#endif
QT_BEGIN_NAMESPACE
@@ -83,10 +86,10 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent)
*/
QFileInfoGatherer::~QFileInfoGatherer()
{
- mutex.lock();
+ QMutexLocker locker(&mutex);
abort = true;
condition.wakeOne();
- mutex.unlock();
+ locker.unlock();
wait();
}
@@ -94,9 +97,8 @@ void QFileInfoGatherer::setResolveSymlinks(bool enable)
{
Q_UNUSED(enable);
#ifdef Q_OS_WIN
- mutex.lock();
+ QMutexLocker locker(&mutex);
m_resolveSymlinks = enable;
- mutex.unlock();
#endif
}
@@ -107,9 +109,8 @@ bool QFileInfoGatherer::resolveSymlinks() const
void QFileInfoGatherer::setIconProvider(QFileIconProvider *provider)
{
- mutex.lock();
+ QMutexLocker locker(&mutex);
m_iconProvider = provider;
- mutex.unlock();
}
QFileIconProvider *QFileInfoGatherer::iconProvider() const
@@ -124,12 +125,11 @@ QFileIconProvider *QFileInfoGatherer::iconProvider() const
*/
void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStringList &files)
{
- mutex.lock();
+ QMutexLocker locker(&mutex);
// See if we already have this dir/file in our que
int loc = this->path.lastIndexOf(path);
while (loc > 0) {
if (this->files.at(loc) == files) {
- mutex.unlock();
return;
}
loc = this->path.lastIndexOf(path, loc - 1);
@@ -137,7 +137,6 @@ void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStr
this->path.push(path);
this->files.push(files);
condition.wakeAll();
- mutex.unlock();
}
/*!
@@ -160,10 +159,9 @@ void QFileInfoGatherer::updateFile(const QString &filePath)
void QFileInfoGatherer::clear()
{
#ifndef QT_NO_FILESYSTEMWATCHER
- mutex.lock();
+ QMutexLocker locker(&mutex);
watcher->removePaths(watcher->files());
watcher->removePaths(watcher->directories());
- mutex.unlock();
#endif
}
@@ -175,9 +173,8 @@ void QFileInfoGatherer::clear()
void QFileInfoGatherer::removePath(const QString &path)
{
#ifndef QT_NO_FILESYSTEMWATCHER
- mutex.lock();
+ QMutexLocker locker(&mutex);
watcher->removePath(path);
- mutex.unlock();
#endif
}
@@ -198,9 +195,8 @@ void QFileInfoGatherer::run()
{
forever {
bool updateFiles = false;
- mutex.lock();
+ QMutexLocker locker(&mutex);
if (abort) {
- mutex.unlock();
return;
}
if (this->path.isEmpty())
@@ -214,8 +210,9 @@ void QFileInfoGatherer::run()
this->files.pop_front();
updateFiles = true;
}
- mutex.unlock();
- if (updateFiles) getFileInfos(path, list);
+ locker.unlock();
+ if (updateFiles)
+ getFileInfos(path, list);
}
}
@@ -287,6 +284,8 @@ QString QFileInfoGatherer::translateDriveName(const QFileInfo &drive) const
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
if (driveName.startsWith(QLatin1Char('/'))) // UNC host
return drive.fileName();
+#endif
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
if (driveName.endsWith(QLatin1Char('/')))
driveName.chop(1);
#endif
diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h
index 455c852..1ca52fa 100644
--- a/src/gui/dialogs/qfileinfogatherer_p.h
+++ b/src/gui/dialogs/qfileinfogatherer_p.h
@@ -184,7 +184,7 @@ private:
QMutex mutex;
QWaitCondition condition;
- bool abort;
+ volatile bool abort;
QStack<QString> path;
QStack<QStringList> files;
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index a41fca4..0f50ff6 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -49,7 +49,7 @@
#include <qapplication.h>
#ifdef Q_OS_WIN
-#include <windows.h>
+#include <qt_windows.h>
#endif
QT_BEGIN_NAMESPACE
@@ -296,22 +296,14 @@ static QString qt_GetLongPathName(const QString &strShortPath)
#else
QString longSection = QDir::toNativeSeparators(section);
#endif
- QT_WA({
- WIN32_FIND_DATAW findData;
- h = ::FindFirstFileW((wchar_t *)longSection.utf16(), &findData);
- if (h != INVALID_HANDLE_VALUE)
- longPath.append(QString::fromUtf16((ushort*)findData.cFileName));
- } , {
- WIN32_FIND_DATAA findData;
- h = ::FindFirstFileA(section.toLocal8Bit(), &findData);
- if (h != INVALID_HANDLE_VALUE)
- longPath.append(QString::fromLocal8Bit(findData.cFileName));
- });
- if (h == INVALID_HANDLE_VALUE) {
+ WIN32_FIND_DATA findData;
+ h = ::FindFirstFile((wchar_t*)longSection.utf16(), &findData);
+ if (h != INVALID_HANDLE_VALUE) {
+ longPath.append(QString::fromWCharArray(findData.cFileName));
+ ::FindClose(h);
+ } else {
longPath.append(section);
break;
- } else {
- ::FindClose(h);
}
}
if (it != constEnd)
@@ -337,7 +329,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
{
Q_Q(const QFileSystemModel);
Q_UNUSED(q);
- if (path.isEmpty() || path == myComputer() || path.startsWith(QLatin1String(":")))
+ if (path.isEmpty() || path == myComputer() || path.startsWith(QLatin1Char(':')))
return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
// Construct the nodes up to the new root path if they need to be built
@@ -355,7 +347,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
// ### TODO can we use bool QAbstractFileEngine::caseSensitive() const?
QStringList pathElements = absolutePath.split(QLatin1Char('/'), QString::SkipEmptyParts);
if ((pathElements.isEmpty())
-#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN)
&& QDir::fromNativeSeparators(longPath) != QLatin1String("/")
#endif
)
@@ -384,9 +376,17 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
r = translateVisibleLocation(rootNode, r);
index = q->index(r, 0, QModelIndex());
pathElements.pop_front();
- } else {
- if (!pathElements.at(0).contains(QLatin1String(":")))
- pathElements.prepend(QDir(longPath).rootPath());
+ } else
+#endif
+
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
+ {
+ if (!pathElements.at(0).contains(QLatin1String(":"))) {
+ // The reason we express it like this instead of with anonymous, temporary
+ // variables, is to workaround a compiler crash with Q_CC_NOKIAX86.
+ QString rootPath = QDir(longPath).rootPath();
+ pathElements.prepend(rootPath);
+ }
if (pathElements.at(0).endsWith(QLatin1Char('/')))
pathElements[0].chop(1);
}
@@ -1408,7 +1408,7 @@ void QFileSystemModel::setIconProvider(QFileIconProvider *provider)
{
Q_D(QFileSystemModel);
d->fileInfoGatherer.setIconProvider(provider);
- qApp->processEvents();
+ QApplication::processEvents();
d->root.updateIcon(provider, QString());
}
@@ -1597,12 +1597,25 @@ void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, cons
if (parentNode->children.count() == 0)
return;
QStringList toRemove;
+#if defined(Q_OS_SYMBIAN)
+ // Filename case must be exact in qBinaryFind below, so create a list of all lowercase names.
+ QStringList newFiles;
+ for(int i = 0; i < files.size(); i++) {
+ newFiles << files.at(i).toLower();
+ }
+#else
QStringList newFiles = files;
+#endif
qSort(newFiles.begin(), newFiles.end());
QHash<QString, QFileSystemNode*>::const_iterator i = parentNode->children.constBegin();
while (i != parentNode->children.constEnd()) {
QStringList::iterator iterator;
- iterator = qBinaryFind(newFiles.begin(), newFiles.end(), i.value()->fileName);
+ iterator = qBinaryFind(newFiles.begin(), newFiles.end(),
+#if defined(Q_OS_SYMBIAN)
+ i.value()->fileName.toLower());
+#else
+ i.value()->fileName);
+#endif
if (iterator == newFiles.end()) {
toRemove.append(i.value()->fileName);
}
@@ -1925,8 +1938,8 @@ bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const
return true;
}
+QT_END_NAMESPACE
+
#include "moc_qfilesystemmodel.cpp"
#endif // QT_NO_FILESYSTEMMODEL
-
-QT_END_NAMESPACE
diff --git a/src/gui/dialogs/qfontdialog.cpp b/src/gui/dialogs/qfontdialog.cpp
index 92cdf57..30afde3 100644
--- a/src/gui/dialogs/qfontdialog.cpp
+++ b/src/gui/dialogs/qfontdialog.cpp
@@ -112,9 +112,8 @@ static const Qt::WindowFlags DefaultWindowFlags =
/*!
\class QFontDialog
- \ingroup dialogs
- \ingroup text
- \mainclass
+ \ingroup standard-dialogs
+
\brief The QFontDialog class provides a dialog widget for selecting a font.
A font dialog is created through one of the static getFont()
@@ -311,11 +310,11 @@ void QFontDialogPrivate::init()
buttonBox->addButton(QDialogButtonBox::Cancel);
QObject::connect(buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
q->resize(180, 120);
#else
q->resize(500, 360);
-#endif // Q_OS_WINCE
+#endif // Q_WS_WINCE
sizeEdit->installEventFilter(q);
familyList->installEventFilter(q);
@@ -501,8 +500,6 @@ void QFontDialogPrivate::updateFamilies()
{
Q_Q(QFontDialog);
- familyList->blockSignals(true);
-
enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };
QStringList familyNames = fdb.families(writingSystem);
@@ -556,7 +553,6 @@ void QFontDialogPrivate::updateFamilies()
&& familyList->hasFocus())
familyEdit->selectAll();
- familyList->blockSignals(false);
updateStyles();
}
@@ -567,9 +563,6 @@ void QFontDialogPrivate::updateFamilies()
void QFontDialogPrivate::updateStyles()
{
Q_Q(QFontDialog);
-
- styleList->blockSignals(true);
-
QStringList styles = fdb.styles(familyList->currentText());
styleList->model()->setStringList(styles);
@@ -613,8 +606,6 @@ void QFontDialogPrivate::updateStyles()
smoothScalable = fdb.isSmoothlyScalable(familyList->currentText(), styleList->currentText());
}
- styleList->blockSignals(false);
-
updateSizes();
}
@@ -628,8 +619,6 @@ void QFontDialogPrivate::updateSizes()
{
Q_Q(QFontDialog);
- sizeList->blockSignals(true);
-
if (!familyList->currentText().isEmpty()) {
QList<int> sizes = fdb.pointSizes(familyList->currentText(), styleList->currentText());
@@ -659,7 +648,6 @@ void QFontDialogPrivate::updateSizes()
sizeEdit->clear();
}
- sizeList->blockSignals(false);
_q_updateSample();
}
diff --git a/src/gui/dialogs/qfscompleter_p.h b/src/gui/dialogs/qfscompleter_p.h
new file mode 100644
index 0000000..fde7706
--- /dev/null
+++ b/src/gui/dialogs/qfscompleter_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFSCOMPLETOR_P_H
+#define QFSCOMPLETOR_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 "qcompleter.h"
+#include <QtGui/qfilesystemmodel.h>
+QT_BEGIN_NAMESPACE
+#ifndef QT_NO_COMPLETER
+
+/*!
+ QCompleter that can deal with QFileSystemModel
+ */
+class QFSCompleter : public QCompleter {
+public:
+ QFSCompleter(QFileSystemModel *model, QObject *parent = 0)
+ : QCompleter(model, parent), proxyModel(0), sourceModel(model)
+ {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ setCaseSensitivity(Qt::CaseInsensitive);
+#endif
+ }
+ QString pathFromIndex(const QModelIndex &index) const;
+ QStringList splitPath(const QString& path) const;
+
+ QAbstractProxyModel *proxyModel;
+ QFileSystemModel *sourceModel;
+};
+#endif // QT_NO_COMPLETER
+QT_END_NAMESPACE
+#endif // QFSCOMPLETOR_P_H
+
diff --git a/src/gui/dialogs/qinputdialog.cpp b/src/gui/dialogs/qinputdialog.cpp
index 156278f..5b3a339 100644
--- a/src/gui/dialogs/qinputdialog.cpp
+++ b/src/gui/dialogs/qinputdialog.cpp
@@ -307,8 +307,7 @@ void QInputDialogPrivate::ensureEnabledConnection(QAbstractSpinBox *spinBox)
{
if (spinBox) {
QAbstractButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
- QObject::disconnect(spinBox, SIGNAL(textChanged(bool)), okButton, SLOT(setEnabled(bool)));
- QObject::connect(spinBox, SIGNAL(textChanged(bool)), okButton, SLOT(setEnabled(bool)));
+ QObject::connect(spinBox, SIGNAL(textChanged(bool)), okButton, SLOT(setEnabled(bool)), Qt::UniqueConnection);
}
}
@@ -426,8 +425,8 @@ void QInputDialogPrivate::_q_currentRowChanged(const QModelIndex &newIndex,
\class QInputDialog
\brief The QInputDialog class provides a simple convenience dialog to get a
single value from the user.
- \ingroup dialogs
- \mainclass
+ \ingroup standard-dialogs
+
The input value can be a string, a number or an item from a list. A label
must be set to tell the user what they should enter.
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index 74ad983..e37ae83 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -45,6 +45,7 @@
#include <QtGui/qdialogbuttonbox.h>
#include "private/qlabel_p.h"
+#include "private/qapplication_p.h"
#include <QtCore/qlist.h>
#include <QtCore/qdebug.h>
#include <QtGui/qstyle.h>
@@ -63,7 +64,7 @@
#include <QtGui/qfontmetrics.h>
#include <QtGui/qclipboard.h>
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
extern bool qt_wince_is_smartphone();//defined in qguifunctions_wince.cpp
extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp
@@ -73,8 +74,6 @@ extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp
QT_BEGIN_NAMESPACE
-extern QHash<QByteArray, QFont> *qt_app_fonts_hash();
-
enum Button { Old_Ok = 1, Old_Cancel = 2, Old_Yes = 3, Old_No = 4, Old_Abort = 5, Old_Retry = 6,
Old_Ignore = 7, Old_YesAll = 8, Old_NoAll = 9, Old_ButtonMask = 0xFF,
NewButtonMask = 0xFFFFFC00 };
@@ -152,7 +151,7 @@ public:
int layoutMinimumWidth();
void retranslateStrings();
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void hideSpecial();
#endif
@@ -258,10 +257,8 @@ void QMessageBoxPrivate::init(const QString &title, const QString &text)
int QMessageBoxPrivate::layoutMinimumWidth()
{
- Q_Q(QMessageBox);
-
- q->layout()->activate();
- return q->layout()->totalMinimumSize().width();
+ layout->activate();
+ return layout->totalMinimumSize().width();
}
void QMessageBoxPrivate::updateSize()
@@ -272,10 +269,7 @@ void QMessageBoxPrivate::updateSize()
return;
QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size();
-#ifdef Q_WS_QWS
- // the width of the screen, less the window border.
- int hardLimit = screenSize.width() - (q->frameGeometry().width() - q->geometry().width());
-#elif defined(Q_OS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_WINCE) || defined(Q_OS_SYMBIAN)
// the width of the screen, less the window border.
int hardLimit = screenSize.width() - (q->frameGeometry().width() - q->geometry().width());
#else
@@ -290,11 +284,11 @@ void QMessageBoxPrivate::updateSize()
int softLimit = qMin(hardLimit, 500);
#else
// note: ideally on windows, hard and soft limits but it breaks compat
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
int softLimit = qMin(screenSize.width()/2, 500);
#else
int softLimit = qMin(screenSize.width() * 3 / 4, 500);
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
#endif
if (informativeLabel)
@@ -337,21 +331,21 @@ void QMessageBoxPrivate::updateSize()
label->setSizePolicy(policy);
}
- QFontMetrics fm(qApp->font("QWorkspaceTitleBar"));
+ QFontMetrics fm(QApplication::font("QWorkspaceTitleBar"));
int windowTitleWidth = qMin(fm.width(q->windowTitle()) + 50, hardLimit);
if (windowTitleWidth > width)
width = windowTitleWidth;
- q->layout()->activate();
- int height = (q->layout()->hasHeightForWidth())
- ? q->layout()->totalHeightForWidth(width)
- : q->layout()->totalMinimumSize().height();
+ layout->activate();
+ int height = (layout->hasHeightForWidth())
+ ? layout->totalHeightForWidth(width)
+ : layout->totalMinimumSize().height();
q->setFixedSize(width, height);
QCoreApplication::removePostedEvents(q, QEvent::LayoutRequest);
}
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
/*!
\internal
Hides special buttons which are rather shown in the title bar
@@ -366,7 +360,7 @@ void QMessageBoxPrivate::hideSpecial()
QPushButton *pb = list.at(i);
QString text = pb->text();
text.remove(QChar::fromLatin1('&'));
- if (text == qApp->translate("QMessageBox", "OK" ))
+ if (text == QApplication::translate("QMessageBox", "OK" ))
pb->setFixedSize(0,0);
}
}
@@ -440,8 +434,8 @@ void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button)
\brief The QMessageBox class provides a modal dialog for informing
the user or for asking the user a question and receiving an answer.
- \ingroup dialogs
- \mainclass
+ \ingroup standard-dialogs
+
A message box displays a primary \l{QMessageBox::text}{text} to
alert the user to a situation, an \l{QMessageBox::informativeText}
@@ -1208,13 +1202,13 @@ bool QMessageBox::event(QEvent *e)
case QEvent::LanguageChange:
d_func()->retranslateStrings();
break;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
case QEvent::OkRequest:
case QEvent::HelpRequest: {
QString bName =
(e->type() == QEvent::OkRequest)
- ? qApp->translate("QMessageBox", "OK")
- : qApp->translate("QMessageBox", "Help");
+ ? QApplication::translate("QMessageBox", "OK")
+ : QApplication::translate("QMessageBox", "Help");
QList<QPushButton*> list = qFindChildren<QPushButton*>(this);
for (int i=0; i<list.size(); ++i) {
QPushButton *pb = list.at(i);
@@ -1313,7 +1307,7 @@ void QMessageBox::keyPressEvent(QKeyEvent *e)
if (e == QKeySequence::Copy) {
QString separator = QString::fromLatin1("---------------------------\n");
QString textToCopy = separator;
- separator.prepend(QLatin1String("\n"));
+ separator.prepend(QLatin1Char('\n'));
textToCopy += windowTitle() + separator; // title
textToCopy += d->label->text() + separator; // text
@@ -1327,7 +1321,7 @@ void QMessageBox::keyPressEvent(QKeyEvent *e)
}
textToCopy += buttonTexts + separator;
- qApp->clipboard()->setText(textToCopy);
+ QApplication::clipboard()->setText(textToCopy);
return;
}
#endif //QT_NO_SHORTCUT QT_NO_CLIPBOARD Q_OS_WIN
@@ -1351,7 +1345,7 @@ void QMessageBox::keyPressEvent(QKeyEvent *e)
QDialog::keyPressEvent(e);
}
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
/*!
\reimp
*/
@@ -1422,7 +1416,7 @@ void QMessageBox::showEvent(QShowEvent *e)
Q_D(QMessageBox);
if (d->autoAddOkButton) {
addButton(Ok);
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
d->hideSpecial();
#endif
}
@@ -1689,10 +1683,13 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title)
}
#endif
- QString translatedTextAboutQt;
- translatedTextAboutQt = QMessageBox::tr(
+ QString translatedTextAboutQtCaption;
+ translatedTextAboutQtCaption = QMessageBox::tr(
"<h3>About Qt</h3>"
"<p>This program uses Qt version %1.</p>"
+ ).arg(QLatin1String(QT_VERSION_STR));
+ QString translatedTextAboutQtText;
+ translatedTextAboutQtText = QMessageBox::tr(
"<p>Qt is a C++ toolkit for cross-platform application "
"development.</p>"
"<p>Qt provides single-source portability across MS&nbsp;Windows, "
@@ -1701,7 +1698,7 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title)
"and Qt for Windows CE.</p>"
"<p>Qt is available under three different licensing options designed "
"to accommodate the needs of our various users.</p>"
- "Qt licensed under our commercial license agreement is appropriate "
+ "<p>Qt licensed under our commercial license agreement is appropriate "
"for development of proprietary/commercial software where you do not "
"want to share any source code with third parties or otherwise cannot "
"comply with the terms of the GNU LGPL version 2.1 or GNU GPL version "
@@ -1720,17 +1717,17 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title)
"<p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).</p>"
"<p>Qt is a Nokia product. See <a href=\"http://qt.nokia.com/\">qt.nokia.com</a> "
"for more information.</p>"
- ).arg(QLatin1String(QT_VERSION_STR));
-
+ );
QMessageBox *msgBox = new QMessageBox(parent);
msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setWindowTitle(title.isEmpty() ? tr("About Qt") : title);
- msgBox->setInformativeText(translatedTextAboutQt);
+ msgBox->setText(translatedTextAboutQtCaption);
+ msgBox->setInformativeText(translatedTextAboutQtText);
QPixmap pm(QLatin1String(":/trolltech/qmessagebox/images/qtlogo-64.png"));
if (!pm.isNull())
msgBox->setIconPixmap(pm);
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
msgBox->setDefaultButton(msgBox->addButton(QMessageBox::Ok));
#endif
diff --git a/src/gui/dialogs/qmessagebox.h b/src/gui/dialogs/qmessagebox.h
index 004669b..5aea38f 100644
--- a/src/gui/dialogs/qmessagebox.h
+++ b/src/gui/dialogs/qmessagebox.h
@@ -145,7 +145,7 @@ public:
QPushButton *addButton(StandardButton button);
void removeButton(QAbstractButton *button);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void setVisible(bool visible);
#endif
@@ -191,6 +191,8 @@ public:
static StandardButton information(QWidget *parent, const QString &title,
const QString &text, StandardButtons buttons = Ok,
StandardButton defaultButton = NoButton);
+ // ### Qt 5: Replace Ok with Yes|No in question() function.
+ // Also consider if Ok == Yes and Cancel == No.
static StandardButton question(QWidget *parent, const QString &title,
const QString &text, StandardButtons buttons = Ok,
StandardButton defaultButton = NoButton);
diff --git a/src/gui/dialogs/qpagesetupdialog.cpp b/src/gui/dialogs/qpagesetupdialog.cpp
index 18cd0ea..a8b0a59 100644
--- a/src/gui/dialogs/qpagesetupdialog.cpp
+++ b/src/gui/dialogs/qpagesetupdialog.cpp
@@ -45,6 +45,52 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class QPageSetupDialog
+
+ \brief The QPageSetupDialog class provides a configuration dialog
+ for the page-related options on a printer.
+
+ \ingroup standard-dialogs
+ \ingroup printing
+
+ On Windows and Mac OS X the page setup dialog is implemented using
+ the native page setup dialogs.
+
+ Note that on Windows and Mac OS X custom paper sizes won't be
+ reflected in the native page setup dialogs. Additionally, custom
+ page margins set on a QPrinter won't show in the native Mac OS X
+ page setup dialog.
+
+ \sa QPrinter, QPrintDialog
+*/
+
+
+/*!
+ \fn QPageSetupDialog::QPageSetupDialog(QPrinter *printer, QWidget *parent)
+
+ Constructs a page setup dialog that configures \a printer with \a
+ parent as the parent widget.
+*/
+
+/*!
+ \since 4.5
+
+ \fn QPageSetupDialog::QPageSetupDialog(QWidget *parent)
+
+ Constructs a page setup dialog that configures a default-constructed
+ QPrinter with \a parent as the parent widget.
+
+ \sa printer()
+*/
+
+/*!
+ \fn QPrinter *QPageSetupDialog::printer()
+
+ Returns the printer that was passed to the QPageSetupDialog
+ constructor.
+*/
+
// hack
class QPageSetupDialogPrivate : public QAbstractPageSetupDialogPrivate
{
diff --git a/src/gui/dialogs/qpagesetupdialog_win.cpp b/src/gui/dialogs/qpagesetupdialog_win.cpp
index f669d0a..8819dfd 100644
--- a/src/gui/dialogs/qpagesetupdialog_win.cpp
+++ b/src/gui/dialogs/qpagesetupdialog_win.cpp
@@ -71,18 +71,17 @@ int QPageSetupDialog::exec()
return Rejected;
QWin32PrintEngine *engine = static_cast<QWin32PrintEngine*>(d->printer->paintEngine());
- QWin32PrintEnginePrivate *ep = static_cast<QWin32PrintEnginePrivate *>(engine->d_ptr);
+ QWin32PrintEnginePrivate *ep = static_cast<QWin32PrintEnginePrivate *>(engine->d_ptr.data());
PAGESETUPDLG psd;
memset(&psd, 0, sizeof(PAGESETUPDLG));
psd.lStructSize = sizeof(PAGESETUPDLG);
// we need a temp DEVMODE struct if we don't have a global DEVMODE
- HGLOBAL hDevMode;
- int devModeSize;
+ HGLOBAL hDevMode = 0;
+ int devModeSize = 0;
if (!ep->globalDevMode) {
- QT_WA( { devModeSize = sizeof(DEVMODEW) + ((DEVMODEW *) ep->devMode)->dmDriverExtra; },
- { devModeSize = sizeof(DEVMODEA) + ((DEVMODEA *) ep->devMode)->dmDriverExtra; });
+ devModeSize = sizeof(DEVMODE) + ep->devMode->dmDriverExtra;
hDevMode = GlobalAlloc(GHND, devModeSize);
if (hDevMode) {
void *dest = GlobalLock(hDevMode);
@@ -98,7 +97,7 @@ int QPageSetupDialog::exec()
psd.hDevNames = tempDevNames;
QWidget *parent = parentWidget();
- parent = parent ? parent->window() : qApp->activeWindow();
+ parent = parent ? parent->window() : QApplication::activeWindow();
Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
psd.hwndOwner = parent ? parent->winId() : 0;
diff --git a/src/gui/embedded/qkbdpc101_qws.h b/src/gui/dialogs/qprintdialog.qdoc
index 042d898..7dabbfe 100644
--- a/src/gui/embedded/qkbdpc101_qws.h
+++ b/src/gui/dialogs/qprintdialog.qdoc
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtGui module of the Qt Toolkit.
+** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,57 +39,34 @@
**
****************************************************************************/
-#ifndef QKBDPC101_QWS_H
-#define QKBDPC101_QWS_H
+#ifdef QT3_SUPPORT
+/*!
+ \fn QPrinter *QPrintDialog::printer() const
-#include <QtGui/qkbd_qws.h>
+ Returns a pointer to the printer this dialog configures, or 0 if
+ this dialog does not operate on any printer.
-QT_BEGIN_HEADER
+ This function is available for Unix platforms only.
+*/
-QT_BEGIN_NAMESPACE
+/*!
+ \fn void QPrintDialog::setPrinter(QPrinter *printer, bool pickupSettings)
-QT_MODULE(Gui)
+ Sets this dialog to configure printer \a printer, or no printer if \a printer
+ is null. If \a pickupSettings is true, the dialog reads most of
+ its settings from \a printer. If \a pickupSettings is false (the
+ default) the dialog keeps its old settings.
-#ifndef QT_NO_QWS_KEYBOARD
+ This function is available for Unix platforms only.
+*/
-#ifndef QT_NO_QWS_KBD_PC101
+/*!
+ \fn void QPrintDialog::addButton(QPushButton *button)
-struct QWSKeyMap {
- uint key_code;
- ushort unicode;
- ushort shift_unicode;
- ushort ctrl_unicode;
-};
+ Adds the \a button to the layout of the print dialog. The added
+ buttons are arranged from the left to the right below the
+ last groupbox of the printdialog.
-class QWSPC101KeyboardHandler : public QWSKeyboardHandler
-{
-public:
- explicit QWSPC101KeyboardHandler(const QString&);
- virtual ~QWSPC101KeyboardHandler();
-
- virtual void doKey(uchar scancode);
- virtual const QWSKeyMap *keyMap() const;
-
-protected:
- bool shift;
- bool alt;
- bool ctrl;
- bool caps;
-#if defined(QT_QWS_IPAQ)
- uint ipaq_return_pressed:1;
+ This function is available for Unix platforms only.
+*/
#endif
- uint extended:2;
- Qt::KeyboardModifiers modifiers;
- int prevuni;
- int prevkey;
-};
-
-#endif // QT_NO_QWS_KBD_PC101
-
-#endif // QT_NO_QWS_KEYBOARD
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QKBDPC101_QWS_H
diff --git a/src/gui/dialogs/qprintdialog_unix.cpp b/src/gui/dialogs/qprintdialog_unix.cpp
index be93bb6..54e0046 100644
--- a/src/gui/dialogs/qprintdialog_unix.cpp
+++ b/src/gui/dialogs/qprintdialog_unix.cpp
@@ -44,17 +44,18 @@
#ifndef QT_NO_PRINTDIALOG
#include "private/qabstractprintdialog_p.h"
-#include "qfiledialog_p.h"
#include <QtGui/qmessagebox.h>
#include "qprintdialog.h"
#include "qfiledialog.h"
#include <QtCore/qdir.h>
+#include <QtGui/qevent.h>
#include <QtGui/qfilesystemmodel.h>
#include <QtGui/qstyleditemdelegate.h>
#include <QtGui/qprinter.h>
#include <QtGui/qdialogbuttonbox.h>
+#include "qfscompleter_p.h"
#include "ui_qprintpropertieswidget.h"
#include "ui_qprintsettingsoutput.h"
#include "ui_qprintwidget.h"
@@ -669,7 +670,7 @@ QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p)
for (int i = 0; i < cupsPrinterCount; ++i) {
QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
if (cupsPrinters[i].instance)
- printerName += QLatin1String("/") + QString::fromLocal8Bit(cupsPrinters[i].instance);
+ printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
widget.printers->addItem(printerName);
if (cupsPrinters[i].is_default)
@@ -696,7 +697,7 @@ QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p)
QFileSystemModel *fsm = new QFileSystemModel(widget.filename);
fsm->setRootPath(QDir::homePath());
#if !defined(QT_NO_COMPLETER) && !defined(QT_NO_FILEDIALOG)
- widget.filename->setCompleter(new QFSCompletor(fsm, widget.filename));
+ widget.filename->setCompleter(new QFSCompleter(fsm, widget.filename));
#endif
#endif
_q_printerChanged(currentPrinterIndex);
@@ -813,7 +814,7 @@ void QUnixPrintWidgetPrivate::_q_printerChanged(int index)
optionsPane->selectPrinter(0);
#endif
if (lprPrinters.count() > 0) {
- QString type = lprPrinters.at(index).name + QLatin1String("@") + lprPrinters.at(index).host;
+ QString type = lprPrinters.at(index).name + QLatin1Char('@') + lprPrinters.at(index).host;
if (!lprPrinters.at(index).comment.isEmpty())
type += QLatin1String(", ") + lprPrinters.at(index).comment;
widget.type->setText(type);
@@ -1194,9 +1195,9 @@ QVariant QPPDOptionsModel::headerData(int section, Qt::Orientation, int role) co
switch(section){
case 0:
- return QVariant(QApplication::translate("QPPDOptionsModel","Name"));
+ return QVariant(QApplication::translate("QPPDOptionsModel", "Name"));
case 1:
- return QVariant(QApplication::translate("QPPDOptionsModel","Value"));
+ return QVariant(QApplication::translate("QPPDOptionsModel", "Value"));
default:
return QVariant();
}
diff --git a/src/gui/dialogs/qprintdialog_win.cpp b/src/gui/dialogs/qprintdialog_win.cpp
index c913371..2d4190e 100644
--- a/src/gui/dialogs/qprintdialog_win.cpp
+++ b/src/gui/dialogs/qprintdialog_win.cpp
@@ -77,27 +77,18 @@ public:
QWin32PrintEnginePrivate *ep;
};
-#ifndef Q_OS_WINCE
-// If you change this function, make sure you also change the unicode equivalent
-template <class PrintDialog, class DeviceMode>
-static PrintDialog *qt_win_make_PRINTDLG(QWidget *parent,
- QPrintDialog *pdlg,
- QPrintDialogPrivate *d, HGLOBAL *tempDevNames)
+static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWidget *parent,
+ QPrintDialog *pdlg,
+ QPrintDialogPrivate *d, HGLOBAL *tempDevNames)
{
- PrintDialog *pd = new PrintDialog;
- memset(pd, 0, sizeof(PrintDialog));
- pd->lStructSize = sizeof(PrintDialog);
-
- void *devMode = sizeof(DeviceMode) == sizeof(DEVMODEA)
- ? (void *) d->ep->devModeA()
- : (void *) d->ep->devModeW();
+ DEVMODE *devMode = d->ep->devMode;
if (devMode) {
- int size = sizeof(DeviceMode) + ((DeviceMode *) devMode)->dmDriverExtra;
+ int size = sizeof(DEVMODE) + devMode->dmDriverExtra;
pd->hDevMode = GlobalAlloc(GHND, size);
{
void *dest = GlobalLock(pd->hDevMode);
- memcpy(dest, d->ep->devMode, size);
+ memcpy(dest, devMode, size);
GlobalUnlock(pd->hDevMode);
}
} else {
@@ -130,37 +121,31 @@ static PrintDialog *qt_win_make_PRINTDLG(QWidget *parent,
if (pd->nMinPage==0 && pd->nMaxPage==0)
pd->Flags |= PD_NOPAGENUMS;
+ // we don't have a 'current page' notion in the QPrinter API yet.
+ // Neither do we support more than one page range, so limit those
+ // options
+ pd->Flags |= PD_NOCURRENTPAGE;
+ pd->nStartPage = START_PAGE_GENERAL;
+ pd->nPageRanges = 1;
+ pd->nMaxPageRanges = 1;
+
if (d->ep->printToFile)
pd->Flags |= PD_PRINTTOFILE;
Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
pd->hwndOwner = parent ? parent->winId() : 0;
- pd->nFromPage = qMax(pdlg->fromPage(), pdlg->minPage());
- pd->nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1;
+ pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage());
+ pd->lpPageRanges[0].nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1;
pd->nCopies = d->ep->num_copies;
-
- return pd;
-}
-#endif // Q_OS_WINCE
-
-// If you change this function, make sure you also change the ansi equivalent
-template <typename T>
-static void qt_win_clean_up_PRINTDLG(T **pd)
-{
- delete *pd;
- *pd = 0;
}
-
-// If you change this function, make sure you also change the ansi equivalent
-template <typename T>
-static void qt_win_read_back_PRINTDLG(T *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d)
+static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d)
{
if (pd->Flags & PD_SELECTION) {
pdlg->setPrintRange(QPrintDialog::Selection);
pdlg->setFromTo(0, 0);
} else if (pd->Flags & PD_PAGENUMS) {
pdlg->setPrintRange(QPrintDialog::PageRange);
- pdlg->setFromTo(pd->nFromPage, pd->nToPage);
+ pdlg->setFromTo(pd->lpPageRanges[0].nFromPage, pd->lpPageRanges[0].nToPage);
} else {
pdlg->setPrintRange(QPrintDialog::AllPages);
pdlg->setFromTo(0, 0);
@@ -225,7 +210,7 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally()
if (parent)
parent = parent->window();
else
- parent = qApp->activeWindow();
+ parent = QApplication::activeWindow();
QWidget modal_widget;
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
@@ -234,34 +219,36 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally()
HGLOBAL *tempDevNames = ep->createDevNames();
- bool result;
bool done;
- void *pd = QT_WA_INLINE(
- (void*)(qt_win_make_PRINTDLG<PRINTDLGW, DEVMODEW>(parent, q, this, tempDevNames)),
- (void*)(qt_win_make_PRINTDLG<PRINTDLGA, DEVMODEA>(parent, q, this, tempDevNames))
- );
+ bool result;
+ bool doPrinting;
+
+ PRINTPAGERANGE pageRange;
+ PRINTDLGEX pd;
+ memset(&pd, 0, sizeof(PRINTDLGEX));
+ pd.lStructSize = sizeof(PRINTDLGEX);
+ pd.lpPageRanges = &pageRange;
+ qt_win_setup_PRINTDLGEX(&pd, parent, q, this, tempDevNames);
do {
done = true;
- QT_WA({
- PRINTDLGW *pdw = reinterpret_cast<PRINTDLGW *>(pd);
- result = PrintDlgW(pdw);
- if ((pdw->Flags & PD_PAGENUMS) && (pdw->nFromPage > pdw->nToPage))
- done = false;
- if (result && pdw->hDC == 0)
- result = false;
- else if (!result)
- done = true;
- }, {
- PRINTDLGA *pda = reinterpret_cast<PRINTDLGA *>(pd);
- result = PrintDlgA(pda);
- if ((pda->Flags & PD_PAGENUMS) && (pda->nFromPage > pda->nToPage))
+ doPrinting = false;
+ result = (PrintDlgEx(&pd) == S_OK);
+ if (result && (pd.dwResultAction == PD_RESULT_PRINT
+ || pd.dwResultAction == PD_RESULT_APPLY))
+ {
+ doPrinting = (pd.dwResultAction == PD_RESULT_PRINT);
+ if ((pd.Flags & PD_PAGENUMS)
+ && (pd.lpPageRanges[0].nFromPage > pd.lpPageRanges[0].nToPage))
+ {
+ pd.lpPageRanges[0].nFromPage = 1;
+ pd.lpPageRanges[0].nToPage = 1;
done = false;
- if (result && pda->hDC == 0)
+ }
+ if (pd.hDC == 0)
result = false;
- else if (!result)
- done = true;
- });
+ }
+
if (!done) {
QMessageBox::warning(0, QPrintDialog::tr("Print"),
QPrintDialog::tr("The 'From' value cannot be greater than the 'To' value."),
@@ -274,16 +261,10 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally()
qt_win_eatMouseMove();
// write values back...
- if (result) {
- QT_WA({
- PRINTDLGW *pdw = reinterpret_cast<PRINTDLGW *>(pd);
- qt_win_read_back_PRINTDLG(pdw, q, this);
- qt_win_clean_up_PRINTDLG(&pdw);
- }, {
- PRINTDLGA *pda = reinterpret_cast<PRINTDLGA *>(pd);
- qt_win_read_back_PRINTDLG(pda, q, this);
- qt_win_clean_up_PRINTDLG(&pda);
- });
+ if (result && (pd.dwResultAction == PD_RESULT_PRINT
+ || pd.dwResultAction == PD_RESULT_APPLY))
+ {
+ qt_win_read_back_PRINTDLGEX(&pd, q, this);
// update printer validity
printer->d_func()->validPrinter = !ep->name.isEmpty();
}
@@ -291,9 +272,9 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally()
// Cleanup...
GlobalFree(tempDevNames);
- q->done(result);
+ q->done(result && doPrinting);
- return result;
+ return result && doPrinting;
}
void QPrintDialog::setVisible(bool visible)
diff --git a/src/gui/dialogs/qprintpreviewdialog.cpp b/src/gui/dialogs/qprintpreviewdialog.cpp
index ddc4992..f5702e0 100644
--- a/src/gui/dialogs/qprintpreviewdialog.cpp
+++ b/src/gui/dialogs/qprintpreviewdialog.cpp
@@ -42,6 +42,7 @@
#include "qprintpreviewdialog.h"
#include "qprintpreviewwidget.h"
#include <private/qprinter_p.h>
+#include "private/qdialog_p.h"
#include <QtGui/qaction.h>
#include <QtGui/qboxlayout.h>
@@ -54,6 +55,9 @@
#include <QtGui/qtoolbutton.h>
#include <QtGui/qvalidator.h>
#include <QtGui/qfiledialog.h>
+#include <QtGui/qmainwindow.h>
+#include <QtGui/qtoolbar.h>
+#include <QtGui/qformlayout.h>
#include <QtCore/QCoreApplication>
#include <math.h>
@@ -63,6 +67,13 @@
QT_BEGIN_NAMESPACE
namespace {
+class QPrintPreviewMainWindow : public QMainWindow
+{
+public:
+ QPrintPreviewMainWindow(QWidget *parent) : QMainWindow(parent) {}
+ QMenu *createPopupMenu() { return 0; }
+};
+
class ZoomFactorValidator : public QDoubleValidator
{
public:
@@ -128,12 +139,12 @@ private:
};
} // anonymous namespace
-class QPrintPreviewDialogPrivate
+class QPrintPreviewDialogPrivate : public QDialogPrivate
{
Q_DECLARE_PUBLIC(QPrintPreviewDialog)
public:
- QPrintPreviewDialogPrivate(QPrintPreviewDialog *q)
- : q_ptr(q), printDialog(0), ownPrinter(false),
+ QPrintPreviewDialogPrivate()
+ : printDialog(0), ownPrinter(false),
initialized(false) {}
// private slots
@@ -158,7 +169,6 @@ public:
void updatePageNumLabel();
void updateZoomFactor();
- QPrintPreviewDialog *q_ptr;
QPrintDialog *printDialog;
QPrintPreviewWidget *preview;
QPrinter *printer;
@@ -197,7 +207,6 @@ public:
QActionGroup *printerGroup;
QAction *printAction;
QAction *pageSetupAction;
- QAction *closeAction;
QPointer<QObject> receiverToDisconnectOnClose;
QByteArray memberToDisconnectOnClose;
@@ -219,27 +228,12 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
QObject::connect(preview, SIGNAL(previewChanged()), q, SLOT(_q_previewChanged()));
setupActions();
- // Navigation
- QToolButton* nextPageButton = new QToolButton;
- nextPageButton->setDefaultAction(nextPageAction);
- QToolButton* prevPageButton = new QToolButton;
- prevPageButton->setDefaultAction(prevPageAction);
- QToolButton* firstPageButton = new QToolButton;
- firstPageButton->setDefaultAction(firstPageAction);
- QToolButton* lastPageButton = new QToolButton;
- lastPageButton->setDefaultAction(lastPageAction);
-
pageNumEdit = new LineEdit;
pageNumEdit->setAlignment(Qt::AlignRight);
- pageNumEdit->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
+ pageNumEdit->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
pageNumLabel = new QLabel;
QObject::connect(pageNumEdit, SIGNAL(editingFinished()), q, SLOT(_q_pageNumEdited()));
- QToolButton* fitWidthButton = new QToolButton;
- fitWidthButton->setDefaultAction(fitWidthAction);
- QToolButton* fitPageButton = new QToolButton;
- fitPageButton->setDefaultAction(fitPageAction);
-
zoomFactor = new QComboBox;
zoomFactor->setEditable(true);
zoomFactor->setMinimumContentsLength(7);
@@ -255,77 +249,66 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
QObject::connect(zoomFactor, SIGNAL(currentIndexChanged(int)),
q, SLOT(_q_zoomFactorChanged()));
- QToolButton* zoomInButton = new QToolButton;
- zoomInButton->setDefaultAction(zoomInAction);
+ QPrintPreviewMainWindow *mw = new QPrintPreviewMainWindow(q);
+ QToolBar *toolbar = new QToolBar(mw);
+ toolbar->addAction(fitWidthAction);
+ toolbar->addAction(fitPageAction);
+ toolbar->addSeparator();
+ toolbar->addWidget(zoomFactor);
+ toolbar->addAction(zoomOutAction);
+ toolbar->addAction(zoomInAction);
+ toolbar->addSeparator();
+ toolbar->addAction(portraitAction);
+ toolbar->addAction(landscapeAction);
+ toolbar->addSeparator();
+ toolbar->addAction(firstPageAction);
+ toolbar->addAction(prevPageAction);
+
+ // this is to ensure the label text and the editor text are
+ // aligned in all styles - the extra QVBoxLayout is a workaround
+ // for bug in QFormLayout
+ QWidget *pageEdit = new QWidget(toolbar);
+ QVBoxLayout *vboxLayout = new QVBoxLayout;
+ vboxLayout->setContentsMargins(0, 0, 0, 0);
+ QFormLayout *formLayout = new QFormLayout;
+ formLayout->setWidget(0, QFormLayout::LabelRole, pageNumEdit);
+ formLayout->setWidget(0, QFormLayout::FieldRole, pageNumLabel);
+ vboxLayout->addLayout(formLayout);
+ vboxLayout->setAlignment(Qt::AlignVCenter);
+ pageEdit->setLayout(vboxLayout);
+ toolbar->addWidget(pageEdit);
+
+ toolbar->addAction(nextPageAction);
+ toolbar->addAction(lastPageAction);
+ toolbar->addSeparator();
+ toolbar->addAction(singleModeAction);
+ toolbar->addAction(facingModeAction);
+ toolbar->addAction(overviewModeAction);
+ toolbar->addSeparator();
+ toolbar->addAction(pageSetupAction);
+ toolbar->addAction(printAction);
+
+ // Cannot use the actions' triggered signal here, since it doesn't autorepeat
+ QToolButton *zoomInButton = static_cast<QToolButton *>(toolbar->widgetForAction(zoomInAction));
+ QToolButton *zoomOutButton = static_cast<QToolButton *>(toolbar->widgetForAction(zoomOutAction));
zoomInButton->setAutoRepeat(true);
zoomInButton->setAutoRepeatInterval(200);
zoomInButton->setAutoRepeatDelay(200);
-
- QToolButton* zoomOutButton = new QToolButton;
- zoomOutButton->setDefaultAction(zoomOutAction);
zoomOutButton->setAutoRepeat(true);
zoomOutButton->setAutoRepeatInterval(200);
zoomOutButton->setAutoRepeatDelay(200);
-
- //Cannot use the actions' triggered signal here, since it doesnt autorepeat
QObject::connect(zoomInButton, SIGNAL(clicked()), q, SLOT(_q_zoomIn()));
QObject::connect(zoomOutButton, SIGNAL(clicked()), q, SLOT(_q_zoomOut()));
- QToolButton* portraitButton = new QToolButton;
- portraitButton->setDefaultAction(portraitAction);
- QToolButton* landscapeButton = new QToolButton;
- landscapeButton->setDefaultAction(landscapeAction);
-
- QToolButton* singleModeButton = new QToolButton;
- singleModeButton->setDefaultAction(singleModeAction);
- QToolButton* facingModeButton = new QToolButton;
- facingModeButton->setDefaultAction(facingModeAction);
- QToolButton* overviewModeButton = new QToolButton;
- overviewModeButton->setDefaultAction(overviewModeAction);
-
- QToolButton *printButton = new QToolButton;
- printButton->setDefaultAction(printAction);
- QToolButton *pageSetupButton = new QToolButton;
- pageSetupButton->setDefaultAction(pageSetupAction);
- QToolButton *closeButton = new QToolButton;
- closeButton->setDefaultAction(closeAction);
-
- QHBoxLayout* modeLayout = new QHBoxLayout;
- modeLayout->setSpacing(0);
- modeLayout->addWidget(singleModeButton);
- modeLayout->addWidget(facingModeButton);
- modeLayout->addWidget(overviewModeButton);
-
- QHBoxLayout *barLayout = new QHBoxLayout;
- barLayout->addWidget(fitWidthButton);
- barLayout->addWidget(fitPageButton);
- barLayout->addWidget(zoomFactor);
- barLayout->addWidget(zoomOutButton);
- barLayout->addWidget(zoomInButton);
- barLayout->addWidget(portraitButton);
- barLayout->addWidget(landscapeButton);
- barLayout->addStretch();
- barLayout->addWidget(firstPageButton);
- barLayout->addWidget(prevPageButton);
- barLayout->addWidget(pageNumEdit);
- barLayout->addWidget(pageNumLabel);
- barLayout->addWidget(nextPageButton);
- barLayout->addWidget(lastPageButton);
- barLayout->addStretch();
- barLayout->addLayout(modeLayout);
- barLayout->addStretch();
- barLayout->addWidget(pageSetupButton);
- barLayout->addWidget(printButton);
- barLayout->addWidget(closeButton);
-
- QWidget* buttonBar = new QWidget;
- buttonBar->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum));
- barLayout->setMargin(0);
- buttonBar->setLayout(barLayout);
+ mw->addToolBar(toolbar);
+ mw->setCentralWidget(preview);
+ // QMainWindows are always created as top levels, force it to be a
+ // plain widget
+ mw->setParent(q, Qt::Widget);
QVBoxLayout *topLayout = new QVBoxLayout;
- topLayout->addWidget(buttonBar);
- topLayout->addWidget(preview);
+ topLayout->addWidget(mw);
+ topLayout->setMargin(0);
q->setLayout(topLayout);
QString caption = QCoreApplication::translate("QPrintPreviewDialog", "Print Preview");
@@ -338,7 +321,8 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
|| printer->outputFormat() != QPrinter::NativeFormat
#endif
)
- pageSetupButton->setEnabled(false);
+ pageSetupAction->setEnabled(false);
+ preview->setFocus();
}
static inline void qt_setupActionIcon(QAction *action, const QLatin1String &name)
@@ -418,12 +402,10 @@ void QPrintPreviewDialogPrivate::setupActions()
printerGroup = new QActionGroup(q);
printAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Print"));
pageSetupAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Page setup"));
- closeAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Close"));
qt_setupActionIcon(printAction, QLatin1String("print"));
qt_setupActionIcon(pageSetupAction, QLatin1String("page-setup"));
QObject::connect(printAction, SIGNAL(triggered(bool)), q, SLOT(_q_print()));
QObject::connect(pageSetupAction, SIGNAL(triggered(bool)), q, SLOT(_q_pageSetup()));
- QObject::connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(reject()));
// Initial state:
fitPageAction->setChecked(true);
@@ -478,7 +460,7 @@ void QPrintPreviewDialogPrivate::updatePageNumLabel()
int numPages = preview->numPages();
int maxChars = QString::number(numPages).length();
- pageNumLabel->setText(QString(QLatin1String("/ %1")).arg(numPages));
+ pageNumLabel->setText(QString::fromLatin1("/ %1").arg(numPages));
int cyphersWidth = q->fontMetrics().width(QString().fill(QLatin1Char('8'), maxChars));
int maxWidth = pageNumEdit->minimumSizeHint().width() + cyphersWidth;
pageNumEdit->setMinimumWidth(maxWidth);
@@ -576,7 +558,7 @@ void QPrintPreviewDialogPrivate::_q_print()
suffix = QLatin1String(".ps");
}
QString fileName = QFileDialog::getSaveFileName(q, title, printer->outputFileName(),
- QLatin1String("*") + suffix);
+ QLatin1Char('*') + suffix);
if (!fileName.isEmpty()) {
if (QFileInfo(fileName).suffix().isEmpty())
fileName.append(suffix);
@@ -629,7 +611,7 @@ void QPrintPreviewDialogPrivate::_q_zoomFactorChanged()
factor = qMax(qreal(1.0), qMin(qreal(1000.0), factor));
if (ok) {
preview->setZoomFactor(factor/100.0);
- zoomFactor->setEditText(QString(QLatin1String("%1%")).arg(factor));
+ zoomFactor->setEditText(QString::fromLatin1("%1%").arg(factor));
setFitting(false);
}
}
@@ -643,6 +625,9 @@ void QPrintPreviewDialogPrivate::_q_zoomFactorChanged()
\brief The QPrintPreviewDialog class provides a dialog for
previewing and configuring page layouts for printer output.
+ \ingroup standard-dialogs
+ \ingroup printing
+
Using QPrintPreviewDialog in your existing application is
straightforward:
@@ -680,7 +665,7 @@ void QPrintPreviewDialogPrivate::_q_zoomFactorChanged()
\sa QWidget::setWindowFlags()
*/
QPrintPreviewDialog::QPrintPreviewDialog(QPrinter* printer, QWidget *parent, Qt::WindowFlags flags)
- : QDialog(parent, flags), d_ptr(new QPrintPreviewDialogPrivate(this))
+ : QDialog(*new QPrintPreviewDialogPrivate, parent, flags)
{
Q_D(QPrintPreviewDialog);
d->init(printer);
@@ -694,7 +679,7 @@ QPrintPreviewDialog::QPrintPreviewDialog(QPrinter* printer, QWidget *parent, Qt:
system default printer.
*/
QPrintPreviewDialog::QPrintPreviewDialog(QWidget *parent, Qt::WindowFlags f)
- : QDialog(parent, f), d_ptr(new QPrintPreviewDialogPrivate(this))
+ : QDialog(*new QPrintPreviewDialogPrivate, parent, f)
{
Q_D(QPrintPreviewDialog);
d->init();
@@ -709,7 +694,6 @@ QPrintPreviewDialog::~QPrintPreviewDialog()
if (d->ownPrinter)
delete d->printer;
delete d->printDialog;
- delete d_ptr;
}
/*!
diff --git a/src/gui/dialogs/qprintpreviewdialog.h b/src/gui/dialogs/qprintpreviewdialog.h
index f74710f..4fd31e6 100644
--- a/src/gui/dialogs/qprintpreviewdialog.h
+++ b/src/gui/dialogs/qprintpreviewdialog.h
@@ -94,7 +94,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_previewChanged())
Q_PRIVATE_SLOT(d_func(), void _q_zoomFactorChanged())
- QPrintPreviewDialogPrivate *d_ptr;
+ void *dummy; // ### Qt 5 - remove me
};
diff --git a/src/gui/dialogs/qprogressdialog.cpp b/src/gui/dialogs/qprogressdialog.cpp
index f1fca75..655e5aa 100644
--- a/src/gui/dialogs/qprogressdialog.cpp
+++ b/src/gui/dialogs/qprogressdialog.cpp
@@ -196,8 +196,8 @@ void QProgressDialogPrivate::_q_disconnectOnClose()
/*!
\class QProgressDialog
\brief The QProgressDialog class provides feedback on the progress of a slow operation.
- \ingroup dialogs
- \mainclass
+ \ingroup standard-dialogs
+
A progress dialog is used to give the user an indication of how long
an operation is going to take, and to demonstrate that the
@@ -643,7 +643,7 @@ void QProgressDialog::setValue(int progress)
if (d->shown_once) {
if (isModal())
- qApp->processEvents();
+ QApplication::processEvents();
} else {
if (progress == 0) {
d->starttime.start();
diff --git a/src/gui/dialogs/qsidebar.cpp b/src/gui/dialogs/qsidebar.cpp
index 219ce81..edbbc8c 100644
--- a/src/gui/dialogs/qsidebar.cpp
+++ b/src/gui/dialogs/qsidebar.cpp
@@ -247,11 +247,16 @@ void QUrlModel::addUrls(const QList<QUrl> &list, int row, bool move)
QUrl url = list.at(i);
if (!url.isValid() || url.scheme() != QLatin1String("file"))
continue;
+ //this makes sure the url is clean
+ const QString cleanUrl = QDir::cleanPath(url.toLocalFile());
+ url = QUrl::fromLocalFile(cleanUrl);
+
for (int j = 0; move && j < rowCount(); ++j) {
+ QString local = index(j, 0).data(UrlRole).toUrl().toLocalFile();
#if defined(Q_OS_WIN)
- if (QDir::cleanPath(index(j, 0).data(UrlRole).toUrl().toLocalFile()).toLower() == QDir::cleanPath(url.toLocalFile()).toLower()) {
+ if (index(j, 0).data(UrlRole).toUrl().toLocalFile().toLower() == cleanUrl.toLower()) {
#else
- if (QDir::cleanPath(index(j, 0).data(UrlRole).toUrl().toLocalFile()) == QDir::cleanPath(url.toLocalFile())) {
+ if (index(j, 0).data(UrlRole).toUrl().toLocalFile() == cleanUrl) {
#endif
removeRow(j);
if (j <= row)
@@ -260,12 +265,12 @@ void QUrlModel::addUrls(const QList<QUrl> &list, int row, bool move)
}
}
row = qMax(row, 0);
- QModelIndex idx = fileSystemModel->index(url.toLocalFile());
+ QModelIndex idx = fileSystemModel->index(cleanUrl);
if (!fileSystemModel->isDir(idx))
continue;
insertRows(row, 1);
setUrl(index(row, 0), url, idx);
- watching.append(QPair<QModelIndex, QString>(idx, url.toLocalFile()));
+ watching.append(qMakePair(idx, cleanUrl));
}
}
diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp
index f541acf..a81a31b 100644
--- a/src/gui/dialogs/qwizard.cpp
+++ b/src/gui/dialogs/qwizard.cpp
@@ -69,7 +69,7 @@
#include "private/qdialog_p.h"
#include <qdebug.h>
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp
#endif
@@ -83,7 +83,7 @@ const int ModernHeaderTopMargin = 2;
const int ClassicHMargin = 4;
const int MacButtonTopMargin = 13;
const int MacLayoutLeftMargin = 20;
-const int MacLayoutTopMargin = 14;
+//const int MacLayoutTopMargin = 14; // Unused. Save some space and avoid warning.
const int MacLayoutRightMargin = 20;
const int MacLayoutBottomMargin = 17;
@@ -343,8 +343,8 @@ void QWizardHeader::setup(const QWizardLayoutInfo &info, const QString &title,
{
bool modern = ((info.wizStyle == QWizard::ModernStyle)
#if !defined(QT_NO_STYLE_WINDOWSVISTA)
- || ((info.wizStyle == QWizard::AeroStyle)
- && (QVistaHelper::vistaState() == QVistaHelper::Classic) || vistaDisabled())
+ || ((info.wizStyle == QWizard::AeroStyle
+ && QVistaHelper::vistaState() == QVistaHelper::Classic) || vistaDisabled())
#endif
);
@@ -377,7 +377,7 @@ void QWizardHeader::setup(const QWizardLayoutInfo &info, const QString &title,
/*
There is no widthForHeight() function, so we simulate it with a loop.
*/
- int candidateSubTitleWidth = qMin(512, 2 * qApp->desktop()->width() / 3);
+ int candidateSubTitleWidth = qMin(512, 2 * QApplication::desktop()->width() / 3);
int delta = candidateSubTitleWidth >> 1;
while (delta > 0) {
if (subTitleLabel->heightForWidth(candidateSubTitleWidth - delta)
@@ -1251,11 +1251,7 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
extraHeight = vistaHelper->titleBarSize() + vistaHelper->topOffset();
#endif
QSize minimumSize = mainLayout->totalMinimumSize() + QSize(0, extraHeight);
- QSize maximumSize;
-#if defined(Q_WS_WIN)
- if (QSysInfo::WindowsVersion > QSysInfo::WV_Me) // ### See Tasks 164078 and 161660
-#endif
- maximumSize = mainLayout->totalMaximumSize();
+ QSize maximumSize = mainLayout->totalMaximumSize();
if (info.header && headerWidget->maximumWidth() != QWIDGETSIZE_MAX) {
minimumSize.setWidth(headerWidget->maximumWidth());
maximumSize.setWidth(headerWidget->maximumWidth());
@@ -1628,66 +1624,6 @@ void QWizardPrivate::setStyle(QStyle *style)
#ifdef Q_WS_MAC
-#ifdef Q_WS_MAC32
-QT_BEGIN_INCLUDE_NAMESPACE
-#include <QuickTime/QuickTime.h>
-QT_END_INCLUDE_NAMESPACE
-typedef OSErr (*PtrQTNewDataReferenceFromCFURL)(CFURLRef, UInt32, Handle*, OSType*);
-typedef OSErr (*PtrGetGraphicsImporterForDataRefWithFlags)(Handle, OSType, ComponentInstance*, long);
-typedef ComponentResult (*PtrGraphicsImportSetFlags)(GraphicsImportComponent, long);
-typedef ComponentResult (*PtrGraphicsImportCreateCGImage)(GraphicsImportComponent, CGImageRef*, UInt32);
-
-static PtrQTNewDataReferenceFromCFURL ptrQTNewDataReferenceFromCFURL = 0;
-static PtrGetGraphicsImporterForDataRefWithFlags ptrGetGraphicsImporterForDataRefWithFlags = 0;
-static PtrGraphicsImportSetFlags ptrGraphicsImportSetFlags = 0;
-static PtrGraphicsImportCreateCGImage ptrGraphicsImportCreateCGImage = 0;
-
-static bool resolveQuickTimeSymbols()
-{
- if (ptrQTNewDataReferenceFromCFURL == 0) {
- QLibrary library(QLatin1String("/System/Library/Frameworks/QuickTime.framework/QuickTime"));
- ptrQTNewDataReferenceFromCFURL = reinterpret_cast<PtrQTNewDataReferenceFromCFURL>(library.resolve("QTNewDataReferenceFromCFURL"));
- ptrGetGraphicsImporterForDataRefWithFlags = reinterpret_cast<PtrGetGraphicsImporterForDataRefWithFlags>(library.resolve("GetGraphicsImporterForDataRefWithFlags"));
- ptrGraphicsImportSetFlags = reinterpret_cast<PtrGraphicsImportSetFlags>(library.resolve("GraphicsImportSetFlags"));
- ptrGraphicsImportCreateCGImage = reinterpret_cast<PtrGraphicsImportCreateCGImage>(library.resolve("GraphicsImportCreateCGImage"));
- }
-
- return ptrQTNewDataReferenceFromCFURL != 0 && ptrGetGraphicsImporterForDataRefWithFlags != 0
- && ptrGraphicsImportSetFlags != 0 && ptrGraphicsImportCreateCGImage != 0;
-}
-
-
-static QPixmap quicktimeTiff(const CFURLRef url)
-{
- if (!resolveQuickTimeSymbols())
- return QPixmap();
-
- QCFType <CGImageRef> imageRef = 0;
- Handle dataRef;
- OSType dataRefType;
- GraphicsImportComponent gi;
- ComponentResult result;
- result = ptrQTNewDataReferenceFromCFURL(url, 0, &dataRef, &dataRefType);
- if (dataRef != 0) {
- OSStatus err = ptrGetGraphicsImporterForDataRefWithFlags(dataRef, dataRefType, &gi, 0);
- if (err == noErr && gi) {
- result = ptrGraphicsImportSetFlags(gi, (kGraphicsImporterDontDoGammaCorrection
- + kGraphicsImporterDontUseColorMatching));
- if (!result)
- result = ptrGraphicsImportCreateCGImage(gi, &imageRef, 0);
- if (result)
- qWarning("Qt: Problem reading TIFF image %ld(%s:%d)", result, __FILE__, __LINE__);
- DisposeHandle(dataRef);
- CloseComponent(gi);
- }
- }
-
- if (imageRef)
- return QPixmap::fromMacCGImageRef(imageRef);
- return QPixmap();
-}
-#endif // Q_WS_MAC32
-
QPixmap QWizardPrivate::findDefaultBackgroundPixmap()
{
QCFType<CFURLRef> url;
@@ -1699,22 +1635,13 @@ QPixmap QWizardPrivate::findDefaultBackgroundPixmap()
if (bundle) {
url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("tif"), 0);
if (url) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, 0);
- QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
- if (image) {
- int width = CGImageGetWidth(image);
- int height = CGImageGetHeight(image);
- if (width == ExpectedImageWidth && height == ExpectedImageHeight)
- return QPixmap::fromMacCGImageRef(image);
- }
- } else
-#endif
- {
-#ifdef Q_WS_MAC32
- return quicktimeTiff(url);
-#endif
+ QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, 0);
+ QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
+ if (image) {
+ int width = CGImageGetWidth(image);
+ int height = CGImageGetHeight(image);
+ if (width == ExpectedImageWidth && height == ExpectedImageHeight)
+ return QPixmap::fromMacCGImageRef(image);
}
}
}
@@ -2145,7 +2072,7 @@ QWizard::QWizard(QWidget *parent, Qt::WindowFlags flags)
{
Q_D(QWizard);
d->init();
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (!qt_wince_is_mobile())
setWindowFlags(windowFlags() & ~Qt::WindowOkButtonHint);
#endif
diff --git a/src/gui/dialogs/qwizard_win.cpp b/src/gui/dialogs/qwizard_win.cpp
index 9f74d64..e094b3b 100644
--- a/src/gui/dialogs/qwizard_win.cpp
+++ b/src/gui/dialogs/qwizard_win.cpp
@@ -279,7 +279,7 @@ QVistaHelper::VistaState QVistaHelper::vistaState()
QColor QVistaHelper::basicWindowFrameColor()
{
DWORD rgb;
- HANDLE hTheme = pOpenThemeData(qApp->desktop()->winId(), L"WINDOW");
+ HANDLE hTheme = pOpenThemeData(QApplication::desktop()->winId(), L"WINDOW");
pGetThemeColor(
hTheme, WIZ_WP_CAPTION, WIZ_CS_ACTIVE,
wizard->isActiveWindow() ? WIZ_TMT_FILLCOLORHINT : WIZ_TMT_BORDERCOLORHINT,
@@ -611,12 +611,12 @@ bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const Q
{
bool value = false;
if (vistaState() == VistaAero) {
- HANDLE hTheme = pOpenThemeData(qApp->desktop()->winId(), L"WINDOW");
+ HANDLE hTheme = pOpenThemeData(QApplication::desktop()->winId(), L"WINDOW");
if (!hTheme) return false;
// Set up a memory DC and bitmap that we'll draw into
HDC dcMem;
HBITMAP bmp;
- BITMAPINFO dib = {0};
+ BITMAPINFO dib = {{0}};
dcMem = CreateCompatibleDC(hdc);
dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
@@ -662,7 +662,7 @@ bool QVistaHelper::drawBlackRect(const QRect &rect, HDC hdc)
// Set up a memory DC and bitmap that we'll draw into
HDC dcMem;
HBITMAP bmp;
- BITMAPINFO dib = {0};
+ BITMAPINFO dib = {{0}};
dcMem = CreateCompatibleDC(hdc);
dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
diff --git a/src/gui/dialogs/qwizard_win_p.h b/src/gui/dialogs/qwizard_win_p.h
index 6c43167..c35716a 100644
--- a/src/gui/dialogs/qwizard_win_p.h
+++ b/src/gui/dialogs/qwizard_win_p.h
@@ -56,7 +56,7 @@
#ifndef QT_NO_WIZARD
#ifndef QT_NO_STYLE_WINDOWSVISTA
-#include <windows.h>
+#include <qt_windows.h>
#include <qobject.h>
#include <qwidget.h>
#include <qabstractbutton.h>
diff --git a/src/gui/effects/effects.pri b/src/gui/effects/effects.pri
new file mode 100644
index 0000000..0ebf96f
--- /dev/null
+++ b/src/gui/effects/effects.pri
@@ -0,0 +1,4 @@
+HEADERS += effects/qgraphicseffect.h \
+ effects/qgraphicseffect_p.h
+
+SOURCES += effects/qgraphicseffect.cpp
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp
new file mode 100644
index 0000000..50644ff
--- /dev/null
+++ b/src/gui/effects/qgraphicseffect.cpp
@@ -0,0 +1,1142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QGraphicsEffect
+ \brief The QGraphicsEffect class is the base class for all graphics
+ effects.
+ \since 4.6
+ \ingroup multimedia
+ \ingroup graphicsview-api
+
+ Effects alter the appearance of elements by hooking into the rendering
+ pipeline and operating between the source (e.g., a QGraphicsPixmapItem)
+ and the destination device (e.g., QGraphicsView's viewport). Effects can be
+ disabled by calling setEnabled(false). If effects are disabled, the source
+ is rendered directly.
+
+ To add a visual effect to a QGraphicsItem, for example, you can use one of
+ the standard effects, or alternately, create your own effect by creating a
+ subclass of QGraphicsEffect. The effect can then be installed on the item
+ using QGraphicsItem::setGraphicsEffect().
+
+ Qt provides the following standard effects:
+
+ \list
+ \o QGraphicsBlurEffect - blurs the item by a given radius
+ \o QGraphicsDropShadowEffect - renders a dropshadow behind the item
+ \o QGraphicsColorizeEffect - renders the item in shades of any given color
+ \o QGraphicsOpacityEffect - renders the item with an opacity
+ \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size
+ \o QGraphicsGrayscaleEffect - renders the item in shades of gray
+ \o QGraphicsShaderEffect - renders the item with a pixel shader fragment
+ \endlist
+
+ \img graphicseffect-effects.png
+ \img graphicseffect-widget.png
+
+ For more information on how to use each effect, refer to the specific
+ effect's documentation.
+
+ To create your own custom effect, create a subclass of QGraphicsEffect (or
+ any other existing effects) and reimplement the virtual function draw().
+ This function is called whenever the effect needs to redraw. The draw()
+ function accepts two arguments: the painter and a pointer to the source
+ (QGraphicsEffectSource). The source provides extra context information,
+ such as a pointer to the item that is rendering the effect, any cached
+ pixmap data, or the device rectangle bounds. For more information, refer to
+ the documenation for draw(). To obtain a pointer to the current source,
+ simply call source().
+
+ If your effect changes, use update() to request for a redraw. If your
+ custom effect changes the bounding rectangle of the source, e.g., a radial
+ glow effect may need to apply an extra margin, you can reimplement the
+ virtual boundingRectFor() function, and call updateBoundingRect() to notify
+ the framework whenever this rectangle changes. The virtual
+ sourceBoundingRectChanged() function is called to notify the effects that
+ the source's bounding rectangle has changed - e.g., if the source is a
+ QGraphicsRectItem and its rectangle parameters have changed.
+
+ \sa QGraphicsItem::setGraphicsEffect(), QWidget::setGraphicsEffect(),
+ QGraphicsEffectSource
+*/
+
+#include "qgraphicseffect_p.h"
+
+#include <QtGui/qimage.h>
+#include <QtGui/qpainter.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGraphicsEffectSource
+ \brief The QGraphicsEffectSource class represents the source on which a
+ QGraphicsEffect is installed on.
+ \since 4.6
+
+ When a QGraphicsEffect is installed on a QGraphicsItem, for example, this
+ class will act as a wrapper around QGraphicsItem. Then, calling update() is
+ effectively the same as calling QGraphicsItem::update().
+
+ QGraphicsEffectSource also provides a pixmap() function which creates a
+ pixmap with the source painted into it.
+
+ \sa QGraphicsItem::setGraphicsEffect(), QWidget::setGraphicsEffect().
+*/
+
+/*!
+ \internal
+*/
+QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{}
+
+/*!
+ Destroys the effect source.
+*/
+QGraphicsEffectSource::~QGraphicsEffectSource()
+{}
+
+/*!
+ Returns the bounds of the current painter's device.
+
+ This function is useful when you want to draw something in device
+ coordinates and ensure the size of the pixmap is not bigger than the size
+ of the device.
+
+ Calling QGraphicsEffectSource::pixmap(Qt::DeviceCoordinates) always returns
+ a pixmap which is bound to the device's size.
+
+ \sa pixmap()
+*/
+QRect QGraphicsEffectSource::deviceRect() const
+{
+ return d_func()->deviceRect();
+}
+
+/*!
+ Returns the bounding rectangle of the source mapped to the given \a system.
+
+ \sa draw()
+*/
+QRectF QGraphicsEffectSource::boundingRect(Qt::CoordinateSystem system) const
+{
+ return d_func()->boundingRect(system);
+}
+
+/*!
+ Returns a pointer to the item if this source is a QGraphicsItem; otherwise
+ returns 0.
+
+ \sa widget()
+*/
+const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const
+{
+ return d_func()->graphicsItem();
+}
+
+/*!
+ Returns a pointer to the widget if this source is a QWidget; otherwise
+ returns 0.
+
+ \sa graphicsItem()
+*/
+const QWidget *QGraphicsEffectSource::widget() const
+{
+ return d_func()->widget();
+}
+
+/*!
+ Returns a pointer to the style options (used when drawing the source) if
+ available; otherwise returns 0.
+
+ \sa graphicsItem(), widget()
+*/
+const QStyleOption *QGraphicsEffectSource::styleOption() const
+{
+ return d_func()->styleOption();
+}
+
+/*!
+ Draws the source using the given \a painter.
+
+ This function should only be called from QGraphicsEffect::draw().
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 0
+
+ \sa QGraphicsEffect::draw()
+*/
+void QGraphicsEffectSource::draw(QPainter *painter)
+{
+ d_func()->draw(painter);
+}
+
+/*!
+ Schedules a redraw of the source. Call this function whenever the source
+ needs to be redrawn.
+
+ \sa QGraphicsEffect::updateBoundingRect(), QWidget::update(),
+ QGraphicsItem::update(),
+*/
+void QGraphicsEffectSource::update()
+{
+ d_func()->update();
+}
+
+/*!
+ Returns true if the source effectively is a pixmap, e.g., a
+ QGraphicsPixmapItem.
+
+ This function is useful for optimization purposes. For instance, there's no
+ point in drawing the source in device coordinates to avoid pixmap scaling
+ if this function returns true - the source pixmap will be scaled anyways.
+*/
+bool QGraphicsEffectSource::isPixmap() const
+{
+ return d_func()->isPixmap();
+}
+
+/*!
+ Returns a pixmap with the source painted into it.
+
+ The \a system specifies which coordinate system to be used for the source.
+ The optional \a offset parameter returns the offset where the pixmap should
+ be painted at using the current painter.
+
+ The returned pixmap is bound to the current painter's device rectangle when
+ \a system is Qt::DeviceCoordinates.
+
+ \sa QGraphicsEffect::draw(), boundingRect(), deviceRect()
+*/
+QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
+{
+ return d_func()->pixmap(system, offset);
+}
+
+/*!
+ Constructs a new QGraphicsEffect instance.
+*/
+QGraphicsEffect::QGraphicsEffect(QObject *parent)
+ : QObject(*new QGraphicsEffectPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Removes the effect from the source, and destroys the graphics effect.
+*/
+QGraphicsEffect::~QGraphicsEffect()
+{
+ Q_D(QGraphicsEffect);
+ d->setGraphicsEffectSource(0);
+}
+
+/*!
+ Returns the bounding rectangle for this effect, i.e., the bounding
+ rectangle of the source, adjusted by any margins applied by the effect
+ itself.
+
+ \sa boundingRectFor(), updateBoundingRect()
+*/
+QRectF QGraphicsEffect::boundingRect() const
+{
+ Q_D(const QGraphicsEffect);
+ if (d->source)
+ return boundingRectFor(d->source->boundingRect());
+ return QRectF();
+}
+
+/*!
+ Returns the bounding rectangle for this effect, given the provided source
+ \a rect. When writing you own custom effect, you must call
+ updateBoundingRect() whenever any parameters are changed that may cause
+ this this function to return a different value.
+
+ \sa boundingRect()
+*/
+QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const
+{
+ return rect;
+}
+
+/*!
+ \property QGraphicsEffect::enabled
+ \brief whether the effect is enabled or not.
+
+ If an effect is disabled, the source will be rendered with as normal, with
+ no interference from the effect. If the effect is enabled, the source will
+ be rendered with the effect applied.
+
+ This property is enabled by default.
+
+ Using this property, you can disable certain effects on slow platforms, in
+ order to ensure that the user interface is responsive.
+*/
+bool QGraphicsEffect::isEnabled() const
+{
+ Q_D(const QGraphicsEffect);
+ return d->isEnabled;
+}
+
+void QGraphicsEffect::setEnabled(bool enable)
+{
+ Q_D(QGraphicsEffect);
+ if (d->isEnabled == enable)
+ return;
+
+ d->isEnabled = enable;
+ if (d->source)
+ d->source->update();
+ emit enabledChanged(enable);
+}
+
+/*!
+ \fn void QGraphicsEffect::enabledChanged(bool enabled)
+
+ This signal is emitted whenever the effect is enabled or disabled.
+ The \a enabled parameter holds the effects's new enabled state.
+
+ \sa isEnabled()
+*/
+
+/*!
+ Returns a pointer to the source, which provides extra context information
+ that can be useful for the effect.
+
+ \sa draw()
+*/
+QGraphicsEffectSource *QGraphicsEffect::source() const
+{
+ Q_D(const QGraphicsEffect);
+ return d->source;
+}
+
+/*!
+ This function notifies the effect framework when the effect's bounding
+ rectangle has changed. As a custom effect author, you must call this
+ function whenever you change any parameters that will cause the virtual
+ boundingRectFor() function to return a different value.
+
+ \sa boundingRectFor(), boundingRect()
+*/
+void QGraphicsEffect::updateBoundingRect()
+{
+ Q_D(QGraphicsEffect);
+ if (d->source)
+ d->source->update();
+}
+
+/*!
+ \fn virtual void QGraphicsEffect::draw(QPainter *painter,
+ QGraphicsEffectSource *source) = 0
+
+ This pure virtual function draws the effect and is called whenever the
+ source() needs to be drawn.
+
+ Reimplement this function in a QGraphicsEffect subclass to provide the
+ effect's drawing implementation, using \a painter. The \a source parameter
+ is provided for convenience; its value is the same as source().
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 1
+
+ This function should not be called explicitly by the user, since it is
+ meant for reimplementation purposes only.
+
+ \sa QGraphicsEffectSource
+*/
+
+/*!
+ \enum QGraphicsEffect::ChangeFlag
+
+ This enum describes what has changed in QGraphicsEffectSource.
+
+ \value SourceAttached The effect is installed on a source.
+ \value SourceDetached The effect is uninstalled on a source.
+ \value SourceBoundingRectChanged The bounding rect of the source has
+ changed.
+ \value SourceInvalidated The visual appearance of the source has changed.
+*/
+
+/*!
+ This virtual function is called by QGraphicsEffect to notify the effect
+ that the source has changed. If the effect applies any cache, then this
+ cache must be purged in order to reflect the new appearance of the source.
+
+ The \a flags describes what has changed.
+*/
+void QGraphicsEffect::sourceChanged(ChangeFlags flags)
+{
+ Q_UNUSED(flags);
+}
+
+/*!
+ \class QGraphicsGrayscaleEffect
+ \brief The QGraphicsGrayscaleEffect class provides a grayscale effect.
+ \since 4.6
+
+ A grayscale effect renders the source in shades of gray.
+
+ \img graphicseffect-grayscale.png
+
+ \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect,
+ QGraphicsColorizeEffect, QGraphicsOpacityEffect
+*/
+
+/*!
+ Constructs a new QGraphicsGrayscale instance.
+ The \a parent parameter is passed to QGraphicsEffect's constructor.
+*/
+QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(QObject *parent)
+ : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate, parent)
+{
+}
+
+/*!
+ Destroys the effect.
+*/
+QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect()
+{
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
+{
+ Q_D(QGraphicsGrayscaleEffect);
+ QPoint offset;
+ if (source->isPixmap()) {
+ // No point in drawing in device coordinates (pixmap will be scaled anyways).
+ const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
+ d->filter->draw(painter, offset, pixmap);
+ return;
+ }
+
+ // Draw pixmap in device coordinates to avoid pixmap scaling;
+ const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
+ QTransform restoreTransform = painter->worldTransform();
+ painter->setWorldTransform(QTransform());
+ d->filter->draw(painter, offset, pixmap);
+ painter->setWorldTransform(restoreTransform);
+
+}
+
+/*!
+ \class QGraphicsColorizeEffect
+ \brief The QGraphicsColorizeEffect class provides a colorize effect.
+ \since 4.6
+
+ A colorize effect renders the source with a tint of its color(). The color
+ can be modified using the setColor() function.
+
+ By default, the color is light blue (QColor(0, 0, 192)).
+
+ \img graphicseffect-colorize.png
+
+ \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect,
+ QGraphicsGrayscaleEffect, QGraphicsOpacityEffect
+*/
+
+/*!
+ Constructs a new QGraphicsColorizeEffect instance.
+ The \a parent parameter is passed to QGraphicsEffect's constructor.
+*/
+QGraphicsColorizeEffect::QGraphicsColorizeEffect(QObject *parent)
+ : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate, parent)
+{
+}
+
+/*!
+ Destroys the effect.
+*/
+QGraphicsColorizeEffect::~QGraphicsColorizeEffect()
+{
+}
+
+/*!
+ \property QGraphicsColorizeEffect::color
+ \brief the color of the effect.
+
+ By default, the color is light blue (QColor(0, 0, 192)).
+*/;
+QColor QGraphicsColorizeEffect::color() const
+{
+ Q_D(const QGraphicsColorizeEffect);
+ return d->filter->color();
+}
+
+void QGraphicsColorizeEffect::setColor(const QColor &color)
+{
+ Q_D(QGraphicsColorizeEffect);
+ if (d->filter->color() == color)
+ return;
+
+ d->filter->setColor(color);
+ emit colorChanged(color);
+}
+
+/*!
+ \fn void QGraphicsColorizeEffect::colorChanged(const QColor &color)
+
+ This signal is emitted whenever the effect's color changes.
+ The \a color parameter holds the effect's new color.
+*/
+
+/*!
+ \reimp
+*/
+void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
+{
+ Q_D(QGraphicsColorizeEffect);
+ QPoint offset;
+ if (source->isPixmap()) {
+ // No point in drawing in device coordinates (pixmap will be scaled anyways).
+ const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
+ d->filter->draw(painter, offset, pixmap);
+ return;
+ }
+
+ // Draw pixmap in deviceCoordinates to avoid pixmap scaling.
+ const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
+ QTransform restoreTransform = painter->worldTransform();
+ painter->setWorldTransform(QTransform());
+ d->filter->draw(painter, offset, pixmap);
+ painter->setWorldTransform(restoreTransform);
+}
+
+/*!
+ \class QGraphicsPixelizeEffect
+ \brief The QGraphicsPixelizeEffect class provides a pixelize effect.
+ \since 4.6
+
+ A pixelize effect renders the source in lower resolution. This effect is
+ useful for reducing details, like censorship. The resolution can be
+ modified using the setPixelSize() function.
+
+ By default, the pixel size is 3.
+
+ \img graphicseffect-pixelize.png
+
+ \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsGrayscaleEffect,
+ QGraphicsColorizeEffect, QGraphicsOpacityEffect
+*/
+
+/*!
+ Constructs a new QGraphicsPixelizeEffect instance.
+ The \a parent parameter is passed to QGraphicsEffect's constructor.
+*/
+QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(QObject *parent)
+ : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate, parent)
+{
+}
+
+/*!
+ Destroys the effect.
+*/
+QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect()
+{
+}
+
+/*!
+ \property QGraphicsPixelizeEffect::pixelSize
+ \brief the size of a pixel in the effect.
+
+ Setting the pixel size to 2 means two pixels in the source will be used to
+ represent one pixel. Using a bigger size results in lower resolution.
+
+ By default, the pixel size is 3.
+*/
+int QGraphicsPixelizeEffect::pixelSize() const
+{
+ Q_D(const QGraphicsPixelizeEffect);
+ return d->pixelSize;
+}
+
+void QGraphicsPixelizeEffect::setPixelSize(int size)
+{
+ Q_D(QGraphicsPixelizeEffect);
+ if (d->pixelSize == size)
+ return;
+
+ d->pixelSize = size;
+ emit pixelSizeChanged(size);
+}
+
+/*!
+ \fn void QGraphicsPixelizeEffect::pixelSizeChanged(int size)
+
+ This signal is emitted whenever the effect's pixel size changes.
+ The \a size parameter holds the effect's new pixel size.
+*/
+
+static inline void pixelize(QImage *image, int pixelSize)
+{
+ Q_ASSERT(pixelSize > 0);
+ Q_ASSERT(image);
+ int width = image->width();
+ int height = image->height();
+ for (int y = 0; y < height; y += pixelSize) {
+ int ys = qMin(height - 1, y + pixelSize / 2);
+ QRgb *sbuf = reinterpret_cast<QRgb*>(image->scanLine(ys));
+ for (int x = 0; x < width; x += pixelSize) {
+ int xs = qMin(width - 1, x + pixelSize / 2);
+ QRgb color = sbuf[xs];
+ for (int yi = 0; yi < qMin(pixelSize, height - y); ++yi) {
+ QRgb *buf = reinterpret_cast<QRgb*>(image->scanLine(y + yi));
+ for (int xi = 0; xi < qMin(pixelSize, width - x); ++xi)
+ buf[x + xi] = color;
+ }
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
+{
+ Q_D(QGraphicsPixelizeEffect);
+ if (d->pixelSize <= 0) {
+ source->draw(painter);
+ return;
+ }
+
+ QPoint offset;
+ if (source->isPixmap()) {
+ const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
+ QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+ pixelize(&image, d->pixelSize);
+ painter->drawImage(offset, image);
+ return;
+ }
+
+ // Draw pixmap in device coordinates to avoid pixmap scaling.
+ const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
+
+ // pixelize routine
+ QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+ pixelize(&image, d->pixelSize);
+
+ QTransform restoreTransform = painter->worldTransform();
+ painter->setWorldTransform(QTransform());
+ painter->drawImage(offset, image);
+ painter->setWorldTransform(restoreTransform);
+}
+
+/*!
+ \class QGraphicsBlurEffect
+ \brief The QGraphicsBlurEffect class provides a blur effect.
+ \since 4.6
+
+ A blur effect blurs the source. This effect is useful for reducing details,
+ such as when the source loses focus and you want to draw attention to other
+ elements. The level of detail can be modified using the setBlurRadius()
+ function.
+
+ By default, the blur radius is 5 pixels.
+
+ \img graphicseffect-blur.png
+
+ \sa QGraphicsDropShadowEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect,
+ QGraphicsColorizeEffect, QGraphicsOpacityEffect
+*/
+
+/*!
+ Constructs a new QGraphicsBlurEffect instance.
+ The \a parent parameter is passed to QGraphicsEffect's constructor.
+*/
+QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent)
+ : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent)
+{
+}
+
+/*!
+ Destroys the effect.
+*/
+QGraphicsBlurEffect::~QGraphicsBlurEffect()
+{
+}
+
+/*!
+ \property QGraphicsBlurEffect::blurRadius
+ \brief the blur radius of the effect.
+
+ Using a smaller radius results in a sharper appearance, whereas a bigger
+ radius results in a more blurred appearance.
+
+ By default, the blur radius is 5 pixels.
+*/
+int QGraphicsBlurEffect::blurRadius() const
+{
+ Q_D(const QGraphicsBlurEffect);
+ return d->filter->radius();
+}
+
+void QGraphicsBlurEffect::setBlurRadius(int radius)
+{
+ Q_D(QGraphicsBlurEffect);
+ if (d->filter->radius() == radius)
+ return;
+
+ d->filter->setRadius(radius);
+ updateBoundingRect();
+ emit blurRadiusChanged(radius);
+}
+
+/*!
+ \fn void QGraphicsBlurEffect::blurRadiusChanged(int radius)
+
+ This signal is emitted whenever the effect's blur radius changes.
+ The \a radius parameter holds the effect's new blur radius.
+*/
+
+/*!
+ \reimp
+*/
+QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const
+{
+ Q_D(const QGraphicsBlurEffect);
+ return d->filter->boundingRectFor(rect);
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
+{
+ Q_D(QGraphicsBlurEffect);
+ if (d->filter->radius() <= 0) {
+ source->draw(painter);
+ return;
+ }
+
+ QPoint offset;
+ if (source->isPixmap()) {
+ // No point in drawing in device coordinates (pixmap will be scaled anyways).
+ const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
+ d->filter->draw(painter, offset, pixmap);
+ return;
+ }
+
+ // Draw pixmap in device coordinates to avoid pixmap scaling.
+ const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
+ QTransform restoreTransform = painter->worldTransform();
+ painter->setWorldTransform(QTransform());
+ d->filter->draw(painter, offset, pixmap);
+ painter->setWorldTransform(restoreTransform);
+}
+
+/*!
+ \class QGraphicsDropShadowEffect
+ \brief The QGraphicsDropShadowEffect class provides a drop shadow effect.
+ \since 4.6
+
+ A drop shadow effect renders the source with a drop shadow. The color of
+ the drop shadow can be modified using the setColor() function. The drop
+ shadow offset can be modified using the setOffset() function and the blur
+ radius of the drop shadow can be changed with the setBlurRadius()
+ function.
+
+ By default, the drop shadow is a semi-transparent dark gray
+ (QColor(63, 63, 63, 180)) shadow, blurred with a radius of 1 at an offset
+ of 8 pixels towards the lower right.
+
+ \img graphicseffect-drop-shadow.png
+
+ \sa QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect,
+ QGraphicsColorizeEffect, QGraphicsOpacityEffect
+*/
+
+/*!
+ Constructs a new QGraphicsDropShadowEffect instance.
+ The \a parent parameter is passed to QGraphicsEffect's constructor.
+*/
+QGraphicsDropShadowEffect::QGraphicsDropShadowEffect(QObject *parent)
+ : QGraphicsEffect(*new QGraphicsDropShadowEffectPrivate, parent)
+{
+}
+
+/*!
+ Destroys the effect.
+*/
+QGraphicsDropShadowEffect::~QGraphicsDropShadowEffect()
+{
+}
+
+/*!
+ \property QGraphicsDropShadowEffect::offset
+ \brief the shadow offset in pixels.
+
+ By default, the offset is 8 pixels towards the lower right.
+
+ \sa blurRadius(), color()
+*/
+QPointF QGraphicsDropShadowEffect::offset() const
+{
+ Q_D(const QGraphicsDropShadowEffect);
+ return d->filter->offset();
+}
+
+void QGraphicsDropShadowEffect::setOffset(const QPointF &offset)
+{
+ Q_D(QGraphicsDropShadowEffect);
+ if (d->filter->offset() == offset)
+ return;
+
+ d->filter->setOffset(offset);
+ updateBoundingRect();
+ emit offsetChanged(offset);
+}
+
+/*!
+ \fn void QGraphicsDropShadowEffect::offsetChanged(const QPointF &offset)
+
+ This signal is emitted whenever the effect's shadow offset changes.
+ The \a offset parameter holds the effect's new shadow offset.
+*/
+
+/*!
+ \property QGraphicsDropShadowEffect::blurRadius
+ \brief the blur radius in pixels of the drop shadow.
+
+ Using a smaller radius results in a sharper shadow, whereas using a bigger
+ radius results in a more blurred shadow.
+
+ By default, the blur radius is 1 pixel.
+
+ \sa color(), offset().
+*/
+int QGraphicsDropShadowEffect::blurRadius() const
+{
+ Q_D(const QGraphicsDropShadowEffect);
+ return d->filter->blurRadius();
+}
+
+void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius)
+{
+ Q_D(QGraphicsDropShadowEffect);
+ if (d->filter->blurRadius() == blurRadius)
+ return;
+
+ d->filter->setBlurRadius(blurRadius);
+ updateBoundingRect();
+ emit blurRadiusChanged(blurRadius);
+}
+
+/*!
+ \fn void QGraphicsDropShadowEffect::blurRadiusChanged(int blurRadius)
+
+ This signal is emitted whenever the effect's blur radius changes.
+ The \a blurRadius parameter holds the effect's new blur radius.
+*/
+
+/*!
+ \property QGraphicsDropShadowEffect::color
+ \brief the color of the drop shadow.
+
+ By default, the drop color is a semi-transparent dark gray
+ (QColor(63, 63, 63, 180)).
+
+ \sa offset(), blurRadius()
+*/
+QColor QGraphicsDropShadowEffect::color() const
+{
+ Q_D(const QGraphicsDropShadowEffect);
+ return d->filter->color();
+}
+
+void QGraphicsDropShadowEffect::setColor(const QColor &color)
+{
+ Q_D(QGraphicsDropShadowEffect);
+ if (d->filter->color() == color)
+ return;
+
+ d->filter->setColor(color);
+ emit colorChanged(color);
+}
+
+/*!
+ \fn void QGraphicsDropShadowEffect::colorChanged(const QColor &color)
+
+ This signal is emitted whenever the effect's color changes.
+ The \a color parameter holds the effect's new color.
+*/
+
+/*!
+ \reimp
+*/
+QRectF QGraphicsDropShadowEffect::boundingRectFor(const QRectF &rect) const
+{
+ Q_D(const QGraphicsDropShadowEffect);
+ return d->filter->boundingRectFor(rect);
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
+{
+ Q_D(QGraphicsDropShadowEffect);
+ if (d->filter->blurRadius() <= 0 && d->filter->offset().isNull()) {
+ source->draw(painter);
+ return;
+ }
+
+ QPoint offset;
+ if (source->isPixmap()) {
+ // No point in drawing in device coordinates (pixmap will be scaled anyways).
+ const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
+ d->filter->draw(painter, offset, pixmap);
+ return;
+ }
+
+ // Draw pixmap in device coordinates to avoid pixmap scaling.
+ const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
+ QTransform restoreTransform = painter->worldTransform();
+ painter->setWorldTransform(QTransform());
+ d->filter->draw(painter, offset, pixmap);
+ painter->setWorldTransform(restoreTransform);
+}
+
+/*!
+ \class QGraphicsOpacityEffect
+ \brief The QGraphicsOpacityEffect class provides an opacity effect.
+ \since 4.6
+
+ An opacity effect renders the source with an opacity. This effect is useful
+ for making the source semi-transparent, similar to a fade-in/fade-out
+ sequence. The opacity can be modified using the setOpacity() function.
+
+ By default, the opacity is 0.7.
+
+ \img graphicseffect-opacity.png
+
+ \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect,
+ QGraphicsGrayscaleEffect, QGraphicsColorizeEffect
+*/
+
+/*!
+ Constructs a new QGraphicsOpacityEffect instance.
+ The \a parent parameter is passed to QGraphicsEffect's constructor.
+*/
+QGraphicsOpacityEffect::QGraphicsOpacityEffect(QObject *parent)
+ : QGraphicsEffect(*new QGraphicsOpacityEffectPrivate, parent)
+{
+}
+
+/*!
+ Destroys the effect.
+*/
+QGraphicsOpacityEffect::~QGraphicsOpacityEffect()
+{
+}
+
+/*!
+ \property QGraphicsOpacityEffect::opacity
+ \brief the opacity of the effect.
+
+ The value should be in the range of 0.0 to 1.0, where 0.0 is
+ fully transparent and 1.0 is fully opaque.
+
+ By default, the opacity is 0.7.
+
+ \sa setOpacityMask()
+*/
+qreal QGraphicsOpacityEffect::opacity() const
+{
+ Q_D(const QGraphicsOpacityEffect);
+ return d->opacity;
+}
+
+void QGraphicsOpacityEffect::setOpacity(qreal opacity)
+{
+ Q_D(QGraphicsOpacityEffect);
+ opacity = qBound(qreal(0.0), opacity, qreal(1.0));
+
+ if (qFuzzyCompare(d->opacity, opacity))
+ return;
+
+ d->opacity = opacity;
+ if ((d->isFullyTransparent = qFuzzyIsNull(d->opacity)))
+ d->isFullyOpaque = 0;
+ else
+ d->isFullyOpaque = qFuzzyIsNull(d->opacity - 1);
+ emit opacityChanged(opacity);
+}
+
+/*!
+ \fn void QGraphicsOpacityEffect::opacityChanged(qreal opacity)
+
+ This signal is emitted whenever the effect's opacity changes.
+ The \a opacity parameter holds the effect's new opacity.
+*/
+
+/*!
+ \property QGraphicsOpacityEffect::opacityMask
+ \brief the opacity mask of the effect.
+
+ An opacity mask allows you apply opacity to portions of an element.
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 2
+
+ There is no opacity mask by default.
+
+ \sa setOpacity()
+*/
+QBrush QGraphicsOpacityEffect::opacityMask() const
+{
+ Q_D(const QGraphicsOpacityEffect);
+ return d->opacityMask;
+}
+
+void QGraphicsOpacityEffect::setOpacityMask(const QBrush &mask)
+{
+ Q_D(QGraphicsOpacityEffect);
+ if (d->opacityMask == mask)
+ return;
+
+ d->opacityMask = mask;
+ d->hasOpacityMask = (mask.style() != Qt::NoBrush);
+
+ emit opacityMaskChanged(mask);
+}
+
+/*!
+ \fn void QGraphicsOpacityEffect::opacityMaskChanged(const QBrush &mask)
+
+ This signal is emitted whenever the effect's opacity mask changes.
+ The \a mask parameter holds the effect's new opacity mask.
+*/
+
+/*!
+ \reimp
+*/
+void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
+{
+ Q_D(QGraphicsOpacityEffect);
+
+ // Transparent; nothing to draw.
+ if (d->isFullyTransparent)
+ return;
+
+ // Opaque; draw directly without going through a pixmap.
+ if (d->isFullyOpaque && !d->hasOpacityMask) {
+ source->draw(painter);
+ return;
+ }
+
+ painter->save();
+ painter->setOpacity(d->opacity);
+
+ QPoint offset;
+ if (source->isPixmap()) {
+ // No point in drawing in device coordinates (pixmap will be scaled anyways).
+ if (!d->hasOpacityMask) {
+ const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
+ painter->drawPixmap(offset, pixmap);
+ } else {
+ QRectF srcBrect = source->boundingRect();
+ QPixmap pixmap(srcBrect.size().toSize());
+ pixmap.fill(Qt::transparent);
+
+ QPainter pixmapPainter(&pixmap);
+ pixmapPainter.setRenderHints(painter->renderHints());
+ pixmapPainter.translate(-srcBrect.topLeft());
+ source->draw(&pixmapPainter);
+ pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ pixmapPainter.fillRect(srcBrect, d->opacityMask);
+ pixmapPainter.end();
+
+ painter->drawPixmap(srcBrect.topLeft(), pixmap);
+ }
+ } else {
+ // Draw pixmap in device coordinates to avoid pixmap scaling;
+ if (!d->hasOpacityMask) {
+ const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
+ painter->setWorldTransform(QTransform());
+ painter->drawPixmap(offset, pixmap);
+ } else {
+ QTransform worldTransform = painter->worldTransform();
+
+ // Calculate source bounding rect in logical and device coordinates.
+ QRectF srcBrect = source->boundingRect();
+ QRect srcDeviceBrect = worldTransform.mapRect(srcBrect).toAlignedRect();
+ srcDeviceBrect &= source->deviceRect();
+
+ offset = srcDeviceBrect.topLeft();
+ worldTransform *= QTransform::fromTranslate(-srcDeviceBrect.x(), -srcDeviceBrect.y());
+
+ QPixmap pixmap(srcDeviceBrect.size());
+ pixmap.fill(Qt::transparent);
+
+ QPainter pixmapPainter(&pixmap);
+ pixmapPainter.setRenderHints(painter->renderHints());
+ pixmapPainter.setWorldTransform(worldTransform);
+ source->draw(&pixmapPainter);
+ pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ pixmapPainter.fillRect(srcBrect, d->opacityMask);
+ pixmapPainter.end();
+
+ painter->setWorldTransform(QTransform());
+ painter->drawPixmap(offset, pixmap);
+ }
+ }
+
+ painter->restore();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h
new file mode 100644
index 0000000..a53357b
--- /dev/null
+++ b/src/gui/effects/qgraphicseffect.h
@@ -0,0 +1,307 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSEFFECT_H
+#define QGRAPHICSEFFECT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qbrush.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGraphicsItem;
+class QStyleOption;
+class QPainter;
+class QPixmap;
+
+class QGraphicsEffectSourcePrivate;
+class Q_GUI_EXPORT QGraphicsEffectSource : public QObject
+{
+ Q_OBJECT
+public:
+ ~QGraphicsEffectSource();
+ const QGraphicsItem *graphicsItem() const;
+ const QWidget *widget() const;
+ const QStyleOption *styleOption() const;
+
+ bool isPixmap() const;
+ void draw(QPainter *painter);
+ void update();
+
+ QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const;
+ QRect deviceRect() const;
+ QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const;
+
+protected:
+ QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsEffectSource)
+ Q_DISABLE_COPY(QGraphicsEffectSource)
+ friend class QGraphicsEffect;
+ friend class QGraphicsEffectPrivate;
+ friend class QGraphicsScenePrivate;
+ friend class QGraphicsItem;
+ friend class QWidget;
+ friend class QWidgetPrivate;
+};
+
+class QGraphicsEffectPrivate;
+class Q_GUI_EXPORT QGraphicsEffect : public QObject
+{
+ Q_OBJECT
+ Q_FLAGS(ChangeFlags)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+public:
+ enum ChangeFlag {
+ SourceAttached = 0x1,
+ SourceDetached = 0x2,
+ SourceBoundingRectChanged = 0x4,
+ SourceInvalidated = 0x8
+ };
+ Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag)
+
+ QGraphicsEffect(QObject *parent = 0);
+ virtual ~QGraphicsEffect();
+
+ virtual QRectF boundingRectFor(const QRectF &rect) const;
+ QRectF boundingRect() const;
+
+ QGraphicsEffectSource *source() const;
+
+ bool isEnabled() const;
+
+public Q_SLOTS:
+ void setEnabled(bool enable);
+ // ### add update() slot
+
+Q_SIGNALS:
+ void enabledChanged(bool enabled);
+
+protected:
+ QGraphicsEffect(QGraphicsEffectPrivate &d, QObject *parent = 0);
+ virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0;
+ virtual void sourceChanged(ChangeFlags flags);
+ void updateBoundingRect();
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsEffect)
+ Q_DISABLE_COPY(QGraphicsEffect)
+ friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
+ friend class QGraphicsScenePrivate;
+ friend class QWidget;
+ friend class QWidgetPrivate;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsEffect::ChangeFlags)
+
+class QGraphicsGrayscaleEffectPrivate;
+class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect
+{
+ Q_OBJECT
+public:
+ QGraphicsGrayscaleEffect(QObject *parent = 0);
+ ~QGraphicsGrayscaleEffect();
+
+protected:
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect)
+ Q_DISABLE_COPY(QGraphicsGrayscaleEffect)
+};
+
+class QGraphicsColorizeEffectPrivate;
+class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+public:
+ QGraphicsColorizeEffect(QObject *parent = 0);
+ ~QGraphicsColorizeEffect();
+
+ QColor color() const;
+
+public Q_SLOTS:
+ void setColor(const QColor &c);
+
+Q_SIGNALS:
+ void colorChanged(const QColor &color);
+
+protected:
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsColorizeEffect)
+ Q_DISABLE_COPY(QGraphicsColorizeEffect)
+};
+
+class QGraphicsPixelizeEffectPrivate;
+class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect
+{
+ Q_OBJECT
+ Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize NOTIFY pixelSizeChanged)
+public:
+ QGraphicsPixelizeEffect(QObject *parent = 0);
+ ~QGraphicsPixelizeEffect();
+
+ int pixelSize() const;
+
+public Q_SLOTS:
+ void setPixelSize(int pixelSize);
+
+Q_SIGNALS:
+ void pixelSizeChanged(int pixelSize);
+
+protected:
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect)
+ Q_DISABLE_COPY(QGraphicsPixelizeEffect)
+};
+
+class QGraphicsBlurEffectPrivate;
+class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect
+{
+ Q_OBJECT
+ Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged)
+public:
+ QGraphicsBlurEffect(QObject *parent = 0);
+ ~QGraphicsBlurEffect();
+
+ QRectF boundingRectFor(const QRectF &rect) const;
+ int blurRadius() const;
+
+public Q_SLOTS:
+ void setBlurRadius(int blurRadius);
+
+Q_SIGNALS:
+ void blurRadiusChanged(int blurRadius);
+
+protected:
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsBlurEffect)
+ Q_DISABLE_COPY(QGraphicsBlurEffect)
+};
+
+class QGraphicsDropShadowEffectPrivate;
+class Q_GUI_EXPORT QGraphicsDropShadowEffect: public QGraphicsEffect
+{
+ Q_OBJECT
+ Q_PROPERTY(QPointF offset READ offset WRITE setOffset NOTIFY offsetChanged)
+ Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+public:
+ QGraphicsDropShadowEffect(QObject *parent = 0);
+ ~QGraphicsDropShadowEffect();
+
+ QRectF boundingRectFor(const QRectF &rect) const;
+ QPointF offset() const;
+ int blurRadius() const;
+ QColor color() const;
+
+public Q_SLOTS:
+ void setOffset(const QPointF &ofs);
+ inline void setOffset(qreal dx, qreal dy)
+ { setOffset(QPointF(dx, dy)); }
+ inline void setOffset(qreal d)
+ { setOffset(QPointF(d, d)); }
+ void setBlurRadius(int blurRadius);
+ void setColor(const QColor &color);
+
+Q_SIGNALS:
+ void offsetChanged(const QPointF &offset);
+ void blurRadiusChanged(int blurRadius);
+ void colorChanged(const QColor &color);
+
+protected:
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsDropShadowEffect)
+ Q_DISABLE_COPY(QGraphicsDropShadowEffect)
+};
+
+class QGraphicsOpacityEffectPrivate;
+class Q_GUI_EXPORT QGraphicsOpacityEffect: public QGraphicsEffect
+{
+ Q_OBJECT
+ Q_PROPERTY(int opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
+ Q_PROPERTY(QBrush opacityMask READ opacityMask WRITE setOpacityMask NOTIFY opacityMaskChanged)
+public:
+ QGraphicsOpacityEffect(QObject *parent = 0);
+ ~QGraphicsOpacityEffect();
+
+ qreal opacity() const;
+ QBrush opacityMask() const;
+
+public Q_SLOTS:
+ void setOpacity(qreal opacity);
+ void setOpacityMask(const QBrush &mask);
+
+Q_SIGNALS:
+ void opacityChanged(qreal opacity);
+ void opacityMaskChanged(const QBrush &mask);
+
+protected:
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsOpacityEffect)
+ Q_DISABLE_COPY(QGraphicsOpacityEffect)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGRAPHICSEFFECT_H
+
diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h
new file mode 100644
index 0000000..c902b67
--- /dev/null
+++ b/src/gui/effects/qgraphicseffect_p.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSEFFECT_P_H
+#define QGRAPHICSEFFECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qgraphicseffect.h"
+
+#include <private/qobject_p.h>
+#include <private/qpixmapfilter_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsEffectSourcePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsEffectSource)
+public:
+ QGraphicsEffectSourcePrivate() : QObjectPrivate() {}
+ virtual ~QGraphicsEffectSourcePrivate() {}
+ virtual void detach() = 0;
+ virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0;
+ virtual QRect deviceRect() const = 0;
+ virtual const QGraphicsItem *graphicsItem() const = 0;
+ virtual const QWidget *widget() const = 0;
+ virtual const QStyleOption *styleOption() const = 0;
+ virtual void draw(QPainter *p) = 0;
+ virtual void update() = 0;
+ virtual bool isPixmap() const = 0;
+ virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0) const = 0;
+ friend class QGraphicsScenePrivate;
+ friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
+};
+
+class Q_GUI_EXPORT QGraphicsEffectPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsEffect)
+public:
+ QGraphicsEffectPrivate() : source(0), isEnabled(1) {}
+
+ inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource)
+ {
+ QGraphicsEffect::ChangeFlags flags;
+ if (source) {
+ flags |= QGraphicsEffect::SourceDetached;
+ source->d_func()->detach();
+ delete source;
+ }
+ source = newSource;
+ if (newSource)
+ flags |= QGraphicsEffect::SourceAttached;
+ q_func()->sourceChanged(flags);
+ }
+
+ QGraphicsEffectSource *source;
+ QRectF boundingRect;
+ quint32 isEnabled : 1;
+ quint32 padding : 31; // feel free to use
+};
+
+class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect)
+public:
+ QGraphicsGrayscaleEffectPrivate()
+ {
+ filter = new QPixmapColorizeFilter;
+ filter->setColor(Qt::black);
+ }
+ ~QGraphicsGrayscaleEffectPrivate() { delete filter; }
+
+ QPixmapColorizeFilter *filter;
+};
+
+class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsColorizeEffect)
+public:
+ QGraphicsColorizeEffectPrivate() { filter = new QPixmapColorizeFilter; }
+ ~QGraphicsColorizeEffectPrivate() { delete filter; }
+
+ QPixmapColorizeFilter *filter;
+};
+
+class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsPixelizeEffect)
+public:
+ QGraphicsPixelizeEffectPrivate() : pixelSize(3) {}
+
+ int pixelSize;
+};
+
+class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsBlurEffect)
+public:
+ QGraphicsBlurEffectPrivate() : filter(new QPixmapBlurFilter) {}
+ ~QGraphicsBlurEffectPrivate() { delete filter; }
+
+ QPixmapBlurFilter *filter;
+};
+
+class QGraphicsDropShadowEffectPrivate : public QGraphicsEffectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsDropShadowEffect)
+public:
+ QGraphicsDropShadowEffectPrivate() : filter(new QPixmapDropShadowFilter) {}
+ ~QGraphicsDropShadowEffectPrivate() { delete filter; }
+
+ QPixmapDropShadowFilter *filter;
+};
+
+class QGraphicsOpacityEffectPrivate : public QGraphicsEffectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsOpacityEffect)
+public:
+ QGraphicsOpacityEffectPrivate()
+ : opacity(qreal(0.7)), isFullyTransparent(0), isFullyOpaque(0), hasOpacityMask(0) {}
+ ~QGraphicsOpacityEffectPrivate() {}
+
+ qreal opacity;
+ QBrush opacityMask;
+ uint isFullyTransparent : 1;
+ uint isFullyOpaque : 1;
+ uint hasOpacityMask : 1;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGRAPHICSEFFECT_P_H
+
diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri
new file mode 100644
index 0000000..75a3d91
--- /dev/null
+++ b/src/gui/egl/egl.pri
@@ -0,0 +1,28 @@
+HEADERS += \
+ egl/qegl_p.h \
+ egl/qeglproperties_p.h
+
+SOURCES += \
+ egl/qegl.cpp \
+ egl/qeglproperties.cpp
+
+contains(QT_CONFIG, wince*): SOURCES += egl/qegl_wince.cpp
+
+unix {
+ embedded {
+ SOURCES += egl/qegl_qws.cpp
+ } else {
+ symbian {
+ SOURCES += egl/qegl_symbian.cpp
+ } else {
+ SOURCES += egl/qegl_x11.cpp
+ }
+ }
+}
+
+for(p, QMAKE_LIBDIR_EGL) {
+ exists($$p):LIBS += -L$$p
+}
+
+!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL
+!isEmpty(QMAKE_LIBS_EGL): LIBS_PRIVATE += $$QMAKE_LIBS_EGL
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
new file mode 100644
index 0000000..f0df0c9
--- /dev/null
+++ b/src/gui/egl/qegl.cpp
@@ -0,0 +1,414 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qwidget.h>
+#include <QtCore/qdebug.h>
+#include "qegl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QEglContext::QEglContext()
+ : apiType(QEgl::OpenGL)
+ , dpy(EGL_NO_DISPLAY)
+ , ctx(EGL_NO_CONTEXT)
+ , surf(EGL_NO_SURFACE)
+ , cfg(0)
+ , share(false)
+ , current(false)
+ , reserved(0)
+{
+}
+
+QEglContext::~QEglContext()
+{
+ destroy();
+}
+
+bool QEglContext::isValid() const
+{
+ return (ctx != EGL_NO_CONTEXT);
+}
+
+bool QEglContext::isSharing() const
+{
+ return share;
+}
+
+bool QEglContext::isCurrent() const
+{
+ return current;
+}
+
+// Open the EGL display associated with "device".
+bool QEglContext::openDisplay(QPaintDevice *device)
+{
+ if (dpy == EGL_NO_DISPLAY)
+ dpy = defaultDisplay(device);
+ return (dpy != EGL_NO_DISPLAY);
+}
+
+// Choose a configuration that matches "properties".
+bool QEglContext::chooseConfig
+ (const QEglProperties& properties, QEgl::PixelFormatMatch match)
+{
+ QEglProperties props(properties);
+ do {
+ // Get the number of matching configurations for this set of properties.
+ EGLint matching = 0;
+ if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching)
+ continue;
+
+ // If we want the best pixel format, then return the first
+ // matching configuration.
+ if (match == QEgl::BestPixelFormat) {
+ eglChooseConfig(dpy, props.properties(), &cfg, 1, &matching);
+ if (matching < 1)
+ continue;
+ return true;
+ }
+
+ // Fetch all of the matching configurations and find the
+ // first that matches the pixel format we wanted.
+ EGLint size = matching;
+ EGLConfig *configs = new EGLConfig [size];
+ eglChooseConfig(dpy, props.properties(), configs, size, &matching);
+ for (EGLint index = 0; index < size; ++index) {
+ EGLint red, green, blue, alpha;
+ eglGetConfigAttrib(dpy, configs[index], EGL_RED_SIZE, &red);
+ eglGetConfigAttrib(dpy, configs[index], EGL_GREEN_SIZE, &green);
+ eglGetConfigAttrib(dpy, configs[index], EGL_BLUE_SIZE, &blue);
+ eglGetConfigAttrib(dpy, configs[index], EGL_ALPHA_SIZE, &alpha);
+ if (red == props.value(EGL_RED_SIZE) &&
+ green == props.value(EGL_GREEN_SIZE) &&
+ blue == props.value(EGL_BLUE_SIZE) &&
+ (props.value(EGL_ALPHA_SIZE) == 0 ||
+ alpha == props.value(EGL_ALPHA_SIZE))) {
+ cfg = configs[index];
+ delete [] configs;
+ return true;
+ }
+ }
+ delete [] configs;
+ } while (props.reduceConfiguration());
+
+#ifdef EGL_BIND_TO_TEXTURE_RGBA
+ // Don't report an error just yet if we failed to get a pbuffer
+ // configuration with texture rendering. Only report failure if
+ // we cannot get any pbuffer configurations at all.
+ if (props.value(EGL_BIND_TO_TEXTURE_RGBA) == EGL_DONT_CARE &&
+ props.value(EGL_BIND_TO_TEXTURE_RGB) == EGL_DONT_CARE)
+#endif
+ {
+ qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
+ qWarning() << "Requested:" << props.toString();
+ qWarning() << "Available:";
+ dumpAllConfigs();
+ }
+ return false;
+}
+
+// Create the EGLContext.
+bool QEglContext::createContext(QEglContext *shareContext)
+{
+ // We need to select the correct API before calling eglCreateContext().
+#ifdef EGL_OPENGL_ES_API
+ if (apiType == QEgl::OpenGL)
+ eglBindAPI(EGL_OPENGL_ES_API);
+#endif
+#ifdef EGL_OPENVG_API
+ if (apiType == QEgl::OpenVG)
+ eglBindAPI(EGL_OPENVG_API);
+#endif
+
+ // Create a new context for the configuration.
+ QEglProperties contextProps;
+#if defined(QT_OPENGL_ES_2)
+ if (apiType == QEgl::OpenGL)
+ contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
+#endif
+ if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
+ shareContext = 0;
+ if (shareContext) {
+ ctx = eglCreateContext(dpy, cfg, shareContext->ctx, contextProps.properties());
+ if (ctx == EGL_NO_CONTEXT) {
+ qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
+ shareContext = 0;
+ }
+ }
+ if (ctx == EGL_NO_CONTEXT) {
+ ctx = eglCreateContext(dpy, cfg, 0, contextProps.properties());
+ if (ctx == EGL_NO_CONTEXT) {
+ qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
+ return false;
+ }
+ }
+ share = (shareContext != 0);
+ return true;
+}
+
+// Recreate the surface for a paint device because the native id has changed.
+bool QEglContext::recreateSurface(QPaintDevice *device)
+{
+ // Bail out if the surface has not been created for the first time yet.
+ if (surf == EGL_NO_SURFACE)
+ return true;
+
+ // Destroy the old surface.
+ eglDestroySurface(dpy, surf);
+ surf = EGL_NO_SURFACE;
+
+ // Create a new one.
+ return createSurface(device);
+}
+
+// Destroy the EGL surface object.
+void QEglContext::destroySurface()
+{
+ if (surf != EGL_NO_SURFACE) {
+ eglDestroySurface(dpy, surf);
+ surf = EGL_NO_SURFACE;
+ }
+}
+
+// Destroy the context. Note: this does not destroy the surface.
+void QEglContext::destroy()
+{
+ if (ctx != EGL_NO_CONTEXT)
+ eglDestroyContext(dpy, ctx);
+ dpy = EGL_NO_DISPLAY;
+ ctx = EGL_NO_CONTEXT;
+ surf = EGL_NO_SURFACE;
+ cfg = 0;
+ share = false;
+}
+
+bool QEglContext::makeCurrent()
+{
+ if (ctx == EGL_NO_CONTEXT) {
+ qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current";
+ return false;
+ }
+
+ current = true;
+
+ bool ok = eglMakeCurrent(dpy, surf, surf, ctx);
+ if (!ok)
+ qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError());
+ return ok;
+}
+
+bool QEglContext::doneCurrent()
+{
+ // If the context is invalid, we assume that an error was reported
+ // when makeCurrent() was called.
+ if (ctx == EGL_NO_CONTEXT)
+ return false;
+
+ current = false;
+
+ // We need to select the correct API before calling eglMakeCurrent()
+ // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG
+ // contexts active at the same time.
+#ifdef EGL_OPENGL_ES_API
+ if (apiType == QEgl::OpenGL)
+ eglBindAPI(EGL_OPENGL_ES_API);
+#endif
+#ifdef EGL_OPENVG_API
+ if (apiType == QEgl::OpenVG)
+ eglBindAPI(EGL_OPENVG_API);
+#endif
+
+ bool ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (!ok)
+ qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError());
+ return ok;
+}
+
+bool QEglContext::swapBuffers()
+{
+ if(ctx == EGL_NO_CONTEXT)
+ return false;
+
+ bool ok = eglSwapBuffers(dpy, surf);
+ if (!ok)
+ qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError());
+ return ok;
+}
+
+// Wait for native rendering operations to complete before starting
+// to use OpenGL/OpenVG operations.
+void QEglContext::waitNative()
+{
+#ifdef EGL_CORE_NATIVE_ENGINE
+ eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+#endif
+}
+
+// Wait for client OpenGL/OpenVG operations to complete before
+// using native rendering operations.
+void QEglContext::waitClient()
+{
+#ifdef EGL_OPENGL_ES_API
+ if (apiType == QEgl::OpenGL) {
+ eglBindAPI(EGL_OPENGL_ES_API);
+ eglWaitClient();
+ }
+#else
+ if (apiType == QEgl::OpenGL)
+ eglWaitGL();
+#endif
+#ifdef EGL_OPENVG_API
+ if (apiType == QEgl::OpenVG) {
+ eglBindAPI(EGL_OPENVG_API);
+ eglWaitClient();
+ }
+#endif
+}
+
+// Query the actual size of the EGL surface.
+QSize QEglContext::surfaceSize() const
+{
+ int w, h;
+ eglQuerySurface(dpy, surf, EGL_WIDTH, &w);
+ eglQuerySurface(dpy, surf, EGL_HEIGHT, &h);
+ return QSize(w, h);
+}
+
+// Query the value of a configuration attribute.
+bool QEglContext::configAttrib(int name, EGLint *value) const
+{
+ return eglGetConfigAttrib(dpy, cfg, name, value);
+}
+
+// Retrieve all of the properties on "cfg". If zero, return
+// the context's configuration.
+QEglProperties QEglContext::configProperties(EGLConfig cfg) const
+{
+ if (!cfg)
+ cfg = config();
+ QEglProperties props;
+ for (int name = 0x3020; name <= 0x304F; ++name) {
+ EGLint value;
+ if (name != EGL_NONE && eglGetConfigAttrib(dpy, cfg, name, &value))
+ props.setValue(name, value);
+ }
+ eglGetError(); // Clear the error state.
+ return props;
+}
+
+// Initialize and return the default display.
+EGLDisplay QEglContext::defaultDisplay(QPaintDevice *device)
+{
+ static EGLDisplay dpy = EGL_NO_DISPLAY;
+ if (dpy == EGL_NO_DISPLAY) {
+ dpy = getDisplay(device);
+ if (dpy == EGL_NO_DISPLAY) {
+ qWarning() << "QEglContext::defaultDisplay(): Cannot open EGL display";
+ return EGL_NO_DISPLAY;
+ }
+ if (!eglInitialize(dpy, NULL, NULL)) {
+ qWarning() << "QEglContext::defaultDisplay(): Cannot initialize EGL display:" << errorString(eglGetError());
+ return EGL_NO_DISPLAY;
+ }
+#ifdef EGL_OPENGL_ES_API
+ eglBindAPI(EGL_OPENGL_ES_API);
+#endif
+ }
+ return dpy;
+}
+
+// Return the error string associated with a specific code.
+QString QEglContext::errorString(EGLint code)
+{
+ static const char * const errors[] = {
+ "Success (0x3000)", // No tr
+ "Not initialized (0x3001)", // No tr
+ "Bad access (0x3002)", // No tr
+ "Bad alloc (0x3003)", // No tr
+ "Bad attribute (0x3004)", // No tr
+ "Bad config (0x3005)", // No tr
+ "Bad context (0x3006)", // No tr
+ "Bad current surface (0x3007)", // No tr
+ "Bad display (0x3008)", // No tr
+ "Bad match (0x3009)", // No tr
+ "Bad native pixmap (0x300A)", // No tr
+ "Bad native window (0x300B)", // No tr
+ "Bad parameter (0x300C)", // No tr
+ "Bad surface (0x300D)", // No tr
+ "Context lost (0x300E)" // No tr
+ };
+ if (code >= 0x3000 && code <= 0x300E) {
+ return QString::fromLatin1(errors[code - 0x3000]);
+ } else {
+ return QLatin1String("0x") + QString::number(int(code), 16);
+ }
+}
+
+// Dump all of the EGL configurations supported by the system.
+void QEglContext::dumpAllConfigs()
+{
+ QEglProperties props;
+ EGLint count = 0;
+ if (!eglGetConfigs(dpy, 0, 0, &count) || count < 1)
+ return;
+ EGLConfig *configs = new EGLConfig [count];
+ eglGetConfigs(dpy, configs, count, &count);
+ for (EGLint index = 0; index < count; ++index) {
+ props = configProperties(configs[index]);
+ qWarning() << props.toString();
+ }
+ delete [] configs;
+}
+
+QString QEglContext::extensions()
+{
+ const char* exts = eglQueryString(QEglContext::defaultDisplay(0), EGL_EXTENSIONS);
+ return QString(QLatin1String(exts));
+}
+
+bool QEglContext::hasExtension(const char* extensionName)
+{
+ return extensions().contains(QLatin1String(extensionName));
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h
new file mode 100644
index 0000000..7d9e4e9
--- /dev/null
+++ b/src/gui/egl/qegl_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGL_P_H
+#define QEGL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience of
+// the QtOpenGL and QtOpenVG modules. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qsize.h>
+#include <QtGui/qimage.h>
+
+#include <private/qeglproperties_p.h>
+
+QT_BEGIN_INCLUDE_NAMESPACE
+
+#if !defined(EGL_VERSION_1_3) && !defined(QEGL_NATIVE_TYPES_DEFINED)
+#undef EGLNativeWindowType
+#undef EGLNativePixmapType
+#undef EGLNativeDisplayType
+typedef NativeWindowType EGLNativeWindowType;
+typedef NativePixmapType EGLNativePixmapType;
+typedef NativeDisplayType EGLNativeDisplayType;
+#define QEGL_NATIVE_TYPES_DEFINED 1
+#endif
+QT_END_INCLUDE_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QEglContext
+{
+public:
+ QEglContext();
+ ~QEglContext();
+
+ bool isValid() const;
+ bool isSharing() const;
+ bool isCurrent() const;
+
+ QEgl::API api() const { return apiType; }
+ void setApi(QEgl::API api) { apiType = api; }
+
+ bool openDisplay(QPaintDevice *device);
+ bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
+ bool createContext(QEglContext *shareContext = 0);
+ bool createSurface(QPaintDevice *device, const QEglProperties *properties = 0);
+ bool recreateSurface(QPaintDevice *device);
+ void destroySurface();
+
+ void destroy();
+
+ bool makeCurrent();
+ bool doneCurrent();
+ bool swapBuffers();
+
+ void waitNative();
+ void waitClient();
+
+ QSize surfaceSize() const;
+
+ bool configAttrib(int name, EGLint *value) const;
+
+ static void clearError() { eglGetError(); }
+ static EGLint error() { return eglGetError(); }
+ static QString errorString(EGLint code);
+
+ EGLDisplay display() const { return dpy; }
+ EGLContext context() const { return ctx; }
+ EGLSurface surface() const { return surf; }
+ void setSurface(EGLSurface surface) { surf = surface; }
+ EGLConfig config() const { return cfg; }
+
+ QEglProperties configProperties(EGLConfig cfg = 0) const;
+
+ static EGLDisplay defaultDisplay(QPaintDevice *device);
+
+ void dumpAllConfigs();
+
+ static QString extensions();
+ static bool hasExtension(const char* extensionName);
+
+private:
+ QEgl::API apiType;
+ EGLDisplay dpy;
+ EGLContext ctx;
+ EGLSurface surf;
+ EGLConfig cfg;
+ bool share;
+ bool current;
+ void *reserved; // For extension data in future versions.
+
+ static EGLDisplay getDisplay(QPaintDevice *device);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGL_P_H
diff --git a/src/gui/egl/qegl_qws.cpp b/src/gui/egl/qegl_qws.cpp
new file mode 100644
index 0000000..32cf9f6
--- /dev/null
+++ b/src/gui/egl/qegl_qws.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qwidget.h>
+#include "qegl_p.h"
+
+#if !defined(QT_NO_EGL)
+
+#include <qscreen_qws.h>
+#include <qscreenproxy_qws.h>
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+// Create the surface for a QPixmap, QImage, or QWidget.
+// We don't have QGLScreen to create EGL surfaces for us,
+// so surface creation needs to be done in QtOpenGL or
+// QtOpenVG for Qt/Embedded.
+bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
+{
+ Q_UNUSED(device);
+ Q_UNUSED(properties);
+ return false;
+}
+
+EGLDisplay QEglContext::getDisplay(QPaintDevice *device)
+{
+ Q_UNUSED(device);
+ return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
+}
+
+static QScreen *screenForDevice(QPaintDevice *device)
+{
+ QScreen *screen = qt_screen;
+ if (!screen)
+ return 0;
+ if (screen->classId() == QScreen::MultiClass) {
+ int screenNumber;
+ if (device && device->devType() == QInternal::Widget)
+ screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device));
+ else
+ screenNumber = 0;
+ screen = screen->subScreens()[screenNumber];
+ }
+ while (screen->classId() == QScreen::ProxyClass) {
+ screen = static_cast<QProxyScreen *>(screen)->screen();
+ }
+ return screen;
+}
+
+// Set pixel format and other properties based on a paint device.
+void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
+{
+ if (!dev)
+ return;
+
+ // Find the QGLScreen for this paint device.
+ QScreen *screen = screenForDevice(dev);
+ if (!screen)
+ return;
+ int devType = dev->devType();
+ if (devType == QInternal::Image)
+ setPixelFormat(static_cast<QImage *>(dev)->format());
+ else
+ setPixelFormat(screen->pixelFormat());
+}
+
+QT_END_NAMESPACE
+
+#endif // !QT_NO_EGL
diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp
new file mode 100644
index 0000000..a143be7
--- /dev/null
+++ b/src/gui/egl/qegl_symbian.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qwidget.h>
+#include "qegl_p.h"
+
+#include <coecntrl.h>
+
+QT_BEGIN_NAMESPACE
+
+bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
+{
+ // Create the native drawable for the paint device.
+ int devType = device->devType();
+ EGLNativePixmapType pixmapDrawable = 0;
+ EGLNativeWindowType windowDrawable = 0;
+ bool ok;
+ if (devType == QInternal::Pixmap) {
+ pixmapDrawable = 0;
+ ok = (pixmapDrawable != 0);
+ } else if (devType == QInternal::Widget) {
+ QWidget *w = static_cast<QWidget *>(device);
+ windowDrawable = (EGLNativeWindowType)(w->winId()->DrawableWindow());
+ ok = (windowDrawable != 0);
+ } else {
+ ok = false;
+ }
+ if (!ok) {
+ qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
+ return false;
+ }
+
+ // Create the EGL surface to draw into, based on the native drawable.
+ const int *props;
+ if (properties)
+ props = properties->properties();
+ else
+ props = 0;
+ if (devType == QInternal::Widget)
+ surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0);
+ else
+ surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, 0);
+ if (surf == EGL_NO_SURFACE) {
+ qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
+ return false;
+ }
+ return true;
+}
+
+EGLDisplay QEglContext::getDisplay(QPaintDevice *device)
+{
+ EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (dpy == EGL_NO_DISPLAY)
+ qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY");
+ return dpy;
+}
+
+// Set pixel format and other properties based on a paint device.
+void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
+{
+ int devType = dev->devType();
+ if (devType == QInternal::Image)
+ setPixelFormat(static_cast<QImage *>(dev)->format());
+ else
+ setPixelFormat(QImage::Format_RGB32);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/egl/qegl_wince.cpp b/src/gui/egl/qegl_wince.cpp
new file mode 100644
index 0000000..2f4aed6
--- /dev/null
+++ b/src/gui/egl/qegl_wince.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qwidget.h>
+#include "qegl_p.h"
+
+#include <windows.h>
+
+
+QT_BEGIN_NAMESPACE
+
+bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
+{
+ // Create the native drawable for the paint device.
+ int devType = device->devType();
+ EGLNativePixmapType pixmapDrawable = 0;
+ EGLNativeWindowType windowDrawable = 0;
+ bool ok;
+ if (devType == QInternal::Pixmap) {
+ pixmapDrawable = 0;
+ ok = (pixmapDrawable != 0);
+ } else if (devType == QInternal::Widget) {
+ windowDrawable = (EGLNativeWindowType)(static_cast<QWidget *>(device))->winId();
+ ok = (windowDrawable != 0);
+ } else {
+ ok = false;
+ }
+ if (!ok) {
+ qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
+ return false;
+ }
+
+ // Create the EGL surface to draw into, based on the native drawable.
+ const int *props;
+ if (properties)
+ props = properties->properties();
+ else
+ props = 0;
+ if (devType == QInternal::Widget)
+ surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props);
+ else
+ surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props);
+ if (surf == EGL_NO_SURFACE) {
+ qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
+ return false;
+ }
+ return true;
+}
+
+EGLDisplay QEglContext::getDisplay(QPaintDevice *device)
+{
+ EGLDisplay dpy = 0;
+ HWND win = (static_cast<QWidget*>(device))->winId();
+ HDC myDc = GetDC(win);
+ if (!myDc) {
+ qWarning("QEglContext::defaultDisplay(): WinCE display is not open");
+ }
+ dpy = eglGetDisplay(EGLNativeDisplayType(myDc));
+ if (dpy == EGL_NO_DISPLAY) {
+ qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY");
+ dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ }
+ return dpy;
+}
+
+// Set pixel format and other properties based on a paint device.
+void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
+{
+ int devType = dev->devType();
+ if (devType == QInternal::Image)
+ setPixelFormat(static_cast<QImage *>(dev)->format());
+ else
+ setPixelFormat(QImage::Format_RGB16); // XXX
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp
new file mode 100644
index 0000000..2b6b92a
--- /dev/null
+++ b/src/gui/egl/qegl_x11.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qdebug.h>
+
+#include <private/qt_x11_p.h>
+#include <QtGui/qx11info_x11.h>
+#include <private/qpixmapdata_p.h>
+#include <private/qpixmap_x11_p.h>
+
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qwidget.h>
+#include "qegl_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
+{
+ // Create the native drawable for the paint device.
+ int devType = device->devType();
+ EGLNativePixmapType pixmapDrawable = 0;
+ EGLNativeWindowType windowDrawable = 0;
+ bool ok;
+ if (devType == QInternal::Pixmap) {
+ pixmapDrawable = (EGLNativePixmapType)(static_cast<QPixmap *>(device))->handle();
+ ok = (pixmapDrawable != 0);
+ } else if (devType == QInternal::Widget) {
+ windowDrawable = (EGLNativeWindowType)(static_cast<QWidget *>(device))->winId();
+ ok = (windowDrawable != 0);
+ } else {
+ ok = false;
+ }
+ if (!ok) {
+ qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
+ return false;
+ }
+
+ // Create the EGL surface to draw into, based on the native drawable.
+ const int *props;
+ if (properties)
+ props = properties->properties();
+ else
+ props = 0;
+ if (devType == QInternal::Widget)
+ surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props);
+ else
+ surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props);
+ if (surf == EGL_NO_SURFACE) {
+ qWarning() << "QEglContext::createSurface(): Unable to create EGL surface:"
+ << errorString(eglGetError());
+ return false;
+ }
+ return true;
+}
+
+EGLDisplay QEglContext::getDisplay(QPaintDevice *device)
+{
+ Q_UNUSED(device);
+ Display *xdpy = QX11Info::display();
+ if (!xdpy) {
+ qWarning("QEglContext::getDisplay(): X11 display is not open");
+ return EGL_NO_DISPLAY;
+ }
+ return eglGetDisplay(EGLNativeDisplayType(xdpy));
+}
+
+static int countBits(unsigned long mask)
+{
+ int count = 0;
+ while (mask != 0) {
+ if (mask & 1)
+ ++count;
+ mask >>= 1;
+ }
+ return count;
+}
+
+// Set the pixel format parameters from the visual in "xinfo".
+void QEglProperties::setVisualFormat(const QX11Info *xinfo)
+{
+ if (!xinfo)
+ return;
+ Visual *visual = (Visual*)xinfo->visual();
+ if (!visual)
+ return;
+ if (visual->c_class != TrueColor && visual->c_class != DirectColor)
+ return;
+ setValue(EGL_RED_SIZE, countBits(visual->red_mask));
+ setValue(EGL_GREEN_SIZE, countBits(visual->green_mask));
+ setValue(EGL_BLUE_SIZE, countBits(visual->blue_mask));
+
+ EGLint alphaBits = 0;
+#if !defined(QT_NO_XRENDER)
+ XRenderPictFormat *format;
+ format = XRenderFindVisualFormat(xinfo->display(), visual);
+ if (format && (format->type == PictTypeDirect) && format->direct.alphaMask) {
+ alphaBits = countBits(format->direct.alphaMask);
+ qDebug("QEglProperties::setVisualFormat() - visual's alphaMask is %d", alphaBits);
+ }
+#endif
+ setValue(EGL_ALPHA_SIZE, alphaBits);
+}
+
+extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
+
+// Set pixel format and other properties based on a paint device.
+void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
+{
+ if (!dev)
+ return;
+ if (dev->devType() == QInternal::Image)
+ setPixelFormat(static_cast<QImage *>(dev)->format());
+ else
+ setVisualFormat(qt_x11Info(dev));
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp
new file mode 100644
index 0000000..a96b26b
--- /dev/null
+++ b/src/gui/egl/qeglproperties.cpp
@@ -0,0 +1,533 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglproperties_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+
+#include "qegl_p.h"
+
+
+// Initialize a property block.
+QEglProperties::QEglProperties()
+{
+ props.append(EGL_NONE);
+}
+
+QEglProperties::QEglProperties(EGLConfig cfg)
+{
+ props.append(EGL_NONE);
+ for (int name = 0x3020; name <= 0x304F; ++name) {
+ EGLint value;
+ if (name != EGL_NONE && eglGetConfigAttrib(QEglContext::defaultDisplay(0), cfg, name, &value))
+ setValue(name, value);
+ }
+ eglGetError(); // Clear the error state.
+}
+
+// Fetch the current value associated with a property.
+int QEglProperties::value(int name) const
+{
+ for (int index = 0; index < (props.size() - 1); index += 2) {
+ if (props[index] == name)
+ return props[index + 1];
+ }
+
+ // If the attribute has not been explicitly set, return the EGL default
+ // The following defaults were taken from the EGL 1.4 spec:
+ switch(name) {
+ case EGL_BUFFER_SIZE: return 0;
+ case EGL_RED_SIZE: return 0;
+ case EGL_GREEN_SIZE: return 0;
+ case EGL_BLUE_SIZE: return 0;
+ case EGL_ALPHA_SIZE: return 0;
+#if defined(EGL_LUMINANCE_SIZE)
+ case EGL_LUMINANCE_SIZE: return 0;
+#endif
+#if defined(EGL_ALPHA_MASK_SIZE)
+ case EGL_ALPHA_MASK_SIZE: return 0;
+#endif
+ case EGL_BIND_TO_TEXTURE_RGB: return EGL_DONT_CARE;
+ case EGL_BIND_TO_TEXTURE_RGBA: return EGL_DONT_CARE;
+#if defined(EGL_COLOR_BUFFER_TYPE)
+ case EGL_COLOR_BUFFER_TYPE: return EGL_RGB_BUFFER;
+#endif
+ case EGL_CONFIG_CAVEAT: return EGL_DONT_CARE;
+ case EGL_CONFIG_ID: return EGL_DONT_CARE;
+ case EGL_DEPTH_SIZE: return 0;
+ case EGL_LEVEL: return 0;
+ case EGL_NATIVE_RENDERABLE: return EGL_DONT_CARE;
+ case EGL_NATIVE_VISUAL_TYPE: return EGL_DONT_CARE;
+ case EGL_MAX_SWAP_INTERVAL: return EGL_DONT_CARE;
+ case EGL_MIN_SWAP_INTERVAL: return EGL_DONT_CARE;
+#if defined(EGL_RENDERABLE_TYPE)
+ case EGL_RENDERABLE_TYPE: return EGL_OPENGL_ES_BIT;
+#endif
+ case EGL_SAMPLE_BUFFERS: return 0;
+ case EGL_SAMPLES: return 0;
+ case EGL_STENCIL_SIZE: return 0;
+ case EGL_SURFACE_TYPE: return EGL_WINDOW_BIT;
+ case EGL_TRANSPARENT_TYPE: return EGL_NONE;
+ case EGL_TRANSPARENT_RED_VALUE: return EGL_DONT_CARE;
+ case EGL_TRANSPARENT_GREEN_VALUE: return EGL_DONT_CARE;
+ case EGL_TRANSPARENT_BLUE_VALUE: return EGL_DONT_CARE;
+
+#if defined(EGL_VERSION_1_3)
+ case EGL_CONFORMANT: return 0;
+ case EGL_MATCH_NATIVE_PIXMAP: return EGL_NONE;
+#endif
+
+ case EGL_MAX_PBUFFER_HEIGHT:
+ case EGL_MAX_PBUFFER_WIDTH:
+ case EGL_MAX_PBUFFER_PIXELS:
+ case EGL_NATIVE_VISUAL_ID:
+ case EGL_NONE:
+ // Attribute does not affect config selection.
+ return EGL_DONT_CARE;
+ default:
+ // Attribute is unknown in EGL <= 1.4.
+ return EGL_DONT_CARE;
+ }
+}
+
+// Set the value associated with a property, replacing an existing
+// value if there is one.
+void QEglProperties::setValue(int name, int value)
+{
+ for (int index = 0; index < (props.size() - 1); index += 2) {
+ if (props[index] == name) {
+ props[index + 1] = value;
+ return;
+ }
+ }
+ props[props.size() - 1] = name;
+ props.append(value);
+ props.append(EGL_NONE);
+}
+
+// Remove a property value. Returns false if the property is not present.
+bool QEglProperties::removeValue(int name)
+{
+ for (int index = 0; index < (props.size() - 1); index += 2) {
+ if (props[index] == name) {
+ while ((index + 2) < props.size()) {
+ props[index] = props[index + 2];
+ ++index;
+ }
+ props.resize(props.size() - 2);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Sets the red, green, blue, and alpha sizes based on a pixel format.
+// Normally used to match a configuration request to the screen format.
+void QEglProperties::setPixelFormat(QImage::Format pixelFormat)
+{
+ int red, green, blue, alpha;
+ switch (pixelFormat) {
+ case QImage::Format_RGB32:
+ case QImage::Format_RGB888:
+ red = green = blue = 8; alpha = 0; break;
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ red = green = blue = alpha = 8; break;
+ case QImage::Format_RGB16:
+ red = 5; green = 6; blue = 5; alpha = 0; break;
+ case QImage::Format_ARGB8565_Premultiplied:
+ red = 5; green = 6; blue = 5; alpha = 8; break;
+ case QImage::Format_RGB666:
+ red = green = blue = 6; alpha = 0; break;
+ case QImage::Format_ARGB6666_Premultiplied:
+ red = green = blue = alpha = 6; break;
+ case QImage::Format_RGB555:
+ red = green = blue = 5; alpha = 0; break;
+ case QImage::Format_ARGB8555_Premultiplied:
+ red = green = blue = 5; alpha = 8; break;
+ case QImage::Format_RGB444:
+ red = green = blue = 4; alpha = 0; break;
+ case QImage::Format_ARGB4444_Premultiplied:
+ red = green = blue = alpha = 4; break;
+ default:
+ qWarning() << "QEglProperties::setPixelFormat(): Unsupported pixel format";
+ red = green = blue = alpha = 1; break;
+ }
+ setValue(EGL_RED_SIZE, red);
+ setValue(EGL_GREEN_SIZE, green);
+ setValue(EGL_BLUE_SIZE, blue);
+ setValue(EGL_ALPHA_SIZE, alpha);
+}
+
+void QEglProperties::setRenderableType(QEgl::API api)
+{
+#if defined(EGL_RENDERABLE_TYPE)
+#if defined(QT_OPENGL_ES_2)
+ if (api == QEgl::OpenGL)
+ setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT);
+#elif defined(QT_OPENGL_ES)
+ if (api == QEgl::OpenGL)
+ setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
+#endif
+#if defined(EGL_OPENVG_BIT)
+ if (api == QEgl::OpenVG)
+ setValue(EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT);
+#endif
+#else
+ Q_UNUSED(api);
+#endif
+}
+
+// Reduce the complexity of a configuration request to ask for less
+// because the previous request did not result in success. Returns
+// true if the complexity was reduced, or false if no further
+// reductions in complexity are possible.
+bool QEglProperties::reduceConfiguration()
+{
+ if (removeValue(EGL_SAMPLE_BUFFERS)) {
+ removeValue(EGL_SAMPLES);
+ return true;
+ }
+ if (removeValue(EGL_ALPHA_SIZE)) {
+#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
+ if (removeValue(EGL_BIND_TO_TEXTURE_RGBA))
+ setValue(EGL_BIND_TO_TEXTURE_RGB, TRUE);
+#endif
+ return true;
+ }
+ if (removeValue(EGL_STENCIL_SIZE))
+ return true;
+ if (removeValue(EGL_DEPTH_SIZE))
+ return true;
+#if defined(EGL_BIND_TO_TEXTURE_RGB)
+ if (removeValue(EGL_BIND_TO_TEXTURE_RGB))
+ return true;
+#endif
+ return false;
+}
+
+static void addTag(QString& str, const QString& tag)
+{
+ int lastnl = str.lastIndexOf(QLatin1String("\n"));
+ if (lastnl == -1)
+ lastnl = 0;
+ if ((str.length() - lastnl) >= 50)
+ str += QLatin1String("\n ");
+ str += tag;
+}
+
+void QEglProperties::dumpAllConfigs()
+{
+ EGLint count = 0;
+ eglGetConfigs(QEglContext::defaultDisplay(0), 0, 0, &count);
+ if (count < 1)
+ return;
+
+ EGLConfig *configs = new EGLConfig [count];
+ eglGetConfigs(QEglContext::defaultDisplay(0), configs, count, &count);
+ for (EGLint index = 0; index < count; ++index)
+ qWarning() << QEglProperties(configs[index]).toString();
+ delete [] configs;
+}
+
+// Convert a property list to a string suitable for debug output.
+QString QEglProperties::toString() const
+{
+ QString str;
+ int val;
+
+ val = value(EGL_CONFIG_ID);
+ if (val != EGL_DONT_CARE) {
+ str += QLatin1String("id=");
+ str += QString::number(val);
+ str += QLatin1Char(' ');
+ }
+
+#ifdef EGL_RENDERABLE_TYPE
+ val = value(EGL_RENDERABLE_TYPE);
+ if (val != EGL_DONT_CARE) {
+ str += QLatin1String("type=");
+ QStringList types;
+ if ((val & EGL_OPENGL_ES_BIT) != 0)
+ types += QLatin1String("es1");
+#ifdef EGL_OPENGL_ES2_BIT
+ if ((val & EGL_OPENGL_ES2_BIT) != 0)
+ types += QLatin1String("es2");
+#endif
+ if ((val & EGL_OPENVG_BIT) != 0)
+ types += QLatin1String("vg");
+ if ((val & ~7) != 0)
+ types += QString::number(val);
+ str += types.join(QLatin1String(","));
+ } else {
+ str += QLatin1String("type=any");
+ }
+#else
+ str += QLatin1String("type=es1");
+#endif
+
+ int red = value(EGL_RED_SIZE);
+ int green = value(EGL_GREEN_SIZE);
+ int blue = value(EGL_BLUE_SIZE);
+ int alpha = value(EGL_ALPHA_SIZE);
+ int bufferSize = value(EGL_BUFFER_SIZE);
+ if (bufferSize == (red + green + blue + alpha))
+ bufferSize = EGL_DONT_CARE;
+ str += QLatin1String(" rgba=");
+ str += QString::number(red);
+ str += QLatin1Char(',');
+ str += QString::number(green);
+ str += QLatin1Char(',');
+ str += QString::number(blue);
+ str += QLatin1Char(',');
+ str += QString::number(alpha);
+ if (bufferSize != EGL_DONT_CARE) {
+ // Only report buffer size if different than r+g+b+a.
+ str += QLatin1String(" buffer-size=");
+ str += QString::number(bufferSize);
+ }
+
+#ifdef EGL_COLOR_BUFFER_TYPE
+ val = value(EGL_COLOR_BUFFER_TYPE);
+ if (val == EGL_LUMINANCE_BUFFER) {
+ addTag(str, QLatin1String(" color-buffer-type=luminance"));
+ } else if (val != EGL_DONT_CARE && val != EGL_RGB_BUFFER) {
+ addTag(str, QLatin1String(" color-buffer-type="));
+ str += QString::number(val, 16);
+ }
+#endif
+
+ val = value(EGL_DEPTH_SIZE);
+ if (val != 0) {
+ addTag(str, QLatin1String(" depth="));
+ str += QString::number(val);
+ }
+
+ val = value(EGL_STENCIL_SIZE);
+ if (val != 0) {
+ addTag(str, QLatin1String(" stencil="));
+ str += QString::number(val);
+ }
+
+ val = value(EGL_SURFACE_TYPE);
+ if (val != EGL_DONT_CARE) {
+ addTag(str, QLatin1String(" surface-type="));
+ QStringList types;
+ if ((val & EGL_WINDOW_BIT) != 0)
+ types += QLatin1String("window");
+ if ((val & EGL_PIXMAP_BIT) != 0)
+ types += QLatin1String("pixmap");
+ if ((val & EGL_PBUFFER_BIT) != 0)
+ types += QLatin1String("pbuffer");
+#ifdef EGL_VG_COLORSPACE_LINEAR_BIT
+ if ((val & EGL_VG_COLORSPACE_LINEAR_BIT) != 0)
+ types += QLatin1String("vg-colorspace-linear");
+#endif
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ if ((val & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0)
+ types += QLatin1String("vg-alpha-format-pre");
+#endif
+ if ((val & ~(EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT
+#ifdef EGL_VG_COLORSPACE_LINEAR_BIT
+ | EGL_VG_COLORSPACE_LINEAR_BIT
+#endif
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ | EGL_VG_ALPHA_FORMAT_PRE_BIT
+#endif
+ )) != 0) {
+ types += QString::number(val);
+ }
+ str += types.join(QLatin1String(","));
+ }
+
+ val = value(EGL_CONFIG_CAVEAT);
+ if (val != EGL_DONT_CARE) {
+ addTag(str, QLatin1String(" caveat="));
+ if (val == EGL_NONE)
+ str += QLatin1String("none");
+ else if (val == EGL_SLOW_CONFIG)
+ str += QLatin1String("slow");
+ else if (val == EGL_NON_CONFORMANT_CONFIG)
+ str += QLatin1String("non-conformant");
+ else
+ str += QString::number(val, 16);
+ }
+
+ val = value(EGL_LEVEL);
+ if (val != 0) {
+ addTag(str, QLatin1String(" level="));
+ str += QString::number(val);
+ }
+
+ int width, height, pixels;
+ width = value(EGL_MAX_PBUFFER_WIDTH);
+ height = value(EGL_MAX_PBUFFER_HEIGHT);
+ pixels = value(EGL_MAX_PBUFFER_PIXELS);
+ if (height != EGL_DONT_CARE || width != EGL_DONT_CARE) {
+ addTag(str, QLatin1String(" max-pbuffer-size="));
+ str += QString::number(width);
+ str += QLatin1Char('x');
+ str += QString::number(height);
+ if (pixels != (width * height)) {
+ addTag(str, QLatin1String(" max-pbuffer-pixels="));
+ str += QString::number(pixels);
+ }
+ }
+
+ val = value(EGL_NATIVE_RENDERABLE);
+ if (val != EGL_DONT_CARE) {
+ if (val)
+ addTag(str, QLatin1String(" native-renderable=true"));
+ else
+ addTag(str, QLatin1String(" native-renderable=false"));
+ }
+
+ val = value(EGL_NATIVE_VISUAL_ID);
+ if (val != EGL_DONT_CARE) {
+ addTag(str, QLatin1String(" visual-id="));
+ str += QString::number(val);
+ }
+
+ val = value(EGL_NATIVE_VISUAL_TYPE);
+ if (val != EGL_DONT_CARE) {
+ addTag(str, QLatin1String(" visual-type="));
+ str += QString::number(val);
+ }
+
+#ifdef EGL_PRESERVED_RESOURCES
+ val = value(EGL_PRESERVED_RESOURCES);
+ if (val != EGL_DONT_CARE) {
+ if (val)
+ addTag(str, QLatin1String(" preserved-resources=true"));
+ else
+ addTag(str, QLatin1String(" preserved-resources=false"));
+ }
+#endif
+
+ val = value(EGL_SAMPLES);
+ if (val != 0) {
+ addTag(str, QLatin1String(" samples="));
+ str += QString::number(val);
+ }
+
+ val = value(EGL_SAMPLE_BUFFERS);
+ if (val != 0) {
+ addTag(str, QLatin1String(" sample-buffers="));
+ str += QString::number(val);
+ }
+
+ val = value(EGL_TRANSPARENT_TYPE);
+ if (val == EGL_TRANSPARENT_RGB) {
+ addTag(str, QLatin1String(" transparent-rgb="));
+ str += QString::number(value(EGL_TRANSPARENT_RED_VALUE));
+ str += QLatin1Char(',');
+ str += QString::number(value(EGL_TRANSPARENT_GREEN_VALUE));
+ str += QLatin1Char(',');
+ str += QString::number(value(EGL_TRANSPARENT_BLUE_VALUE));
+ }
+
+#if defined(EGL_BIND_TO_TEXTURE_RGB) && defined(EGL_BIND_TO_TEXTURE_RGBA)
+ val = value(EGL_BIND_TO_TEXTURE_RGB);
+ int val2 = value(EGL_BIND_TO_TEXTURE_RGBA);
+ if (val != EGL_DONT_CARE || val2 != EGL_DONT_CARE) {
+ addTag(str, QLatin1String(" bind-texture="));
+ if (val == EGL_TRUE)
+ str += QLatin1String("rgb");
+ else
+ str += QLatin1String("no-rgb");
+ if (val2 == EGL_TRUE)
+ str += QLatin1String(",rgba");
+ else
+ str += QLatin1String(",no-rgba");
+ }
+#endif
+
+#ifdef EGL_MIN_SWAP_INTERVAL
+ val = value(EGL_MIN_SWAP_INTERVAL);
+ if (val != EGL_DONT_CARE) {
+ addTag(str, QLatin1String(" min-swap-interval="));
+ str += QString::number(val);
+ }
+#endif
+
+#ifdef EGL_MIN_SWAP_INTERVAL
+ val = value(EGL_MAX_SWAP_INTERVAL);
+ if (val != EGL_DONT_CARE) {
+ addTag(str, QLatin1String(" max-swap-interval="));
+ str += QString::number(val);
+ }
+#endif
+
+#ifdef EGL_LUMINANCE_SIZE
+ val = value(EGL_LUMINANCE_SIZE);
+ if (val != 0) {
+ addTag(str, QLatin1String(" luminance="));
+ str += QString::number(val);
+ }
+#endif
+
+#ifdef EGL_ALPHA_MASK_SIZE
+ val = value(EGL_ALPHA_MASK_SIZE);
+ if (val != 0) {
+ addTag(str, QLatin1String(" alpha-mask="));
+ str += QString::number(val);
+ }
+#endif
+
+#ifdef EGL_CONFORMANT
+ val = value(EGL_CONFORMANT);
+ if (val != 0) {
+ if (val)
+ addTag(str, QLatin1String(" conformant=true"));
+ else
+ addTag(str, QLatin1String(" conformant=false"));
+ }
+#endif
+
+ return str;
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h
new file mode 100644
index 0000000..383a873
--- /dev/null
+++ b/src/gui/egl/qeglproperties_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLPROPERTIES_P_H
+#define QEGLPROPERTIES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QtOpenGL and QtOpenVG modules. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qvarlengtharray.h>
+#include <QtGui/qimage.h>
+
+QT_BEGIN_INCLUDE_NAMESPACE
+
+#if defined(QT_GLES_EGL)
+#include <GLES/egl.h>
+#else
+#include <EGL/egl.h>
+#endif
+
+#if defined(Q_WS_X11)
+// If <EGL/egl.h> included <X11/Xlib.h>, then the global namespace
+// may have been polluted with X #define's. The following makes sure
+// the X11 headers were included properly and then cleans things up.
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#undef Bool
+#undef Status
+#undef None
+#undef KeyPress
+#undef KeyRelease
+#undef FocusIn
+#undef FocusOut
+#undef Type
+#undef FontChange
+#undef CursorShape
+#endif
+
+QT_END_INCLUDE_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+namespace QEgl {
+ enum API
+ {
+ OpenGL,
+ OpenVG
+ };
+
+ enum PixelFormatMatch
+ {
+ ExactPixelFormat,
+ BestPixelFormat
+ };
+};
+
+class QX11Info;
+class QPaintDevice;
+
+class Q_GUI_EXPORT QEglProperties
+{
+public:
+ QEglProperties();
+ QEglProperties(EGLConfig);
+ QEglProperties(const QEglProperties& other) : props(other.props) {}
+ ~QEglProperties() {}
+
+ int value(int name) const;
+ void setValue(int name, int value);
+ bool removeValue(int name);
+ bool isEmpty() const { return props[0] == EGL_NONE; }
+
+ const int *properties() const { return props.constData(); }
+
+ void setPixelFormat(QImage::Format pixelFormat);
+#ifdef Q_WS_X11
+ void setVisualFormat(const QX11Info *xinfo);
+#endif
+ void setRenderableType(QEgl::API api);
+
+ void setPaintDeviceFormat(QPaintDevice *dev);
+
+ bool reduceConfiguration();
+
+ QString toString() const;
+
+ static void dumpAllConfigs();
+
+private:
+ QVarLengthArray<int> props;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLPROPERTIES_P_H
diff --git a/src/gui/embedded/embedded.pri b/src/gui/embedded/embedded.pri
index 95c4132..255a504 100644
--- a/src/gui/embedded/embedded.pri
+++ b/src/gui/embedded/embedded.pri
@@ -89,6 +89,8 @@ embedded {
HEADERS += embedded/qscreendriverplugin_qws.h \
embedded/qscreendriverfactory_qws.h \
embedded/qkbd_qws.h \
+ embedded/qkbd_qws_p.h \
+ embedded/qkbd_defaultmap_qws_p.h \
embedded/qkbddriverplugin_qws.h \
embedded/qkbddriverfactory_qws.h \
embedded/qmouse_qws.h \
@@ -112,11 +114,18 @@ embedded {
SOURCES += embedded/qscreenlinuxfb_qws.cpp
}
+ contains( gfx-drivers, qnx ) {
+ HEADERS += embedded/qscreenqnx_qws.h
+ SOURCES += embedded/qscreenqnx_qws.cpp
+ LIBS += -lgf
+ }
+
contains( gfx-drivers, qvfb ) {
HEADERS += embedded/qscreenvfb_qws.h
SOURCES += embedded/qscreenvfb_qws.cpp
}
+
contains( gfx-drivers, vnc ) {
VNCDIR = $$QT_SOURCE_TREE/src/plugins/gfxdrivers/vnc
INCLUDEPATH += $$VNCDIR
@@ -139,30 +148,16 @@ embedded {
!contains( kbd-drivers, qvfb ) {
kbd-drivers += qvfb
}
- }
-
- contains( kbd-drivers, sl5000 ) {
- HEADERS +=embedded/qkbdsl5000_qws.h
- SOURCES +=embedded/qkbdsl5000_qws.cpp
- !contains( kbd-drivers, tty ) {
- kbd-drivers += tty
- }
- }
+ }
contains( kbd-drivers, tty ) {
HEADERS +=embedded/qkbdtty_qws.h
SOURCES +=embedded/qkbdtty_qws.cpp
- !contains( kbd-drivers, pc101 ) {
- kbd-drivers += pc101
- }
}
- contains( kbd-drivers, usb ) {
- HEADERS +=embedded/qkbdusb_qws.h
- SOURCES +=embedded/qkbdusb_qws.cpp
- !contains( kbd-drivers, pc101 ) {
- kbd-drivers += pc101
- }
+ contains( kbd-drivers, linuxinput ) {
+ HEADERS +=embedded/qkbdlinuxinput_qws.h
+ SOURCES +=embedded/qkbdlinuxinput_qws.cpp
}
contains( kbd-drivers, um ) {
@@ -170,20 +165,10 @@ embedded {
SOURCES +=embedded/qkbdum_qws.cpp
}
- contains( kbd-drivers, pc101 ) {
- HEADERS +=embedded/qkbdpc101_qws.h
- SOURCES +=embedded/qkbdpc101_qws.cpp
- }
-
- contains( kbd-drivers, yopy ) {
- HEADERS +=embedded/qkbdyopy_qws.h
- SOURCES +=embedded/qkbdyopy_qws.cpp
- }
-
- contains( kbd-drivers, vr41xx ) {
- HEADERS +=embedded/qkbdvr41xx_qws.h
- SOURCES +=embedded/qkbdvr41xx_qws.cpp
- }
+ contains( kbd-drivers, qnx ) {
+ HEADERS += embedded/qkbdqnx_qws.h
+ SOURCES += embedded/qkbdqnx_qws.cpp
+ }
#
# Mouse drivers
@@ -198,29 +183,24 @@ embedded {
SOURCES +=embedded/qmousepc_qws.cpp
}
- contains( mouse-drivers, bus ) {
- HEADERS +=embedded/qmousebus_qws.h
- SOURCES +=embedded/qmousebus_qws.cpp
- }
-
contains( mouse-drivers, linuxtp ) {
HEADERS +=embedded/qmouselinuxtp_qws.h
SOURCES +=embedded/qmouselinuxtp_qws.cpp
}
- contains( mouse-drivers, vr41xx ) {
- HEADERS +=embedded/qmousevr41xx_qws.h
- SOURCES +=embedded/qmousevr41xx_qws.cpp
- }
-
- contains( mouse-drivers, yopy ) {
- HEADERS +=embedded/qmouseyopy_qws.h
- SOURCES +=embedded/qmouseyopy_qws.cpp
- }
-
contains( mouse-drivers, tslib ) {
- LIBS += -lts
+ LIBS_PRIVATE += -lts
HEADERS +=embedded/qmousetslib_qws.h
SOURCES +=embedded/qmousetslib_qws.cpp
}
+
+ contains( mouse-drivers, linuxinput ) {
+ HEADERS +=embedded/qmouselinuxinput_qws.h
+ SOURCES +=embedded/qmouselinuxinput_qws.cpp
+ }
+
+ contains( mouse-drivers, qnx ) {
+ HEADERS += embedded/qmouseqnx_qws.h
+ SOURCES += embedded/qmouseqnx_qws.cpp
+ }
}
diff --git a/src/gui/embedded/qdirectpainter_qws.cpp b/src/gui/embedded/qdirectpainter_qws.cpp
index 6aa6bb7..1412ea9 100644
--- a/src/gui/embedded/qdirectpainter_qws.cpp
+++ b/src/gui/embedded/qdirectpainter_qws.cpp
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QDirectPainter
- \ingroup multimedia
+ \ingroup painting
\ingroup qws
\brief The QDirectPainter class provides direct access to the
@@ -150,14 +150,14 @@ QT_BEGIN_NAMESPACE
\value ReservedSynchronous The allocated region will never change and
each function that changes the allocated region will be blocking.
- \sa reservedRegion(), allocatedRegion()
+ \sa allocatedRegion()
*/
/*!
\fn QRegion QDirectPainter::region()
\obsolete
- Use QDirectPainter::reservedRegion() instead.
+ Use QDirectPainter::allocatedRegion() instead.
*/
static inline QScreen *getPrimaryScreen()
@@ -346,7 +346,7 @@ void QDirectPainter::setRegion(const QRegion &region)
returned by the allocatedRegion() function. Otherwise they might
differ (see \l {Dynamic Allocation} for details).
- \sa geometry(), setRegion()
+ \sa geometry(), setRegion(), allocatedRegion()
*/
QRegion QDirectPainter::requestedRegion() const
{
@@ -540,7 +540,7 @@ void QDirectPainter::lower()
any. If not released explicitly, the region will be released on
application exit.
- \sa reservedRegion(), {Static Allocation}
+ \sa allocatedRegion(), {Static Allocation}
\obsolete
diff --git a/src/gui/embedded/qkbd_defaultmap_qws_p.h b/src/gui/embedded/qkbd_defaultmap_qws_p.h
new file mode 100644
index 0000000..a6c2d25
--- /dev/null
+++ b/src/gui/embedded/qkbd_defaultmap_qws_p.h
@@ -0,0 +1,798 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSKEYBOARDHANDLER_DEFAULTMAP_H
+#define QWSKEYBOARDHANDLER_DEFAULTMAP_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.
+//
+
+// no QT_BEGIN_NAMESPACE, since we include it internally...
+
+const QWSKeyboard::Mapping QWSKbPrivate::s_keymap_default[] = {
+ { 1, 0xffff, 0x01000000, 0x00, 0x00, 0x0000 },
+ { 2, 0x0031, 0x00000031, 0x00, 0x00, 0x0000 },
+ { 2, 0x0021, 0x00000021, 0x01, 0x00, 0x0000 },
+ { 3, 0x0032, 0x00000032, 0x00, 0x00, 0x0000 },
+ { 3, 0x0040, 0x00000040, 0x01, 0x00, 0x0000 },
+ { 3, 0x0040, 0x00000040, 0x02, 0x00, 0x0000 },
+ { 4, 0x0033, 0x00000033, 0x00, 0x00, 0x0000 },
+ { 4, 0x0023, 0x00000023, 0x01, 0x00, 0x0000 },
+ { 4, 0xffff, 0x01000000, 0x04, 0x00, 0x0000 },
+ { 5, 0x0034, 0x00000034, 0x00, 0x00, 0x0000 },
+ { 5, 0x0024, 0x00000024, 0x01, 0x00, 0x0000 },
+ { 5, 0x0024, 0x00000024, 0x02, 0x00, 0x0000 },
+ { 5, 0x005c, 0x0400005c, 0x04, 0x00, 0x0000 },
+ { 6, 0x0035, 0x00000035, 0x00, 0x00, 0x0000 },
+ { 6, 0x0025, 0x00000025, 0x01, 0x00, 0x0000 },
+ { 6, 0x005d, 0x0400005d, 0x04, 0x00, 0x0000 },
+ { 7, 0x0036, 0x00000036, 0x00, 0x00, 0x0000 },
+ { 7, 0x005e, 0x0000005e, 0x01, 0x00, 0x0000 },
+ { 7, 0x005e, 0x01001252, 0x02, 0x01, 0x0000 },
+ { 7, 0x005e, 0x0400005e, 0x04, 0x00, 0x0000 },
+ { 8, 0x0037, 0x00000037, 0x00, 0x00, 0x0000 },
+ { 8, 0x0026, 0x00000026, 0x01, 0x00, 0x0000 },
+ { 8, 0x007b, 0x0000007b, 0x02, 0x00, 0x0000 },
+ { 8, 0x005f, 0x0400005f, 0x04, 0x00, 0x0000 },
+ { 9, 0x0038, 0x00000038, 0x00, 0x00, 0x0000 },
+ { 9, 0x002a, 0x0000002a, 0x01, 0x00, 0x0000 },
+ { 9, 0x005b, 0x0000005b, 0x02, 0x00, 0x0000 },
+ { 9, 0xffff, 0x01000003, 0x04, 0x00, 0x0000 },
+ { 10, 0x0039, 0x00000039, 0x00, 0x00, 0x0000 },
+ { 10, 0x0028, 0x00000028, 0x01, 0x00, 0x0000 },
+ { 10, 0x005d, 0x0000005d, 0x02, 0x00, 0x0000 },
+ { 11, 0x0030, 0x00000030, 0x00, 0x00, 0x0000 },
+ { 11, 0x0029, 0x00000029, 0x01, 0x00, 0x0000 },
+ { 11, 0x007d, 0x0000007d, 0x02, 0x00, 0x0000 },
+ { 12, 0x002d, 0x0000002d, 0x00, 0x00, 0x0000 },
+ { 12, 0x005f, 0x0000005f, 0x01, 0x00, 0x0000 },
+ { 12, 0x005c, 0x0000005c, 0x02, 0x00, 0x0000 },
+ { 12, 0x005f, 0x0400005f, 0x04, 0x00, 0x0000 },
+ { 12, 0x005f, 0x0400005f, 0x05, 0x00, 0x0000 },
+ { 13, 0x003d, 0x0000003d, 0x00, 0x00, 0x0000 },
+ { 13, 0x002b, 0x0000002b, 0x01, 0x00, 0x0000 },
+ { 14, 0xffff, 0x01000003, 0x00, 0x00, 0x0000 },
+ { 14, 0xffff, 0x01000000, 0x0c, 0x08, 0x0300 },
+ { 15, 0xffff, 0x01000001, 0x00, 0x00, 0x0000 },
+ { 16, 0x0071, 0x00000051, 0x00, 0x00, 0x0000 },
+ { 16, 0x0051, 0x00000051, 0x01, 0x00, 0x0000 },
+ { 16, 0x0071, 0x00000051, 0x02, 0x00, 0x0000 },
+ { 16, 0x0051, 0x00000051, 0x03, 0x00, 0x0000 },
+ { 16, 0x0071, 0x04000051, 0x04, 0x00, 0x0000 },
+ { 16, 0x0071, 0x04000051, 0x05, 0x00, 0x0000 },
+ { 16, 0x0071, 0x04000051, 0x06, 0x00, 0x0000 },
+ { 16, 0x0071, 0x04000051, 0x07, 0x00, 0x0000 },
+ { 16, 0x0071, 0x08000051, 0x08, 0x00, 0x0000 },
+ { 16, 0x0071, 0x08000051, 0x09, 0x00, 0x0000 },
+ { 16, 0x0071, 0x08000051, 0x0a, 0x00, 0x0000 },
+ { 16, 0x0071, 0x08000051, 0x0b, 0x00, 0x0000 },
+ { 16, 0x0071, 0x0c000051, 0x0c, 0x00, 0x0000 },
+ { 16, 0x0071, 0x0c000051, 0x0d, 0x00, 0x0000 },
+ { 16, 0x0071, 0x0c000051, 0x0e, 0x00, 0x0000 },
+ { 16, 0x0071, 0x0c000051, 0x0f, 0x00, 0x0000 },
+ { 17, 0x0077, 0x00000057, 0x00, 0x00, 0x0000 },
+ { 17, 0x0057, 0x00000057, 0x01, 0x00, 0x0000 },
+ { 17, 0x0077, 0x00000057, 0x02, 0x00, 0x0000 },
+ { 17, 0x0057, 0x00000057, 0x03, 0x00, 0x0000 },
+ { 17, 0x0077, 0x04000057, 0x04, 0x00, 0x0000 },
+ { 17, 0x0077, 0x04000057, 0x05, 0x00, 0x0000 },
+ { 17, 0x0077, 0x04000057, 0x06, 0x00, 0x0000 },
+ { 17, 0x0077, 0x04000057, 0x07, 0x00, 0x0000 },
+ { 17, 0x0077, 0x08000057, 0x08, 0x00, 0x0000 },
+ { 17, 0x0077, 0x08000057, 0x09, 0x00, 0x0000 },
+ { 17, 0x0077, 0x08000057, 0x0a, 0x00, 0x0000 },
+ { 17, 0x0077, 0x08000057, 0x0b, 0x00, 0x0000 },
+ { 17, 0x0077, 0x0c000057, 0x0c, 0x00, 0x0000 },
+ { 17, 0x0077, 0x0c000057, 0x0d, 0x00, 0x0000 },
+ { 17, 0x0077, 0x0c000057, 0x0e, 0x00, 0x0000 },
+ { 17, 0x0077, 0x0c000057, 0x0f, 0x00, 0x0000 },
+ { 18, 0x0065, 0x00000045, 0x00, 0x00, 0x0000 },
+ { 18, 0x0045, 0x00000045, 0x01, 0x00, 0x0000 },
+ { 18, 0x0065, 0x00000045, 0x02, 0x00, 0x0000 },
+ { 18, 0x0045, 0x00000045, 0x03, 0x00, 0x0000 },
+ { 18, 0x0065, 0x04000045, 0x04, 0x00, 0x0000 },
+ { 18, 0x0065, 0x04000045, 0x05, 0x00, 0x0000 },
+ { 18, 0x0065, 0x04000045, 0x06, 0x00, 0x0000 },
+ { 18, 0x0065, 0x04000045, 0x07, 0x00, 0x0000 },
+ { 18, 0x0065, 0x08000045, 0x08, 0x00, 0x0000 },
+ { 18, 0x0065, 0x08000045, 0x09, 0x00, 0x0000 },
+ { 18, 0x0065, 0x08000045, 0x0a, 0x00, 0x0000 },
+ { 18, 0x0065, 0x08000045, 0x0b, 0x00, 0x0000 },
+ { 18, 0x0065, 0x0c000045, 0x0c, 0x00, 0x0000 },
+ { 18, 0x0065, 0x0c000045, 0x0d, 0x00, 0x0000 },
+ { 18, 0x0065, 0x0c000045, 0x0e, 0x00, 0x0000 },
+ { 18, 0x0065, 0x0c000045, 0x0f, 0x00, 0x0000 },
+ { 19, 0x0072, 0x00000052, 0x00, 0x00, 0x0000 },
+ { 19, 0x0052, 0x00000052, 0x01, 0x00, 0x0000 },
+ { 19, 0x0072, 0x00000052, 0x02, 0x00, 0x0000 },
+ { 19, 0x0052, 0x00000052, 0x03, 0x00, 0x0000 },
+ { 19, 0x0072, 0x04000052, 0x04, 0x00, 0x0000 },
+ { 19, 0x0072, 0x04000052, 0x05, 0x00, 0x0000 },
+ { 19, 0x0072, 0x04000052, 0x06, 0x00, 0x0000 },
+ { 19, 0x0072, 0x04000052, 0x07, 0x00, 0x0000 },
+ { 19, 0x0072, 0x08000052, 0x08, 0x00, 0x0000 },
+ { 19, 0x0072, 0x08000052, 0x09, 0x00, 0x0000 },
+ { 19, 0x0072, 0x08000052, 0x0a, 0x00, 0x0000 },
+ { 19, 0x0072, 0x08000052, 0x0b, 0x00, 0x0000 },
+ { 19, 0x0072, 0x0c000052, 0x0c, 0x00, 0x0000 },
+ { 19, 0x0072, 0x0c000052, 0x0d, 0x00, 0x0000 },
+ { 19, 0x0072, 0x0c000052, 0x0e, 0x00, 0x0000 },
+ { 19, 0x0072, 0x0c000052, 0x0f, 0x00, 0x0000 },
+ { 20, 0x0074, 0x00000054, 0x00, 0x00, 0x0000 },
+ { 20, 0x0054, 0x00000054, 0x01, 0x00, 0x0000 },
+ { 20, 0x0074, 0x00000054, 0x02, 0x00, 0x0000 },
+ { 20, 0x0054, 0x00000054, 0x03, 0x00, 0x0000 },
+ { 20, 0x0074, 0x04000054, 0x04, 0x00, 0x0000 },
+ { 20, 0x0074, 0x04000054, 0x05, 0x00, 0x0000 },
+ { 20, 0x0074, 0x04000054, 0x06, 0x00, 0x0000 },
+ { 20, 0x0074, 0x04000054, 0x07, 0x00, 0x0000 },
+ { 20, 0x0074, 0x08000054, 0x08, 0x00, 0x0000 },
+ { 20, 0x0074, 0x08000054, 0x09, 0x00, 0x0000 },
+ { 20, 0x0074, 0x08000054, 0x0a, 0x00, 0x0000 },
+ { 20, 0x0074, 0x08000054, 0x0b, 0x00, 0x0000 },
+ { 20, 0x0074, 0x0c000054, 0x0c, 0x00, 0x0000 },
+ { 20, 0x0074, 0x0c000054, 0x0d, 0x00, 0x0000 },
+ { 20, 0x0074, 0x0c000054, 0x0e, 0x00, 0x0000 },
+ { 20, 0x0074, 0x0c000054, 0x0f, 0x00, 0x0000 },
+ { 21, 0x0079, 0x00000059, 0x00, 0x00, 0x0000 },
+ { 21, 0x0059, 0x00000059, 0x01, 0x00, 0x0000 },
+ { 21, 0x0079, 0x00000059, 0x02, 0x00, 0x0000 },
+ { 21, 0x0059, 0x00000059, 0x03, 0x00, 0x0000 },
+ { 21, 0x0079, 0x04000059, 0x04, 0x00, 0x0000 },
+ { 21, 0x0079, 0x04000059, 0x05, 0x00, 0x0000 },
+ { 21, 0x0079, 0x04000059, 0x06, 0x00, 0x0000 },
+ { 21, 0x0079, 0x04000059, 0x07, 0x00, 0x0000 },
+ { 21, 0x0079, 0x08000059, 0x08, 0x00, 0x0000 },
+ { 21, 0x0079, 0x08000059, 0x09, 0x00, 0x0000 },
+ { 21, 0x0079, 0x08000059, 0x0a, 0x00, 0x0000 },
+ { 21, 0x0079, 0x08000059, 0x0b, 0x00, 0x0000 },
+ { 21, 0x0079, 0x0c000059, 0x0c, 0x00, 0x0000 },
+ { 21, 0x0079, 0x0c000059, 0x0d, 0x00, 0x0000 },
+ { 21, 0x0079, 0x0c000059, 0x0e, 0x00, 0x0000 },
+ { 21, 0x0079, 0x0c000059, 0x0f, 0x00, 0x0000 },
+ { 22, 0x0075, 0x00000055, 0x00, 0x00, 0x0000 },
+ { 22, 0x0055, 0x00000055, 0x01, 0x00, 0x0000 },
+ { 22, 0x0075, 0x00000055, 0x02, 0x00, 0x0000 },
+ { 22, 0x0055, 0x00000055, 0x03, 0x00, 0x0000 },
+ { 22, 0x0075, 0x04000055, 0x04, 0x00, 0x0000 },
+ { 22, 0x0075, 0x04000055, 0x05, 0x00, 0x0000 },
+ { 22, 0x0075, 0x04000055, 0x06, 0x00, 0x0000 },
+ { 22, 0x0075, 0x04000055, 0x07, 0x00, 0x0000 },
+ { 22, 0x0075, 0x08000055, 0x08, 0x00, 0x0000 },
+ { 22, 0x0075, 0x08000055, 0x09, 0x00, 0x0000 },
+ { 22, 0x0075, 0x08000055, 0x0a, 0x00, 0x0000 },
+ { 22, 0x0075, 0x08000055, 0x0b, 0x00, 0x0000 },
+ { 22, 0x0075, 0x0c000055, 0x0c, 0x00, 0x0000 },
+ { 22, 0x0075, 0x0c000055, 0x0d, 0x00, 0x0000 },
+ { 22, 0x0075, 0x0c000055, 0x0e, 0x00, 0x0000 },
+ { 22, 0x0075, 0x0c000055, 0x0f, 0x00, 0x0000 },
+ { 23, 0x0069, 0x00000049, 0x00, 0x00, 0x0000 },
+ { 23, 0x0049, 0x00000049, 0x01, 0x00, 0x0000 },
+ { 23, 0x0069, 0x00000049, 0x02, 0x00, 0x0000 },
+ { 23, 0x0049, 0x00000049, 0x03, 0x00, 0x0000 },
+ { 23, 0x0069, 0x04000049, 0x04, 0x00, 0x0000 },
+ { 23, 0x0069, 0x04000049, 0x05, 0x00, 0x0000 },
+ { 23, 0x0069, 0x04000049, 0x06, 0x00, 0x0000 },
+ { 23, 0x0069, 0x04000049, 0x07, 0x00, 0x0000 },
+ { 23, 0x0069, 0x08000049, 0x08, 0x00, 0x0000 },
+ { 23, 0x0069, 0x08000049, 0x09, 0x00, 0x0000 },
+ { 23, 0x0069, 0x08000049, 0x0a, 0x00, 0x0000 },
+ { 23, 0x0069, 0x08000049, 0x0b, 0x00, 0x0000 },
+ { 23, 0x0069, 0x0c000049, 0x0c, 0x00, 0x0000 },
+ { 23, 0x0069, 0x0c000049, 0x0d, 0x00, 0x0000 },
+ { 23, 0x0069, 0x0c000049, 0x0e, 0x00, 0x0000 },
+ { 23, 0x0069, 0x0c000049, 0x0f, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0000004f, 0x00, 0x00, 0x0000 },
+ { 24, 0x004f, 0x0000004f, 0x01, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0000004f, 0x02, 0x00, 0x0000 },
+ { 24, 0x004f, 0x0000004f, 0x03, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0400004f, 0x04, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0400004f, 0x05, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0400004f, 0x06, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0400004f, 0x07, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0800004f, 0x08, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0800004f, 0x09, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0800004f, 0x0a, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0800004f, 0x0b, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0c00004f, 0x0c, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0c00004f, 0x0d, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0c00004f, 0x0e, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0c00004f, 0x0f, 0x00, 0x0000 },
+ { 25, 0x0070, 0x00000050, 0x00, 0x00, 0x0000 },
+ { 25, 0x0050, 0x00000050, 0x01, 0x00, 0x0000 },
+ { 25, 0x0070, 0x00000050, 0x02, 0x00, 0x0000 },
+ { 25, 0x0050, 0x00000050, 0x03, 0x00, 0x0000 },
+ { 25, 0x0070, 0x04000050, 0x04, 0x00, 0x0000 },
+ { 25, 0x0070, 0x04000050, 0x05, 0x00, 0x0000 },
+ { 25, 0x0070, 0x04000050, 0x06, 0x00, 0x0000 },
+ { 25, 0x0070, 0x04000050, 0x07, 0x00, 0x0000 },
+ { 25, 0x0070, 0x08000050, 0x08, 0x00, 0x0000 },
+ { 25, 0x0070, 0x08000050, 0x09, 0x00, 0x0000 },
+ { 25, 0x0070, 0x08000050, 0x0a, 0x00, 0x0000 },
+ { 25, 0x0070, 0x08000050, 0x0b, 0x00, 0x0000 },
+ { 25, 0x0070, 0x0c000050, 0x0c, 0x00, 0x0000 },
+ { 25, 0x0070, 0x0c000050, 0x0d, 0x00, 0x0000 },
+ { 25, 0x0070, 0x0c000050, 0x0e, 0x00, 0x0000 },
+ { 25, 0x0070, 0x0c000050, 0x0f, 0x00, 0x0000 },
+ { 26, 0x005b, 0x0000005b, 0x00, 0x00, 0x0000 },
+ { 26, 0x007b, 0x0000007b, 0x01, 0x00, 0x0000 },
+ { 26, 0xffff, 0x01000000, 0x04, 0x00, 0x0000 },
+ { 27, 0x005d, 0x0000005d, 0x00, 0x00, 0x0000 },
+ { 27, 0x007d, 0x0000007d, 0x01, 0x00, 0x0000 },
+ { 27, 0x007e, 0x0000007e, 0x02, 0x00, 0x0000 },
+ { 27, 0x005d, 0x0400005d, 0x04, 0x00, 0x0000 },
+ { 28, 0xffff, 0x01000004, 0x00, 0x00, 0x0000 },
+ { 28, 0x006d, 0x0c00004d, 0x08, 0x00, 0x0000 },
+ { 29, 0xffff, 0x01000021, 0x00, 0x04, 0x0004 },
+ { 30, 0x0061, 0x00000041, 0x00, 0x00, 0x0000 },
+ { 30, 0x0041, 0x00000041, 0x01, 0x00, 0x0000 },
+ { 30, 0x0061, 0x00000041, 0x02, 0x00, 0x0000 },
+ { 30, 0x0041, 0x00000041, 0x03, 0x00, 0x0000 },
+ { 30, 0x0061, 0x04000041, 0x04, 0x00, 0x0000 },
+ { 30, 0x0061, 0x04000041, 0x05, 0x00, 0x0000 },
+ { 30, 0x0061, 0x04000041, 0x06, 0x00, 0x0000 },
+ { 30, 0x0061, 0x04000041, 0x07, 0x00, 0x0000 },
+ { 30, 0x0061, 0x08000041, 0x08, 0x00, 0x0000 },
+ { 30, 0x0061, 0x08000041, 0x09, 0x00, 0x0000 },
+ { 30, 0x0061, 0x08000041, 0x0a, 0x00, 0x0000 },
+ { 30, 0x0061, 0x08000041, 0x0b, 0x00, 0x0000 },
+ { 30, 0x0061, 0x0c000041, 0x0c, 0x00, 0x0000 },
+ { 30, 0x0061, 0x0c000041, 0x0d, 0x00, 0x0000 },
+ { 30, 0x0061, 0x0c000041, 0x0e, 0x00, 0x0000 },
+ { 30, 0x0061, 0x0c000041, 0x0f, 0x00, 0x0000 },
+ { 31, 0x0073, 0x00000053, 0x00, 0x00, 0x0000 },
+ { 31, 0x0053, 0x00000053, 0x01, 0x00, 0x0000 },
+ { 31, 0x0073, 0x00000053, 0x02, 0x00, 0x0000 },
+ { 31, 0x0053, 0x00000053, 0x03, 0x00, 0x0000 },
+ { 31, 0x0073, 0x04000053, 0x04, 0x00, 0x0000 },
+ { 31, 0x0073, 0x04000053, 0x05, 0x00, 0x0000 },
+ { 31, 0x0073, 0x04000053, 0x06, 0x00, 0x0000 },
+ { 31, 0x0073, 0x04000053, 0x07, 0x00, 0x0000 },
+ { 31, 0x0073, 0x08000053, 0x08, 0x00, 0x0000 },
+ { 31, 0x0073, 0x08000053, 0x09, 0x00, 0x0000 },
+ { 31, 0x0073, 0x08000053, 0x0a, 0x00, 0x0000 },
+ { 31, 0x0073, 0x08000053, 0x0b, 0x00, 0x0000 },
+ { 31, 0x0073, 0x0c000053, 0x0c, 0x00, 0x0000 },
+ { 31, 0x0073, 0x0c000053, 0x0d, 0x00, 0x0000 },
+ { 31, 0x0073, 0x0c000053, 0x0e, 0x00, 0x0000 },
+ { 31, 0x0073, 0x0c000053, 0x0f, 0x00, 0x0000 },
+ { 32, 0x0064, 0x00000044, 0x00, 0x00, 0x0000 },
+ { 32, 0x0044, 0x00000044, 0x01, 0x00, 0x0000 },
+ { 32, 0x0064, 0x00000044, 0x02, 0x00, 0x0000 },
+ { 32, 0x0044, 0x00000044, 0x03, 0x00, 0x0000 },
+ { 32, 0x0064, 0x04000044, 0x04, 0x00, 0x0000 },
+ { 32, 0x0064, 0x04000044, 0x05, 0x00, 0x0000 },
+ { 32, 0x0064, 0x04000044, 0x06, 0x00, 0x0000 },
+ { 32, 0x0064, 0x04000044, 0x07, 0x00, 0x0000 },
+ { 32, 0x0064, 0x08000044, 0x08, 0x00, 0x0000 },
+ { 32, 0x0064, 0x08000044, 0x09, 0x00, 0x0000 },
+ { 32, 0x0064, 0x08000044, 0x0a, 0x00, 0x0000 },
+ { 32, 0x0064, 0x08000044, 0x0b, 0x00, 0x0000 },
+ { 32, 0x0064, 0x0c000044, 0x0c, 0x00, 0x0000 },
+ { 32, 0x0064, 0x0c000044, 0x0d, 0x00, 0x0000 },
+ { 32, 0x0064, 0x0c000044, 0x0e, 0x00, 0x0000 },
+ { 32, 0x0064, 0x0c000044, 0x0f, 0x00, 0x0000 },
+ { 33, 0x0066, 0x00000046, 0x00, 0x00, 0x0000 },
+ { 33, 0x0046, 0x00000046, 0x01, 0x00, 0x0000 },
+ { 33, 0x0066, 0x00000046, 0x02, 0x00, 0x0000 },
+ { 33, 0x0046, 0x00000046, 0x03, 0x00, 0x0000 },
+ { 33, 0x0066, 0x04000046, 0x04, 0x00, 0x0000 },
+ { 33, 0x0066, 0x04000046, 0x05, 0x00, 0x0000 },
+ { 33, 0x0066, 0x04000046, 0x06, 0x00, 0x0000 },
+ { 33, 0x0066, 0x04000046, 0x07, 0x00, 0x0000 },
+ { 33, 0x0066, 0x08000046, 0x08, 0x00, 0x0000 },
+ { 33, 0x0066, 0x08000046, 0x09, 0x00, 0x0000 },
+ { 33, 0x0066, 0x08000046, 0x0a, 0x00, 0x0000 },
+ { 33, 0x0066, 0x08000046, 0x0b, 0x00, 0x0000 },
+ { 33, 0x0066, 0x0c000046, 0x0c, 0x00, 0x0000 },
+ { 33, 0x0066, 0x0c000046, 0x0d, 0x00, 0x0000 },
+ { 33, 0x0066, 0x0c000046, 0x0e, 0x00, 0x0000 },
+ { 33, 0x0066, 0x0c000046, 0x0f, 0x00, 0x0000 },
+ { 34, 0x0067, 0x00000047, 0x00, 0x00, 0x0000 },
+ { 34, 0x0047, 0x00000047, 0x01, 0x00, 0x0000 },
+ { 34, 0x0067, 0x00000047, 0x02, 0x00, 0x0000 },
+ { 34, 0x0047, 0x00000047, 0x03, 0x00, 0x0000 },
+ { 34, 0x0067, 0x04000047, 0x04, 0x00, 0x0000 },
+ { 34, 0x0067, 0x04000047, 0x05, 0x00, 0x0000 },
+ { 34, 0x0067, 0x04000047, 0x06, 0x00, 0x0000 },
+ { 34, 0x0067, 0x04000047, 0x07, 0x00, 0x0000 },
+ { 34, 0x0067, 0x08000047, 0x08, 0x00, 0x0000 },
+ { 34, 0x0067, 0x08000047, 0x09, 0x00, 0x0000 },
+ { 34, 0x0067, 0x08000047, 0x0a, 0x00, 0x0000 },
+ { 34, 0x0067, 0x08000047, 0x0b, 0x00, 0x0000 },
+ { 34, 0x0067, 0x0c000047, 0x0c, 0x00, 0x0000 },
+ { 34, 0x0067, 0x0c000047, 0x0d, 0x00, 0x0000 },
+ { 34, 0x0067, 0x0c000047, 0x0e, 0x00, 0x0000 },
+ { 34, 0x0067, 0x0c000047, 0x0f, 0x00, 0x0000 },
+ { 35, 0x0068, 0x00000048, 0x00, 0x00, 0x0000 },
+ { 35, 0x0048, 0x00000048, 0x01, 0x00, 0x0000 },
+ { 35, 0x0068, 0x00000048, 0x02, 0x00, 0x0000 },
+ { 35, 0x0048, 0x00000048, 0x03, 0x00, 0x0000 },
+ { 35, 0x0068, 0x04000048, 0x04, 0x00, 0x0000 },
+ { 35, 0x0068, 0x04000048, 0x05, 0x00, 0x0000 },
+ { 35, 0x0068, 0x04000048, 0x06, 0x00, 0x0000 },
+ { 35, 0x0068, 0x04000048, 0x07, 0x00, 0x0000 },
+ { 35, 0x0068, 0x08000048, 0x08, 0x00, 0x0000 },
+ { 35, 0x0068, 0x08000048, 0x09, 0x00, 0x0000 },
+ { 35, 0x0068, 0x08000048, 0x0a, 0x00, 0x0000 },
+ { 35, 0x0068, 0x08000048, 0x0b, 0x00, 0x0000 },
+ { 35, 0x0068, 0x0c000048, 0x0c, 0x00, 0x0000 },
+ { 35, 0x0068, 0x0c000048, 0x0d, 0x00, 0x0000 },
+ { 35, 0x0068, 0x0c000048, 0x0e, 0x00, 0x0000 },
+ { 35, 0x0068, 0x0c000048, 0x0f, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0000004a, 0x00, 0x00, 0x0000 },
+ { 36, 0x004a, 0x0000004a, 0x01, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0000004a, 0x02, 0x00, 0x0000 },
+ { 36, 0x004a, 0x0000004a, 0x03, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0400004a, 0x04, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0400004a, 0x05, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0400004a, 0x06, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0400004a, 0x07, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0800004a, 0x08, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0800004a, 0x09, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0800004a, 0x0a, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0800004a, 0x0b, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0c00004a, 0x0c, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0c00004a, 0x0d, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0c00004a, 0x0e, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0c00004a, 0x0f, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0000004b, 0x00, 0x00, 0x0000 },
+ { 37, 0x004b, 0x0000004b, 0x01, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0000004b, 0x02, 0x00, 0x0000 },
+ { 37, 0x004b, 0x0000004b, 0x03, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0400004b, 0x04, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0400004b, 0x05, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0400004b, 0x06, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0400004b, 0x07, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0800004b, 0x08, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0800004b, 0x09, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0800004b, 0x0a, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0800004b, 0x0b, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0c00004b, 0x0c, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0c00004b, 0x0d, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0c00004b, 0x0e, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0c00004b, 0x0f, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0000004c, 0x00, 0x00, 0x0000 },
+ { 38, 0x004c, 0x0000004c, 0x01, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0000004c, 0x02, 0x00, 0x0000 },
+ { 38, 0x004c, 0x0000004c, 0x03, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0400004c, 0x04, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0400004c, 0x05, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0400004c, 0x06, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0400004c, 0x07, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0800004c, 0x08, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0800004c, 0x09, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0800004c, 0x0a, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0800004c, 0x0b, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0c00004c, 0x0c, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0c00004c, 0x0d, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0c00004c, 0x0e, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0c00004c, 0x0f, 0x00, 0x0000 },
+ { 39, 0x003b, 0x0000003b, 0x00, 0x00, 0x0000 },
+ { 39, 0x003a, 0x0000003a, 0x01, 0x00, 0x0000 },
+ { 40, 0x0027, 0x00000027, 0x00, 0x00, 0x0000 },
+ { 40, 0x0022, 0x00000022, 0x01, 0x00, 0x0000 },
+ { 40, 0x0027, 0x01001251, 0x02, 0x01, 0x0000 },
+ { 40, 0x0022, 0x01001257, 0x03, 0x01, 0x0000 },
+ { 40, 0x0067, 0x04000047, 0x04, 0x00, 0x0000 },
+ { 41, 0x0060, 0x00000060, 0x00, 0x00, 0x0000 },
+ { 41, 0x007e, 0x0000007e, 0x01, 0x00, 0x0000 },
+ { 41, 0x0060, 0x01001250, 0x02, 0x01, 0x0000 },
+ { 41, 0x007e, 0x01001253, 0x03, 0x01, 0x0000 },
+ { 42, 0xffff, 0x01000020, 0x00, 0x04, 0x0001 },
+ { 43, 0x005c, 0x0000005c, 0x00, 0x00, 0x0000 },
+ { 43, 0x007c, 0x0000007c, 0x01, 0x00, 0x0000 },
+ { 43, 0x005c, 0x0400005c, 0x04, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0000005a, 0x00, 0x00, 0x0000 },
+ { 44, 0x005a, 0x0000005a, 0x01, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0000005a, 0x02, 0x00, 0x0000 },
+ { 44, 0x005a, 0x0000005a, 0x03, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0400005a, 0x04, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0400005a, 0x05, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0400005a, 0x06, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0400005a, 0x07, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0800005a, 0x08, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0800005a, 0x09, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0800005a, 0x0a, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0800005a, 0x0b, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0c00005a, 0x0c, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0c00005a, 0x0d, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0c00005a, 0x0e, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0c00005a, 0x0f, 0x00, 0x0000 },
+ { 45, 0x0078, 0x00000058, 0x00, 0x00, 0x0000 },
+ { 45, 0x0058, 0x00000058, 0x01, 0x00, 0x0000 },
+ { 45, 0x0078, 0x00000058, 0x02, 0x00, 0x0000 },
+ { 45, 0x0058, 0x00000058, 0x03, 0x00, 0x0000 },
+ { 45, 0x0078, 0x04000058, 0x04, 0x00, 0x0000 },
+ { 45, 0x0078, 0x04000058, 0x05, 0x00, 0x0000 },
+ { 45, 0x0078, 0x04000058, 0x06, 0x00, 0x0000 },
+ { 45, 0x0078, 0x04000058, 0x07, 0x00, 0x0000 },
+ { 45, 0x0078, 0x08000058, 0x08, 0x00, 0x0000 },
+ { 45, 0x0078, 0x08000058, 0x09, 0x00, 0x0000 },
+ { 45, 0x0078, 0x08000058, 0x0a, 0x00, 0x0000 },
+ { 45, 0x0078, 0x08000058, 0x0b, 0x00, 0x0000 },
+ { 45, 0x0078, 0x0c000058, 0x0c, 0x00, 0x0000 },
+ { 45, 0x0078, 0x0c000058, 0x0d, 0x00, 0x0000 },
+ { 45, 0x0078, 0x0c000058, 0x0e, 0x00, 0x0000 },
+ { 45, 0x0078, 0x0c000058, 0x0f, 0x00, 0x0000 },
+ { 46, 0x0063, 0x00000043, 0x00, 0x00, 0x0000 },
+ { 46, 0x0043, 0x00000043, 0x01, 0x00, 0x0000 },
+ { 46, 0x0063, 0x00000043, 0x02, 0x00, 0x0000 },
+ { 46, 0x0043, 0x00000043, 0x03, 0x00, 0x0000 },
+ { 46, 0x0063, 0x04000043, 0x04, 0x00, 0x0000 },
+ { 46, 0x0063, 0x04000043, 0x05, 0x00, 0x0000 },
+ { 46, 0x0063, 0x04000043, 0x06, 0x00, 0x0000 },
+ { 46, 0x0063, 0x04000043, 0x07, 0x00, 0x0000 },
+ { 46, 0x0063, 0x08000043, 0x08, 0x00, 0x0000 },
+ { 46, 0x0063, 0x08000043, 0x09, 0x00, 0x0000 },
+ { 46, 0x0063, 0x08000043, 0x0a, 0x00, 0x0000 },
+ { 46, 0x0063, 0x08000043, 0x0b, 0x00, 0x0000 },
+ { 46, 0x0063, 0x0c000043, 0x0c, 0x00, 0x0000 },
+ { 46, 0x0063, 0x0c000043, 0x0d, 0x00, 0x0000 },
+ { 46, 0x0063, 0x0c000043, 0x0e, 0x00, 0x0000 },
+ { 46, 0x0063, 0x0c000043, 0x0f, 0x00, 0x0000 },
+ { 47, 0x0076, 0x00000056, 0x00, 0x00, 0x0000 },
+ { 47, 0x0056, 0x00000056, 0x01, 0x00, 0x0000 },
+ { 47, 0x0076, 0x00000056, 0x02, 0x00, 0x0000 },
+ { 47, 0x0056, 0x00000056, 0x03, 0x00, 0x0000 },
+ { 47, 0x0076, 0x04000056, 0x04, 0x00, 0x0000 },
+ { 47, 0x0076, 0x04000056, 0x05, 0x00, 0x0000 },
+ { 47, 0x0076, 0x04000056, 0x06, 0x00, 0x0000 },
+ { 47, 0x0076, 0x04000056, 0x07, 0x00, 0x0000 },
+ { 47, 0x0076, 0x08000056, 0x08, 0x00, 0x0000 },
+ { 47, 0x0076, 0x08000056, 0x09, 0x00, 0x0000 },
+ { 47, 0x0076, 0x08000056, 0x0a, 0x00, 0x0000 },
+ { 47, 0x0076, 0x08000056, 0x0b, 0x00, 0x0000 },
+ { 47, 0x0076, 0x0c000056, 0x0c, 0x00, 0x0000 },
+ { 47, 0x0076, 0x0c000056, 0x0d, 0x00, 0x0000 },
+ { 47, 0x0076, 0x0c000056, 0x0e, 0x00, 0x0000 },
+ { 47, 0x0076, 0x0c000056, 0x0f, 0x00, 0x0000 },
+ { 48, 0x0062, 0x00000042, 0x00, 0x00, 0x0000 },
+ { 48, 0x0042, 0x00000042, 0x01, 0x00, 0x0000 },
+ { 48, 0x0062, 0x00000042, 0x02, 0x00, 0x0000 },
+ { 48, 0x0042, 0x00000042, 0x03, 0x00, 0x0000 },
+ { 48, 0x0062, 0x04000042, 0x04, 0x00, 0x0000 },
+ { 48, 0x0062, 0x04000042, 0x05, 0x00, 0x0000 },
+ { 48, 0x0062, 0x04000042, 0x06, 0x00, 0x0000 },
+ { 48, 0x0062, 0x04000042, 0x07, 0x00, 0x0000 },
+ { 48, 0x0062, 0x08000042, 0x08, 0x00, 0x0000 },
+ { 48, 0x0062, 0x08000042, 0x09, 0x00, 0x0000 },
+ { 48, 0x0062, 0x08000042, 0x0a, 0x00, 0x0000 },
+ { 48, 0x0062, 0x08000042, 0x0b, 0x00, 0x0000 },
+ { 48, 0x0062, 0x0c000042, 0x0c, 0x00, 0x0000 },
+ { 48, 0x0062, 0x0c000042, 0x0d, 0x00, 0x0000 },
+ { 48, 0x0062, 0x0c000042, 0x0e, 0x00, 0x0000 },
+ { 48, 0x0062, 0x0c000042, 0x0f, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0000004e, 0x00, 0x00, 0x0000 },
+ { 49, 0x004e, 0x0000004e, 0x01, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0000004e, 0x02, 0x00, 0x0000 },
+ { 49, 0x004e, 0x0000004e, 0x03, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0400004e, 0x04, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0400004e, 0x05, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0400004e, 0x06, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0400004e, 0x07, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0800004e, 0x08, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0800004e, 0x09, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0800004e, 0x0a, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0800004e, 0x0b, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0c00004e, 0x0c, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0c00004e, 0x0d, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0c00004e, 0x0e, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0c00004e, 0x0f, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0000004d, 0x00, 0x00, 0x0000 },
+ { 50, 0x004d, 0x0000004d, 0x01, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0000004d, 0x02, 0x00, 0x0000 },
+ { 50, 0x004d, 0x0000004d, 0x03, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0400004d, 0x04, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0400004d, 0x05, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0400004d, 0x06, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0400004d, 0x07, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0800004d, 0x08, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0800004d, 0x09, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0800004d, 0x0a, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0800004d, 0x0b, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0c00004d, 0x0c, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0c00004d, 0x0d, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0c00004d, 0x0e, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0c00004d, 0x0f, 0x00, 0x0000 },
+ { 51, 0x002c, 0x0000002c, 0x00, 0x00, 0x0000 },
+ { 51, 0x003c, 0x0000003c, 0x01, 0x00, 0x0000 },
+ { 51, 0x002c, 0x0100125b, 0x02, 0x01, 0x0000 },
+ { 52, 0x002e, 0x0000002e, 0x00, 0x00, 0x0000 },
+ { 52, 0x003e, 0x0000003e, 0x01, 0x00, 0x0000 },
+ { 52, 0xffff, 0x01001120, 0x02, 0x00, 0x0000 },
+ { 53, 0x002f, 0x0000002f, 0x00, 0x00, 0x0000 },
+ { 53, 0x003f, 0x0000003f, 0x01, 0x00, 0x0000 },
+ { 53, 0xffff, 0x01000003, 0x04, 0x00, 0x0000 },
+ { 54, 0xffff, 0x01000020, 0x00, 0x04, 0x0001 },
+ { 55, 0x002a, 0x2000002a, 0x00, 0x00, 0x0000 },
+ { 56, 0xffff, 0x01000023, 0x00, 0x04, 0x0008 },
+ { 57, 0x0020, 0x00000020, 0x00, 0x00, 0x0000 },
+ { 58, 0xffff, 0x01000024, 0x00, 0x00, 0x0000 },
+ { 59, 0xffff, 0x01000030, 0x00, 0x00, 0x0000 },
+ { 59, 0xffff, 0x0100003c, 0x01, 0x00, 0x0000 },
+ { 59, 0xffff, 0x01000048, 0x04, 0x00, 0x0000 },
+ { 59, 0xffff, 0x01000000, 0x0c, 0x08, 0x0100 },
+ { 60, 0xffff, 0x01000031, 0x00, 0x00, 0x0000 },
+ { 60, 0xffff, 0x0100003d, 0x01, 0x00, 0x0000 },
+ { 60, 0xffff, 0x01000049, 0x04, 0x00, 0x0000 },
+ { 60, 0xffff, 0x01000000, 0x0c, 0x08, 0x0101 },
+ { 61, 0xffff, 0x01000032, 0x00, 0x00, 0x0000 },
+ { 61, 0xffff, 0x0100003e, 0x01, 0x00, 0x0000 },
+ { 61, 0xffff, 0x0100004a, 0x04, 0x00, 0x0000 },
+ { 61, 0xffff, 0x01000000, 0x0c, 0x08, 0x0102 },
+ { 62, 0xffff, 0x01000033, 0x00, 0x00, 0x0000 },
+ { 62, 0xffff, 0x0100003f, 0x01, 0x00, 0x0000 },
+ { 62, 0xffff, 0x0100004b, 0x04, 0x00, 0x0000 },
+ { 62, 0xffff, 0x01000000, 0x0c, 0x08, 0x0103 },
+ { 63, 0xffff, 0x01000034, 0x00, 0x00, 0x0000 },
+ { 63, 0xffff, 0x01000040, 0x01, 0x00, 0x0000 },
+ { 63, 0xffff, 0x0100004c, 0x04, 0x00, 0x0000 },
+ { 63, 0xffff, 0x01000000, 0x0c, 0x08, 0x0104 },
+ { 64, 0xffff, 0x01000035, 0x00, 0x00, 0x0000 },
+ { 64, 0xffff, 0x01000041, 0x01, 0x00, 0x0000 },
+ { 64, 0xffff, 0x0100004d, 0x04, 0x00, 0x0000 },
+ { 64, 0xffff, 0x01000000, 0x0c, 0x08, 0x0105 },
+ { 65, 0xffff, 0x01000036, 0x00, 0x00, 0x0000 },
+ { 65, 0xffff, 0x01000042, 0x01, 0x00, 0x0000 },
+ { 65, 0xffff, 0x0100004e, 0x04, 0x00, 0x0000 },
+ { 65, 0xffff, 0x01000000, 0x0c, 0x08, 0x0106 },
+ { 66, 0xffff, 0x01000037, 0x00, 0x00, 0x0000 },
+ { 66, 0xffff, 0x01000043, 0x01, 0x00, 0x0000 },
+ { 66, 0xffff, 0x0100004f, 0x04, 0x00, 0x0000 },
+ { 66, 0xffff, 0x01000000, 0x0c, 0x08, 0x0107 },
+ { 67, 0xffff, 0x01000038, 0x00, 0x00, 0x0000 },
+ { 67, 0xffff, 0x01000044, 0x01, 0x00, 0x0000 },
+ { 67, 0xffff, 0x01000050, 0x04, 0x00, 0x0000 },
+ { 67, 0xffff, 0x01000000, 0x0c, 0x08, 0x0108 },
+ { 68, 0xffff, 0x01000039, 0x00, 0x00, 0x0000 },
+ { 68, 0xffff, 0x01000045, 0x01, 0x00, 0x0000 },
+ { 68, 0xffff, 0x01000051, 0x04, 0x00, 0x0000 },
+ { 68, 0xffff, 0x01000000, 0x0c, 0x08, 0x0109 },
+ { 69, 0xffff, 0x01000025, 0x00, 0x00, 0x0000 },
+ { 70, 0xffff, 0x01000026, 0x00, 0x00, 0x0000 },
+ { 70, 0xffff, 0x01000026, 0x08, 0x00, 0x0000 },
+ { 71, 0x0037, 0x20000037, 0x00, 0x00, 0x0000 },
+ { 72, 0x0038, 0x20000038, 0x00, 0x00, 0x0000 },
+ { 73, 0x0039, 0x20000039, 0x00, 0x00, 0x0000 },
+ { 74, 0x002d, 0x2000002d, 0x00, 0x00, 0x0000 },
+ { 75, 0x0034, 0x20000034, 0x00, 0x00, 0x0000 },
+ { 76, 0x0035, 0x20000035, 0x00, 0x00, 0x0000 },
+ { 77, 0x0036, 0x20000036, 0x00, 0x00, 0x0000 },
+ { 78, 0x002b, 0x2000002b, 0x00, 0x00, 0x0000 },
+ { 79, 0x0031, 0x20000031, 0x00, 0x00, 0x0000 },
+ { 80, 0x0032, 0x20000032, 0x00, 0x00, 0x0000 },
+ { 81, 0x0033, 0x20000033, 0x00, 0x00, 0x0000 },
+ { 82, 0x0030, 0x20000030, 0x00, 0x00, 0x0000 },
+ { 83, 0x002e, 0x2000002e, 0x00, 0x00, 0x0000 },
+ { 83, 0xffff, 0x01000000, 0x06, 0x08, 0x0200 },
+ { 83, 0xffff, 0x01000000, 0x0c, 0x08, 0x0200 },
+ { 86, 0x003c, 0x0000003c, 0x00, 0x00, 0x0000 },
+ { 86, 0x003e, 0x0000003e, 0x01, 0x00, 0x0000 },
+ { 86, 0x007c, 0x0000007c, 0x02, 0x00, 0x0000 },
+ { 87, 0xffff, 0x0100003a, 0x00, 0x00, 0x0000 },
+ { 87, 0xffff, 0x01000046, 0x01, 0x00, 0x0000 },
+ { 87, 0xffff, 0x01000052, 0x04, 0x00, 0x0000 },
+ { 87, 0xffff, 0x01000000, 0x0c, 0x08, 0x010a },
+ { 88, 0xffff, 0x0100003b, 0x00, 0x00, 0x0000 },
+ { 88, 0xffff, 0x01000047, 0x01, 0x00, 0x0000 },
+ { 88, 0xffff, 0x01000000, 0x0c, 0x08, 0x010b },
+ { 96, 0xffff, 0x21000005, 0x00, 0x00, 0x0000 },
+ { 97, 0xffff, 0x01000021, 0x00, 0x04, 0x0004 },
+ { 98, 0x002f, 0x2000002f, 0x00, 0x00, 0x0000 },
+ { 99, 0x005c, 0x0400005c, 0x00, 0x00, 0x0000 },
+ { 100, 0xffff, 0x01001103, 0x00, 0x04, 0x0002 },
+ { 102, 0xffff, 0x01000010, 0x00, 0x00, 0x0000 },
+ { 103, 0xffff, 0x01000013, 0x00, 0x00, 0x0000 },
+ { 104, 0xffff, 0x01000016, 0x00, 0x00, 0x0000 },
+ { 105, 0xffff, 0x01000012, 0x00, 0x00, 0x0000 },
+ { 105, 0xffff, 0x01000000, 0x0c, 0x08, 0x0180 },
+ { 106, 0xffff, 0x01000014, 0x00, 0x00, 0x0000 },
+ { 106, 0xffff, 0x01000000, 0x0c, 0x08, 0x0181 },
+ { 107, 0xffff, 0x01000011, 0x00, 0x00, 0x0000 },
+ { 108, 0xffff, 0x01000015, 0x00, 0x00, 0x0000 },
+ { 109, 0xffff, 0x01000017, 0x00, 0x00, 0x0000 },
+ { 110, 0xffff, 0x01000006, 0x00, 0x00, 0x0000 },
+ { 111, 0xffff, 0x01000007, 0x00, 0x00, 0x0000 },
+ { 111, 0xffff, 0x01000000, 0x06, 0x08, 0x0200 },
+ { 111, 0xffff, 0x01000000, 0x0c, 0x08, 0x0200 },
+ { 119, 0xffff, 0x01000008, 0x00, 0x00, 0x0000 },
+};
+
+const QWSKeyboard::Composing QWSKbPrivate::s_keycompose_default[] = {
+ { 0x0060, 0x0041, 0x00c0 },
+ { 0x0060, 0x0061, 0x00e0 },
+ { 0x0027, 0x0041, 0x00c1 },
+ { 0x0027, 0x0061, 0x00e1 },
+ { 0x005e, 0x0041, 0x00c2 },
+ { 0x005e, 0x0061, 0x00e2 },
+ { 0x007e, 0x0041, 0x00c3 },
+ { 0x007e, 0x0061, 0x00e3 },
+ { 0x0022, 0x0041, 0x00c4 },
+ { 0x0022, 0x0061, 0x00e4 },
+ { 0x002d, 0x0061, 0x00aa },
+ { 0x002d, 0x0041, 0x00aa },
+ { 0x004f, 0x0041, 0x00c5 },
+ { 0x006f, 0x0061, 0x00e5 },
+ { 0x0030, 0x0041, 0x00c5 },
+ { 0x0030, 0x0061, 0x00e5 },
+ { 0x0041, 0x0041, 0x00c5 },
+ { 0x0061, 0x0061, 0x00e5 },
+ { 0x00b0, 0x0041, 0x00c5 },
+ { 0x00b0, 0x0061, 0x00e5 },
+ { 0x0041, 0x0045, 0x00c6 },
+ { 0x0061, 0x0065, 0x00e6 },
+ { 0x002c, 0x0043, 0x00c7 },
+ { 0x002c, 0x0063, 0x00e7 },
+ { 0x005e, 0x0043, 0x00c7 },
+ { 0x005e, 0x0063, 0x00e7 },
+ { 0x0060, 0x0045, 0x00c8 },
+ { 0x0060, 0x0065, 0x00e8 },
+ { 0x0027, 0x0045, 0x00c9 },
+ { 0x0027, 0x0065, 0x00e9 },
+ { 0x005e, 0x0045, 0x00ca },
+ { 0x005e, 0x0065, 0x00ea },
+ { 0x0022, 0x0045, 0x00cb },
+ { 0x0022, 0x0065, 0x00eb },
+ { 0x0060, 0x0049, 0x00cc },
+ { 0x0060, 0x0069, 0x00ec },
+ { 0x0027, 0x0049, 0x00cd },
+ { 0x0027, 0x0069, 0x00ed },
+ { 0x005e, 0x0049, 0x00ce },
+ { 0x005e, 0x0069, 0x00ee },
+ { 0x0022, 0x0049, 0x00cf },
+ { 0x0022, 0x0069, 0x00ef },
+ { 0x002d, 0x0044, 0x00d0 },
+ { 0x002d, 0x0064, 0x00f0 },
+ { 0x005e, 0x0044, 0x00d0 },
+ { 0x005e, 0x0064, 0x00f0 },
+ { 0x007e, 0x004e, 0x00d1 },
+ { 0x007e, 0x006e, 0x00f1 },
+ { 0x005e, 0x004e, 0x00d1 },
+ { 0x005e, 0x006e, 0x00f1 },
+ { 0x0060, 0x004f, 0x00d2 },
+ { 0x0060, 0x006f, 0x00f2 },
+ { 0x0027, 0x004f, 0x00d3 },
+ { 0x0027, 0x006f, 0x00f3 },
+ { 0x005e, 0x004f, 0x00d4 },
+ { 0x005e, 0x006f, 0x00f4 },
+ { 0x007e, 0x004f, 0x00d5 },
+ { 0x007e, 0x006f, 0x00f5 },
+ { 0x0022, 0x004f, 0x00d6 },
+ { 0x0022, 0x006f, 0x00f6 },
+ { 0x002f, 0x004f, 0x00d8 },
+ { 0x002f, 0x006f, 0x00f8 },
+ { 0x002d, 0x006f, 0x00ba },
+ { 0x002d, 0x004f, 0x00ba },
+ { 0x0060, 0x0055, 0x00d9 },
+ { 0x0060, 0x0075, 0x00f9 },
+ { 0x0027, 0x0055, 0x00da },
+ { 0x0027, 0x0075, 0x00fa },
+ { 0x005e, 0x0055, 0x00db },
+ { 0x005e, 0x0075, 0x00fb },
+ { 0x0022, 0x0055, 0x00dc },
+ { 0x0022, 0x0075, 0x00fc },
+ { 0x0027, 0x0059, 0x00dd },
+ { 0x0027, 0x0079, 0x00fd },
+ { 0x0054, 0x0048, 0x00de },
+ { 0x0074, 0x0068, 0x00fe },
+ { 0x0073, 0x0073, 0x00df },
+ { 0x0022, 0x0079, 0x00ff },
+ { 0x0073, 0x007a, 0x00df },
+ { 0x006e, 0x006e, 0x00f1 },
+ { 0x006e, 0x0068, 0x00f1 },
+ { 0x004e, 0x0059, 0x00d1 },
+ { 0x004e, 0x004e, 0x00d1 },
+ { 0x004e, 0x0048, 0x00d1 },
+ { 0x004e, 0x0079, 0x00d1 },
+ { 0x004e, 0x006e, 0x00d1 },
+ { 0x004e, 0x0068, 0x00d1 },
+ { 0x002d, 0x004c, 0x00a3 },
+ { 0x003c, 0x003c, 0x00ab },
+ { 0x003e, 0x003e, 0x00bb },
+ { 0x003f, 0x003f, 0x00bf },
+ { 0x005e, 0x003f, 0x00bf },
+ { 0x0021, 0x0021, 0x00a1 },
+ { 0x005e, 0x0021, 0x00a1 },
+ { 0x005e, 0x0031, 0x00b9 },
+ { 0x005e, 0x0032, 0x00b2 },
+ { 0x005e, 0x0033, 0x00b3 },
+ { 0x002b, 0x002d, 0x00b1 },
+ { 0x0063, 0x003d, 0x00a2 },
+ { 0x0063, 0x002f, 0x00a2 },
+ { 0x002f, 0x0063, 0x00a2 },
+ { 0x002d, 0x0063, 0x00a2 },
+ { 0x002d, 0x0043, 0x00a2 },
+ { 0x004c, 0x003d, 0x00a3 },
+ { 0x002d, 0x004c, 0x00a3 },
+ { 0x002d, 0x006c, 0x00a3 },
+ { 0x005e, 0x002a, 0x00d7 },
+ { 0x005e, 0x0078, 0x00d7 },
+ { 0x0078, 0x0078, 0x00d7 },
+ { 0x005e, 0x002e, 0x00b7 },
+ { 0x002e, 0x002e, 0x00b7 },
+ { 0x005e, 0x002f, 0x00f7 },
+ { 0x005e, 0x003a, 0x00f7 },
+ { 0x002d, 0x003a, 0x00f7 },
+ { 0x003a, 0x002d, 0x00f7 },
+ { 0x0059, 0x003d, 0x00a5 },
+ { 0x002d, 0x0059, 0x00a5 },
+ { 0x002d, 0x006c, 0x00a5 },
+ { 0x0028, 0x0063, 0x00a9 },
+ { 0x0022, 0x0063, 0x00a9 },
+ { 0x002d, 0x0061, 0x00aa },
+ { 0x002d, 0x0041, 0x00aa },
+ { 0x002d, 0x006f, 0x00ba },
+ { 0x002d, 0x004f, 0x00ba },
+ { 0x0028, 0x0072, 0x00ae },
+ { 0x0022, 0x0072, 0x00ae },
+ { 0x006d, 0x0075, 0x00b5 },
+ { 0x0031, 0x0034, 0x0152 },
+ { 0x0031, 0x0032, 0x0153 },
+ { 0x0033, 0x0034, 0x0178 },
+ { 0x0065, 0x003d, 0x20ac },
+ { 0x002d, 0x0065, 0x20ac },
+ { 0x002d, 0x0045, 0x20ac },
+ { 0x0076, 0x0053, 0x0160 },
+ { 0x005e, 0x0053, 0x0160 },
+ { 0x0076, 0x0073, 0x0161 },
+ { 0x005e, 0x0073, 0x0161 },
+ { 0x0076, 0x005a, 0x017d },
+ { 0x005e, 0x005a, 0x017d },
+ { 0x0076, 0x007a, 0x017e },
+ { 0x005e, 0x007a, 0x017e },
+ { 0x004f, 0x0045, 0x0152 },
+ { 0x004f, 0x0065, 0x0152 },
+ { 0x006f, 0x0065, 0x0153 },
+ { 0x0022, 0x0059, 0x0178 },
+ { 0x0069, 0x006a, 0x00ff },
+ { 0x0049, 0x004a, 0x0178 },
+};
+
+#endif
diff --git a/src/gui/embedded/qkbd_qws.cpp b/src/gui/embedded/qkbd_qws.cpp
index 43f7774..4d97ba7 100644
--- a/src/gui/embedded/qkbd_qws.cpp
+++ b/src/gui/embedded/qkbd_qws.cpp
@@ -40,56 +40,217 @@
****************************************************************************/
#include "qkbd_qws.h"
+#include "qkbd_qws_p.h"
#ifndef QT_NO_QWS_KEYBOARD
+#include <QFile>
+#include <QDataStream>
+#include <QStringList>
+
#include "qwindowsystem_qws.h"
#include "qscreen_qws.h"
#include "qtimer.h"
#include <stdlib.h>
+//#define QT_DEBUG_KEYMAP
+
+
QT_BEGIN_NAMESPACE
class QWSKbPrivate : public QObject
{
Q_OBJECT
public:
- QWSKbPrivate(QWSKeyboardHandler *h) {
- handler = h;
- arTimer = new QTimer(this);
- arTimer->setSingleShot(true);
- connect(arTimer, SIGNAL(timeout()), SLOT(autoRepeat()));
- repeatdelay = 400;
- repeatperiod = 80;
+ QWSKbPrivate(QWSKeyboardHandler *h, const QString &device)
+ : m_handler(h), m_modifiers(0), m_composing(0), m_dead_unicode(0xffff),
+ m_no_zap(false), m_do_compose(false),
+ m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0)
+ {
+ m_ar_timer = new QTimer(this);
+ m_ar_timer->setSingleShot(true);
+ connect(m_ar_timer, SIGNAL(timeout()), SLOT(autoRepeat()));
+ m_ar_delay = 400;
+ m_ar_period = 80;
+
+ memset(m_locks, 0, sizeof(m_locks));
+
+ QString keymap;
+ QStringList args = device.split(QLatin1Char(':'));
+ foreach (const QString &arg, args) {
+ if (arg.startsWith(QLatin1String("keymap=")))
+ keymap = arg.mid(7);
+ else if (arg == QLatin1String("disable-zap"))
+ m_no_zap = true;
+ else if (arg == QLatin1String("enable-compose"))
+ m_do_compose = true;
+ else if (arg.startsWith(QLatin1String("repeat-delay=")))
+ m_ar_delay = arg.mid(13).toInt();
+ else if (arg.startsWith(QLatin1String("repeat-rate=")))
+ m_ar_period = arg.mid(12).toInt();
+ }
+
+ if (keymap.isEmpty() || !loadKeymap(keymap))
+ unloadKeymap();
}
- void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod) {
- unicode = uni;
- keycode = code;
- modifier = mod;
- arTimer->start(repeatdelay);
+ ~QWSKbPrivate()
+ {
+ unloadKeymap();
}
- void endAutoRepeat() {
- arTimer->stop();
+
+ void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod)
+ {
+ m_ar_unicode = uni;
+ m_ar_keycode = code;
+ m_ar_modifier = mod;
+ m_ar_timer->start(m_ar_delay);
+ }
+
+ void endAutoRepeat()
+ {
+ m_ar_timer->stop();
}
+ static Qt::KeyboardModifiers toQtModifiers(quint8 mod)
+ {
+ Qt::KeyboardModifiers qtmod = Qt::NoModifier;
+
+ if (mod & (QWSKeyboard::ModShift | QWSKeyboard::ModShiftL | QWSKeyboard::ModShiftR))
+ qtmod |= Qt::ShiftModifier;
+ if (mod & (QWSKeyboard::ModControl | QWSKeyboard::ModCtrlL | QWSKeyboard::ModCtrlR))
+ qtmod |= Qt::ControlModifier;
+ if (mod & QWSKeyboard::ModAlt)
+ qtmod |= Qt::AltModifier;
+
+ return qtmod;
+ }
+
+ void unloadKeymap();
+ bool loadKeymap(const QString &file);
+
private slots:
- void autoRepeat() {
- handler->processKeyEvent(unicode, keycode, modifier, false, true);
- handler->processKeyEvent(unicode, keycode, modifier, true, true);
- arTimer->start(repeatperiod);
+ void autoRepeat()
+ {
+ m_handler->processKeyEvent(m_ar_unicode, m_ar_keycode, m_ar_modifier, false, true);
+ m_handler->processKeyEvent(m_ar_unicode, m_ar_keycode, m_ar_modifier, true, true);
+ m_ar_timer->start(m_ar_period);
}
private:
- QWSKeyboardHandler *handler;
- int unicode;
- int keycode;
- Qt::KeyboardModifiers modifier;
- int repeatdelay;
- int repeatperiod;
- QTimer *arTimer;
+ QWSKeyboardHandler *m_handler;
+
+ // auto repeat simulation
+ int m_ar_unicode;
+ int m_ar_keycode;
+ Qt::KeyboardModifiers m_ar_modifier;
+ int m_ar_delay;
+ int m_ar_period;
+ QTimer *m_ar_timer;
+
+ // keymap handling
+ quint8 m_modifiers;
+ quint8 m_locks[3];
+ int m_composing;
+ quint16 m_dead_unicode;
+
+ bool m_no_zap;
+ bool m_do_compose;
+
+ const QWSKeyboard::Mapping *m_keymap;
+ int m_keymap_size;
+ const QWSKeyboard::Composing *m_keycompose;
+ int m_keycompose_size;
+
+ static const QWSKeyboard::Mapping s_keymap_default[];
+ static const QWSKeyboard::Composing s_keycompose_default[];
+
+ friend class QWSKeyboardHandler;
};
+// simple builtin US keymap
+#include "qkbd_defaultmap_qws_p.h"
+
+// the unloadKeymap() function needs to be AFTER the defaultmap include,
+// since the sizeof(s_keymap_default) wouldn't work otherwise.
+
+void QWSKbPrivate::unloadKeymap()
+{
+ if (m_keymap && m_keymap != s_keymap_default)
+ delete [] m_keymap;
+ if (m_keycompose && m_keycompose != s_keycompose_default)
+ delete [] m_keycompose;
+
+ m_keymap = s_keymap_default;
+ m_keymap_size = sizeof(s_keymap_default) / sizeof(s_keymap_default[0]);
+ m_keycompose = s_keycompose_default;
+ m_keycompose_size = sizeof(s_keycompose_default) / sizeof(s_keycompose_default[0]);
+
+ // reset state, so we could switch keymaps at runtime
+ m_modifiers = 0;
+ memset(m_locks, 0, sizeof(m_locks));
+ m_composing = 0;
+ m_dead_unicode = 0xffff;
+}
+
+bool QWSKbPrivate::loadKeymap(const QString &file)
+{
+ QFile f(file);
+
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Could not open keymap file '%s'", qPrintable(file));
+ return false;
+ }
+
+ // .qmap files have a very simple structure:
+ // quint32 magic (QWSKeyboard::FileMagic)
+ // quint32 version (1)
+ // quint32 keymap_size (# of struct QWSKeyboard::Mappings)
+ // quint32 keycompose_size (# of struct QWSKeyboard::Composings)
+ // all QWSKeyboard::Mappings via QDataStream::operator(<<|>>)
+ // all QWSKeyboard::Composings via QDataStream::operator(<<|>>)
+
+ quint32 qmap_magic, qmap_version, qmap_keymap_size, qmap_keycompose_size;
+
+ QDataStream ds(&f);
+
+ ds >> qmap_magic >> qmap_version >> qmap_keymap_size >> qmap_keycompose_size;
+
+ if (ds.status() != QDataStream::Ok || qmap_magic != QWSKeyboard::FileMagic || qmap_version != 1 || qmap_keymap_size == 0) {
+ qWarning("'%s' is ot a valid.qmap keymap file.", qPrintable(file));
+ return false;
+ }
+
+ QWSKeyboard::Mapping *qmap_keymap = new QWSKeyboard::Mapping[qmap_keymap_size];
+ QWSKeyboard::Composing *qmap_keycompose = qmap_keycompose_size ? new QWSKeyboard::Composing[qmap_keycompose_size] : 0;
+
+ for (quint32 i = 0; i < qmap_keymap_size; ++i)
+ ds >> qmap_keymap[i];
+ for (quint32 i = 0; i < qmap_keycompose_size; ++i)
+ ds >> qmap_keycompose[i];
+
+ if (ds.status() != QDataStream::Ok) {
+ delete [] qmap_keymap;
+ delete [] qmap_keycompose;
+
+ qWarning("Keymap file '%s' can not be loaded.", qPrintable(file));
+ return false;
+ }
+
+ // unload currently active and clear state
+ unloadKeymap();
+
+ m_keymap = qmap_keymap;
+ m_keymap_size = qmap_keymap_size;
+ m_keycompose = qmap_keycompose;
+ m_keycompose_size = qmap_keycompose_size;
+
+ m_do_compose = true;
+
+ return true;
+}
+
+
/*!
\class QWSKeyboardHandler
\ingroup qws
@@ -132,18 +293,29 @@ private:
/*!
- Constructs a keyboard driver.
+ Constructs a keyboard driver. The \a device argument is passed by the
+ QWS_KEYBOARD environment variable.
Call the QWSServer::setKeyboardHandler() function to make the
newly created keyboard driver, the primary driver. Note that the
primary driver is controlled by the system, i.e., the system will
delete it upon exit.
*/
+QWSKeyboardHandler::QWSKeyboardHandler(const QString &device)
+{
+ d = new QWSKbPrivate(this, device);
+}
+
+/*!
+ \overload
+*/
QWSKeyboardHandler::QWSKeyboardHandler()
{
- d = new QWSKbPrivate(this);
+ d = new QWSKbPrivate(this, QString());
}
+
+
/*!
Destroys this keyboard driver.
@@ -172,7 +344,10 @@ QWSKeyboardHandler::~QWSKeyboardHandler()
event is caused by an auto-repeat mechanism and not an actual key
press.
- \sa beginAutoRepeat(), endAutoRepeat(), transformDirKey()
+ Note that this function does not handle key mapping. Please use
+ processKeycode() if you need that functionality.
+
+ \sa processKeycode(), beginAutoRepeat(), endAutoRepeat(), transformDirKey()
*/
void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
bool isPress, bool autoRepeat)
@@ -241,6 +416,254 @@ void QWSKeyboardHandler::endAutoRepeat()
d->endAutoRepeat();
}
+/*!
+ \enum QWSKeyboardHandler::KeycodeAction
+
+ This enum describes the various special actions that actual
+ QWSKeyboardHandler implementations have to take care of.
+
+ \value None No further action required.
+
+ \value CapsLockOn Set the state of the Caps lock LED to on.
+ \value CapsLockOff Set the state of the Caps lock LED to off.
+ \value NumLockOn Set the state of the Num lock LED to on.
+ \value NumLockOff Set the state of the Num lock LED to off.
+ \value ScrollLockOn Set the state of the Scroll lock LED to on.
+ \value ScrollLockOff Set the state of the Scroll lock LED to off.
+
+ \value PreviousConsole Switch to the previous virtual console (by
+ default Ctrl+Alt+Left on Linux).
+ \value NextConsole Switch to the next virtual console (by default
+ Ctrl+Alt+Right on Linux).
+ \value SwitchConsoleFirst Switch to the first virtual console (0).
+ \value SwitchConsoleLast Switch to the last virtual console (255).
+ \value SwitchConsoleMask If the KeyAction value is between SwitchConsoleFirst
+ and SwitchConsoleLast, you can use this mask to get
+ the specific virtual console number to switch to.
+
+ \value Reboot Reboot the machine - this is ignored in both the TTY and
+ LinuxInput handlers though (by default Ctrl+Alt+Del on Linux).
+
+ \sa processKeycode()
+*/
+
+/*!
+ \fn QWSKeyboardHandler::KeycodeAction QWSKeyboardHandler::processKeycode(quint16 keycode, bool isPress, bool autoRepeat)
+
+ Maps \a keycode according to a keymap and sends that key event to the
+ \l{Qt for Embedded Linux} server application.
+
+ Please see the \l{Qt for Embedded Linux Character Input} and the \l
+ {kmap2qmap} documentations for a description on how to create and use
+ keymap files.
+
+ The key event is identified by its \a keycode value and the \a isPress
+ and \a autoRepeat parameters.
+
+ The \a keycode parameter is \bold NOT the Qt keycode value as defined by
+ the Qt::Key enum. This functions expects a standard Linux 16 bit kernel
+ keycode as it is used in the Linux Input Event sub-system. This
+ \a keycode is transformed to a Qt::Key code by using either a
+ compiled-in US keyboard layout or by dynamically loading a keymap at
+ startup which can be specified via the QWS_KEYBOARD environment
+ variable.
+
+ The \a isPress parameter is true if the event is a key press event and
+ \a autoRepeat is true if the event is caused by an auto-repeat mechanism
+ and not an actual key press.
+
+ The return value indicates if the actual QWSKeyboardHandler
+ implementation needs to take care of a special action, like console
+ switching or LED handling.
+
+ If standard Linux console keymaps are used, \a keycode must be one of the
+ standardized values defined in \c /usr/include/linux/input.h
+
+ \sa processKeyEvent(), KeycodeAction
+*/
+
+QWSKeyboardHandler::KeycodeAction QWSKeyboardHandler::processKeycode(quint16 keycode, bool pressed, bool autorepeat)
+{
+ KeycodeAction result = None;
+ bool first_press = pressed && !autorepeat;
+
+ const QWSKeyboard::Mapping *map_plain = 0;
+ const QWSKeyboard::Mapping *map_withmod = 0;
+
+ // get a specific and plain mapping for the keycode and the current modifiers
+ for (int i = 0; i < d->m_keymap_size && !(map_plain && map_withmod); ++i) {
+ const QWSKeyboard::Mapping *m = d->m_keymap + i;
+ if (m->keycode == keycode) {
+ if (m->modifiers == 0)
+ map_plain = m;
+
+ quint8 testmods = d->m_modifiers;
+ if (d->m_locks[0] /*CapsLock*/ && (m->flags & QWSKeyboard::IsLetter))
+ testmods ^= QWSKeyboard::ModShift;
+ if (m->modifiers == testmods)
+ map_withmod = m;
+ }
+ }
+
+#ifdef QT_DEBUG_KEYMAP
+ qWarning("Processing key event: keycode=%3d, modifiers=%02x pressed=%d, autorepeat=%d | plain=%d, withmod=%d, size=%d", \
+ keycode, d->m_modifiers, pressed ? 1 : 0, autorepeat ? 1 : 0, \
+ map_plain ? map_plain - d->m_keymap : -1, \
+ map_withmod ? map_withmod - d->m_keymap : -1, \
+ d->m_keymap_size);
+#endif
+
+ const QWSKeyboard::Mapping *it = map_withmod ? map_withmod : map_plain;
+
+ if (!it) {
+#ifdef QT_DEBUG_KEYMAP
+ // we couldn't even find a plain mapping
+ qWarning("Could not find a suitable mapping for keycode: %3d, modifiers: %02x", keycode, d->m_modifiers);
+#endif
+ return result;
+ }
+
+ bool skip = false;
+ quint16 unicode = it->unicode;
+ quint32 qtcode = it->qtcode;
+
+ if ((it->flags & QWSKeyboard::IsModifier) && it->special) {
+ // this is a modifier, i.e. Shift, Alt, ...
+ if (pressed)
+ d->m_modifiers |= quint8(it->special);
+ else
+ d->m_modifiers &= ~quint8(it->special);
+ } else if (qtcode >= Qt::Key_CapsLock && qtcode <= Qt::Key_ScrollLock) {
+ // (Caps|Num|Scroll)Lock
+ if (first_press) {
+ quint8 &lock = d->m_locks[qtcode - Qt::Key_CapsLock];
+ lock ^= 1;
+
+ switch (qtcode) {
+ case Qt::Key_CapsLock : result = lock ? CapsLockOn : CapsLockOff; break;
+ case Qt::Key_NumLock : result = lock ? NumLockOn : NumLockOff; break;
+ case Qt::Key_ScrollLock: result = lock ? ScrollLockOn : ScrollLockOff; break;
+ default : break;
+ }
+ }
+ } else if ((it->flags & QWSKeyboard::IsSystem) && it->special && first_press) {
+ switch (it->special) {
+ case QWSKeyboard::SystemReboot:
+ result = Reboot;
+ break;
+
+ case QWSKeyboard::SystemZap:
+ if (!d->m_no_zap)
+ qApp->quit();
+ break;
+
+ case QWSKeyboard::SystemConsolePrevious:
+ result = PreviousConsole;
+ break;
+
+ case QWSKeyboard::SystemConsoleNext:
+ result = NextConsole;
+ break;
+
+ default:
+ if (it->special >= QWSKeyboard::SystemConsoleFirst &&
+ it->special <= QWSKeyboard::SystemConsoleLast) {
+ result = KeycodeAction(SwitchConsoleFirst + ((it->special & QWSKeyboard::SystemConsoleMask) & SwitchConsoleMask));
+ }
+ break;
+ }
+
+ skip = true; // no need to tell QWS about it
+ } else if ((qtcode == Qt::Key_Multi_key) && d->m_do_compose) {
+ // the Compose key was pressed
+ if (first_press)
+ d->m_composing = 2;
+ skip = true;
+ } else if ((it->flags & QWSKeyboard::IsDead) && d->m_do_compose) {
+ // a Dead key was pressed
+ if (first_press && d->m_composing == 1 && d->m_dead_unicode == unicode) { // twice
+ d->m_composing = 0;
+ qtcode = Qt::Key_unknown; // otherwise it would be Qt::Key_Dead...
+ } else if (first_press && unicode != 0xffff) {
+ d->m_dead_unicode = unicode;
+ d->m_composing = 1;
+ skip = true;
+ } else {
+ skip = true;
+ }
+ }
+
+ if (!skip) {
+ // a normal key was pressed
+ const int modmask = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier;
+
+ // we couldn't find a specific mapping for the current modifiers,
+ // or that mapping didn't have special modifiers:
+ // so just report the plain mapping with additional modifiers.
+ if ((it == map_plain && it != map_withmod) ||
+ (map_withmod && !(map_withmod->qtcode & modmask))) {
+ qtcode |= QWSKbPrivate::toQtModifiers(d->m_modifiers);
+ }
+
+ if (d->m_composing == 2 && first_press && !(it->flags & QWSKeyboard::IsModifier)) {
+ // the last key press was the Compose key
+ if (unicode != 0xffff) {
+ int idx = 0;
+ // check if this code is in the compose table at all
+ for ( ; idx < d->m_keycompose_size; ++idx) {
+ if (d->m_keycompose[idx].first == unicode)
+ break;
+ }
+ if (idx < d->m_keycompose_size) {
+ // found it -> simulate a Dead key press
+ d->m_dead_unicode = unicode;
+ unicode = 0xffff;
+ d->m_composing = 1;
+ skip = true;
+ } else {
+ d->m_composing = 0;
+ }
+ } else {
+ d->m_composing = 0;
+ }
+ } else if (d->m_composing == 1 && first_press && !(it->flags & QWSKeyboard::IsModifier)) {
+ // the last key press was a Dead key
+ bool valid = false;
+ if (unicode != 0xffff) {
+ int idx = 0;
+ // check if this code is in the compose table at all
+ for ( ; idx < d->m_keycompose_size; ++idx) {
+ if (d->m_keycompose[idx].first == d->m_dead_unicode && d->m_keycompose[idx].second == unicode)
+ break;
+ }
+ if (idx < d->m_keycompose_size) {
+ quint16 composed = d->m_keycompose[idx].result;
+ if (composed != 0xffff) {
+ unicode = composed;
+ qtcode = Qt::Key_unknown;
+ valid = true;
+ }
+ }
+ }
+ if (!valid) {
+ unicode = d->m_dead_unicode;
+ qtcode = Qt::Key_unknown;
+ }
+ d->m_composing = 0;
+ }
+
+ if (!skip) {
+#ifdef QT_DEBUG_KEYMAP
+ qWarning("Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode & ~modmask, (qtcode & modmask));
+#endif
+
+ // send the result to the QWS server
+ processKeyEvent(unicode, qtcode & ~modmask, Qt::KeyboardModifiers(qtcode & modmask), pressed, autorepeat);
+ }
+ }
+ return result;
+}
+
QT_END_NAMESPACE
#include "qkbd_qws.moc"
diff --git a/src/gui/embedded/qkbd_qws.h b/src/gui/embedded/qkbd_qws.h
index 25a4260..c9572c0 100644
--- a/src/gui/embedded/qkbd_qws.h
+++ b/src/gui/embedded/qkbd_qws.h
@@ -58,11 +58,33 @@ class Q_GUI_EXPORT QWSKeyboardHandler
{
public:
QWSKeyboardHandler();
+ QWSKeyboardHandler(const QString &device);
virtual ~QWSKeyboardHandler();
virtual void processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
bool isPress, bool autoRepeat);
+ enum KeycodeAction {
+ None = 0,
+
+ CapsLockOff = 0x01000000,
+ CapsLockOn = 0x01000001,
+ NumLockOff = 0x02000000,
+ NumLockOn = 0x02000001,
+ ScrollLockOff = 0x03000000,
+ ScrollLockOn = 0x03000001,
+
+ Reboot = 0x04000000,
+
+ PreviousConsole = 0x05000000,
+ NextConsole = 0x05000001,
+ SwitchConsoleFirst = 0x06000000,
+ SwitchConsoleLast = 0x0600007f,
+ SwitchConsoleMask = 0x0000007f,
+ };
+
+ KeycodeAction processKeycode(quint16 keycode, bool pressed, bool autorepeat);
+
protected:
int transformDirKey(int key);
void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod);
diff --git a/src/gui/embedded/qkbd_qws_p.h b/src/gui/embedded/qkbd_qws_p.h
new file mode 100644
index 0000000..5af8f7c
--- /dev/null
+++ b/src/gui/embedded/qkbd_qws_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSKEYBOARD_P_H
+#define QWSKEYBOARD_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 <QDataStream>
+
+QT_BEGIN_NAMESPACE
+
+namespace QWSKeyboard {
+ const quint32 FileMagic = 0x514d4150; // 'QMAP'
+
+ struct Mapping {
+ quint16 keycode;
+ quint16 unicode;
+ quint32 qtcode;
+ quint8 modifiers;
+ quint8 flags;
+ quint16 special;
+
+ };
+
+ enum Flags {
+ IsDead = 0x01,
+ IsLetter = 0x02,
+ IsModifier = 0x04,
+ IsSystem = 0x08,
+ };
+
+ enum System {
+ SystemConsoleFirst = 0x0100,
+ SystemConsoleMask = 0x007f,
+ SystemConsoleLast = 0x017f,
+ SystemConsolePrevious = 0x0180,
+ SystemConsoleNext = 0x0181,
+ SystemReboot = 0x0200,
+ SystemZap = 0x0300,
+ };
+
+ struct Composing {
+ quint16 first;
+ quint16 second;
+ quint16 result;
+ };
+
+ enum Modifiers {
+ ModPlain = 0x00,
+ ModShift = 0x01,
+ ModAltGr = 0x02,
+ ModControl = 0x04,
+ ModAlt = 0x08,
+ ModShiftL = 0x10,
+ ModShiftR = 0x20,
+ ModCtrlL = 0x40,
+ ModCtrlR = 0x80,
+ // ModCapsShift = 0x100, // not supported!
+ };
+};
+
+#ifndef QT_NO_DATASTREAM
+inline QDataStream &operator>>(QDataStream &ds, QWSKeyboard::Mapping &m)
+{
+ return ds >> m.keycode >> m.unicode >> m.qtcode >> m.modifiers >> m.flags >> m.special;
+}
+
+inline QDataStream &operator<<(QDataStream &ds, const QWSKeyboard::Mapping &m)
+{
+ return ds << m.keycode << m.unicode << m.qtcode << m.modifiers << m.flags << m.special;
+}
+
+inline QDataStream &operator>>(QDataStream &ds, QWSKeyboard::Composing &c)
+{
+ return ds >> c.first >> c.second >> c.result;
+}
+
+inline QDataStream &operator<<(QDataStream &ds, const QWSKeyboard::Composing &c)
+{
+ return ds << c.first << c.second << c.result;
+}
+#endif // QT_NO_DATASTREAM
+
+QT_END_NAMESPACE
+
+#endif // QWSKEYBOARD_H
diff --git a/src/gui/embedded/qkbddriverfactory_qws.cpp b/src/gui/embedded/qkbddriverfactory_qws.cpp
index d762dea..db02f70 100644
--- a/src/gui/embedded/qkbddriverfactory_qws.cpp
+++ b/src/gui/embedded/qkbddriverfactory_qws.cpp
@@ -45,12 +45,10 @@
#include "qapplication.h"
#include "qkbdtty_qws.h"
-#include "qkbdusb_qws.h"
+#include "qkbdlinuxinput_qws.h"
#include "qkbdum_qws.h"
-#include "qkbdsl5000_qws.h"
#include "qkbdvfb_qws.h"
-#include "qkbdyopy_qws.h"
-#include "qkbdvr41xx_qws.h"
+#include "qkbdqnx_qws.h"
#include <stdlib.h>
#include "private/qfactoryloader_p.h"
#include "qkbddriverplugin_qws.h"
@@ -104,26 +102,20 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
QWSKeyboardHandler *QKbdDriverFactory::create(const QString& key, const QString& device)
{
QString driver = key.toLower();
-#ifndef QT_NO_QWS_KBD_SL5000
- if (driver == QLatin1String("sl5000") || driver.isEmpty())
- return new QWSSL5000KeyboardHandler(device);
-#endif
-#ifndef QT_NO_QWS_KBD_YOPY
- if (driver == QLatin1String("yopy") || driver.isEmpty())
- return new QWSYopyKeyboardHandler(device);
-#endif
-#ifndef QT_NO_QWS_KBD_VR41XX
- if (driver == QLatin1String("vr41xx") || driver.isEmpty())
- return new QWSVr41xxKeyboardHandler(device);
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_KBD_QNX)
+ if (driver == QLatin1String("qnx") || driver.isEmpty())
+ return new QWSQnxKeyboardHandler(device);
#endif
#ifndef QT_NO_QWS_KEYBOARD
# ifndef QT_NO_QWS_KBD_TTY
if (driver == QLatin1String("tty") || driver.isEmpty())
return new QWSTtyKeyboardHandler(device);
# endif
-# ifndef QT_NO_QWS_KBD_USB
- if (driver == QLatin1String("usb"))
- return new QWSUsbKeyboardHandler(device);
+# ifndef QT_NO_QWS_KBD_LINUXINPUT
+ if (driver == QLatin1String("linuxinput") || \
+ driver == QLatin1String("usb") || \
+ driver == QLatin1String("linuxis"))
+ return new QWSLinuxInputKeyboardHandler(device);
# endif
# ifndef QT_NO_QWS_KBD_UM
if (driver == QLatin1String("um") || driver == QLatin1String("qvfbkeyboard"))
@@ -156,20 +148,14 @@ QStringList QKbdDriverFactory::keys()
{
QStringList list;
-#ifndef QT_NO_QWS_KBD_SL5000
- list << QLatin1String("SL5000");
-#endif
-#ifndef QT_NO_QWS_KBD_YOPY
- list << QLatin1String("YOPY");
-#endif
-#ifndef QT_NO_QWS_KBD_VR41XX
- list << QLatin1String("VR41xx");
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_KBD_QNX)
+ list << QLatin1String("QNX");
#endif
#ifndef QT_NO_QWS_KBD_TTY
list << QLatin1String("TTY");
#endif
-#ifndef QT_NO_QWS_KBD_USB
- list << QLatin1String("USB");
+#ifndef QT_NO_QWS_KBD_LINUXINPUT
+ list << QLatin1String("LinuxInput");
#endif
#ifndef QT_NO_QWS_KBD_UM
list << QLatin1String("UM");
diff --git a/src/gui/embedded/qkbdlinuxinput_qws.cpp b/src/gui/embedded/qkbdlinuxinput_qws.cpp
new file mode 100644
index 0000000..f3e498e
--- /dev/null
+++ b/src/gui/embedded/qkbdlinuxinput_qws.cpp
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdlinuxinput_qws.h"
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#include <QSocketNotifier>
+#include <QStringList>
+
+#include <qplatformdefs.h>
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
+
+#include <errno.h>
+#include <termios.h>
+
+#include <linux/kd.h>
+#include <linux/input.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QWSLinuxInputKbPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSLinuxInputKbPrivate(QWSLinuxInputKeyboardHandler *, const QString &);
+ ~QWSLinuxInputKbPrivate();
+
+private:
+ void switchLed(int, bool);
+
+private Q_SLOTS:
+ void readKeycode();
+
+private:
+ QWSLinuxInputKeyboardHandler *m_handler;
+ int m_fd;
+ int m_tty_fd;
+ struct termios m_tty_attr;
+ int m_orig_kbmode;
+};
+
+QWSLinuxInputKeyboardHandler::QWSLinuxInputKeyboardHandler(const QString &device)
+ : QWSKeyboardHandler(device)
+{
+ d = new QWSLinuxInputKbPrivate(this, device);
+}
+
+QWSLinuxInputKeyboardHandler::~QWSLinuxInputKeyboardHandler()
+{
+ delete d;
+}
+
+bool QWSLinuxInputKeyboardHandler::filterInputEvent(quint16 &, qint32 &)
+{
+ return false;
+}
+
+QWSLinuxInputKbPrivate::QWSLinuxInputKbPrivate(QWSLinuxInputKeyboardHandler *h, const QString &device)
+ : m_handler(h), m_fd(-1), m_tty_fd(-1), m_orig_kbmode(K_XLATE)
+{
+ setObjectName(QLatin1String("LinuxInputSubsystem Keyboard Handler"));
+
+ QString dev = QLatin1String("/dev/input/event1");
+ int repeat_delay = -1;
+ int repeat_rate = -1;
+
+ QStringList args = device.split(QLatin1Char(':'));
+ foreach (const QString &arg, args) {
+ if (arg.startsWith(QLatin1String("repeat-delay=")))
+ repeat_delay = arg.mid(13).toInt();
+ else if (arg.startsWith(QLatin1String("repeat-rate=")))
+ repeat_rate = arg.mid(12).toInt();
+ else if (arg.startsWith(QLatin1String("/dev/")))
+ dev = arg;
+ }
+
+ m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDWR, 0);
+ if (m_fd >= 0) {
+ if (repeat_delay > 0 && repeat_rate > 0) {
+ int kbdrep[2] = { repeat_delay, repeat_rate };
+ ::ioctl(m_fd, EVIOCSREP, kbdrep);
+ }
+
+ QSocketNotifier *notifier;
+ notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode()));
+
+ // play nice in case we are started from a shell (e.g. for debugging)
+ m_tty_fd = isatty(0) ? 0 : -1;
+
+ if (m_tty_fd >= 0) {
+ // save tty config for restore.
+ tcgetattr(m_tty_fd, &m_tty_attr);
+
+ struct ::termios termdata;
+ tcgetattr(m_tty_fd, &termdata);
+
+ // record the original mode so we can restore it again in the destructor.
+ ::ioctl(m_tty_fd, KDGKBMODE, &m_orig_kbmode);
+
+ // setting this tranlation mode is even needed in INPUT mode to prevent
+ // the shell from also interpreting codes, if the process has a tty
+ // attached: e.g. Ctrl+C wouldn't copy, but kill the application.
+ ::ioctl(m_tty_fd, KDSKBMODE, K_MEDIUMRAW);
+
+ // set the tty layer to pass-through
+ termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
+ termdata.c_oflag = 0;
+ termdata.c_cflag = CREAD | CS8;
+ termdata.c_lflag = 0;
+ termdata.c_cc[VTIME]=0;
+ termdata.c_cc[VMIN]=1;
+ cfsetispeed(&termdata, 9600);
+ cfsetospeed(&termdata, 9600);
+ tcsetattr(m_tty_fd, TCSANOW, &termdata);
+ }
+ } else {
+ qWarning("Cannot open keyboard input device '%s': %s", qPrintable(dev), strerror(errno));
+ return;
+ }
+}
+
+QWSLinuxInputKbPrivate::~QWSLinuxInputKbPrivate()
+{
+ if (m_tty_fd >= 0) {
+ ::ioctl(m_tty_fd, KDSKBMODE, m_orig_kbmode);
+ tcsetattr(m_tty_fd, TCSANOW, &m_tty_attr);
+ }
+ if (m_fd >= 0)
+ QT_CLOSE(m_fd);
+}
+
+void QWSLinuxInputKbPrivate::switchLed(int led, bool state)
+{
+ struct ::input_event led_ie;
+ ::gettimeofday(&led_ie.time, 0);
+ led_ie.type = EV_LED;
+ led_ie.code = led;
+ led_ie.value = state;
+
+ QT_WRITE(m_fd, &led_ie, sizeof(led_ie));
+}
+
+void QWSLinuxInputKbPrivate::readKeycode()
+{
+ struct ::input_event buffer[32];
+ int n = 0;
+
+ forever {
+ n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);
+
+ if (n == 0) {
+ qWarning("Got EOF from the input device.");
+ return;
+ } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
+ qWarning("Could not read from input device: %s", strerror(errno));
+ return;
+ } else if (n % sizeof(buffer[0]) == 0) {
+ break;
+ }
+ }
+
+ n /= sizeof(buffer[0]);
+
+ for (int i = 0; i < n; ++i) {
+ if (buffer[i].type != EV_KEY)
+ continue;
+
+ quint16 code = buffer[i].code;
+ qint32 value = buffer[i].value;
+
+ if (m_handler->filterInputEvent(code, value))
+ continue;
+
+ QWSKeyboardHandler::KeycodeAction ka;
+ ka = m_handler->processKeycode(code, value != 0, value == 2);
+
+ switch (ka) {
+ case QWSKeyboardHandler::CapsLockOn:
+ case QWSKeyboardHandler::CapsLockOff:
+ switchLed(LED_CAPSL, ka == QWSKeyboardHandler::CapsLockOn);
+ break;
+
+ case QWSKeyboardHandler::NumLockOn:
+ case QWSKeyboardHandler::NumLockOff:
+ switchLed(LED_NUML, ka == QWSKeyboardHandler::NumLockOn);
+ break;
+
+ case QWSKeyboardHandler::ScrollLockOn:
+ case QWSKeyboardHandler::ScrollLockOff:
+ switchLed(LED_SCROLLL, ka == QWSKeyboardHandler::ScrollLockOn);
+ break;
+
+ default:
+ // ignore console switching and reboot
+ break;
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qkbdlinuxinput_qws.moc"
+
+#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbdlinuxinput_qws.h b/src/gui/embedded/qkbdlinuxinput_qws.h
new file mode 100644
index 0000000..098a51d
--- /dev/null
+++ b/src/gui/embedded/qkbdlinuxinput_qws.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDLINUXINPUT_QWS_H
+#define QKBDLINUXINPUT_QWS_H
+
+#include <QtGui/qkbd_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#ifndef QT_NO_QWS_KBD_LINUXINPUT
+
+class QWSLinuxInputKbPrivate;
+
+class QWSLinuxInputKeyboardHandler : public QWSKeyboardHandler
+{
+public:
+ QWSLinuxInputKeyboardHandler(const QString&);
+ virtual ~QWSLinuxInputKeyboardHandler();
+
+ virtual bool filterInputEvent(quint16 &input_code, qint32 &input_value);
+
+private:
+ QWSLinuxInputKbPrivate *d;
+};
+
+#endif // QT_NO_QWS_KBD_LINUXINPUT
+
+#endif // QT_NO_QWS_KEYBOARD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDLINUXINPUT_QWS_H
diff --git a/src/gui/embedded/qkbdpc101_qws.cpp b/src/gui/embedded/qkbdpc101_qws.cpp
deleted file mode 100644
index 8e419db..0000000
--- a/src/gui/embedded/qkbdpc101_qws.cpp
+++ /dev/null
@@ -1,485 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkbdpc101_qws.h"
-
-#ifndef QT_NO_QWS_KEYBOARD
-
-#include "qscreen_qws.h"
-#include "qwindowsystem_qws.h"
-#include "qnamespace.h"
-#include "qapplication.h"
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#ifdef Q_OS_LINUX
-#include <sys/kd.h>
-#include <sys/vt.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-static const QWSKeyMap pc101KeyM[] = {
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Escape, 27 , 27 , 0xffff },
- { Qt::Key_1, '1' , '!' , 0xffff },
- { Qt::Key_2, '2' , '@' , 0xffff },
- { Qt::Key_3, '3' , '#' , 0xffff },
- { Qt::Key_4, '4' , '$' , 0xffff },
- { Qt::Key_5, '5' , '%' , 0xffff },
- { Qt::Key_6, '6' , '^' , 0xffff },
- { Qt::Key_7, '7' , '&' , 0xffff },
- { Qt::Key_8, '8' , '*' , 0xffff },
- { Qt::Key_9, '9' , '(' , 0xffff }, // 10
- { Qt::Key_0, '0' , ')' , 0xffff },
- { Qt::Key_Minus, '-' , '_' , 0xffff },
- { Qt::Key_Equal, '=' , '+' , 0xffff },
- { Qt::Key_Backspace, 8 , 8 , 0xffff },
- { Qt::Key_Tab, 9 , 9 , 0xffff },
- { Qt::Key_Q, 'q' , 'Q' , 'Q'-64 },
- { Qt::Key_W, 'w' , 'W' , 'W'-64 },
- { Qt::Key_E, 'e' , 'E' , 'E'-64 },
- { Qt::Key_R, 'r' , 'R' , 'R'-64 },
- { Qt::Key_T, 't' , 'T' , 'T'-64 }, // 20
- { Qt::Key_Y, 'y' , 'Y' , 'Y'-64 },
- { Qt::Key_U, 'u' , 'U' , 'U'-64 },
- { Qt::Key_I, 'i' , 'I' , 'I'-64 },
- { Qt::Key_O, 'o' , 'O' , 'O'-64 },
- { Qt::Key_P, 'p' , 'P' , 'P'-64 },
- { Qt::Key_BraceLeft, '[' , '{' , 0xffff },
- { Qt::Key_BraceRight, ']' , '}' , 0xffff },
- { Qt::Key_Return, 13 , 13 , 0xffff },
- { Qt::Key_Control, 0xffff , 0xffff , 0xffff },
- { Qt::Key_A, 'a' , 'A' , 'A'-64 }, // 30
- { Qt::Key_S, 's' , 'S' , 'S'-64 },
- { Qt::Key_D, 'd' , 'D' , 'D'-64 },
- { Qt::Key_F, 'f' , 'F' , 'F'-64 },
- { Qt::Key_G, 'g' , 'G' , 'G'-64 },
- { Qt::Key_H, 'h' , 'H' , 'H'-64 },
- { Qt::Key_J, 'j' , 'J' , 'J'-64 },
- { Qt::Key_K, 'k' , 'K' , 'K'-64 },
- { Qt::Key_L, 'l' , 'L' , 'L'-64 },
- { Qt::Key_Semicolon, ';' , ':' , 0xffff },
- { Qt::Key_Apostrophe, '\'' , '"' , 0xffff }, // 40
- { Qt::Key_QuoteLeft, '`' , '~' , 0xffff },
- { Qt::Key_Shift, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Backslash, '\\' , '|' , 0xffff },
- { Qt::Key_Z, 'z' , 'Z' , 'Z'-64 },
- { Qt::Key_X, 'x' , 'X' , 'X'-64 },
- { Qt::Key_C, 'c' , 'C' , 'C'-64 },
- { Qt::Key_V, 'v' , 'V' , 'V'-64 },
- { Qt::Key_B, 'b' , 'B' , 'B'-64 },
- { Qt::Key_N, 'n' , 'N' , 'N'-64 },
- { Qt::Key_M, 'm' , 'M' , 'M'-64 }, // 50
- { Qt::Key_Comma, ',' , '<' , 0xffff },
- { Qt::Key_Period, '.' , '>' , 0xffff },
- { Qt::Key_Slash, '/' , '?' , 0xffff },
- { Qt::Key_Shift, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Asterisk, '*' , '*' , 0xffff },
- { Qt::Key_Alt, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Space, ' ' , ' ' , 0xffff },
- { Qt::Key_CapsLock, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F1, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F2, 0xffff , 0xffff , 0xffff }, // 60
- { Qt::Key_F3, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F4, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F5, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F6, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F7, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F8, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F9, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F10, 0xffff , 0xffff , 0xffff },
- { Qt::Key_NumLock, 0xffff , 0xffff , 0xffff },
- { Qt::Key_ScrollLock, 0xffff , 0xffff , 0xffff }, // 70
- { Qt::Key_7, '7' , '7' , 0xffff },
- { Qt::Key_8, '8' , '8' , 0xffff },
- { Qt::Key_9, '9' , '9' , 0xffff },
- { Qt::Key_Minus, '-' , '-' , 0xffff },
- { Qt::Key_4, '4' , '4' , 0xffff },
- { Qt::Key_5, '5' , '5' , 0xffff },
- { Qt::Key_6, '6' , '6' , 0xffff },
- { Qt::Key_Plus, '+' , '+' , 0xffff },
- { Qt::Key_1, '1' , '1' , 0xffff },
- { Qt::Key_2, '2' , '2' , 0xffff }, // 80
- { Qt::Key_3, '3' , '3' , 0xffff },
- { Qt::Key_0, '0' , '0' , 0xffff },
- { Qt::Key_Period, '.' , '.' , 0xffff },
- { Qt::Key_SysReq, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Less, '<' , '>' , 0xffff },
- { Qt::Key_F11, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F12, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 90
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Enter, 13 , 13 , 0xffff },
- { Qt::Key_Control, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Slash, '/' , '/' , 0xffff },
- { Qt::Key_SysReq, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Meta, 0xffff , 0xffff , 0xffff }, // 100
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // break
- { Qt::Key_Home, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Up, 0xffff , 0xffff , 0xffff },
- { Qt::Key_PageUp, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Left, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Right, 0xffff , 0xffff , 0xffff },
- { Qt::Key_End, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Down, 0xffff , 0xffff , 0xffff },
- { Qt::Key_PageDown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Insert, 0xffff , 0xffff , 0xffff }, // 110
- { Qt::Key_Delete, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // macro
- { Qt::Key_F13, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F14, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Help, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // do
- { Qt::Key_F17, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Plus, '+' , '-' , 0xffff },
- { Qt::Key_Pause, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { 0, 0xffff , 0xffff , 0xffff }
-};
-
-static const int keyMSize = sizeof(pc101KeyM)/sizeof(QWSKeyMap)-1;
-
-//===========================================================================
-
-//
-// PC-101 type keyboards
-//
-
-/*!
- \class QWSPC101KeyboardHandler
- \ingroup qws
-
- \internal
-*/
-
-QWSPC101KeyboardHandler::QWSPC101KeyboardHandler(const QString&)
-{
- shift = false;
- alt = false;
- ctrl = false;
- extended = 0;
- prevuni = 0;
- prevkey = 0;
- caps = false;
-#if defined(QT_QWS_IPAQ)
- // iPAQ Action Key has ScanCode 0x60: 0x60|0x80 = 0xe0 == extended mode 1 !
- ipaq_return_pressed = false;
-#endif
-}
-
-QWSPC101KeyboardHandler::~QWSPC101KeyboardHandler()
-{
-}
-
-const QWSKeyMap *QWSPC101KeyboardHandler::keyMap() const
-{
- return pc101KeyM;
-}
-
-void QWSPC101KeyboardHandler::doKey(uchar code)
-{
-
- int keyCode = Qt::Key_unknown;
- bool release = false;
- int keypad = 0;
- bool softwareRepeat = false;
-
-#ifndef QT_QWS_USE_KEYCODES
- // extended?
- if (code == 224
-#if defined(QT_QWS_IPAQ)
- && !ipaq_return_pressed
-#endif
- ) {
- extended = 1;
- return;
- } else if (code == 225) {
- extended = 2;
- return;
- }
-#endif
-
- if (code & 0x80) {
- release = true;
- code &= 0x7f;
- }
-
-#ifndef QT_QWS_USE_KEYCODES
- if (extended == 1) {
- switch (code) {
- case 72:
- keyCode = Qt::Key_Up;
- break;
- case 75:
- keyCode = Qt::Key_Left;
- break;
- case 77:
- keyCode = Qt::Key_Right;
- break;
- case 80:
- keyCode = Qt::Key_Down;
- break;
- case 82:
- keyCode = Qt::Key_Insert;
- break;
- case 71:
- keyCode = Qt::Key_Home;
- break;
- case 73:
- keyCode = Qt::Key_PageUp;
- break;
- case 83:
- keyCode = Qt::Key_Delete;
- break;
- case 79:
- keyCode = Qt::Key_End;
- break;
- case 81:
- keyCode = Qt::Key_PageDown;
- break;
- case 28:
- keyCode = Qt::Key_Enter;
- break;
- case 53:
- keyCode = Qt::Key_Slash;
- break;
- case 0x1d:
- keyCode = Qt::Key_Control;
- break;
- case 0x2a:
- keyCode = Qt::Key_Print;
- break;
- case 0x38:
- keyCode = Qt::Key_Alt;
- break;
- case 0x5b:
- keyCode = Qt::Key_Super_L;
- break;
- case 0x5c:
- keyCode = Qt::Key_Super_R;
- break;
- case 0x5d:
- keyCode = Qt::Key_Menu;
- break;
-#if 0
- default:
- qDebug("extended1 code %x release %d", code, release);
- break;
-#endif
- }
- } else if (extended == 2) {
- switch (code) {
- case 0x1d:
- return;
- case 0x45:
- keyCode = Qt::Key_Pause;
- break;
- }
- } else
-#endif
- {
- if (code < keyMSize) {
- keyCode = pc101KeyM[code].key_code;
- }
-
-#if defined(QT_QWS_IPAQ) || defined(QT_QWS_EBX)
- softwareRepeat = true;
-
- switch (code) {
- case 0x7a: case 0x7b: case 0x7c: case 0x7d:
- keyCode = code - 0x7a + Qt::Key_F9;
- softwareRepeat = false;
- break;
- case 0x79:
- keyCode = Qt::Key_SysReq;
- softwareRepeat = false;
- break;
- case 0x78:
-# ifdef QT_QWS_IPAQ
- keyCode = Qt::Key_F24; // record
-# else
- keyCode = Qt::Key_Escape;
-# endif
- softwareRepeat = false;
- break;
- case 0x60:
- keyCode = Qt::Key_Return;
-# ifdef QT_QWS_IPAQ
- ipaq_return_pressed = !release;
-# endif
- break;
- case 0x67:
- keyCode = Qt::Key_Right;
- break;
- case 0x69:
- keyCode = Qt::Key_Up;
- break;
- case 0x6a:
- keyCode = Qt::Key_Down;
- break;
- case 0x6c:
- keyCode = Qt::Key_Left;
- break;
- }
-
- if (qt_screen->isTransformed()
- && keyCode >= Qt::Key_Left && keyCode <= Qt::Key_Down)
- {
- keyCode = transformDirKey(keyCode);
- }
-#endif
- /*
- Translate shift+Qt::Key_Tab to Qt::Key_Backtab
- */
- if ((keyCode == Qt::Key_Tab) && shift)
- keyCode = Qt::Key_Backtab;
- }
-
-#ifndef QT_QWS_USE_KEYCODES
- /*
- Qt::Keypad consists of extended keys 53 and 28,
- and non-extended keys 55 and 71 through 83.
- */
- if ((extended == 1) ? (code == 53 || code == 28) :
- (code == 55 || (code >= 71 && code <= 83)))
-#else
- if (code == 55 || code >= 71 && code <= 83 || code == 96
- || code == 98 || code == 118)
-#endif
- {
- keypad = Qt::KeypadModifier;
- }
-
- // Ctrl-Alt-Backspace exits qws
- if (ctrl && alt && keyCode == Qt::Key_Backspace) {
- qApp->quit();
- }
-
- if (keyCode == Qt::Key_Alt) {
- alt = !release;
- } else if (keyCode == Qt::Key_Control) {
- ctrl = !release;
- } else if (keyCode == Qt::Key_Shift) {
- shift = !release;
- } else if (keyCode == Qt::Key_CapsLock && release) {
- caps = !caps;
-#if defined(Q_OS_LINUX)
- char leds;
- ioctl(0, KDGETLED, &leds);
- leds = leds & ~LED_CAP;
- if (caps) leds |= LED_CAP;
- ioctl(0, KDSETLED, leds);
-#endif
- }
- if (keyCode != Qt::Key_unknown) {
- bool bAlt = alt;
- bool bCtrl = ctrl;
- bool bShift = shift;
- int unicode = 0;
- if (code < keyMSize) {
- if (!extended) {
- bool bCaps = shift ||
- (caps ? QChar(keyMap()[code].unicode).isLetter() : false);
- if (bCtrl)
- unicode = keyMap()[code].ctrl_unicode ? keyMap()[code].ctrl_unicode : 0xffff;
- else if (bCaps)
- unicode = keyMap()[code].shift_unicode ? keyMap()[code].shift_unicode : 0xffff;
- else
- unicode = keyMap()[code].unicode ? keyMap()[code].unicode : 0xffff;
-#ifndef QT_QWS_USE_KEYCODES
- } else if (extended==1) {
- if (code == 53)
- unicode = '/';
-#endif
- }
- }
-
- modifiers = 0;
- if (bAlt) modifiers |= Qt::AltModifier;
- if (bCtrl) modifiers |= Qt::ControlModifier;
- if (bShift) modifiers |= Qt::ShiftModifier;
- if (keypad) modifiers |= Qt::KeypadModifier;
-
- // looks wrong -- WWA
- bool repeat = false;
- if (prevuni == unicode && prevkey == keyCode && !release)
- repeat = true;
-
- processKeyEvent(unicode, keyCode, modifiers, !release, repeat);
-
- if (!release) {
- prevuni = unicode;
- prevkey = keyCode;
- } else {
- prevkey = prevuni = 0;
- }
- }
-
- if (softwareRepeat && !release)
- beginAutoRepeat(prevuni, prevkey, modifiers);
- else
- endAutoRepeat();
-
- extended = 0;
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbdqnx_qws.cpp b/src/gui/embedded/qkbdqnx_qws.cpp
new file mode 100644
index 0000000..6e147dd
--- /dev/null
+++ b/src/gui/embedded/qkbdqnx_qws.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdqnx_qws.h"
+#include "QtCore/qsocketnotifier.h"
+#include "QtCore/qdebug.h"
+
+#include <sys/dcmd_input.h>
+#include <photon/keycodes.h>
+
+#include "qplatformdefs.h"
+#include <errno.h>
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWSQnxKeyboardHandler
+ \preliminary
+ \ingroup qws
+ \since 4.6
+ \internal
+
+ \brief The QWSQnxKeyboardHandler class implements a keyboard driver
+ for the QNX \c{devi-hid} input manager.
+
+ To be able to compile this mouse handler, \l{Qt for Embedded Linux}
+ must be configured with the \c -qt-kbd-qnx option, see the
+ \l{Qt for Embedded Linux Character Input} documentation for details.
+
+ In order to use this keyboard handler, the \c{devi-hid} input manager
+ must be set up and run with the resource manager interface (option \c{-r}).
+ Also, Photon must not be running.
+
+ Example invocation from command line: \c{/usr/photon/bin/devi-hid -Pr kbd mouse}
+ Note that after running \c{devi-hid}, you will not be able to use the local
+ shell anymore. It is suggested to run the command in a shell scrip, that launches
+ a Qt application after invocation of \c{devi-hid}.
+
+ To make \l{Qt for Embedded Linux} explicitly choose the qnx keyboard
+ handler, set the QWS_KEYBOARD environment variable to \c{qnx}. By default,
+ the first keyboard device (\c{/dev/devi/keyboard0}) is used. To override, pass a device
+ name as the first and only parameter, for example
+ \c{QWS_KEYBOARD=qnx:/dev/devi/keyboard1; export QWS_KEYBOARD}.
+
+ \sa {Qt for Embedded Linux Character Input}, {Qt for Embedded Linux}
+*/
+
+/*!
+ Constructs a keyboard handler for the specified \a device, defaulting to
+ \c{/dev/devi/keyboard0}.
+
+ Note that you should never instanciate this class, instead let QKbdDriverFactory
+ handle the keyboard handlers.
+
+ \sa QKbdDriverFactory
+ */
+QWSQnxKeyboardHandler::QWSQnxKeyboardHandler(const QString &device)
+{
+ // open the keyboard device
+ keyboardFD = QT_OPEN(device.isEmpty() ? "/dev/devi/keyboard0" : device.toLatin1().constData(),
+ QT_OPEN_RDONLY);
+ if (keyboardFD == -1) {
+ qErrnoWarning(errno, "QWSQnxKeyboardHandler: Unable to open device");
+ return;
+ }
+
+ // create a socket notifier so we'll wake up whenever keyboard input is detected.
+ QSocketNotifier *notifier = new QSocketNotifier(keyboardFD, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), SLOT(socketActivated()));
+
+ qDebug() << "QWSQnxKeyboardHandler: connected.";
+
+}
+
+/*!
+ Destroys this keyboard handler and closes the connection to the keyboard device.
+ */
+QWSQnxKeyboardHandler::~QWSQnxKeyboardHandler()
+{
+ QT_CLOSE(keyboardFD);
+}
+
+/*! \internal
+ Translates the QNX keyboard events to Qt keyboard events
+ */
+void QWSQnxKeyboardHandler::socketActivated()
+{
+ _keyboard_packet packet;
+
+ // read one keyboard event
+ int bytesRead = QT_READ(keyboardFD, &packet, sizeof(_keyboard_packet));
+ if (bytesRead == -1) {
+ qErrnoWarning(errno, "QWSQnxKeyboardHandler::socketActivated(): Unable to read data.");
+ return;
+ }
+
+ // the bytes read must be the size of a keyboard packet
+ Q_ASSERT(bytesRead == sizeof(_keyboard_packet));
+
+#if 0
+ qDebug() << "keyboard got scancode"
+ << hex << packet.data.modifiers
+ << packet.data.flags
+ << packet.data.key_cap
+ << packet.data.key_sym
+ << packet.data.key_scan;
+#endif
+
+ // QNX is nice enough to translate the raw keyboard data into a QNX data structure
+ // Now we just have to translate it into a format Qt understands.
+
+ // figure out whether it's a press
+ bool isPress = packet.data.key_cap & KEY_DOWN;
+ // figure out wheter the key is still pressed and the key event is repeated
+ bool isRepeat = packet.data.key_cap & KEY_REPEAT;
+
+ Qt::Key key = Qt::Key_unknown;
+ int unicode = 0xffff;
+
+ // TODO - this switch is not complete!
+ switch (packet.data.key_scan) {
+ case KEYCODE_SPACE: key = Qt::Key_Space; unicode = 0x20; break;
+ case KEYCODE_F1: key = Qt::Key_F1; break;
+ case KEYCODE_F2: key = Qt::Key_F2; break;
+ case KEYCODE_F3: key = Qt::Key_F3; break;
+ case KEYCODE_F4: key = Qt::Key_F4; break;
+ case KEYCODE_F5: key = Qt::Key_F5; break;
+ case KEYCODE_F6: key = Qt::Key_F6; break;
+ case KEYCODE_F7: key = Qt::Key_F7; break;
+ case KEYCODE_F8: key = Qt::Key_F8; break;
+ case KEYCODE_F9: key = Qt::Key_F9; break;
+ case KEYCODE_F10: key = Qt::Key_F10; break;
+ case KEYCODE_F11: key = Qt::Key_F11; break;
+ case KEYCODE_F12: key = Qt::Key_F12; break;
+ case KEYCODE_BACKSPACE: key = Qt::Key_Backspace; break;
+ case KEYCODE_TAB: key = Qt::Key_Tab; break;
+ case KEYCODE_RETURN: key = Qt::Key_Return; break;
+ case KEYCODE_KP_ENTER: key = Qt::Key_Enter; break;
+ case KEYCODE_UP:
+ case KEYCODE_KP_UP:
+ key = Qt::Key_Up; break;
+ case KEYCODE_DOWN:
+ case KEYCODE_KP_DOWN:
+ key = Qt::Key_Down; break;
+ case KEYCODE_LEFT:
+ case KEYCODE_KP_LEFT:
+ key = Qt::Key_Left; break;
+ case KEYCODE_RIGHT:
+ case KEYCODE_KP_RIGHT:
+ key = Qt::Key_Right; break;
+ case KEYCODE_HOME:
+ case KEYCODE_KP_HOME:
+ key = Qt::Key_Home; break;
+ case KEYCODE_END:
+ case KEYCODE_KP_END:
+ key = Qt::Key_End; break;
+ case KEYCODE_PG_UP:
+ case KEYCODE_KP_PG_UP:
+ key = Qt::Key_PageUp; break;
+ case KEYCODE_PG_DOWN:
+ case KEYCODE_KP_PG_DOWN:
+ key = Qt::Key_PageDown; break;
+ case KEYCODE_INSERT:
+ case KEYCODE_KP_INSERT:
+ key = Qt::Key_Insert; break;
+ case KEYCODE_DELETE:
+ case KEYCODE_KP_DELETE:
+ key = Qt::Key_Delete; break;
+ case KEYCODE_ESCAPE:
+ key = Qt::Key_Escape; break;
+ default: // none of the above, try the key_scan directly
+ unicode = packet.data.key_scan;
+ break;
+ }
+
+ // figure out the modifiers that are currently pressed
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+ if (packet.data.flags & KEYMOD_SHIFT)
+ modifiers |= Qt::ShiftModifier;
+ if (packet.data.flags & KEYMOD_CTRL)
+ modifiers |= Qt::ControlModifier;
+ if (packet.data.flags & KEYMOD_ALT)
+ modifiers |= Qt::AltModifier;
+
+ // if the unicode value is not ascii, we ignore it.
+ // TODO - do a complete mapping between all QNX scan codes and Qt codes
+ if (unicode != 0xffff && !isascii(unicode))
+ return; // unprintable character
+
+ // call processKeyEvent. This is where all the magic happens to insert a
+ // key event into Qt's event loop.
+ // Note that for repeated key events, isPress must be true
+ // (on QNX, isPress is not set when the key event is repeated).
+ processKeyEvent(unicode, key, modifiers, isPress || isRepeat, isRepeat);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qkbdvr41xx_qws.h b/src/gui/embedded/qkbdqnx_qws.h
index 0317c96..5a94f52 100644
--- a/src/gui/embedded/qkbdvr41xx_qws.h
+++ b/src/gui/embedded/qkbdqnx_qws.h
@@ -9,8 +9,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -21,27 +21,28 @@
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QKBDVR41XX_QWS_H
-#define QKBDVR41XX_QWS_H
+#ifndef QKBDQNX_QWS_H
+#define QKBDQNX_QWS_H
+#include <QtGui/qapplication.h>
#include <QtGui/qkbd_qws.h>
QT_BEGIN_HEADER
@@ -50,24 +51,26 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_VR41XX)
+#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_QNX)
-class QWSVr41xxKbPrivate;
-
-class QWSVr41xxKeyboardHandler : public QWSKeyboardHandler
+class Q_GUI_EXPORT QWSQnxKeyboardHandler : public QObject, public QWSKeyboardHandler
{
+ Q_OBJECT
public:
- explicit QWSVr41xxKeyboardHandler(const QString&);
- virtual ~QWSVr41xxKeyboardHandler();
+ QWSQnxKeyboardHandler(const QString &device);
+ ~QWSQnxKeyboardHandler();
+
+private Q_SLOTS:
+ void socketActivated();
private:
- QWSVr41xxKbPrivate *d;
+ int keyboardFD;
};
-#endif // QT_NO_QWS_KBD_VR41XX
+#endif // QT_NO_QWS_KEYBOARD
QT_END_NAMESPACE
QT_END_HEADER
-#endif // QKBDVR41XX_QWS_H
+#endif // QKBDQNX_QWS_H
diff --git a/src/gui/embedded/qkbdsl5000_qws.cpp b/src/gui/embedded/qkbdsl5000_qws.cpp
deleted file mode 100644
index 161d427..0000000
--- a/src/gui/embedded/qkbdsl5000_qws.cpp
+++ /dev/null
@@ -1,356 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkbdsl5000_qws.h"
-
-#ifndef QT_NO_QWS_KBD_SL5000
-
-#include "qwindowsystem_qws.h"
-#include "qwsutils_qws.h"
-#include "qscreen_qws.h"
-
-#include "qapplication.h"
-#include "qnamespace.h"
-#include "qtimer.h"
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-
-#include <asm/sharp_char.h>
-
-#include <string.h>
-
-QT_BEGIN_NAMESPACE
-
-static const QWSKeyMap sl5000KeyMap[] = {
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 00
- { Qt::Key_A, 'a' , 'A' , 'A'-64 }, // 01
- { Qt::Key_B, 'b' , 'B' , 'B'-64 }, // 02
- { Qt::Key_C, 'c' , 'C' , 'C'-64 }, // 03
- { Qt::Key_D, 'd' , 'D' , 'D'-64 }, // 04
- { Qt::Key_E, 'e' , 'E' , 'E'-64 }, // 05
- { Qt::Key_F, 'f' , 'F' , 'F'-64 }, // 06
- { Qt::Key_G, 'g' , 'G' , 'G'-64 }, // 07
- { Qt::Key_H, 'h' , 'H' , 'H'-64 }, // 08
- { Qt::Key_I, 'i' , 'I' , 'I'-64 }, // 09
- { Qt::Key_J, 'j' , 'J' , 'J'-64 }, // 0a 10
- { Qt::Key_K, 'k' , 'K' , 'K'-64 }, // 0b
- { Qt::Key_L, 'l' , 'L' , 'L'-64 }, // 0c
- { Qt::Key_M, 'm' , 'M' , 'M'-64 }, // 0d
- { Qt::Key_N, 'n' , 'N' , 'N'-64 }, // 0e
- { Qt::Key_O, 'o' , 'O' , 'O'-64 }, // 0f
- { Qt::Key_P, 'p' , 'P' , 'P'-64 }, // 10
- { Qt::Key_Q, 'q' , 'Q' , 'Q'-64 }, // 11
- { Qt::Key_R, 'r' , 'R' , 'R'-64 }, // 12
- { Qt::Key_S, 's' , 'S' , 'S'-64 }, // 13
- { Qt::Key_T, 't' , 'T' , 'T'-64 }, // 14 20
- { Qt::Key_U, 'u' , 'U' , 'U'-64 }, // 15
- { Qt::Key_V, 'v' , 'V' , 'V'-64 }, // 16
- { Qt::Key_W, 'w' , 'W' , 'W'-64 }, // 17
- { Qt::Key_X, 'x' , 'X' , 'X'-64 }, // 18
- { Qt::Key_Y, 'y' , 'Y' , 'Y'-64 }, // 19
- { Qt::Key_Z, 'z' , 'Z' , 'Z'-64 }, // 1a
- { Qt::Key_Shift, 0xffff , 0xffff , 0xffff }, // 1b
- { Qt::Key_Return, 13 , 13 , 0xffff }, // 1c
- { Qt::Key_F11, 0xffff , 0xffff , 0xffff }, // 1d todo
- { Qt::Key_F22, 0xffff , 0xffff , 0xffff }, // 1e 30
- { Qt::Key_Backspace, 8 , 8 , 0xffff }, // 1f
- { Qt::Key_F31, 0xffff , 0xffff , 0xffff }, // 20
- { Qt::Key_F35, 0xffff , 0xffff , 0xffff }, // 21 light
- { Qt::Key_Escape, 0xffff , 0xffff , 0xffff }, // 22
-
- // Direction key code are for *UNROTATED* display.
- { Qt::Key_Up, 0xffff , 0xffff , 0xffff }, // 23
- { Qt::Key_Right, 0xffff , 0xffff , 0xffff }, // 24
- { Qt::Key_Left, 0xffff , 0xffff , 0xffff }, // 25
- { Qt::Key_Down, 0xffff , 0xffff , 0xffff }, // 26
-
- { Qt::Key_F33, 0xffff , 0xffff , 0xffff }, // 27 OK
- { Qt::Key_F12, 0xffff , 0xffff , 0xffff }, // 28 40 home
- { Qt::Key_1, '1' , 'q' , 'Q'-64 }, // 29
- { Qt::Key_2, '2' , 'w' , 'W'-64 }, // 2a
- { Qt::Key_3, '3' , 'e' , 'E'-64 }, // 2b
- { Qt::Key_4, '4' , 'r' , 'R'-64 }, // 2c
- { Qt::Key_5, '5' , 't' , 'T'-64 }, // 2d
- { Qt::Key_6, '6' , 'y' , 'Y'-64 }, // 2e
- { Qt::Key_7, '7' , 'u' , 'U'-64 }, // 2f
- { Qt::Key_8, '8' , 'i' , 'I'-64 }, // 30
- { Qt::Key_9, '9' , 'o' , 'O'-64 }, // 31
- { Qt::Key_0, '0' , 'p' , 'P'-64 }, // 32 50
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 33
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 34
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 35
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 36
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 37
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 38
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 39
- { Qt::Key_Minus, '-' , 'b' , 'B'-64 }, // 3a
- { Qt::Key_Plus, '+' , 'n' , 'N'-64 }, // 3b
- { Qt::Key_CapsLock, 0xffff , 0xffff , 0xffff }, // 3c 60
- { Qt::Key_At, '@' , 's' , 'S'-64 }, // 3d
- { Qt::Key_Question, '?' , '?' , 0xffff }, // 3e
- { Qt::Key_Comma, ',' , ',' , 0xffff }, // 3f
- { Qt::Key_Period, '.' , '.' , 0xffff }, // 40
- { Qt::Key_Tab, 9 , '\\' , 0xffff }, // 41
- { Qt::Key_X, 0xffff , 'x' , 'X'-64 }, // 42
- { Qt::Key_C, 0xffff , 'c' , 'C'-64 }, // 43
- { Qt::Key_V, 0xffff , 'v' , 'V'-64 }, // 44
- { Qt::Key_Slash, '/' , '/' , 0xffff }, // 45
- { Qt::Key_Apostrophe, '\'' , '\'' , 0xffff }, // 46 70
- { Qt::Key_Semicolon, ';' , ';' , 0xffff }, // 47
- { Qt::Key_QuoteDbl, '\"' , '\"' , 0xffff }, // 48
- { Qt::Key_Colon, ':' , ':' , 0xffff }, // 49
- { Qt::Key_NumberSign, '#' , 'd' , 'D'-64 }, // 4a
- { Qt::Key_Dollar, '$' , 'f' , 'F'-64 }, // 4b
- { Qt::Key_Percent, '%' , 'g' , 'G'-64 }, // 4c
- { Qt::Key_Underscore, '_' , 'h' , 'H'-64 }, // 4d
- { Qt::Key_Ampersand, '&' , 'j' , 'J'-64 }, // 4e
- { Qt::Key_Asterisk, '*' , 'k' , 'K'-64 }, // 4f
- { Qt::Key_ParenLeft, '(' , 'l' , 'L'-64 }, // 50 80
- { Qt::Key_Delete, '[' , '[' , '[' }, // 51
- { Qt::Key_Z, 0xffff , 'z' , 'Z'-64 }, // 52
- { Qt::Key_Equal, '=' , 'm' , 'M'-64 }, // 53
- { Qt::Key_ParenRight, ')' , ']' , ']' }, // 54
- { Qt::Key_AsciiTilde, '~' , '^' , '^' }, // 55
- { Qt::Key_Less, '<' , '{' , '{' }, // 56
- { Qt::Key_Greater, '>' , '}' , '}' }, // 57
- { Qt::Key_F9, 0xffff , 0xffff , 0xffff }, // 58 datebook
- { Qt::Key_F10, 0xffff , 0xffff , 0xffff }, // 59 address
- { Qt::Key_F13, 0xffff , 0xffff , 0xffff }, // 5a 90 email
- { Qt::Key_F30, ' ' , ' ' , 0xffff }, // 5b select
- { Qt::Key_Space, ' ' , '|' , '`' }, // 5c
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 5d
- { Qt::Key_Exclam, '!' , 'a' , 'A'-64 }, // 5e
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 5f
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 60
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 61
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 62
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 63
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 64
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 65
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 66
- { Qt::Key_Meta, 0xffff , 0xffff , 0xffff }, // 67
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 68
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 69
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 6a
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 6b
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 6c
- { Qt::Key_F34, 0xffff , 0xffff , 0xffff }, // 6d power
- { Qt::Key_F13, 0xffff , 0xffff , 0xffff }, // 6e mail long
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 6f
- { Qt::Key_NumLock, 0xffff , 0xffff , 0xffff }, // 70
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 71
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 72
- { 0x20ac, 0xffff , 0x20ac , 0x20ac }, // 73 Euro sign
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 74
- { Qt::Key_F32, 0xffff , 0xffff , 0xffff }, // 75 Sync
- { 0, 0xffff , 0xffff , 0xffff }
-};
-
-static const int keyMSize = sizeof(sl5000KeyMap)/sizeof(QWSKeyMap)-1;
-
-QWSSL5000KeyboardHandler::QWSSL5000KeyboardHandler(const QString &device)
- : QWSTtyKeyboardHandler(device)
-{
- meta = false;
- fn = false;
- numLock = false;
-
- sharp_kbdctl_modifstat st;
- int dev = ::open(device.isEmpty()?"/dev/sharp_kbdctl":device.toLocal8Bit().constData(), O_RDWR);
- if (dev >= 0) {
- memset(&st, 0, sizeof(st));
- st.which = 3;
- int ret = ioctl(dev, SHARP_KBDCTL_GETMODIFSTAT, (char*)&st);
- if(!ret)
- numLock = (bool)st.stat;
- ::close(dev);
- }
-}
-
-QWSSL5000KeyboardHandler::~QWSSL5000KeyboardHandler()
-{
-}
-
-const QWSKeyMap *QWSSL5000KeyboardHandler::keyMap() const
-{
- return sl5000KeyMap;
-}
-
-void QWSSL5000KeyboardHandler::doKey(uchar code)
-{
- int keyCode = Qt::Key_unknown;
- bool release = false;
-
- if (code & 0x80) {
- release = true;
- code &= 0x7f;
- }
-
- if (fn && !meta && (code >= 0x42 && code <= 0x52)) {
- ushort unicode=0;
- int scan=0;
- if (code == 0x42) { unicode='X'-'@'; scan=Qt::Key_X; } // Cut
- else if (code == 0x43) { unicode='C'-'@'; scan=Qt::Key_C; } // Copy
- else if (code == 0x44) { unicode='V'-'@'; scan=Qt::Key_V; } // Paste
- else if (code == 0x52) { unicode='Z'-'@'; scan=Qt::Key_Z; } // Undo
- if (scan) {
- processKeyEvent(unicode, scan, Qt::ControlModifier, !release, false);
- return;
- }
- }
-
- if (code < keyMSize) {
- keyCode = keyMap()[code].key_code;
- }
-
- bool repeatable = true;
-
- if (release && (keyCode == Qt::Key_F34 || keyCode == Qt::Key_F35))
- return; // no release for power and light keys
- if (keyCode >= Qt::Key_F1 && keyCode <= Qt::Key_F35
- || keyCode == Qt::Key_Escape || keyCode == Qt::Key_Home
- || keyCode == Qt::Key_Shift || keyCode == Qt::Key_Meta)
- repeatable = false;
-
- if (qt_screen->isTransformed()
- && keyCode >= Qt::Key_Left && keyCode <= Qt::Key_Down)
- {
- keyCode = transformDirKey(keyCode);
- }
-
- // Ctrl-Alt-Delete exits qws
- if (ctrl && alt && keyCode == Qt::Key_Delete) {
- qApp->quit();
- }
-
- if (keyCode == Qt::Key_F22) { /* Fn key */
- fn = !release;
- } else if (keyCode == Qt::Key_NumLock) {
- if (release)
- numLock = !numLock;
- } else if (keyCode == Qt::AltModifier) {
- alt = !release;
- } else if (keyCode == Qt::ControlModifier) {
- ctrl = !release;
- } else if (keyCode == Qt::ShiftModifier) {
- shift = !release;
- } else if (keyCode == Qt::MetaModifier) {
- meta = !release;
- } else if (keyCode == Qt::Key_CapsLock && release) {
- caps = !caps;
- }
- if (keyCode != Qt::Key_unknown) {
- bool bAlt = alt;
- bool bCtrl = ctrl;
- bool bShift = shift;
- int unicode = 0;
- if (code < keyMSize) {
- bool bCaps = caps ^ shift;
- if (fn) {
- if (shift) {
- bCaps = bShift = false;
- bCtrl = true;
- }
- if (meta) {
- bCaps = bShift = true;
- bAlt = true;
- }
- } else if (meta) {
- bCaps = bShift = true;
- }
- if (code > 40 && caps) {
- // fn-keys should only react to shift, not caps
- bCaps = bShift = shift;
- }
- if (numLock) {
- if (keyCode != Qt::Key_Space && keyCode != Qt::Key_Tab)
- bCaps = bShift = false;
- }
- if (keyCode == Qt::Key_Delete && (bAlt || bCtrl)) {
- keyCode = Qt::Key_BraceLeft;
- unicode = '[';
- bCaps = bShift = bAlt = bCtrl = false;
- } else if (keyCode == Qt::Key_F31 && bCtrl) {
- keyCode = Qt::Key_QuoteLeft;
- unicode = '`';
- } else if (bCtrl)
- unicode = keyMap()[code].ctrl_unicode ? keyMap()[code].ctrl_unicode : 0xffff;
- else if (bCaps)
- unicode = keyMap()[code].shift_unicode ? keyMap()[code].shift_unicode : 0xffff;
- else
- unicode = keyMap()[code].unicode ? keyMap()[code].unicode : 0xffff;
- }
-
- modifiers = 0;
- if (bAlt) modifiers |= Qt::AltModifier;
- if (bCtrl) modifiers |= Qt::ControlModifier;
- if (bShift) modifiers |= Qt::ShiftModifier;
-
- // looks wrong -- WWA
- bool repeat = false;
- if (prevuni == unicode && prevkey == keyCode && !release)
- repeat = true;
-
- processKeyEvent(unicode, keyCode, modifiers, !release, repeat);
-
- if (!release) {
- prevuni = unicode;
- prevkey = keyCode;
- } else {
- prevkey = prevuni = 0;
- }
- }
-
- if (repeatable && !release)
- beginAutoRepeat(prevuni, prevkey, modifiers);
- else
- endAutoRepeat();
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_QWS_KBD_SL5000
diff --git a/src/gui/embedded/qkbdtty_qws.cpp b/src/gui/embedded/qkbdtty_qws.cpp
index 982ffc8..292f629 100644
--- a/src/gui/embedded/qkbdtty_qws.cpp
+++ b/src/gui/embedded/qkbdtty_qws.cpp
@@ -43,65 +43,59 @@
#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_TTY)
-#include "qscreen_qws.h"
-
-#include "qwindowsystem_qws.h"
-#include "qapplication.h"
-#include "qsocketnotifier.h"
-#include "qnamespace.h"
-#include "qtimer.h"
-#include <private/qwssignalhandler_p.h>
-#include <private/qwindowsurface_qws_p.h>
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <termios.h>
+#include <QSocketNotifier>
+#include <QStringList>
-#include <qeventloop.h>
+#include <qplatformdefs.h>
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
-#ifdef Q_OS_LINUX
-#include <sys/kd.h>
-#include <sys/vt.h>
-#endif
+#include <errno.h>
+#include <termios.h>
-QT_BEGIN_NAMESPACE
+#if defined Q_OS_LINUX
+# include <linux/kd.h>
+# include <linux/vt.h> //TODO: move vt handling somewhere else (QLinuxFbScreen?)
-#define VTACQSIG SIGUSR1
-#define VTRELSIG SIGUSR2
+# include "qscreen_qws.h"
+# include "qwindowsystem_qws.h"
+# include "qapplication.h"
+# include "private/qwindowsurface_qws_p.h"
+# include "private/qwssignalhandler_p.h"
-static int vtQws = 0;
-static int kbdFD = -1;
+# define VTACQSIG SIGUSR1
+# define VTRELSIG SIGUSR2
+#endif
-//===========================================================================
-//
-// Tty keyboard
-//
+QT_BEGIN_NAMESPACE
class QWSTtyKbPrivate : public QObject
{
Q_OBJECT
public:
- QWSTtyKbPrivate(QWSPC101KeyboardHandler *, const QString &device);
+ QWSTtyKbPrivate(QWSTtyKeyboardHandler *handler, const QString &device);
~QWSTtyKbPrivate();
-private slots:
- void readKeyboardData();
- void handleTtySwitch(int);
+private:
+ void switchLed(char, bool);
+ void switchConsole(int vt);
+
+private Q_SLOTS:
+ void readKeycode();
+ void handleConsoleSwitch(int sig);
private:
- QWSPC101KeyboardHandler *handler;
- struct termios origTermData;
- int originalKbdMode;
+ QWSTtyKeyboardHandler *m_handler;
+ int m_tty_fd;
+ struct termios m_tty_attr;
+ char m_last_keycode;
+ int m_vt_qws;
+ int m_orig_kbmode;
};
+
QWSTtyKeyboardHandler::QWSTtyKeyboardHandler(const QString &device)
- : QWSPC101KeyboardHandler(device)
+ : QWSKeyboardHandler(device)
{
d = new QWSTtyKbPrivate(this, device);
}
@@ -111,60 +105,66 @@ QWSTtyKeyboardHandler::~QWSTtyKeyboardHandler()
delete d;
}
-void QWSTtyKeyboardHandler::processKeyEvent(int unicode, int keycode,
- Qt::KeyboardModifiers modifiers, bool isPress,
- bool autoRepeat)
+bool QWSTtyKeyboardHandler::filterKeycode(char &)
{
-#if defined(Q_OS_LINUX)
- // Virtual console switching
- int term = 0;
- bool ctrl = modifiers & Qt::ControlModifier;
- bool alt = modifiers & Qt::AltModifier;
- if (ctrl && alt && keycode >= Qt::Key_F1 && keycode <= Qt::Key_F10)
- term = keycode - Qt::Key_F1 + 1;
- else if (ctrl && alt && keycode == Qt::Key_Left)
- term = qMax(vtQws - 1, 1);
- else if (ctrl && alt && keycode == Qt::Key_Right)
- term = qMin(vtQws + 1, 10);
- if (term && isPress) {
- ioctl(kbdFD, VT_ACTIVATE, term);
- return;
- }
-#endif
-
- QWSPC101KeyboardHandler::processKeyEvent(unicode, keycode, modifiers,
- isPress, autoRepeat);
+ return false;
}
-
-QWSTtyKbPrivate::QWSTtyKbPrivate(QWSPC101KeyboardHandler *h, const QString &device) : handler(h)
+QWSTtyKbPrivate::QWSTtyKbPrivate(QWSTtyKeyboardHandler *h, const QString &device)
+ : m_handler(h), m_tty_fd(-1), m_last_keycode(0), m_vt_qws(0), m_orig_kbmode(K_XLATE)
{
- kbdFD = ::open(device.isEmpty()?"/dev/tty0":device.toLatin1().constData(), O_RDWR|O_NDELAY, 0);
+ setObjectName(QLatin1String("TTY Keyboard Handler"));
#ifndef QT_NO_QWS_SIGNALHANDLER
QWSSignalHandler::instance()->addObject(this);
#endif
- if (kbdFD >= 0) {
+ QString dev = QLatin1String("/dev/tty0");
+ int repeat_delay = -1;
+ int repeat_rate = -1;
+
+ QStringList args = device.split(QLatin1Char(':'));
+ foreach (const QString &arg, args) {
+ if (arg.startsWith(QLatin1String("repeat-delay=")))
+ repeat_delay = arg.mid(13).toInt();
+ else if (arg.startsWith(QLatin1String("repeat-rate=")))
+ repeat_rate = arg.mid(12).toInt();
+ else if (arg.startsWith(QLatin1String("/dev/")))
+ dev = arg;
+ }
+
+ m_tty_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDWR, 0);
+ if (m_tty_fd >= 0) {
+ if (repeat_delay > 0 && repeat_rate > 0) {
+#if defined(Q_OS_LINUX)
+ struct ::kbd_repeat kbdrep = { repeat_delay, repeat_rate };
+ ::ioctl(m_tty_fd, KDKBDREP, &kbdrep);
+#endif
+ }
+
QSocketNotifier *notifier;
- notifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)),this,
- SLOT(readKeyboardData()));
+ notifier = new QSocketNotifier(m_tty_fd, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode()));
- // save for restore.
- tcgetattr(kbdFD, &origTermData);
+ // save tty config for restore.
+ tcgetattr(m_tty_fd, &m_tty_attr);
- struct termios termdata;
- tcgetattr(kbdFD, &termdata);
+ struct ::termios termdata;
+ tcgetattr(m_tty_fd, &termdata);
#if defined(Q_OS_LINUX)
- ioctl(kbdFD, KDGKBMODE, &originalKbdMode);
-# ifdef QT_QWS_USE_KEYCODES
- ioctl(kbdFD, KDSKBMODE, K_MEDIUMRAW);
-# else
- ioctl(kbdFD, KDSKBMODE, K_RAW);
-# endif
+ // record the original mode so we can restore it again in the destructor.
+ ::ioctl(m_tty_fd, KDGKBMODE, &m_orig_kbmode);
+
+ // PLEASE NOTE:
+ // the tty keycode interface can only report keycodes 0x01 .. 0x7f
+ // KEY_MAX is however defined to 0x1ff. In practice this is sufficient
+ // for a PC style keyboard though.
+ // we don't support K_RAW anymore - if you need that, you have to add
+ // a scan- to keycode converter yourself.
+ ::ioctl(m_tty_fd, KDSKBMODE, K_MEDIUMRAW);
#endif
+ // set the tty layer to pass-through
termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
termdata.c_oflag = 0;
termdata.c_cflag = CREAD | CS8;
@@ -173,50 +173,146 @@ QWSTtyKbPrivate::QWSTtyKbPrivate(QWSPC101KeyboardHandler *h, const QString &devi
termdata.c_cc[VMIN]=1;
cfsetispeed(&termdata, 9600);
cfsetospeed(&termdata, 9600);
- tcsetattr(kbdFD, TCSANOW, &termdata);
+ tcsetattr(m_tty_fd, TCSANOW, &termdata);
#if defined(Q_OS_LINUX)
-
- connect(QApplication::instance(), SIGNAL(unixSignal(int)), this, SLOT(handleTtySwitch(int)));
+ // VT switching is handled via unix signals
+ connect(QApplication::instance(), SIGNAL(unixSignal(int)), this, SLOT(handleConsoleSwitch(int)));
QApplication::instance()->watchUnixSignal(VTACQSIG, true);
QApplication::instance()->watchUnixSignal(VTRELSIG, true);
- struct vt_mode vtMode;
- ioctl(kbdFD, VT_GETMODE, &vtMode);
+ struct ::vt_mode vtMode;
+ if (::ioctl(m_tty_fd, VT_GETMODE, &vtMode) == 0) {
+ vtMode.mode = VT_PROCESS;
+ vtMode.relsig = VTRELSIG;
+ vtMode.acqsig = VTACQSIG;
- // let us control VT switching
- vtMode.mode = VT_PROCESS;
- vtMode.relsig = VTRELSIG;
- vtMode.acqsig = VTACQSIG;
- ioctl(kbdFD, VT_SETMODE, &vtMode);
+ if (::ioctl(m_tty_fd, VT_SETMODE, &vtMode) == 0) {
+ struct ::vt_stat vtStat;
+ ::memset(&vtStat, 0, sizeof(vtStat));
- struct vt_stat vtStat;
- ioctl(kbdFD, VT_GETSTATE, &vtStat);
- vtQws = vtStat.v_active;
+ if (::ioctl(m_tty_fd, VT_GETSTATE, &vtStat) == 0 ) {
+ m_vt_qws = vtStat.v_active;
+ }
+ }
+ }
+
+ if (!m_vt_qws)
+ qWarning("Could not initialize virtual console switching");
#endif
} else {
- qCritical("Cannot open keyboard: %s", strerror(errno));
+ qWarning("Cannot open input device '%s': %s", qPrintable(dev), strerror(errno));
+ return;
}
}
QWSTtyKbPrivate::~QWSTtyKbPrivate()
{
- if (kbdFD >= 0) {
+ if (m_tty_fd >= 0) {
#if defined(Q_OS_LINUX)
- ioctl(kbdFD, KDSKBMODE, originalKbdMode);
+ ::ioctl(m_tty_fd, KDSKBMODE, m_orig_kbmode);
#endif
- tcsetattr(kbdFD, TCSANOW, &origTermData);
- ::close(kbdFD);
- kbdFD = -1;
+ tcsetattr(m_tty_fd, TCSANOW, &m_tty_attr);
+ QT_CLOSE(m_tty_fd);
}
}
-void QWSTtyKbPrivate::handleTtySwitch(int sig)
+
+
+void QWSTtyKbPrivate::switchLed(char led, bool state)
{
#if defined(Q_OS_LINUX)
+ char ledstate;
+
+ ::ioctl(m_tty_fd, KDGETLED, &ledstate);
+ if (state)
+ ledstate |= led;
+ else
+ ledstate &= ~led;
+ ::ioctl(m_tty_fd, KDSETLED, ledstate);
+#endif
+}
+
+void QWSTtyKbPrivate::readKeycode()
+{
+ char buffer[32];
+ int n = 0;
+
+ forever {
+ n = QT_READ(m_tty_fd, buffer + n, 32 - n);
+
+ if (n == 0) {
+ qWarning("Got EOF from the input device.");
+ return;
+ } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
+ qWarning("Could not read from input device: %s", strerror(errno));
+ return;
+ } else {
+ break;
+ }
+ }
+
+ for (int i = 0; i < n; ++i) {
+ if (m_handler->filterKeycode(buffer[i]))
+ continue;
+
+ QWSKeyboardHandler::KeycodeAction ka;
+ ka = m_handler->processKeycode(buffer[i] & 0x7f, (buffer[i] & 0x80) == 0x00, buffer[i] == m_last_keycode);
+ m_last_keycode = buffer[i];
+
+ switch (ka) {
+ case QWSKeyboardHandler::CapsLockOn:
+ case QWSKeyboardHandler::CapsLockOff:
+ switchLed(LED_CAP, ka == QWSKeyboardHandler::CapsLockOn);
+ break;
+
+ case QWSKeyboardHandler::NumLockOn:
+ case QWSKeyboardHandler::NumLockOff:
+ switchLed(LED_NUM, ka == QWSKeyboardHandler::NumLockOn);
+ break;
+
+ case QWSKeyboardHandler::ScrollLockOn:
+ case QWSKeyboardHandler::ScrollLockOff:
+ switchLed(LED_SCR, ka == QWSKeyboardHandler::ScrollLockOn);
+ break;
+
+ case QWSKeyboardHandler::PreviousConsole:
+ switchConsole(qBound(1, m_vt_qws - 1, 10));
+ break;
+
+ case QWSKeyboardHandler::NextConsole:
+ switchConsole(qBound(1, m_vt_qws + 1, 10));
+ break;
+
+ default:
+ if (ka >= QWSKeyboardHandler::SwitchConsoleFirst &&
+ ka <= QWSKeyboardHandler::SwitchConsoleLast) {
+ switchConsole(1 + (ka & QWSKeyboardHandler::SwitchConsoleMask));
+ }
+ //ignore reboot
+ break;
+ }
+ }
+}
+
+
+void QWSTtyKbPrivate::switchConsole(int vt)
+{
+#if defined(Q_OS_LINUX)
+ if (m_vt_qws && vt && (m_tty_fd >= 0 ))
+ ::ioctl(m_tty_fd, VT_ACTIVATE, vt);
+#endif
+}
+
+void QWSTtyKbPrivate::handleConsoleSwitch(int sig)
+{
+#if defined(Q_OS_LINUX)
+ // received a notification from the kernel that the current VT is
+ // changing: either enable or disable QWS painting accordingly.
+
if (sig == VTACQSIG) {
- if (ioctl(kbdFD, VT_RELDISP, VT_ACKACQ) == 0) {
+ if (::ioctl(m_tty_fd, VT_RELDISP, VT_ACKACQ) == 0) {
qwsServer->enablePainting(true);
qt_screen->restore();
qwsServer->resumeMouse();
@@ -238,9 +334,9 @@ void QWSTtyKbPrivate::handleTtySwitch(int sig)
}
if (!allWindowsHidden) {
- ioctl(kbdFD, VT_RELDISP, 0); // abort console switch
+ ::ioctl(m_tty_fd, VT_RELDISP, 0); // abort console switch
qwsServer->enablePainting(true);
- } else if (ioctl(kbdFD, VT_RELDISP, 1) == 0) {
+ } else if (::ioctl(m_tty_fd, VT_RELDISP, 1) == 0) {
qt_screen->save();
qwsServer->suspendMouse();
} else {
@@ -250,14 +346,6 @@ void QWSTtyKbPrivate::handleTtySwitch(int sig)
#endif
}
-void QWSTtyKbPrivate::readKeyboardData()
-{
- unsigned char buf[81];
- int n = read(kbdFD, buf, 80);
- for (int loop = 0; loop < n; loop++)
- handler->doKey(buf[loop]);
-}
-
QT_END_NAMESPACE
#include "qkbdtty_qws.moc"
diff --git a/src/gui/embedded/qkbdtty_qws.h b/src/gui/embedded/qkbdtty_qws.h
index 1a834f8..6b5fe1d 100644
--- a/src/gui/embedded/qkbdtty_qws.h
+++ b/src/gui/embedded/qkbdtty_qws.h
@@ -42,7 +42,7 @@
#ifndef QKBDTTY_QWS_H
#define QKBDTTY_QWS_H
-#include <QtGui/qkbdpc101_qws.h>
+#include <QtGui/qkbd_qws.h>
QT_BEGIN_HEADER
@@ -56,15 +56,13 @@ QT_MODULE(Gui)
class QWSTtyKbPrivate;
-class QWSTtyKeyboardHandler : public QWSPC101KeyboardHandler
+class QWSTtyKeyboardHandler : public QWSKeyboardHandler
{
public:
explicit QWSTtyKeyboardHandler(const QString&);
virtual ~QWSTtyKeyboardHandler();
-protected:
- virtual void processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
- bool isPress, bool autoRepeat);
+ virtual bool filterKeycode(char &code);
private:
QWSTtyKbPrivate *d;
diff --git a/src/gui/embedded/qkbdum_qws.cpp b/src/gui/embedded/qkbdum_qws.cpp
index dc6d93a..db38a60 100644
--- a/src/gui/embedded/qkbdum_qws.cpp
+++ b/src/gui/embedded/qkbdum_qws.cpp
@@ -54,6 +54,7 @@
#include <qstring.h>
#include <qwindowsystem_qws.h>
#include <qsocketnotifier.h>
+#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE
@@ -81,13 +82,13 @@ QWSUmKeyboardHandlerPrivate::QWSUmKeyboardHandlerPrivate(const QString &device)
{
kbdBuffer = new unsigned char [kbdBufferLen];
- if ((kbdFD = open((const char *)device.toLocal8Bit(), O_RDONLY | O_NDELAY)) < 0) {
+ if ((kbdFD = QT_OPEN((const char *)device.toLocal8Bit(), O_RDONLY | O_NDELAY, 0)) < 0) {
qDebug("Cannot open %s (%s)", (const char *)device.toLocal8Bit(),
strerror(errno));
} else {
// Clear pending input
char buf[2];
- while (read(kbdFD, buf, 1) > 0) { }
+ while (QT_READ(kbdFD, buf, 1) > 0) { }
notifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this);
connect(notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()));
@@ -97,7 +98,7 @@ QWSUmKeyboardHandlerPrivate::QWSUmKeyboardHandlerPrivate(const QString &device)
QWSUmKeyboardHandlerPrivate::~QWSUmKeyboardHandlerPrivate()
{
if (kbdFD >= 0)
- close(kbdFD);
+ QT_CLOSE(kbdFD);
delete [] kbdBuffer;
}
@@ -106,7 +107,7 @@ void QWSUmKeyboardHandlerPrivate::readKeyboardData()
{
int n;
do {
- n = read(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx);
+ n = QT_READ(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx);
if (n > 0)
kbdIdx += n;
} while (n > 0);
diff --git a/src/gui/embedded/qkbdusb_qws.cpp b/src/gui/embedded/qkbdusb_qws.cpp
deleted file mode 100644
index 0e6e3d8..0000000
--- a/src/gui/embedded/qkbdusb_qws.cpp
+++ /dev/null
@@ -1,401 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkbdusb_qws.h"
-
-#ifndef QT_NO_QWS_KEYBOARD
-
-#include "qscreen_qws.h"
-
-#include "qwindowsystem_qws.h"
-#include "qapplication.h"
-#include "qsocketnotifier.h"
-#include "qnamespace.h"
-#include "qtimer.h"
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-
-#include <linux/input.h>
-
-#ifdef Q_OS_LINUX
-#include <sys/kd.h>
-#include <sys/vt.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-/* USB driver */
-
-
-class QWSUsbKbPrivate : public QObject
-{
- Q_OBJECT
-public:
- QWSUsbKbPrivate(QWSPC101KeyboardHandler *, const QString &);
- ~QWSUsbKbPrivate();
-
-private slots:
- void readKeyboardData();
-
-private:
- QWSPC101KeyboardHandler *handler;
- int fd;
-#ifdef QT_QWS_ZYLONITE
- bool shift;
-#endif
-};
-
-QWSUsbKeyboardHandler::QWSUsbKeyboardHandler(const QString &device)
- : QWSPC101KeyboardHandler(device)
-{
- d = new QWSUsbKbPrivate(this, device);
-}
-
-QWSUsbKeyboardHandler::~QWSUsbKeyboardHandler()
-{
- delete d;
-}
-
-QWSUsbKbPrivate::QWSUsbKbPrivate(QWSPC101KeyboardHandler *h, const QString &device) : handler(h)
-{
-#ifdef QT_QWS_ZYLONITE
- shift = FALSE;
-#endif
- fd = ::open(device.isEmpty()?"/dev/input/event1":device.toLocal8Bit(),O_RDONLY, 0);
- if (fd >= 0) {
- QSocketNotifier *notifier;
- notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)),this,
- SLOT(readKeyboardData()));
- }
-}
-
-QWSUsbKbPrivate::~QWSUsbKbPrivate()
-{
- ::close(fd);
-}
-
-void QWSUsbKbPrivate::readKeyboardData()
-{
- input_event event;
- if (read(fd, &event, sizeof(input_event)) != sizeof(input_event))
- return;
-
- if (event.type != EV_KEY)
- return;
-
-#ifdef QT_QWS_ZYLONITE
- qDebug("keypressed: code=%03d (%s)\n",event.code,((event.value)!=0) ? "Down":"Up");
- int modifiers=0;
- int unicode=0xffff;
- int key_code=0;
-
- switch(event.code)
- {
- case 0xA2:
- key_code = ((!shift) ? Qt::Key_0 : Qt::Key_Plus );
- unicode = ((!shift) ? 0x30 : 0x2B );
- break;
- case 0x70:
- key_code = ((!shift) ? Qt::Key_1 : Qt::Key_At );
- unicode = ((!shift) ? 0x31 : 0x40 );
- break;
- case 0x72:
- key_code = ((!shift) ? Qt::Key_2 : Qt::Key_Ampersand );
- unicode = ((!shift) ? 0x32 : 0x26 );
- break;
- case 0x74:
- key_code = ((!shift) ? Qt::Key_3 : Qt::Key_At );
- unicode = ((!shift) ? 0x33 : 0x3F );
- break;
- case 0x80:
- key_code = ((!shift) ? Qt::Key_4 : Qt::Key_Minus );
- unicode = ((!shift) ? 0x34 : 0x2D );
- break;
- case 0x82:
- key_code = ((!shift) ? Qt::Key_5 : Qt::Key_Apostrophe);
- unicode = ((!shift) ? 0x35 : 0x27 );
- break;
- case 0x84:
- key_code = ((!shift) ? Qt::Key_6 : Qt::Key_Slash );
- unicode = ((!shift) ? 0x36 : 0x5C );
- break;
- case 0x90:
- key_code = ((!shift) ? Qt::Key_7 : Qt::Key_Colon );
- unicode = ((!shift) ? 0x37 : 0x3A );
- break;
- case 0x92:
- key_code = ((!shift) ? Qt::Key_8 : Qt::Key_Semicolon );
- unicode = ((!shift) ? 0x38 : 0x3B );
- break;
- case 0x94:
- key_code = ((!shift) ? Qt::Key_9 : Qt::Key_QuoteDbl );
- unicode = ((!shift) ? 0x39 : 0x22 );
- break;
- case 0x0:
- key_code = Qt::Key_A;
- unicode = ((!shift) ? 0x61 : 0x41 );
- break;
- case 0x10:
- key_code = Qt::Key_B;
- unicode = ((!shift) ? 0x62 : 0x42 );
- break;
- case 0x20:
- key_code = Qt::Key_C;
- unicode = ((!shift) ? 0x63 : 0x43 );
- break;
- case 0x30:
- key_code = Qt::Key_D;
- unicode = ((!shift) ? 0x64 : 0x44 );
- break;
- case 0x40:
- key_code = Qt::Key_E;
- unicode = ((!shift) ? 0x65 : 0x45 );
- break;
- case 0x50:
- key_code = Qt::Key_F;
- unicode = ((!shift) ? 0x66 : 0x46 );
- break;
- case 0x01:
- key_code = Qt::Key_G;
- unicode = ((!shift) ? 0x67 : 0x47 );
- break;
- case 0x11:
- key_code = Qt::Key_H;
- unicode = ((!shift) ? 0x68 : 0x48 );
- break;
- case 0x21:
- key_code = Qt::Key_I;
- unicode = ((!shift) ? 0x69 : 0x49 );
- break;
- case 0x31:
- key_code = Qt::Key_J;
- unicode = ((!shift) ? 0x6A : 0x4A );
- break;
- case 0x41:
- key_code = Qt::Key_K;
- unicode = ((!shift) ? 0x6B : 0x4B );
- break;
- case 0x51:
- key_code = Qt::Key_L;
- unicode = ((!shift) ? 0x6C : 0x4C );
- break;
- case 0x02:
- key_code = Qt::Key_M;
- unicode = ((!shift) ? 0x6D : 0x4D );
- break;
- case 0x12:
- key_code = Qt::Key_N;
- unicode = ((!shift) ? 0x6E : 0x4E );
- break;
- case 0x22:
- key_code = Qt::Key_O;
- unicode = ((!shift) ? 0x6F : 0x4F );
- break;
- case 0x32:
- key_code = Qt::Key_P;
- unicode = ((!shift) ? 0x70 : 0x50 );
- break;
- case 0x42:
- key_code = Qt::Key_Q;
- unicode = ((!shift) ? 0x71 : 0x51 );
- break;
- case 0x52:
- key_code = Qt::Key_R;
- unicode = ((!shift) ? 0x72 : 0x52 );
- break;
- case 0x03:
- key_code = Qt::Key_S;
- unicode = ((!shift) ? 0x73 : 0x53 );
- break;
- case 0x13:
- key_code = Qt::Key_T;
- unicode = ((!shift) ? 0x74 : 0x54 );
- break;
- case 0x23:
- key_code = Qt::Key_U;
- unicode = ((!shift) ? 0x75 : 0x55 );
- break;
- case 0x33:
- key_code = Qt::Key_V;
- unicode = ((!shift) ? 0x76 : 0x56 );
- break;
- case 0x43:
- key_code = Qt::Key_W;
- unicode = ((!shift) ? 0x77 : 0x57 );
- break;
- case 0x53:
- key_code = Qt::Key_X;
- unicode = ((!shift) ? 0x78 : 0x58 );
- break;
- case 0x24:
- key_code = Qt::Key_Y;
- unicode = ((!shift) ? 0x79 : 0x59 );
- break;
- case 0x34:
- key_code = Qt::Key_Z;
- unicode = ((!shift) ? 0x7A : 0x5A );
- break;
- case 0xA4:
- key_code = ((!shift) ? Qt::Key_NumberSign : Qt::Key_Period);
- unicode = ((!shift) ? 0x23 : 0x2E );
- break;
- case 0xA0:
- key_code = ((!shift) ? Qt::Key_Asterisk : Qt::Key_NumberSign );
- unicode = ((!shift) ? 0x2A : 0x2C );
- break;
- case 0x25:
- key_code = Qt::Key_Space;
- unicode = 0x20;
- break;
- case 0x06:
- key_code = Qt::Key_Up;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x16:
- key_code = Qt::Key_Down;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x26:
- key_code = Qt::Key_Left;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x36:
- key_code = Qt::Key_Right;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x46:
- key_code = Qt::Key_Select;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x61:
- key_code = Qt::Key_No;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x60:
- key_code = Qt::Key_Call;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x55:
- key_code = Qt::Key_Hangup;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x62:
- key_code = Qt::Key_Context1;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x63:
- key_code = Qt::Key_No;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x05:
- key_code = Qt::Key_Home;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x15:
- key_code = Qt::Key_Shift;
- unicode = 0xffff; modifiers |= Qt::ShiftModifier;
- if(event.value==0) break;
- if(shift) {
- shift = FALSE;
- qWarning("Caps Off!");
- } else {
- shift = TRUE;
- qWarning("Caps On!");
- }
- break;
- case 0x1C:
- key_code = ((!shift) ? Qt::Key_Back : Qt::Key_Enter );
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x19:
- key_code = Qt::Key_Context2;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x1A:
- key_code = Qt::Key_Context3;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x1B:
- key_code = Qt::Key_Context4;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- }
- if(shift) modifiers |= Qt::ShiftModifier;
- handler->processKeyEvent(unicode, key_code, (Qt::KeyboardModifiers)modifiers, event.value!=0, false);
-#else
-
- int key=event.code;
-#ifndef QT_QWS_USE_KEYCODES
- // Handle SOME keys, otherwise it's useless.
-
- if(key==103) {
- handler->processKeyEvent(0, Qt::Key_Up, 0, event.value!=0, false);
- } else if(key==106) {
- handler->processKeyEvent(0, Qt::Key_Right, 0, event.value!=0, false );
- } else if(key==108) {
- handler->processKeyEvent(0, Qt::Key_Down, 0, event.value!=0, false);
- } else if(key==105) {
- handler->processKeyEvent(0, Qt::Key_Left, 0, event.value!=0, false);
- } else
-
-#endif
-
- {
- if(event.value == 0) {
- key=key | 0x80;
- }
- handler->doKey(key);
- }
-#endif
-}
-
-QT_END_NAMESPACE
-
-#include "qkbdusb_qws.moc"
-
-#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbdvfb_qws.cpp b/src/gui/embedded/qkbdvfb_qws.cpp
index 2e92652..c922138 100644
--- a/src/gui/embedded/qkbdvfb_qws.cpp
+++ b/src/gui/embedded/qkbdvfb_qws.cpp
@@ -55,6 +55,7 @@
#include <qwindowsystem_qws.h>
#include <qsocketnotifier.h>
#include <qapplication.h>
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
QT_BEGIN_NAMESPACE
@@ -69,13 +70,13 @@ QVFbKeyboardHandler::QVFbKeyboardHandler(const QString &device)
kbdBufferLen = sizeof(QVFbKeyData) * 5;
kbdBuffer = new unsigned char [kbdBufferLen];
- if ((kbdFD = open(terminalName.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) {
+ if ((kbdFD = QT_OPEN(terminalName.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) {
qWarning("Cannot open %s (%s)", terminalName.toLatin1().constData(),
strerror(errno));
} else {
// Clear pending input
char buf[2];
- while (read(kbdFD, buf, 1) > 0) { }
+ while (QT_READ(kbdFD, buf, 1) > 0) { }
notifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this);
connect(notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()));
@@ -85,7 +86,7 @@ QVFbKeyboardHandler::QVFbKeyboardHandler(const QString &device)
QVFbKeyboardHandler::~QVFbKeyboardHandler()
{
if (kbdFD >= 0)
- close(kbdFD);
+ QT_CLOSE(kbdFD);
delete [] kbdBuffer;
}
@@ -94,7 +95,7 @@ void QVFbKeyboardHandler::readKeyboardData()
{
int n;
do {
- n = read(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx);
+ n = QT_READ(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx);
if (n > 0)
kbdIdx += n;
} while (n > 0);
diff --git a/src/gui/embedded/qkbdvr41xx_qws.cpp b/src/gui/embedded/qkbdvr41xx_qws.cpp
deleted file mode 100644
index 9469323..0000000
--- a/src/gui/embedded/qkbdvr41xx_qws.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkbdvr41xx_qws.h"
-
-#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_VR41XX)
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <qsocketnotifier.h>
-
-QT_BEGIN_NAMESPACE
-
-class QWSVr41xxKbPrivate : public QObject
-{
- Q_OBJECT
-public:
- QWSVr41xxKbPrivate(QWSVr41xxKeyboardHandler *h, const QString&);
- virtual ~QWSVr41xxKbPrivate();
-
- bool isOpen() { return buttonFD > 0; }
-
-private slots:
- void readKeyboardData();
-
-private:
- QString terminalName;
- int buttonFD;
- int kbdIdx;
- int kbdBufferLen;
- unsigned char *kbdBuffer;
- QSocketNotifier *notifier;
- QWSVr41xxKeyboardHandler *handler;
-};
-
-QWSVr41xxKeyboardHandler::QWSVr41xxKeyboardHandler(const QString &device)
-{
- d = new QWSVr41xxKbPrivate(this, device);
-}
-
-QWSVr41xxKeyboardHandler::~QWSVr41xxKeyboardHandler()
-{
- delete d;
-}
-
-QWSVr41xxKbPrivate::QWSVr41xxKbPrivate(QWSVr41xxKeyboardHandler *h, const QString &device) : handler(h)
-{
- terminalName = device;
- if (terminalName.isEmpty())
- terminalName = QLatin1String("/dev/buttons");
- buttonFD = -1;
- notifier = 0;
-
- buttonFD = open(terminalName.toLatin1().constData(), O_RDWR | O_NDELAY, 0);;
- if (buttonFD < 0) {
- qWarning("Cannot open %s\n", qPrintable(terminalName));
- return;
- }
-
- if (buttonFD >= 0) {
- notifier = new QSocketNotifier(buttonFD, QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)),this,
- SLOT(readKeyboardData()));
- }
-
- kbdBufferLen = 80;
- kbdBuffer = new unsigned char [kbdBufferLen];
- kbdIdx = 0;
-}
-
-QWSVr41xxKbPrivate::~QWSVr41xxKbPrivate()
-{
- if (buttonFD > 0) {
- ::close(buttonFD);
- buttonFD = -1;
- }
- delete notifier;
- notifier = 0;
- delete [] kbdBuffer;
-}
-
-void QWSVr41xxKbPrivate::readKeyboardData()
-{
- int n = 0;
- do {
- n = read(buttonFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx);
- if (n > 0)
- kbdIdx += n;
- } while (n > 0);
-
- int idx = 0;
- while (kbdIdx - idx >= 2) {
- unsigned char *next = kbdBuffer + idx;
- unsigned short *code = (unsigned short *)next;
- int keycode = Qt::Key_unknown;
- switch ((*code) & 0x0fff) {
- case 0x7:
- keycode = Qt::Key_Up;
- break;
- case 0x9:
- keycode = Qt::Key_Right;
- break;
- case 0x8:
- keycode = Qt::Key_Down;
- break;
- case 0xa:
- keycode = Qt::Key_Left;
- break;
- case 0x3:
- keycode = Qt::Key_Up;
- break;
- case 0x4:
- keycode = Qt::Key_Down;
- break;
- case 0x1:
- keycode = Qt::Key_Return;
- break;
- case 0x2:
- keycode = Qt::Key_F4;
- break;
- default:
- qDebug("Unrecognised key sequence %d", *code);
- }
- if ((*code) & 0x8000)
- handler->processKeyEvent(0, keycode, 0, false, false);
- else
- handler->processKeyEvent(0, keycode, 0, true, false);
- idx += 2;
- }
-
- int surplus = kbdIdx - idx;
- for (int i = 0; i < surplus; i++)
- kbdBuffer[i] = kbdBuffer[idx+i];
- kbdIdx = surplus;
-}
-
-QT_END_NAMESPACE
-
-#include "qkbdvr41xx_qws.moc"
-
-#endif // QT_NO_QWS_KBD_VR41XX
diff --git a/src/gui/embedded/qkbdyopy_qws.cpp b/src/gui/embedded/qkbdyopy_qws.cpp
deleted file mode 100644
index 16ed51c..0000000
--- a/src/gui/embedded/qkbdyopy_qws.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*
- * YOPY buttons driver
- * Contributed by Ron Victorelli (victorrj at icubed.com)
- */
-
-#include "qkbdyopy_qws.h"
-
-#ifndef QT_NO_QWS_KBD_YOPY
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <linux/kd.h>
-#include <linux/fb.h>
-#include <linux/yopy_button.h>
-
-extern "C" {
- int getpgid(int);
-}
-
-#include <qwidget.h>
-#include <qsocketnotifier.h>
-
-QT_BEGIN_NAMESPACE
-
-class QWSYopyKbPrivate : public QObject
-{
- Q_OBJECT
-public:
- QWSYopyKbPrivate(QWSYopyKeyboardHandler *h, const QString&);
- virtual ~QWSYopyKbPrivate();
-
- bool isOpen() { return buttonFD > 0; }
-
-private slots:
- void readKeyboardData();
-
-private:
- QString terminalName;
- int buttonFD;
- struct termios newT, oldT;
- QSocketNotifier *notifier;
- QWSYopyKeyboardHandler *handler;
-};
-
-QWSYopyKeyboardHandler::QWSYopyKeyboardHandler(const QString &device)
-{
- d = new QWSYopyKbPrivate(this, device);
-}
-
-QWSYopyKeyboardHandler::~QWSYopyKeyboardHandler()
-{
- delete d;
-}
-
-QWSYopyKbPrivate::QWSYopyKbPrivate(QWSYopyKeyboardHandler *h, const QString &device) : handler(h)
-{
- terminalName = device.isEmpty()?"/dev/tty1":device.toLatin1().constData();
- buttonFD = -1;
- notifier = 0;
-
- buttonFD = ::open(terminalName.toLatin1().constData(), O_RDWR | O_NDELAY, 0);
- if (buttonFD < 0) {
- qWarning("Cannot open %s\n", qPrintable(terminalName));
- return;
- } else {
-
- tcsetpgrp(buttonFD, getpgid(0));
-
- /* put tty into "straight through" mode.
- */
- if (tcgetattr(buttonFD, &oldT) < 0) {
- qFatal("Linux-kbd: tcgetattr failed");
- }
-
- newT = oldT;
- newT.c_lflag &= ~(ICANON | ECHO | ISIG);
- newT.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
- newT.c_iflag |= IGNBRK;
- newT.c_cc[VMIN] = 0;
- newT.c_cc[VTIME] = 0;
-
-
- if (tcsetattr(buttonFD, TCSANOW, &newT) < 0) {
- qFatal("Linux-kbd: TCSANOW tcsetattr failed");
- }
-
- if (ioctl(buttonFD, KDSKBMODE, K_MEDIUMRAW) < 0) {
- qFatal("Linux-kbd: KDSKBMODE tcsetattr failed");
- }
-
- notifier = new QSocketNotifier(buttonFD, QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)),this,
- SLOT(readKeyboardData()));
- }
-}
-
-QWSYopyKbPrivate::~QWSYopyKbPrivate()
-{
- if (buttonFD > 0) {
- ::close(buttonFD);
- buttonFD = -1;
- }
-}
-
-void QWSYopyKbPrivate::readKeyboardData()
-{
- uchar buf[1];
- char c='1';
- int fd;
-
- int n=read(buttonFD,buf,1);
- if (n<0) {
- qDebug("Keyboard read error %s",strerror(errno));
- } else {
- uint code = buf[0]&YPBUTTON_CODE_MASK;
- bool press = !(buf[0]&0x80);
- // printf("Key=%d/%d/%d\n",buf[1],code,press);
- int k=(-1);
- switch(code) {
- case 39: k=Qt::Key_Up; break;
- case 44: k=Qt::Key_Down; break;
- case 41: k=Qt::Key_Left; break;
- case 42: k=Qt::Key_Right; break;
- case 56: k=Qt::Key_F1; break; //windows
- case 29: k=Qt::Key_F2; break; //cycle
- case 24: k=Qt::Key_F3; break; //record
- case 23: k=Qt::Key_F4; break; //mp3
- case 4: k=Qt::Key_F5; break; // PIMS
- case 1: k=Qt::Key_Escape; break; // Escape
- case 40: k=Qt::Key_Up; break; // prev
- case 45: k=Qt::Key_Down; break; // next
- case 35: if(!press) {
- fd = open("/proc/sys/pm/sleep",O_RDWR,0);
- if(fd >= 0) {
- write(fd,&c,sizeof(c));
- close(fd);
- //
- // Updates all widgets.
- //
- QWidgetList list = QApplication::allWidgets();
- for (int i = 0; i < list.size(); ++i) {
- QWidget *w = list.at(i);
- w->update();
- }
- }
- }
- break;
-
- default: k=(-1); break;
- }
-
- if (k >= 0) {
- handler->processKeyEvent(0, k, 0, press, false);
- }
- }
-}
-
-QT_END_NAMESPACE
-
-#include "qkbdyopy_qws.moc"
-
-#endif // QT_NO_QWS_KBD_YOPY
diff --git a/src/gui/embedded/qlock.cpp b/src/gui/embedded/qlock.cpp
index a9da04c..c8ec5fd 100644
--- a/src/gui/embedded/qlock.cpp
+++ b/src/gui/embedded/qlock.cpp
@@ -41,9 +41,49 @@
#include "qlock_p.h"
-#ifndef QT_NO_QWS_MULTIPROCESS
+
+#ifdef QT_NO_QWS_MULTIPROCESS
+
+QT_BEGIN_NAMESPACE
+
+/* no multiprocess - use a dummy */
+
+QLock::QLock(const QString & /*filename*/, char /*id*/, bool /*create*/)
+ : type(Read), data(0)
+{
+}
+
+QLock::~QLock()
+{
+}
+
+bool QLock::isValid() const
+{
+ return true;
+}
+
+void QLock::lock(Type t)
+{
+ data = (QLockData *)-1;
+ type = t;
+}
+
+void QLock::unlock()
+{
+ data = 0;
+}
+
+bool QLock::locked() const
+{
+ return data;
+}
+
+QT_END_NAMESPACE
+
+#else // QT_NO_QWS_MULTIPROCESS
#include "qwssignalhandler_p.h"
+
#include <unistd.h>
#include <sys/types.h>
#if defined(Q_OS_DARWIN)
@@ -71,14 +111,13 @@ union semun {
#include <qdebug.h>
#include <signal.h>
-#endif // QT_NO_QWS_MULTIPROCESS
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
-#define MAX_LOCKS 200 // maximum simultaneous read locks
QT_BEGIN_NAMESPACE
+#define MAX_LOCKS 200 // maximum simultaneous read locks
-#ifndef QT_NO_QWS_MULTIPROCESS
class QLockData
{
public:
@@ -89,14 +128,12 @@ public:
int count;
bool owned;
};
-#endif // QT_NO_QWS_MULTIPROCESS
/*!
\class QLock
\brief The QLock class is a wrapper for a System V shared semaphore.
\ingroup qws
- \ingroup io
\internal
@@ -124,17 +161,12 @@ public:
QLock::QLock(const QString &filename, char id, bool create)
{
-#ifdef QT_NO_QWS_MULTIPROCESS
- Q_UNUSED(filename);
- Q_UNUSED(id);
- Q_UNUSED(create);
-#else
data = new QLockData;
data->count = 0;
#ifdef Q_NO_SEMAPHORE
data->file = QString(filename+id).toLocal8Bit().constData();
for(int x = 0; x < 2; x++) {
- data->id = open(data->file, O_RDWR | (x ? O_CREAT : 0), S_IRWXU);
+ data->id = QT_OPEN(data->file, O_RDWR | (x ? O_CREAT : 0), S_IRWXU);
if(data->id != -1 || !create) {
data->owned = x;
break;
@@ -161,7 +193,6 @@ QLock::QLock(const QString &filename, char id, bool create)
qPrintable(filename), id);
qDebug() << "Error" << eno << strerror(eno);
}
-#endif
}
/*!
@@ -172,12 +203,11 @@ QLock::QLock(const QString &filename, char id, bool create)
QLock::~QLock()
{
-#ifndef QT_NO_QWS_MULTIPROCESS
if (locked())
unlock();
#ifdef Q_NO_SEMAPHORE
if(isValid()) {
- close(data->id);
+ QT_CLOSE(data->id);
if(data->owned)
unlink(data->file);
}
@@ -186,7 +216,6 @@ QLock::~QLock()
QWSSignalHandler::instance()->removeSemaphore(data->id);
#endif
delete data;
-#endif
}
/*!
@@ -198,11 +227,7 @@ QLock::~QLock()
bool QLock::isValid() const
{
-#ifndef QT_NO_QWS_MULTIPROCESS
return (data->id != -1);
-#else
- return true;
-#endif
}
/*!
@@ -219,9 +244,6 @@ bool QLock::isValid() const
void QLock::lock(Type t)
{
-#ifdef QT_NO_QWS_MULTIPROCESS
- Q_UNUSED(t);
-#else
if (!data->count) {
#ifdef Q_NO_SEMAPHORE
int op = LOCK_SH;
@@ -254,7 +276,6 @@ void QLock::lock(Type t)
#endif
}
data->count++;
-#endif
}
/*!
@@ -267,7 +288,6 @@ void QLock::lock(Type t)
void QLock::unlock()
{
-#ifndef QT_NO_QWS_MULTIPROCESS
if(data->count) {
data->count--;
if(!data->count) {
@@ -296,7 +316,6 @@ void QLock::unlock()
} else {
qDebug("Unlock without corresponding lock");
}
-#endif
}
/*!
@@ -308,11 +327,10 @@ void QLock::unlock()
bool QLock::locked() const
{
-#ifndef QT_NO_QWS_MULTIPROCESS
return (data->count > 0);
-#else
- return false;
-#endif
}
QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_MULTIPROCESS
+
diff --git a/src/gui/embedded/qmouse_qws.cpp b/src/gui/embedded/qmouse_qws.cpp
index d1c9c2e..85b5a2a 100644
--- a/src/gui/embedded/qmouse_qws.cpp
+++ b/src/gui/embedded/qmouse_qws.cpp
@@ -413,8 +413,8 @@ void QWSCalibratedMouseHandler::writeCalibration()
QFile file(calFile);
if (file.open(QIODevice::WriteOnly)) {
QTextStream t(&file);
- t << a << " " << b << " " << c << " ";
- t << d << " " << e << " " << f << " " << s << endl;
+ t << a << ' ' << b << ' ' << c << ' ';
+ t << d << ' ' << e << ' ' << f << ' ' << s << endl;
} else
#endif
{
diff --git a/src/gui/embedded/qmousebus_qws.cpp b/src/gui/embedded/qmousebus_qws.cpp
deleted file mode 100644
index d054742..0000000
--- a/src/gui/embedded/qmousebus_qws.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmousebus_qws.h"
-
-#ifndef QT_NO_QWS_MOUSE_BUS
-
-#include "qwindowsystem_qws.h"
-#include "qsocketnotifier.h"
-
-#include "qapplication.h"
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <termios.h>
-
-QT_BEGIN_NAMESPACE
-
-/*
- * bus mouse driver (a.k.a. Logitech busmouse)
- */
-
-class QWSBusMouseHandlerPrivate : public QObject
-{
- Q_OBJECT
-public:
- QWSBusMouseHandlerPrivate(QWSBusMouseHandler *h, const QString &driver, const QString &device);
- ~QWSBusMouseHandlerPrivate();
-
- void suspend();
- void resume();
-
-private slots:
- void readMouseData();
-
-protected:
- enum { mouseBufSize = 128 };
- QWSBusMouseHandler *handler;
- QSocketNotifier *mouseNotifier;
- int mouseFD;
- int mouseIdx;
- int obstate;
- uchar mouseBuf[mouseBufSize];
-};
-
-QWSBusMouseHandler::QWSBusMouseHandler(const QString &driver, const QString &device)
- : QWSMouseHandler(driver, device)
-{
- d = new QWSBusMouseHandlerPrivate(this, driver, device);
-}
-
-QWSBusMouseHandler::~QWSBusMouseHandler()
-{
- delete d;
-}
-
-void QWSBusMouseHandler::suspend()
-{
- d->suspend();
-}
-
-void QWSBusMouseHandler::resume()
-{
- d->resume();
-}
-
-
-QWSBusMouseHandlerPrivate::QWSBusMouseHandlerPrivate(QWSBusMouseHandler *h,
- const QString &, const QString &device)
- : handler(h)
-
-{
- QString mouseDev = device;
- if (mouseDev.isEmpty())
- mouseDev = QLatin1String("/dev/mouse");
- obstate = -1;
- mouseFD = -1;
- mouseFD = open(mouseDev.toLocal8Bit(), O_RDWR | O_NDELAY);
- if (mouseFD < 0)
- mouseFD = open(mouseDev.toLocal8Bit(), O_RDONLY | O_NDELAY);
- if (mouseFD < 0)
- qDebug("Cannot open %s (%s)", qPrintable(mouseDev), strerror(errno));
-
- // Clear pending input
- tcflush(mouseFD,TCIFLUSH);
- usleep(50000);
-
- char buf[100]; // busmouse driver will not read if bufsize < 3, YYD
- while (read(mouseFD, buf, 100) > 0) { } // eat unwanted replies
-
- mouseIdx = 0;
-
- mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
- connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
-}
-
-QWSBusMouseHandlerPrivate::~QWSBusMouseHandlerPrivate()
-{
- if (mouseFD >= 0) {
- tcflush(mouseFD,TCIFLUSH); // yyd.
- close(mouseFD);
- }
-}
-
-
-void QWSBusMouseHandlerPrivate::suspend()
-{
- mouseNotifier->setEnabled(false);
-}
-
-
-void QWSBusMouseHandlerPrivate::resume()
-{
- mouseIdx = 0;
- obstate = -1;
- mouseNotifier->setEnabled(true);
-}
-
-void QWSBusMouseHandlerPrivate::readMouseData()
-{
- int n;
- // It'll only read 3 bytes a time and return all other buffer zeroed, thus cause protocol errors
- for (;;) {
- if (mouseBufSize - mouseIdx < 3)
- break;
- n = read(mouseFD, mouseBuf+mouseIdx, 3);
- if (n != 3)
- break;
- mouseIdx += 3;
- }
-
- static const int accel_limit = 5;
- static const int accel = 2;
-
- int idx = 0;
- int bstate = 0;
- int dx = 0, dy = 0;
- bool sendEvent = false;
- int tdx = 0, tdy = 0;
-
- while (mouseIdx-idx >= 3) {
-#if 0 // debug
- qDebug("Got mouse data");
-#endif
- uchar *mb = mouseBuf+idx;
- bstate = 0;
- dx = 0;
- dy = 0;
- sendEvent = false;
- if (((mb[0] & 0x04)))
- bstate |= Qt::LeftButton;
- if (((mb[0] & 0x01)))
- bstate |= Qt::RightButton;
-
- dx=(signed char)mb[1];
- dy=(signed char)mb[2];
- sendEvent=true;
-
- if (sendEvent) {
- if (qAbs(dx) > accel_limit || qAbs(dy) > accel_limit) {
- dx *= accel;
- dy *= accel;
- }
- tdx += dx;
- tdy += dy;
- if (bstate != obstate) {
- QPoint pos = handler->pos() + QPoint(tdx,-tdy);
- handler->limitToScreen(pos);
- handler->mouseChanged(pos,bstate);
- sendEvent = false;
- tdx = 0;
- tdy = 0;
- obstate = bstate;
- }
- }
- idx += 3;
- }
- if (sendEvent) {
- QPoint pos = handler->pos() + QPoint(tdx,-tdy);
- handler->limitToScreen(pos);
- handler->mouseChanged(pos,bstate);
- }
-
- int surplus = mouseIdx - idx;
- for (int i = 0; i < surplus; i++)
- mouseBuf[i] = mouseBuf[idx+i];
- mouseIdx = surplus;
-}
-
-QT_END_NAMESPACE
-
-#include "qmousebus_qws.moc"
-
-#endif // QT_NO_QWS_MOUSE_BUS
diff --git a/src/gui/embedded/qmousedriverfactory_qws.cpp b/src/gui/embedded/qmousedriverfactory_qws.cpp
index 82b136f..2b8ab59 100644
--- a/src/gui/embedded/qmousedriverfactory_qws.cpp
+++ b/src/gui/embedded/qmousedriverfactory_qws.cpp
@@ -43,12 +43,11 @@
#include "qapplication.h"
#include "qmousepc_qws.h"
-#include "qmousebus_qws.h"
-#include "qmousevr41xx_qws.h"
-#include "qmouseyopy_qws.h"
#include "qmouselinuxtp_qws.h"
+#include "qmouselinuxinput_qws.h"
#include "qmousevfb_qws.h"
#include "qmousetslib_qws.h"
+#include "qmouseqnx_qws.h"
#include <stdlib.h>
#include "private/qfactoryloader_p.h"
#include "qmousedriverplugin_qws.h"
@@ -104,18 +103,14 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
QWSMouseHandler *QMouseDriverFactory::create(const QString& key, const QString &device)
{
QString driver = key.toLower();
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_MOUSE_QNX)
+ if (driver == QLatin1String("qnx") || driver.isEmpty())
+ return new QQnxMouseHandler(key, device);
+#endif
#ifndef QT_NO_QWS_MOUSE_LINUXTP
if (driver == QLatin1String("linuxtp") || driver.isEmpty())
return new QWSLinuxTPMouseHandler(key, device);
#endif
-#ifndef QT_NO_QWS_MOUSE_YOPY
- if (driver == QLatin1String("yopy") || driver.isEmpty())
- return new QWSYopyMouseHandler(key, device);
-#endif
-#ifndef QT_NO_QWS_MOUSE_VR41XX
- if (driver == QLatin1String("vr41xx") || driver.isEmpty())
- return new QWSVr41xxMouseHandler(key, device);
-#endif
#ifndef QT_NO_QWS_MOUSE_PC
if (driver == QLatin1String("auto")
|| driver == QLatin1String("intellimouse")
@@ -126,14 +121,16 @@ QWSMouseHandler *QMouseDriverFactory::create(const QString& key, const QString &
return new QWSPcMouseHandler(key, device);
}
#endif
-#ifndef QT_NO_QWS_MOUSE_BUS
- if (driver == QLatin1String("bus"))
- return new QWSBusMouseHandler(key, device);
-#endif
#ifndef QT_NO_QWS_MOUSE_TSLIB
if (driver == QLatin1String("tslib") || driver.isEmpty())
return new QWSTslibMouseHandler(key, device);
#endif
+# ifndef QT_NO_QWS_MOUSE_LINUXINPUT
+ if (driver == QLatin1String("linuxinput") || \
+ driver == QLatin1String("usb") || \
+ driver == QLatin1String("linuxis"))
+ return new QWSLinuxInputMouseHandler(device);
+# endif
#ifndef QT_NO_QWS_MOUSE_QVFB
if (driver == QLatin1String("qvfbmouse") || driver == QLatin1String("qvfb"))
return new QVFbMouseHandler(key, device);
@@ -157,15 +154,12 @@ QStringList QMouseDriverFactory::keys()
{
QStringList list;
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_MOUSE_QNX)
+ list << QLatin1String("QNX");
+#endif
#ifndef QT_NO_QWS_MOUSE_LINUXTP
list << QLatin1String("LinuxTP");
#endif
-#ifndef QT_NO_QWS_MOUSE_YOPY
- list << QLatin1String("Yopy");
-#endif
-#ifndef QT_NO_QWS_MOUSE_VR41XX
- list << QLatin1String("VR41xx");
-#endif
#ifndef QT_NO_QWS_MOUSE_PC
list << QLatin1String("Auto")
<< QLatin1String("IntelliMouse")
@@ -173,12 +167,12 @@ QStringList QMouseDriverFactory::keys()
<< QLatin1String("MouseSystems")
<< QLatin1String("MouseMan");
#endif
-#ifndef QT_NO_QWS_MOUSE_BUS
- list << QLatin1String("Bus");
-#endif
#ifndef QT_NO_QWS_MOUSE_TSLIB
list << QLatin1String("Tslib");
#endif
+#ifndef QT_NO_QWS_MOUSE_LINUXINPUT
+ list << QLatin1String("LinuxInput");
+#endif
#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
#ifndef QT_NO_LIBRARY
diff --git a/src/gui/embedded/qmouselinuxinput_qws.cpp b/src/gui/embedded/qmouselinuxinput_qws.cpp
new file mode 100644
index 0000000..32a29db
--- /dev/null
+++ b/src/gui/embedded/qmouselinuxinput_qws.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmouselinuxinput_qws.h"
+
+#include <QScreen>
+#include <QSocketNotifier>
+
+#include <qplatformdefs.h>
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
+
+#include <errno.h>
+
+#include <linux/input.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QWSLinuxInputMousePrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSLinuxInputMousePrivate(QWSLinuxInputMouseHandler *, const QString &);
+ ~QWSLinuxInputMousePrivate();
+
+ void enable(bool on);
+
+private Q_SLOTS:
+ void readMouseData();
+
+private:
+ QWSLinuxInputMouseHandler *m_handler;
+ QSocketNotifier * m_notify;
+ int m_fd;
+ int m_x, m_y;
+ int m_buttons;
+};
+
+QWSLinuxInputMouseHandler::QWSLinuxInputMouseHandler(const QString &device)
+ : QWSCalibratedMouseHandler(device)
+{
+ d = new QWSLinuxInputMousePrivate(this, device);
+}
+
+QWSLinuxInputMouseHandler::~QWSLinuxInputMouseHandler()
+{
+ delete d;
+}
+
+void QWSLinuxInputMouseHandler::suspend()
+{
+ d->enable(false);
+}
+
+void QWSLinuxInputMouseHandler::resume()
+{
+ d->enable(true);
+}
+
+QWSLinuxInputMousePrivate::QWSLinuxInputMousePrivate(QWSLinuxInputMouseHandler *h, const QString &device)
+ : m_handler(h), m_notify(0), m_x(0), m_y(0), m_buttons(0)
+{
+ setObjectName(QLatin1String("LinuxInputSubsystem Mouse Handler"));
+
+ QString dev = QLatin1String("/dev/input/event0");
+ if (device.startsWith(QLatin1String("/dev/")))
+ dev = device;
+
+ m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
+ if (m_fd >= 0) {
+ m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
+ connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));
+ } else {
+ qWarning("Cannot open mouse input device '%s': %s", qPrintable(dev), strerror(errno));
+ return;
+ }
+}
+
+QWSLinuxInputMousePrivate::~QWSLinuxInputMousePrivate()
+{
+ if (m_fd >= 0)
+ QT_CLOSE(m_fd);
+}
+
+void QWSLinuxInputMousePrivate::enable(bool on)
+{
+ if (m_notify)
+ m_notify->setEnabled(on);
+}
+
+void QWSLinuxInputMousePrivate::readMouseData()
+{
+ if (!qt_screen)
+ return;
+
+ struct ::input_event buffer[32];
+ int n = 0;
+
+ forever {
+ n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);
+
+ if (n == 0) {
+ qWarning("Got EOF from the input device.");
+ return;
+ } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
+ qWarning("Could not read from input device: %s", strerror(errno));
+ return;
+ } else if (n % sizeof(buffer[0]) == 0) {
+ break;
+ }
+ }
+
+ n /= sizeof(buffer[0]);
+
+ for (int i = 0; i < n; ++i) {
+ struct ::input_event *data = &buffer[i];
+
+ bool unknown = false;
+ if (data->type == EV_ABS) {
+ if (data->code == ABS_X) {
+ m_x = data->value;
+ } else if (data->code == ABS_Y) {
+ m_y = data->value;
+ } else {
+ unknown = true;
+ }
+ } else if (data->type == EV_REL) {
+ if (data->code == REL_X) {
+ m_x += data->value;
+ } else if (data->code == REL_Y) {
+ m_y += data->value;
+ } else {
+ unknown = true;
+ }
+ } else if (data->type == EV_KEY && data->code == BTN_TOUCH) {
+ m_buttons = data->value ? Qt::LeftButton : 0;
+ } else if (data->type == EV_KEY) {
+ int button = 0;
+ switch (data->code) {
+ case BTN_LEFT: button = Qt::LeftButton; break;
+ case BTN_MIDDLE: button = Qt::MidButton; break;
+ case BTN_RIGHT: button = Qt::RightButton; break;
+ }
+ if (data->value)
+ m_buttons |= button;
+ else
+ m_buttons &= ~button;
+ } else if (data->type == EV_SYN && data->code == SYN_REPORT) {
+ QPoint pos(m_x, m_y);
+ pos = m_handler->transform(pos);
+ m_handler->limitToScreen(pos);
+ m_handler->mouseChanged(pos, m_buttons);
+ } else if (data->type == EV_MSC && data->code == MSC_SCAN) {
+ // kernel encountered an unmapped key - just ignore it
+ continue;
+ } else {
+ unknown = true;
+ }
+ if (unknown) {
+ qWarning("unknown mouse event type=%x, code=%x, value=%x", data->type, data->code, data->value);
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qmouselinuxinput_qws.moc"
diff --git a/src/gui/embedded/qmouselinuxinput_qws.h b/src/gui/embedded/qmouselinuxinput_qws.h
new file mode 100644
index 0000000..bc0c113
--- /dev/null
+++ b/src/gui/embedded/qmouselinuxinput_qws.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSELINUXINPUT_QWS_H
+#define QMOUSELINUXINPUT_QWS_H
+
+#include <QtGui/QWSCalibratedMouseHandler>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_MOUSE_LINUXINPUT
+
+class QWSLinuxInputMousePrivate;
+
+class QWSLinuxInputMouseHandler : public QWSCalibratedMouseHandler
+{
+public:
+ QWSLinuxInputMouseHandler(const QString &);
+ ~QWSLinuxInputMouseHandler();
+
+ void suspend();
+ void resume();
+
+private:
+ QWSLinuxInputMousePrivate *d;
+
+ friend class QWSLinuxInputMousePrivate;
+};
+
+#endif // QT_NO_QWS_MOUSE_LINUXINPUT
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSELINUXINPUT_QWS_H
diff --git a/src/gui/embedded/qmouselinuxtp_qws.cpp b/src/gui/embedded/qmouselinuxtp_qws.cpp
index 240ae7e..d48a541 100644
--- a/src/gui/embedded/qmouselinuxtp_qws.cpp
+++ b/src/gui/embedded/qmouselinuxtp_qws.cpp
@@ -47,6 +47,7 @@
#include "qtimer.h"
#include "qapplication.h"
#include "qscreen_qws.h"
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <unistd.h>
#include <stdlib.h>
@@ -190,7 +191,7 @@ QWSLinuxTPMouseHandlerPrivate::QWSLinuxTPMouseHandlerPrivate(QWSLinuxTPMouseHand
} else {
mousedev = device;
}
- if ((mouseFD = open(mousedev.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) {
+ if ((mouseFD = QT_OPEN(mousedev.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) {
qWarning("Cannot open %s (%s)", qPrintable(mousedev), strerror(errno));
return;
}
@@ -205,7 +206,7 @@ QWSLinuxTPMouseHandlerPrivate::QWSLinuxTPMouseHandlerPrivate(QWSLinuxTPMouseHand
QWSLinuxTPMouseHandlerPrivate::~QWSLinuxTPMouseHandlerPrivate()
{
if (mouseFD >= 0)
- close(mouseFD);
+ QT_CLOSE(mouseFD);
}
void QWSLinuxTPMouseHandlerPrivate::suspend()
@@ -233,7 +234,7 @@ void QWSLinuxTPMouseHandlerPrivate::readMouseData()
int n;
do {
- n = read(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx);
+ n = QT_READ(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx);
if (n > 0)
mouseIdx += n;
} while (n > 0 && mouseIdx < mouseBufSize);
diff --git a/src/gui/embedded/qmousepc_qws.cpp b/src/gui/embedded/qmousepc_qws.cpp
index c8aa92e..4647d05 100644
--- a/src/gui/embedded/qmousepc_qws.cpp
+++ b/src/gui/embedded/qmousepc_qws.cpp
@@ -55,6 +55,7 @@
#include "qfile.h"
#include "qtextstream.h"
#include "qstringlist.h"
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <unistd.h>
#include <stdlib.h>
@@ -107,7 +108,7 @@ public:
{
if (fd != f) {
f = fd;
- close(fd);
+ QT_CLOSE(fd);
}
}
@@ -170,7 +171,7 @@ public:
}
static const uchar initseq[] = { 243, 200, 243, 100, 243, 80 };
static const uchar query[] = { 0xf2 };
- if (write(fd, initseq, sizeof(initseq))!=sizeof(initseq)) {
+ if (QT_WRITE(fd, initseq, sizeof(initseq))!=sizeof(initseq)) {
badness = 100;
return;
}
@@ -180,12 +181,12 @@ public:
perror("QWSPcMouseSubHandler_intellimouse: post-init tcflush");
#endif
}
- if (write(fd, query, sizeof(query))!=sizeof(query)) {
+ if (QT_WRITE(fd, query, sizeof(query))!=sizeof(query)) {
badness = 100;
return;
}
usleep(10000);
- n = read(fd, reply, 20);
+ n = QT_READ(fd, reply, 20);
if (n > 0) {
goodness = 10;
switch (reply[n-1]) {
@@ -256,13 +257,13 @@ public:
perror("QWSPcMouseSubHandler_mouseman: initial tcflush");
#endif
}
- write(fd,"",1);
+ QT_WRITE(fd,"",1);
usleep(50000);
- write(fd,"@EeI!",5);
+ QT_WRITE(fd,"@EeI!",5);
usleep(10000);
static const char ibuf[] = { 246, 244 };
- write(fd,ibuf,1);
- write(fd,ibuf+1,1);
+ QT_WRITE(fd,ibuf,1);
+ QT_WRITE(fd,ibuf+1,1);
if (tcflush(fd,TCIOFLUSH) == -1) {
#ifdef QWS_MOUSE_DEBUG
perror("QWSPcMouseSubHandler_mouseman: tcflush");
@@ -271,7 +272,7 @@ public:
usleep(10000);
char buf[100];
- while (read(fd, buf, 100) > 0) { } // eat unwanted replies
+ while (QT_READ(fd, buf, 100) > 0) { } // eat unwanted replies
}
int tryData()
@@ -331,7 +332,7 @@ protected:
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_cflag = f | CREAD | CLOCAL | HUPCL;
-#if !defined(Q_OS_DARWIN) && !defined(Q_OS_SOLARIS) && !defined(Q_OS_INTEGRITY)
+#ifdef Q_OS_LINUX
tty.c_line = 0;
#endif
tty.c_cc[VTIME] = 0;
@@ -350,7 +351,7 @@ private:
for (int n = 0; n < 4; n++) {
setflags(CSTOPB | speed[n]);
- write(fd, "*q", 2);
+ QT_WRITE(fd, "*q", 2);
usleep(10000);
}
}
@@ -369,7 +370,7 @@ public:
{
setflags(B1200|CS8|CSTOPB);
// 60Hz
- if (write(fd, "R", 1)!=1) {
+ if (QT_WRITE(fd, "R", 1)!=1) {
badness = 100;
return;
}
@@ -418,7 +419,7 @@ public:
{
setflags(B1200|CS7);
// 60Hz
- if (write(fd, "R", 1)!=1) {
+ if (QT_WRITE(fd, "R", 1)!=1) {
badness = 100;
return;
}
@@ -648,25 +649,25 @@ void QWSPcMouseHandlerPrivate::openDevices()
if (drv == QLatin1String("intellimouse")) {
if (dev.isEmpty())
dev = "/dev/psaux";
- fd = open(dev, O_RDWR | O_NDELAY);
+ fd = QT_OPEN(dev, O_RDWR | O_NDELAY);
if (fd >= 0)
sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
} else if (drv == QLatin1String("microsoft")) {
if (dev.isEmpty())
dev = "/dev/ttyS0";
- fd = open(dev, O_RDWR | O_NDELAY);
+ fd = QT_OPEN(dev, O_RDWR | O_NDELAY);
if (fd >= 0)
sub[nsub++] = new QWSPcMouseSubHandler_ms(fd);
} else if (drv == QLatin1String("mousesystems")) {
if (dev.isEmpty())
dev = "/dev/ttyS0";
- fd = open(dev, O_RDWR | O_NDELAY);
+ fd = QT_OPEN(dev, O_RDWR | O_NDELAY);
if (fd >= 0)
sub[nsub++] = new QWSPcMouseSubHandler_mousesystems(fd);
} else if (drv == QLatin1String("mouseman")) {
if (dev.isEmpty())
dev = "/dev/psaux";
- fd = open(dev, O_RDWR | O_NDELAY);
+ fd = QT_OPEN(dev, O_RDWR | O_NDELAY);
if (fd >= 0)
sub[nsub++] = new QWSPcMouseSubHandler_mouseman(fd);
}
@@ -677,12 +678,12 @@ void QWSPcMouseHandlerPrivate::openDevices()
dev.constData(), strerror(errno));
} else {
// Try automatically
- fd = open("/dev/psaux", O_RDWR | O_NDELAY);
+ fd = QT_OPEN("/dev/psaux", O_RDWR | O_NDELAY);
if (fd >= 0) {
sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
notify(fd);
}
- fd = open("/dev/input/mice", O_RDWR | O_NDELAY);
+ fd = QT_OPEN("/dev/input/mice", O_RDWR | O_NDELAY);
if (fd >= 0) {
sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
notify(fd);
@@ -694,7 +695,7 @@ void QWSPcMouseHandlerPrivate::openDevices()
#if 0
const char fn[4][11] = { "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3" };
for (int ch = 0; ch < 4; ++ch) {
- fd = open(fn[ch], O_RDWR | O_NDELAY);
+ fd = QT_OPEN(fn[ch], O_RDWR | O_NDELAY);
if (fd >= 0) {
//sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
sub[nsub++] = new QWSPcMouseSubHandler_mousesystems(fd);
diff --git a/src/gui/embedded/qmouseqnx_qws.cpp b/src/gui/embedded/qmouseqnx_qws.cpp
new file mode 100644
index 0000000..319ae8e
--- /dev/null
+++ b/src/gui/embedded/qmouseqnx_qws.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qmouseqnx_qws.h"
+
+#include "qsocketnotifier.h"
+#include "qdebug.h"
+
+#include <sys/dcmd_input.h>
+
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQnxMouseHandler
+ \preliminary
+ \ingroup qws
+ \internal
+ \since 4.6
+
+ \brief The QQnxMouseHandler class implements a mouse driver
+ for the QNX \c{devi-hid} input manager.
+
+ To be able to compile this mouse handler, \l{Qt for Embedded Linux}
+ must be configured with the \c -qt-mouse-qnx option, see the
+ \l{Qt for Embedded Linux Pointer Handling}{Pointer Handling} documentation for details.
+
+ In order to use this mouse handler, the \c{devi-hid} input manager
+ must be set up and run with the resource manager interface (option \c{-r}).
+ Also, Photon must not be running.
+
+ Example invocation from command line: \c{/usr/photon/bin/devi-hid -Pr kbd mouse}
+ Note that after running \c{devi-hid}, you will not be able to use the local
+ shell anymore. It is suggested to run the command in a shell scrip, that launches
+ a Qt application after invocation of \c{devi-hid}.
+
+ To make \l{Qt for Embedded Linux} explicitly choose the qnx mouse
+ handler, set the QWS_MOUSE_PROTO environment variable to \c{qnx}. By default,
+ the first mouse device (\c{/dev/devi/mouse0}) is used. To override, pass a device
+ name as the first and only parameter, for example
+ \c{QWS_MOUSE_PROTO=qnx:/dev/devi/mouse1; export QWS_MOUSE_PROTO}.
+
+ \sa {Qt for Embedded Linux Pointer Handling}{Pointer Handling}, {Qt for Embedded Linux}
+*/
+
+/*!
+ Constructs a mouse handler for the specified \a device, defaulting to \c{/dev/devi/mouse0}.
+ The \a driver parameter must be \c{"qnx"}.
+
+ Note that you should never instanciate this class, instead let QMouseDriverFactory
+ handle the mouse handlers.
+
+ \sa QMouseDriverFactory
+ */
+QQnxMouseHandler::QQnxMouseHandler(const QString & /*driver*/, const QString &device)
+{
+ // open the mouse device with O_NONBLOCK so reading won't block when there's no data
+ mouseFD = QT_OPEN(device.isEmpty() ? "/dev/devi/mouse0" : device.toLatin1().constData(),
+ QT_OPEN_RDONLY | O_NONBLOCK);
+ if (mouseFD == -1) {
+ qErrnoWarning(errno, "QQnxMouseHandler: Unable to open mouse device");
+ return;
+ }
+
+ // register a socket notifier on the file descriptor so we'll wake up whenever
+ // there's a mouse move waiting for us.
+ mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
+ connect(mouseNotifier, SIGNAL(activated(int)), SLOT(socketActivated()));
+
+ qDebug() << "QQnxMouseHandler: connected.";
+}
+
+/*!
+ Destroys this mouse handler and closes the connection to the mouse device.
+ */
+QQnxMouseHandler::~QQnxMouseHandler()
+{
+ QT_CLOSE(mouseFD);
+}
+
+/*! \reimp */
+void QQnxMouseHandler::resume()
+{
+ if (mouseNotifier)
+ mouseNotifier->setEnabled(true);
+}
+
+/*! \reimp */
+void QQnxMouseHandler::suspend()
+{
+ if (mouseNotifier)
+ mouseNotifier->setEnabled(false);
+}
+
+/*! \internal
+
+ This function is called whenever there is activity on the mouse device.
+ By default, it reads up to 10 mouse move packets and calls mouseChanged()
+ for each of them.
+*/
+void QQnxMouseHandler::socketActivated()
+{
+ // _mouse_packet is a QNX structure. devi-hid is nice enough to translate
+ // the raw byte data from mouse devices into generic format for us.
+ _mouse_packet packet;
+
+ int iteration = 0;
+
+ // read mouse events in batches of 10. Since we're getting quite a lot
+ // of mouse events, it's better to do them in batches than to return to the
+ // event loop every time.
+ do {
+ int bytesRead = QT_READ(mouseFD, &packet, sizeof(packet));
+ if (bytesRead == -1) {
+ // EAGAIN means that there are no more mouse events to read
+ if (errno != EAGAIN)
+ qErrnoWarning(errno, "QQnxMouseHandler: Unable to read from socket");
+ return;
+ }
+
+ // bytes read should always be equal to the size of a packet.
+ Q_ASSERT(bytesRead == sizeof(packet));
+
+ // translate the coordinates from the QNX data structure to Qt coordinates
+ // note the swapped y axis
+ QPoint pos = mousePos;
+ pos += QPoint(packet.dx, -packet.dy);
+
+ // QNX only tells us relative mouse movements, not absolute ones, so limit the
+ // cursor position manually to the screen
+ limitToScreen(pos);
+
+ // translate the QNX mouse button bitmask to Qt buttons
+ int buttons = Qt::NoButton;
+
+ if (packet.hdr.buttons & _POINTER_BUTTON_LEFT)
+ buttons |= Qt::LeftButton;
+ if (packet.hdr.buttons & _POINTER_BUTTON_MIDDLE)
+ buttons |= Qt::MidButton;
+ if (packet.hdr.buttons & _POINTER_BUTTON_RIGHT)
+ buttons |= Qt::RightButton;
+
+ // call mouseChanged() - this does all the magic to actually move the on-screen
+ // mouse cursor.
+ mouseChanged(pos, buttons, 0);
+ } while (++iteration < 11);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/embedded/qmousebus_qws.h b/src/gui/embedded/qmouseqnx_qws.h
index b51f2d9..238aabd 100644
--- a/src/gui/embedded/qmousebus_qws.h
+++ b/src/gui/embedded/qmouseqnx_qws.h
@@ -39,9 +39,10 @@
**
****************************************************************************/
-#ifndef QMOUSEBUS_QWS_H
-#define QMOUSEBUS_QWS_H
+#ifndef QMOUSE_QNX_H
+#define QMOUSE_QNX_H
+#include <QtCore/qobject.h>
#include <QtGui/qmouse_qws.h>
QT_BEGIN_HEADER
@@ -50,27 +51,29 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-#ifndef QT_NO_QWS_MOUSE_BUS
+class QSocketNotifier;
-class QWSBusMouseHandlerPrivate;
-
-class QWSBusMouseHandler : public QWSMouseHandler
+class Q_GUI_EXPORT QQnxMouseHandler : public QObject, public QWSMouseHandler
{
+ Q_OBJECT
public:
- explicit QWSBusMouseHandler(const QString & = QString(),
- const QString & = QString());
- ~QWSBusMouseHandler();
+ explicit QQnxMouseHandler(const QString &driver = QString(),
+ const QString &device = QString());
+ ~QQnxMouseHandler();
- void suspend();
void resume();
-protected:
- QWSBusMouseHandlerPrivate *d;
-};
+ void suspend();
+
+private Q_SLOTS:
+ void socketActivated();
-#endif // QT_NO_QWS_MOUSE_BUS
+private:
+ QSocketNotifier *mouseNotifier;
+ int mouseFD;
+};
QT_END_NAMESPACE
QT_END_HEADER
-#endif // QMOUSEBUS_QWS_H
+#endif // QMOUSE_QWS_H
diff --git a/src/gui/embedded/qmousetslib_qws.h b/src/gui/embedded/qmousetslib_qws.h
index 61155db..33c30b7 100644
--- a/src/gui/embedded/qmousetslib_qws.h
+++ b/src/gui/embedded/qmousetslib_qws.h
@@ -73,8 +73,8 @@ protected:
};
-QT_END_NAMESPACE
#endif // QT_NO_QWS_MOUSE_TSLIB
+QT_END_NAMESPACE
QT_END_HEADER
#endif // QMOUSETSLIB_QWS_H
diff --git a/src/gui/embedded/qmousevfb_qws.cpp b/src/gui/embedded/qmousevfb_qws.cpp
index b66496d..68865af 100644
--- a/src/gui/embedded/qmousevfb_qws.cpp
+++ b/src/gui/embedded/qmousevfb_qws.cpp
@@ -54,6 +54,7 @@
#include <qsocketnotifier.h>
#include <qapplication.h>
#include <qtimer.h>
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
QT_BEGIN_NAMESPACE
@@ -64,7 +65,7 @@ QVFbMouseHandler::QVFbMouseHandler(const QString &driver, const QString &device)
if (device.isEmpty())
mouseDev = QLatin1String("/dev/vmouse");
- mouseFD = open(mouseDev.toLatin1().constData(), O_RDWR | O_NDELAY);
+ mouseFD = QT_OPEN(mouseDev.toLatin1().constData(), O_RDWR | O_NDELAY);
if (mouseFD == -1) {
perror("QVFbMouseHandler::QVFbMouseHandler");
qWarning("QVFbMouseHander: Unable to open device %s",
@@ -74,7 +75,7 @@ QVFbMouseHandler::QVFbMouseHandler(const QString &driver, const QString &device)
// Clear pending input
char buf[2];
- while (read(mouseFD, buf, 1) > 0) { }
+ while (QT_READ(mouseFD, buf, 1) > 0) { }
mouseIdx = 0;
@@ -85,7 +86,7 @@ QVFbMouseHandler::QVFbMouseHandler(const QString &driver, const QString &device)
QVFbMouseHandler::~QVFbMouseHandler()
{
if (mouseFD >= 0)
- close(mouseFD);
+ QT_CLOSE(mouseFD);
}
void QVFbMouseHandler::resume()
@@ -102,7 +103,7 @@ void QVFbMouseHandler::readMouseData()
{
int n;
do {
- n = read(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx);
+ n = QT_READ(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx);
if (n > 0)
mouseIdx += n;
} while (n > 0);
diff --git a/src/gui/embedded/qmousevr41xx_qws.cpp b/src/gui/embedded/qmousevr41xx_qws.cpp
deleted file mode 100644
index ec46bab..0000000
--- a/src/gui/embedded/qmousevr41xx_qws.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmousevr41xx_qws.h"
-
-#ifndef QT_NO_QWS_MOUSE_VR41XX
-#include "qwindowsystem_qws.h"
-#include "qsocketnotifier.h"
-#include "qtimer.h"
-#include "qapplication.h"
-#include "qscreen_qws.h"
-#include <qstringlist.h>
-#include <qvarlengtharray.h>
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <termios.h>
-
-QT_BEGIN_NAMESPACE
-
-static const int defaultFilterSize = 3;
-
-class QWSVr41xxMouseHandlerPrivate : public QObject
-{
- Q_OBJECT
-public:
- QWSVr41xxMouseHandlerPrivate(QWSVr41xxMouseHandler *, const QString &, const QString &);
- ~QWSVr41xxMouseHandlerPrivate();
-
- void resume();
- void suspend();
-
-private slots:
- void sendRelease();
- void readMouseData();
-
-private:
- bool getSample();
- ushort currSample[6];
- uint currLength;
-
- int mouseFD;
- int mouseIdx;
- QTimer *rtimer;
- QSocketNotifier *mouseNotifier;
- QWSVr41xxMouseHandler *handler;
- QPoint lastPos;
- bool isPressed;
- int filterSize;
- int pressLimit;
-};
-
-QWSVr41xxMouseHandler::QWSVr41xxMouseHandler(const QString &drv, const QString &dev)
- : QWSCalibratedMouseHandler(drv, dev)
-{
- d = new QWSVr41xxMouseHandlerPrivate(this, drv, dev);
-}
-
-QWSVr41xxMouseHandler::~QWSVr41xxMouseHandler()
-{
- delete d;
-}
-
-void QWSVr41xxMouseHandler::resume()
-{
- d->resume();
-}
-
-void QWSVr41xxMouseHandler::suspend()
-{
- d->suspend();
-}
-
-QWSVr41xxMouseHandlerPrivate::QWSVr41xxMouseHandlerPrivate(QWSVr41xxMouseHandler *h, const QString &, const QString &device)
- : currLength(0), handler(h)
-{
- QStringList options = device.split(QLatin1String(":"));
- int index = -1;
-
- filterSize = defaultFilterSize;
- QRegExp filterRegExp(QLatin1String("filter=(\\d+)"));
- index = options.indexOf(filterRegExp);
- if (index != -1) {
- filterSize = qMax(1, filterRegExp.cap(1).toInt());
- options.removeAt(index);
- }
- handler->setFilterSize(filterSize);
-
- pressLimit = 750;
- QRegExp pressRegExp(QLatin1String("press=(\\d+)"));
- index = options.indexOf(pressRegExp);
- if (index != -1) {
- pressLimit = filterRegExp.cap(1).toInt();
- options.removeAt(index);
- }
-
- QString dev;
- if (options.isEmpty())
- dev = QLatin1String("/dev/vrtpanel");
- else
- dev = options.first();
-
- if ((mouseFD = open(dev.toLocal8Bit().constData(), O_RDONLY)) < 0) {
- qWarning("Cannot open %s (%s)", qPrintable(dev), strerror(errno));
- return;
- }
- sleep(1);
-
- if (fcntl(mouseFD, F_SETFL, O_NONBLOCK) < 0) {
- qWarning("Error initializing touch panel.");
- return;
- }
-
- mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
- connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
-
- rtimer = new QTimer(this);
- rtimer->setSingleShot(true);
- connect(rtimer, SIGNAL(timeout()), this, SLOT(sendRelease()));
- mouseIdx = 0;
-}
-
-QWSVr41xxMouseHandlerPrivate::~QWSVr41xxMouseHandlerPrivate()
-{
- if (mouseFD >= 0)
- close(mouseFD);
-}
-
-void QWSVr41xxMouseHandlerPrivate::suspend()
-{
- mouseNotifier->setEnabled(false);
-}
-
-
-void QWSVr41xxMouseHandlerPrivate::resume()
-{
- mouseIdx = 0;
- mouseNotifier->setEnabled(true);
-}
-
-void QWSVr41xxMouseHandlerPrivate::sendRelease()
-{
- handler->sendFiltered(lastPos, Qt::NoButton);
- isPressed = false;
-}
-
-bool QWSVr41xxMouseHandlerPrivate::getSample()
-{
- const int n = read(mouseFD,
- reinterpret_cast<uchar*>(currSample) + currLength,
- sizeof(currSample) - currLength);
-
- if (n > 0)
- currLength += n;
-
- if (currLength < sizeof(currSample))
- return false;
-
- currLength = 0;
- return true;
-}
-
-void QWSVr41xxMouseHandlerPrivate::readMouseData()
-{
- const int sampleLength = sizeof(currSample) / sizeof(ushort);
- QVarLengthArray<ushort, sampleLength * defaultFilterSize> samples(sampleLength * filterSize);
-
- // Only return last 'filterSize' samples
- int head = 0;
- int tail = 0;
- int nSamples = 0;
- while (getSample()) {
- if (!(currSample[0] & 0x8000) || (currSample[5] < pressLimit))
- continue;
-
- ushort *data = samples.data() + head * sampleLength;
- memcpy(data, currSample, sizeof(currSample));
- ++nSamples;
- head = (head + 1) % filterSize;
- if (nSamples >= filterSize)
- tail = (tail + 1) % filterSize;
- }
-
- if (nSamples == 0)
- return;
-
- // send mouse events
- while (tail != head || filterSize == 1) {
- const ushort *data = samples.data() + tail * sampleLength;
- lastPos = QPoint(data[3] - data[4], data[2] - data[1]);
- handler->sendFiltered(lastPos, Qt::LeftButton);
- isPressed = true;
- tail = (tail + 1) % filterSize;
- if (filterSize == 1)
- break;
- }
-
- if (isPressed)
- rtimer->start(50); // release unreliable
-}
-
-QT_END_NAMESPACE
-
-#include "qmousevr41xx_qws.moc"
-
-#endif //QT_NO_QWS_MOUSE_VR41
diff --git a/src/gui/embedded/qmouseyopy_qws.cpp b/src/gui/embedded/qmouseyopy_qws.cpp
deleted file mode 100644
index 8745572..0000000
--- a/src/gui/embedded/qmouseyopy_qws.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmouseyopy_qws.h"
-
-#ifndef QT_NO_QWS_MOUSE_YOPY
-#include "qwindowsystem_qws.h"
-#include "qsocketnotifier.h"
-#include "qapplication.h"
-#include "qscreen_qws.h"
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <termios.h>
-
-QT_BEGIN_NAMESPACE
-
-class QWSYopyMouseHandlerPrivate : public QObject
-{
- Q_OBJECT
-public:
- QWSYopyMouseHandlerPrivate(QWSYopyMouseHandler *h);
- ~QWSYopyMouseHandlerPrivate();
-
- void suspend();
- void resume();
-
-private slots:
- void readMouseData();
-
-private:
- int mouseFD;
- int prevstate;
- QSocketNotifier *mouseNotifier;
- QWSYopyMouseHandler *handler;
-};
-
-QWSYopyMouseHandler::QWSYopyMouseHandler(const QString &driver, const QString &device)
- : QWSMouseHandler(driver, device)
-{
- d = new QWSYopyMouseHandlerPrivate(this);
-}
-
-QWSYopyMouseHandler::~QWSYopyMouseHandler()
-{
- delete d;
-}
-
-void QWSYopyMouseHandler::resume()
-{
- d->resume();
-}
-
-void QWSYopyMouseHandler::suspend()
-{
- d->suspend();
-}
-
-QWSYopyMouseHandlerPrivate::QWSYopyMouseHandlerPrivate(QWSYopyMouseHandler *h)
- : handler(h)
-{
- if ((mouseFD = open("/dev/ts", O_RDONLY)) < 0) {
- qWarning("Cannot open /dev/ts (%s)", strerror(errno));
- return;
- } else {
- sleep(1);
- }
- prevstate=0;
- mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read,
- this);
- connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
-}
-
-QWSYopyMouseHandlerPrivate::~QWSYopyMouseHandlerPrivate()
-{
- if (mouseFD >= 0)
- close(mouseFD);
-}
-
-#define YOPY_XPOS(d) (d[1]&0x3FF)
-#define YOPY_YPOS(d) (d[2]&0x3FF)
-#define YOPY_PRES(d) (d[0]&0xFF)
-#define YOPY_STAT(d) (d[3]&0x01)
-
-struct YopyTPdata {
-
- unsigned char status;
- unsigned short xpos;
- unsigned short ypos;
-
-};
-
-void QWSYopyMouseHandlerPrivate::suspend()
-{
- mouseNotifier->setEnabled(false);
-}
-
-
-void QWSYopyMouseHandlerPrivate::resume()
-{
- prevstate = 0;
- mouseNotifier->setEnabled(true);
-}
-
-void QWSYopyMouseHandlerPrivate::readMouseData()
-{
- if(!qt_screen)
- return;
- YopyTPdata data;
-
- unsigned int yopDat[4];
-
- int ret;
-
- ret=read(mouseFD,&yopDat,sizeof(yopDat));
-
- if(ret) {
- data.status= (YOPY_PRES(yopDat)) ? 1 : 0;
- data.xpos=YOPY_XPOS(yopDat);
- data.ypos=YOPY_YPOS(yopDat);
- QPoint q;
- q.setX(data.xpos);
- q.setY(data.ypos);
- if (data.status && !prevstate) {
- handler->mouseChanged(q,Qt::LeftButton);
- } else if(!data.status && prevstate) {
- handler->mouseChanged(q,0);
- }
- prevstate = data.status;
- }
- if(ret<0) {
- qDebug("Error %s",strerror(errno));
- }
-}
-
-QT_END_NAMESPACE
-
-#include "qmouseyopy_qws.moc"
-
-#endif //QT_NO_QWS_MOUSE_YOPY
diff --git a/src/gui/embedded/qmouseyopy_qws.h b/src/gui/embedded/qmouseyopy_qws.h
deleted file mode 100644
index 1a1ad20..0000000
--- a/src/gui/embedded/qmouseyopy_qws.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QMOUSEYOPY_QWS_H
-#define QMOUSEYOPY_QWS_H
-
-#include <QtGui/qmouse_qws.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Gui)
-
-#ifndef QT_NO_QWS_MOUSE_YOPY
-
-// YOPY touch panel support based on changes contributed by Ron Victorelli
-// (victorrj at icubed.com) to Custom TP driver.
-
-class QWSYopyMouseHandlerPrivate;
-
-class QWSYopyMouseHandler : public QWSMouseHandler
-{
-public:
- explicit QWSYopyMouseHandler(const QString & = QString(),
- const QString & = QString());
- ~QWSYopyMouseHandler();
-
- void resume();
- void suspend();
-
-protected:
- QWSYopyMouseHandlerPrivate *d;
-};
-
-#endif // QT_NO_QWS_MOUSE_YOPY
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QMOUSEYOPY_QWS_H
diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp
index cfce78c..fafa35d 100644
--- a/src/gui/embedded/qscreen_qws.cpp
+++ b/src/gui/embedded/qscreen_qws.cpp
@@ -49,6 +49,7 @@
#include "qpixmap.h"
#include "qvarlengtharray.h"
#include "qwsdisplay_qws.h"
+#include "qpainter.h"
#include <private/qdrawhelper_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qpixmap_raster_p.h>
@@ -180,7 +181,27 @@ void QScreenCursor::set(const QImage &image, int hotx, int hoty)
const QRect r = boundingRect();
hotspot = QPoint(hotx, hoty);
- cursor = image;
+ // These are in almost all cases the fastest formats to blend
+ QImage::Format f;
+ switch (qt_screen->depth()) {
+ case 12:
+ f = QImage::Format_ARGB4444_Premultiplied;
+ break;
+ case 15:
+ f = QImage::Format_ARGB8555_Premultiplied;
+ break;
+ case 16:
+ f = QImage::Format_ARGB8565_Premultiplied;
+ break;
+ case 18:
+ f = QImage::Format_ARGB6666_Premultiplied;
+ break;
+ default:
+ f = QImage::Format_ARGB32_Premultiplied;
+ }
+
+ cursor = image.convertToFormat(f);
+
size = image.size();
if (enable && !hwaccel)
@@ -198,10 +219,12 @@ void QScreenCursor::set(const QImage &image, int hotx, int hoty)
*/
void QScreenCursor::move(int x, int y)
{
- const QRegion r = boundingRect();
+ QRegion r = boundingRect();
pos = QPoint(x,y);
- if (enable && !hwaccel)
- qt_screen->exposeRegion(r | boundingRect(), 0);
+ if (enable && !hwaccel) {
+ r |= boundingRect();
+ qt_screen->exposeRegion(r, 0);
+ }
}
@@ -2417,7 +2440,7 @@ void QScreen::exposeRegion(QRegion r, int windowIndex)
#endif
compose(0, r, blendRegion, &blendBuffer, changing);
- if (blendBuffer) {
+ if (blendBuffer && !blendBuffer->isNull()) {
const QPoint offset = blendRegion.boundingRect().topLeft();
#ifndef QT_NO_QWS_CURSOR
if (qt_screencursor && !qt_screencursor->isAccelerated()) {
@@ -2708,7 +2731,7 @@ void QScreen::compose(int level, const QRegion &exposed, QRegion &blend,
default:
break;
}
- spanData.setup(qwsServer->backgroundBrush(), 256);
+ spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_SourceOver);
spanData.dx = off.x();
spanData.dy = off.y();
} else if (!surface->isBuffered()) {
@@ -2773,7 +2796,7 @@ void QScreen::paintBackground(const QRegion &r)
rb.prepare(&img);
QSpanData spanData;
spanData.init(&rb, 0);
- spanData.setup(bg, 256);
+ spanData.setup(bg, 256, QPainter::CompositionMode_Source);
spanData.dx = off.x();
spanData.dy = off.y();
Q_ASSERT(spanData.blend);
diff --git a/src/gui/embedded/qscreen_qws.h b/src/gui/embedded/qscreen_qws.h
index 200478c..a505dfd 100644
--- a/src/gui/embedded/qscreen_qws.h
+++ b/src/gui/embedded/qscreen_qws.h
@@ -50,6 +50,8 @@
#include <QtGui/qimage.h>
#include <QtGui/qregion.h>
+struct fb_cmap;
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -169,8 +171,6 @@ private:
#endif // QT_NO_QWS_CURSOR
-struct fb_cmap;
-
// A (used) chunk of offscreen memory
class QPoolEntry
diff --git a/src/gui/embedded/qscreendriverfactory_qws.cpp b/src/gui/embedded/qscreendriverfactory_qws.cpp
index 1bbcd33..21058af 100644
--- a/src/gui/embedded/qscreendriverfactory_qws.cpp
+++ b/src/gui/embedded/qscreendriverfactory_qws.cpp
@@ -47,6 +47,7 @@
#include "qscreentransformed_qws.h"
#include "qscreenvfb_qws.h"
#include "qscreenmulti_qws_p.h"
+#include "qscreenqnx_qws.h"
#include <stdlib.h>
#include "private/qfactoryloader_p.h"
#include "qscreendriverplugin_qws.h"
@@ -105,6 +106,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
QScreen *QScreenDriverFactory::create(const QString& key, int displayId)
{
QString driver = key.toLower();
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_QNX)
+ if (driver == QLatin1String("qnx") || driver.isEmpty())
+ return new QQnxScreen(displayId);
+#endif
#ifndef QT_NO_QWS_QVFB
if (driver == QLatin1String("qvfb") || driver.isEmpty())
return new QVFbScreen(displayId);
@@ -146,6 +151,9 @@ QStringList QScreenDriverFactory::keys()
{
QStringList list;
+#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_QNX)
+ list << QLatin1String("QNX");
+#endif
#ifndef QT_NO_QWS_QVFB
list << QLatin1String("QVFb");
#endif
diff --git a/src/gui/embedded/qscreenlinuxfb_qws.cpp b/src/gui/embedded/qscreenlinuxfb_qws.cpp
index 21fd8ad..4ec0290 100644
--- a/src/gui/embedded/qscreenlinuxfb_qws.cpp
+++ b/src/gui/embedded/qscreenlinuxfb_qws.cpp
@@ -46,6 +46,7 @@
#include "qwsdisplay_qws.h"
#include "qpixmap.h"
#include <private/qwssignalhandler_p.h>
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <unistd.h>
#include <stdlib.h>
@@ -122,12 +123,12 @@ void QLinuxFbScreenPrivate::openTty()
if (ttyDevice.isEmpty()) {
for (const char * const *dev = devs; *dev; ++dev) {
- ttyfd = ::open(*dev, O_RDWR);
+ ttyfd = QT_OPEN(*dev, O_RDWR);
if (ttyfd != -1)
break;
}
} else {
- ttyfd = ::open(ttyDevice.toAscii().constData(), O_RDWR);
+ ttyfd = QT_OPEN(ttyDevice.toAscii().constData(), O_RDWR);
}
if (ttyfd == -1)
@@ -144,7 +145,7 @@ void QLinuxFbScreenPrivate::openTty()
// No blankin' screen, no blinkin' cursor!, no cursor!
const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c";
- ::write(ttyfd, termctl, sizeof(termctl));
+ QT_WRITE(ttyfd, termctl, sizeof(termctl));
}
void QLinuxFbScreenPrivate::closeTty()
@@ -157,9 +158,9 @@ void QLinuxFbScreenPrivate::closeTty()
// Blankin' screen, blinkin' cursor!
const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c";
- ::write(ttyfd, termctl, sizeof(termctl));
+ QT_WRITE(ttyfd, termctl, sizeof(termctl));
- ::close(ttyfd);
+ QT_CLOSE(ttyfd);
ttyfd = -1;
}
@@ -270,18 +271,16 @@ bool QLinuxFbScreen::connect(const QString &displaySpec)
QScreen::setFrameBufferLittleEndian(true);
#endif
- // Check for explicitly specified device
- const int len = 8; // "/dev/fbx"
- int m = displaySpec.indexOf(QLatin1String("/dev/fb"));
-
- QString dev;
- if (m > 0)
- dev = displaySpec.mid(m, len);
- else
- dev = QLatin1String("/dev/fb0");
+ QString dev = QLatin1String("/dev/fb0");
+ foreach(QString d, args) {
+ if (d.startsWith(QLatin1Char('/'))) {
+ dev = d;
+ break;
+ }
+ }
if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)
- d_ptr->fd = open(dev.toLatin1().constData(), O_RDWR);
+ d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);
if (d_ptr->fd == -1) {
if (QApplication::type() == QApplication::GuiServer) {
perror("QScreenLinuxFb::connect");
@@ -289,11 +288,11 @@ bool QLinuxFbScreen::connect(const QString &displaySpec)
return false;
}
if (access(dev.toLatin1().constData(), R_OK) == 0)
- d_ptr->fd = open(dev.toLatin1().constData(), O_RDONLY);
+ d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);
}
- fb_fix_screeninfo finfo;
- fb_var_screeninfo vinfo;
+ ::fb_fix_screeninfo finfo;
+ ::fb_var_screeninfo vinfo;
//#######################
// Shut up Valgrind
memset(&vinfo, 0, sizeof(vinfo));
@@ -430,7 +429,7 @@ bool QLinuxFbScreen::connect(const QString &displaySpec)
if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) {
screencols= (vinfo.bits_per_pixel==8) ? 256 : 16;
int loopc;
- fb_cmap startcmap;
+ ::fb_cmap startcmap;
startcmap.start=0;
startcmap.len=screencols;
startcmap.red=(unsigned short int *)
@@ -681,7 +680,7 @@ bool QLinuxFbScreen::initDevice()
#ifdef __i386__
// Now init mtrr
if(!::getenv("QWS_NOMTRR")) {
- int mfd=open("/proc/mtrr",O_WRONLY,0);
+ int mfd=QT_OPEN("/proc/mtrr",O_WRONLY,0);
// MTRR entry goes away when file is closed - i.e.
// hopefully when QWS is killed
if(mfd != -1) {
@@ -702,6 +701,9 @@ bool QLinuxFbScreen::initDevice()
//sentry.base,sentry.size,strerror(errno));
}
}
+
+ // Should we close mfd here?
+ //QT_CLOSE(mfd);
}
#endif
if ((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4) || (finfo.visual==FB_VISUAL_DIRECTCOLOR))
diff --git a/src/gui/embedded/qscreenlinuxfb_qws.h b/src/gui/embedded/qscreenlinuxfb_qws.h
index 87b6a6d..1b6ac31 100644
--- a/src/gui/embedded/qscreenlinuxfb_qws.h
+++ b/src/gui/embedded/qscreenlinuxfb_qws.h
@@ -44,6 +44,11 @@
#include <QtGui/qscreen_qws.h>
+struct fb_cmap;
+struct fb_var_screeninfo;
+struct fb_fix_screeninfo;
+
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -70,9 +75,6 @@ public:
};
-struct fb_cmap;
-struct fb_var_screeninfo;
-struct fb_fix_screeninfo;
class QLinuxFbScreenPrivate;
class Q_GUI_EXPORT QLinuxFbScreen : public QScreen
diff --git a/src/gui/embedded/qscreenmulti_qws.cpp b/src/gui/embedded/qscreenmulti_qws.cpp
index 9637153..28a38c7 100644
--- a/src/gui/embedded/qscreenmulti_qws.cpp
+++ b/src/gui/embedded/qscreenmulti_qws.cpp
@@ -221,9 +221,9 @@ bool QMultiScreen::connect(const QString &displaySpec)
{
QString dSpec = displaySpec;
if (dSpec.startsWith(QLatin1String("Multi:"), Qt::CaseInsensitive))
- dSpec = dSpec.mid(QString(QLatin1String("Multi:")).size());
+ dSpec = dSpec.mid(QString::fromLatin1("Multi:").size());
- const QString displayIdSpec = QString(QLatin1String(" :%1")).arg(displayId);
+ const QString displayIdSpec = QString::fromLatin1(" :%1").arg(displayId);
if (dSpec.endsWith(displayIdSpec))
dSpec = dSpec.left(dSpec.size() - displayIdSpec.size());
diff --git a/src/gui/embedded/qscreenproxy_qws.cpp b/src/gui/embedded/qscreenproxy_qws.cpp
index 36a308b..f50a2bb 100644
--- a/src/gui/embedded/qscreenproxy_qws.cpp
+++ b/src/gui/embedded/qscreenproxy_qws.cpp
@@ -45,6 +45,7 @@
#include <qregexp.h>
+QT_BEGIN_NAMESPACE
#ifndef QT_NO_QWS_CURSOR
/*!
@@ -279,6 +280,7 @@ void QProxyScreen::exposeRegion(QRegion r, int changing)
}
realScreen->exposeRegion(r, changing);
+ r &= realScreen->region();
const QVector<QRect> rects = r.rects();
for (int i = 0; i < rects.size(); ++i)
@@ -536,7 +538,7 @@ int QProxyScreen::transformOrientation() const
}
/*!
-\reimp
+\internal
*/
int QProxyScreen::memoryNeeded(const QString &str)
{
@@ -547,7 +549,7 @@ int QProxyScreen::memoryNeeded(const QString &str)
}
/*!
-\reimp
+\internal
*/
int QProxyScreen::sharedRamSize(void *ptr)
{
@@ -558,7 +560,7 @@ int QProxyScreen::sharedRamSize(void *ptr)
}
/*!
-\reimp
+\internal
*/
void QProxyScreen::haltUpdates()
{
@@ -567,7 +569,7 @@ void QProxyScreen::haltUpdates()
}
/*!
-\reimp
+\internal
*/
void QProxyScreen::resumeUpdates()
{
@@ -628,4 +630,6 @@ QRegion QProxyScreen::region() const
return QScreen::region();
}
+QT_END_NAMESPACE
+
#endif // QT_NO_QWS_PROXYSCREEN
diff --git a/src/gui/embedded/qscreenqnx_qws.cpp b/src/gui/embedded/qscreenqnx_qws.cpp
new file mode 100644
index 0000000..77fe13e
--- /dev/null
+++ b/src/gui/embedded/qscreenqnx_qws.cpp
@@ -0,0 +1,450 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscreenqnx_qws.h"
+#include "qdebug.h"
+
+#include <gf/gf.h>
+
+QT_BEGIN_NAMESPACE
+
+// This struct holds all the pointers to QNX's internals
+struct QQnxScreenContext
+{
+ inline QQnxScreenContext()
+ : device(0), display(0), layer(0), hwSurface(0), memSurface(0), context(0)
+ {}
+
+ gf_dev_t device;
+ gf_dev_info_t deviceInfo;
+ gf_display_t display;
+ gf_display_info_t displayInfo;
+ gf_layer_t layer;
+ gf_surface_t hwSurface;
+ gf_surface_t memSurface;
+ gf_surface_info_t memSurfaceInfo;
+ gf_context_t context;
+};
+
+/*!
+ \class QQnxScreen
+ \preliminary
+ \ingroup qws
+ \since 4.6
+ \internal
+
+ \brief The QQnxScreen class implements a screen driver
+ for QNX io-display based devices.
+
+ Note - you never have to instanciate this class, the QScreenDriverFactory
+ does that for us based on the \c{QWS_DISPLAY} environment variable.
+
+ To activate this driver, set \c{QWS_DISPLAY} to \c{qnx}.
+
+ Example:
+ \c{QWS_DISPLAY=qnx; export QWS_DISPLAY}
+
+ By default, the main layer of the first display of the first device is used.
+ If you have multiple graphic cards, multiple displays or multiple layers and
+ don't want to connect to the default, you can override that with setting
+ the corresponding options \c{device}, \c{display} or \c{layer} in the \c{QWS_DISPLAY} variable:
+
+ \c{QWS_DISPLAY=qnx:device=3:display=4:layer=5}
+
+ In addition, it is suggested to set the physical width and height of the display.
+ QQnxScreen will use that information to compute the dots per inch (DPI) in order to render
+ fonts correctly. If this informaiton is omitted, QQnxScreen defaults to 72 dpi.
+
+ \c{QWS_DISPLAY=qnx:mmWidth=120:mmHeight=80}
+
+ \c{mmWidth} and \c{mmHeight} are the physical width/height of the screen in millimeters.
+
+ \sa QScreen, QScreenDriverPlugin, {Running Qt for Embedded Linux Applications}{Running Applications}
+*/
+
+/*!
+ Constructs a QQnxScreen object. The \a display_id argument
+ identifies the Qt for Embedded Linux server to connect to.
+*/
+QQnxScreen::QQnxScreen(int display_id)
+ : QScreen(display_id), d(new QQnxScreenContext)
+{
+}
+
+/*!
+ Destroys this QQnxScreen object.
+*/
+QQnxScreen::~QQnxScreen()
+{
+ delete d;
+}
+
+/*! \reimp
+*/
+bool QQnxScreen::initDevice()
+{
+ // implement this if you have multiple processes that want to access the display
+ // (not required if QT_NO_QWS_MULTIPROCESS is set)
+ return true;
+}
+
+/*! \internal
+ Attaches to the named device \a name.
+*/
+static bool attachDevice(QQnxScreenContext * const d, const char *name)
+{
+ int ret = gf_dev_attach(&d->device, name, &d->deviceInfo);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_dev_attach(%s) failed with error code %d", name, ret);
+ return false;
+ }
+ return true;
+}
+
+/*! \internal
+ Attaches to the display at index \a displayIndex.
+ */
+static bool attachDisplay(QQnxScreenContext * const d, int displayIndex)
+{
+ int ret = gf_display_attach(&d->display, d->device, displayIndex, &d->displayInfo);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_display_attach(%d) failed with error code %d",
+ displayIndex, ret);
+ return false;
+ }
+ return true;
+}
+
+/*! \internal
+ Attaches to the layer \a layerIndex.
+ */
+static bool attachLayer(QQnxScreenContext * const d, int layerIndex)
+{
+ int ret = gf_layer_attach(&d->layer, d->display, layerIndex, 0);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_layer_attach(%d) failed with error code %d", layerIndex,
+ ret);
+ return false;
+ }
+ gf_layer_enable(d->layer);
+
+ return true;
+}
+
+/*! \internal
+ Creates a new hardware surface (usually on the Gfx card memory) with the dimensions \a w * \a h.
+ */
+static bool createHwSurface(QQnxScreenContext * const d, int w, int h)
+{
+ int ret = gf_surface_create_layer(&d->hwSurface, &d->layer, 1, 0,
+ w, h, GF_FORMAT_ARGB8888, 0, 0);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_surface_create_layer(%dx%d) failed with error code %d",
+ w, h, ret);
+ return false;
+ }
+
+ gf_layer_set_surfaces(d->layer, &d->hwSurface, 1);
+
+ ret = gf_layer_update(d->layer, 0);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_layer_update() failed with error code %d\n", ret);
+ return false;
+ }
+
+ return true;
+}
+
+/*! \internal
+ Creates an in-memory, linear accessible surface of dimensions \a w * \a h.
+ This is the main surface that QWS blits to.
+ */
+static bool createMemSurface(QQnxScreenContext * const d, int w, int h)
+{
+ // Note: gf_surface_attach() could also be used, so we'll create the buffer
+ // and let the surface point to it. Here, we use surface_create instead.
+
+ int ret = gf_surface_create(&d->memSurface, d->device, w, h,
+ GF_FORMAT_ARGB8888, 0,
+ GF_SURFACE_CREATE_CPU_FAST_ACCESS | GF_SURFACE_CREATE_CPU_LINEAR_ACCESSIBLE
+ | GF_SURFACE_PHYS_CONTIG);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_surface_create(%dx%d) failed with error code %d",
+ w, h, ret);
+ return false;
+ }
+
+ gf_surface_get_info(d->memSurface, &d->memSurfaceInfo);
+
+ if (d->memSurfaceInfo.sid == unsigned(GF_SID_INVALID)) {
+ qWarning("QQnxScreen: gf_surface_get_info() failed.");
+ return false;
+ }
+
+ return true;
+}
+
+/* \internal
+ Creates a QNX gf context and sets our memory surface on it.
+ */
+static bool createContext(QQnxScreenContext * const d)
+{
+ int ret = gf_context_create(&d->context);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_context_create() failed with error code %d", ret);
+ return false;
+ }
+
+ ret = gf_context_set_surface(d->context, d->memSurface);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_context_set_surface() failed with error code %d", ret);
+ return false;
+ }
+
+ return true;
+}
+
+/*! \reimp
+ Connects to QNX's io-display based device based on the \a displaySpec parameters
+ from the \c{QWS_DISPLAY} environment variable. See the QQnxScreen class documentation
+ for possible parameters.
+
+ \sa QQnxScreen
+ */
+bool QQnxScreen::connect(const QString &displaySpec)
+{
+ const QStringList params = displaySpec.split(QLatin1Char(':'), QString::SkipEmptyParts);
+
+ bool isOk = false;
+ QRegExp deviceRegExp(QLatin1String("^device=(.+)$"));
+ if (params.indexOf(deviceRegExp) != -1) {
+ isOk = attachDevice(d, deviceRegExp.cap(1).toLocal8Bit().constData());
+ } else {
+ // no device specified - attach to device 0 (the default)
+ isOk = attachDevice(d, GF_DEVICE_INDEX(0));
+ }
+
+ if (!isOk)
+ return false;
+
+ qDebug("QQnxScreen: Attached to Device, number of displays: %d", d->deviceInfo.ndisplays);
+
+ // default to display 0
+ int displayIndex = 0;
+ QRegExp displayRegexp(QLatin1String("^display=(\\d+)$"));
+ if (params.indexOf(displayRegexp) != -1) {
+ displayIndex = displayRegexp.cap(1).toInt();
+ }
+
+ if (!attachDisplay(d, displayIndex))
+ return false;
+
+ qDebug("QQnxScreen: Attached to Display %d, resolution %dx%d, refresh %d Hz",
+ displayIndex, d->displayInfo.xres, d->displayInfo.yres,
+ d->displayInfo.refresh);
+
+
+ // default to main_layer_index from the displayInfo struct
+ int layerIndex = 0;
+ QRegExp layerRegexp(QLatin1String("^layer=(\\d+)$"));
+ if (params.indexOf(layerRegexp) != -1) {
+ layerIndex = layerRegexp.cap(1).toInt();
+ } else {
+ layerIndex = d->displayInfo.main_layer_index;
+ }
+
+ if (!attachLayer(d, layerIndex))
+ return false;
+
+ // tell QWSDisplay the width and height of the display
+ w = dw = d->displayInfo.xres;
+ h = dh = d->displayInfo.yres;
+
+ // we only support 32 bit displays for now.
+ QScreen::d = 32;
+
+ // assume 72 dpi as default, to calculate the physical dimensions if not specified
+ const int defaultDpi = 72;
+
+ // Handle display physical size spec.
+ QRegExp mmWidthRegexp(QLatin1String("^mmWidth=(\\d+)$"));
+ if (params.indexOf(mmWidthRegexp) == -1) {
+ physWidth = qRound(dw * 25.4 / defaultDpi);
+ } else {
+ physWidth = mmWidthRegexp.cap(1).toInt();
+ }
+
+ QRegExp mmHeightRegexp(QLatin1String("^mmHeight=(\\d+)$"));
+ if (params.indexOf(mmHeightRegexp) == -1) {
+ physHeight = qRound(dh * 25.4 / defaultDpi);
+ } else {
+ physHeight = mmHeightRegexp.cap(1).toInt();
+ }
+
+ // create a hardware surface with our dimensions. In the old days, it was possible
+ // to get a pointer directly to the hw surface, so we could blit directly. Now, we
+ // have to use one indirection more, because it's not guaranteed that the hw surface
+ // is mappable into our process.
+ if (!createHwSurface(d, w, h))
+ return false;
+
+ // create an in-memory linear surface that is used by QWS. QWS will blit directly in here.
+ if (!createMemSurface(d, w, h))
+ return false;
+
+ // set the address of the in-memory buffer that QWS is blitting to
+ data = d->memSurfaceInfo.vaddr;
+ // set the line stepping
+ lstep = d->memSurfaceInfo.stride;
+
+ // the overall size of the in-memory buffer is linestep * height
+ size = mapsize = lstep * h;
+
+ // create a QNX drawing context
+ if (!createContext(d))
+ return false;
+
+ // we're always using a software cursor for now. Initialize it here.
+ QScreenCursor::initSoftwareCursor();
+
+ // done, the driver should be connected to the display now.
+ return true;
+}
+
+/*! \reimp
+ */
+void QQnxScreen::disconnect()
+{
+ if (d->context)
+ gf_context_free(d->context);
+
+ if (d->memSurface)
+ gf_surface_free(d->memSurface);
+
+ if (d->hwSurface)
+ gf_surface_free(d->hwSurface);
+
+ if (d->layer)
+ gf_layer_detach(d->layer);
+
+ if (d->display)
+ gf_display_detach(d->display);
+
+ if (d->device)
+ gf_dev_detach(d->device);
+
+ d->memSurface = 0;
+ d->hwSurface = 0;
+ d->context = 0;
+ d->layer = 0;
+ d->display = 0;
+ d->device = 0;
+}
+
+/*! \reimp
+ */
+void QQnxScreen::shutdownDevice()
+{
+}
+
+
+/*! \reimp
+ QQnxScreen doesn't support setting the mode, use io-display instead.
+ */
+void QQnxScreen::setMode(int,int,int)
+{
+ qWarning("QQnxScreen: Unable to change mode, use io-display instead.");
+}
+
+/*! \reimp
+ */
+bool QQnxScreen::supportsDepth(int depth) const
+{
+ // only 32-bit for the moment
+ return depth == 32;
+}
+
+/*! \reimp
+ */
+void QQnxScreen::exposeRegion(QRegion r, int changing)
+{
+ // here is where the actual magic happens. QWS will call exposeRegion whenever
+ // a region on the screen is dirty and needs to be updated on the actual screen.
+
+ // first, call the parent implementation. The parent implementation will update
+ // the region on our in-memory surface
+ QScreen::exposeRegion(r, changing);
+
+ // now our in-memory surface should be up to date with the latest changes.
+ // the code below copies the region from the in-memory surface to the hardware.
+
+ // just get the bounding rectangle of the region. Most screen updates are rectangular
+ // anyways. Code could be optimized to blit each and every member of the region
+ // individually, but in real life, the speed-up is neglectable
+ const QRect br = r.boundingRect();
+ if (br.isEmpty())
+ return; // ignore empty regions because gf_draw_blit2 doesn't like 0x0 dimensions
+
+ // start drawing.
+ int ret = gf_draw_begin(d->context);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_draw_begin() failed with error code %d", ret);
+ return;
+ }
+
+ // blit the changed region from the memory surface to the hardware surface
+ ret = gf_draw_blit2(d->context, d->memSurface, d->hwSurface,
+ br.x(), br.y(), br.right(), br.bottom(), br.x(), br.y());
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_draw_blit2() failed with error code %d", ret);
+ }
+
+ // flush all drawing commands (in our case, a single blit)
+ ret = gf_draw_flush(d->context);
+ if (ret != GF_ERR_OK) {
+ qWarning("QQnxScreen: gf_draw_flush() failed with error code %d", ret);
+ }
+
+ // tell QNX that we're done drawing.
+ gf_draw_end(d->context);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qkbdusb_qws.h b/src/gui/embedded/qscreenqnx_qws.h
index f2ab085..5ec9ede 100644
--- a/src/gui/embedded/qkbdusb_qws.h
+++ b/src/gui/embedded/qscreenqnx_qws.h
@@ -39,10 +39,12 @@
**
****************************************************************************/
-#ifndef QKBDUSB_QWS_H
-#define QKBDUSB_QWS_H
+#ifndef QSCREENQNX_QWS_H
+#define QSCREENQNX_QWS_H
-#include <QtGui/qkbdpc101_qws.h>
+#include <QtGui/qscreen_qws.h>
+
+#ifndef QT_NO_QWS_QNX
QT_BEGIN_HEADER
@@ -50,28 +52,31 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-#ifndef QT_NO_QWS_KEYBOARD
-
-#ifndef QT_NO_QWS_KBD_USB
+struct QQnxScreenContext;
-class QWSUsbKbPrivate;
-
-class QWSUsbKeyboardHandler : public QWSPC101KeyboardHandler
+class QQnxScreen : public QScreen
{
public:
- QWSUsbKeyboardHandler(const QString&);
- virtual ~QWSUsbKeyboardHandler();
+ explicit QQnxScreen(int display_id);
+ ~QQnxScreen();
-private:
- QWSUsbKbPrivate *d;
-};
+ bool initDevice();
+ bool connect(const QString &displaySpec);
+ void disconnect();
+ void shutdownDevice();
+ void setMode(int,int,int);
+ bool supportsDepth(int) const;
-#endif // QT_NO_QWS_KBD_USB
+ void exposeRegion(QRegion r, int changing);
-#endif // QT_NO_QWS_KEYBOARD
+private:
+ QQnxScreenContext * const d;
+};
QT_END_NAMESPACE
QT_END_HEADER
-#endif // QKBDUSB_QWS_H
+#endif // QT_NO_QWS_QNX
+
+#endif
diff --git a/src/gui/embedded/qscreentransformed_qws.cpp b/src/gui/embedded/qscreentransformed_qws.cpp
index 2187235..f8fb3c5 100644
--- a/src/gui/embedded/qscreentransformed_qws.cpp
+++ b/src/gui/embedded/qscreentransformed_qws.cpp
@@ -206,11 +206,11 @@ bool QTransformedScreen::connect(const QString &displaySpec)
{
QString dspec = displaySpec.trimmed();
if (dspec.startsWith(QLatin1String("Transformed:"), Qt::CaseInsensitive))
- dspec = dspec.mid(QString(QLatin1String("Transformed:")).size());
+ dspec = dspec.mid(QString::fromLatin1("Transformed:").size());
else if (!dspec.compare(QLatin1String("Transformed"), Qt::CaseInsensitive))
dspec = QString();
- const QString displayIdSpec = QString(QLatin1String(" :%1")).arg(displayId);
+ const QString displayIdSpec = QString::fromLatin1(" :%1").arg(displayId);
if (dspec.endsWith(displayIdSpec))
dspec = dspec.left(dspec.size() - displayIdSpec.size());
@@ -223,7 +223,7 @@ bool QTransformedScreen::connect(const QString &displaySpec)
if (!QScreenDriverFactory::keys().contains(driver, Qt::CaseInsensitive))
if (!dspec.isEmpty())
- dspec.prepend(QLatin1String(":"));
+ dspec.prepend(QLatin1Char(':'));
const int id = getDisplayId(dspec);
QScreen *s = qt_get_screen(id, dspec.toLatin1().constData());
diff --git a/src/gui/embedded/qscreenvfb_qws.cpp b/src/gui/embedded/qscreenvfb_qws.cpp
index b98d7db..b6c52ab 100644
--- a/src/gui/embedded/qscreenvfb_qws.cpp
+++ b/src/gui/embedded/qscreenvfb_qws.cpp
@@ -330,7 +330,7 @@ void QVFbScreen::disconnect()
bool QVFbScreen::initDevice()
{
#ifndef QT_NO_QWS_MOUSE_QVFB
- const QString mouseDev = QString(QLatin1String(QT_VFB_MOUSE_PIPE))
+ const QString mouseDev = QString::fromLatin1(QT_VFB_MOUSE_PIPE)
.arg(displayId);
d_ptr->mouse = new QVFbMouseHandler(QLatin1String("QVFbMouse"), mouseDev);
qwsServer->setDefaultMouse("None");
@@ -339,7 +339,7 @@ bool QVFbScreen::initDevice()
#endif
#if !defined(QT_NO_QWS_KBD_QVFB) && !defined(QT_NO_QWS_KEYBOARD)
- const QString keyboardDev = QString(QLatin1String(QT_VFB_KEYBOARD_PIPE))
+ const QString keyboardDev = QString::fromLatin1(QT_VFB_KEYBOARD_PIPE)
.arg(displayId);
d_ptr->keyboard = new QVFbKeyboardHandler(keyboardDev);
qwsServer->setDefaultKeyboard("None");
diff --git a/src/gui/embedded/qsoundqss_qws.cpp b/src/gui/embedded/qsoundqss_qws.cpp
index 83600d7..3bd83a4 100644
--- a/src/gui/embedded/qsoundqss_qws.cpp
+++ b/src/gui/embedded/qsoundqss_qws.cpp
@@ -53,6 +53,7 @@
#include <qtimer.h>
#include <qpointer.h>
#include <qendian.h>
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <unistd.h>
#include <stdlib.h>
@@ -66,10 +67,10 @@
#include <qdebug.h>
-QT_BEGIN_NAMESPACE
-
extern int errno;
+QT_BEGIN_NAMESPACE
+
#define QT_QWS_SOUND_16BIT 1 // or 0, or undefined for always 0
#define QT_QWS_SOUND_STEREO 1 // or 0, or undefined for always 0
@@ -1036,24 +1037,28 @@ void QWSSoundServerPrivate::stopFile(int wid, int sid)
void QWSSoundServerPrivate::stopAll(int wid)
{
QWSSoundServerProvider *bucket;
- QList<QWSSoundServerProvider*>::Iterator it = active.begin();
- while (it != active.end()) {
- bucket = *it;
- if (bucket->groupId() == wid) {
- it = active.erase(it);
- delete bucket;
- } else {
- ++it;
+ if (!active.isEmpty()) {
+ QList<QWSSoundServerProvider*>::Iterator it = active.begin();
+ while (it != active.end()) {
+ bucket = *it;
+ if (bucket->groupId() == wid) {
+ it = active.erase(it);
+ delete bucket;
+ } else {
+ ++it;
+ }
}
}
- it = inactive.begin();
- while (it != inactive.end()) {
- bucket = *it;
- if (bucket->groupId() == wid) {
- it = inactive.erase(it);
- delete bucket;
- } else {
- ++it;
+ if (!inactive.isEmpty()) {
+ QList<QWSSoundServerProvider*>::Iterator it = inactive.begin();
+ while (it != inactive.end()) {
+ bucket = *it;
+ if (bucket->groupId() == wid) {
+ it = inactive.erase(it);
+ delete bucket;
+ } else {
+ ++it;
+ }
}
}
}
@@ -1137,7 +1142,7 @@ void QWSSoundServerPrivate::sendCompletedSignals()
int QWSSoundServerPrivate::openFile(int wid, int sid, const QString& filename)
{
stopFile(wid, sid); // close and re-open.
- int f = ::open(QFile::encodeName(filename), O_RDONLY|O_NONBLOCK);
+ int f = QT_OPEN(QFile::encodeName(filename), O_RDONLY|O_NONBLOCK);
if (f == -1) {
// XXX check ferror, check reason.
qDebug("Failed opening \"%s\"",filename.toLatin1().data());
@@ -1157,7 +1162,7 @@ bool QWSSoundServerPrivate::openDevice()
{
if (fd < 0) {
if( silent ) {
- fd = ::open( "/dev/null", O_WRONLY );
+ fd = QT_OPEN( "/dev/null", O_WRONLY );
// Emulate write to audio device
int delay = 1000*(sound_buffer_size>>(sound_stereo+sound_16bit))/sound_speed/2;
timerId = startTimer(delay);
@@ -1168,7 +1173,7 @@ bool QWSSoundServerPrivate::openDevice()
// Don't block open right away.
//
bool openOkay = false;
- if ((fd = ::open("/dev/dsp", O_WRONLY|O_NONBLOCK)) != -1) {
+ if ((fd = QT_OPEN("/dev/dsp", O_WRONLY|O_NONBLOCK)) != -1) {
int flags = fcntl(fd, F_GETFL);
flags &= ~O_NONBLOCK;
openOkay = (fcntl(fd, F_SETFL, flags) == 0);
@@ -1222,7 +1227,7 @@ bool QWSSoundServerPrivate::openDevice()
//
// Check system volume
//
- int mixerHandle = ::open( "/dev/mixer", O_RDWR|O_NONBLOCK );
+ int mixerHandle = QT_OPEN( "/dev/mixer", O_RDWR|O_NONBLOCK );
if ( mixerHandle >= 0 ) {
int volume;
ioctl( mixerHandle, MIXER_READ(0), &volume );
diff --git a/src/gui/embedded/qtransportauth_qws.cpp b/src/gui/embedded/qtransportauth_qws.cpp
index 585077f..3a5b6c6 100644
--- a/src/gui/embedded/qtransportauth_qws.cpp
+++ b/src/gui/embedded/qtransportauth_qws.cpp
@@ -56,6 +56,7 @@
#include "qlibraryinfo.h"
#include "qfile.h"
#include "qdebug.h"
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <syslog.h>
#include <unistd.h>
@@ -572,7 +573,7 @@ bool QTransportAuth::authorizeRequest( QTransportAuth::Data &d, const QString &r
//get cmdline from proc/pid/cmdline
snprintf( cmdlinePath, BUF_SIZE, "/proc/%d/cmdline", d.processId );
- int cmdlineFd = open( cmdlinePath, O_RDONLY );
+ int cmdlineFd = QT_OPEN( cmdlinePath, O_RDONLY );
if ( cmdlineFd == -1 )
{
qWarning( "SXE:- Error encountered in opening /proc/%u/cmdline: %s",
@@ -581,13 +582,13 @@ bool QTransportAuth::authorizeRequest( QTransportAuth::Data &d, const QString &r
}
else
{
- if ( -1 == ::read(cmdlineFd, cmdline, BUF_SIZE - 1 ) )
+ if ( -1 == QT_READ(cmdlineFd, cmdline, BUF_SIZE - 1 ) )
{
qWarning( "SXE:- Error encountered in reading /proc/%u/cmdline : %s",
d.processId, strerror(errno) );
snprintf( cmdline, BUF_SIZE, "%s", "Unknown" );
}
- close( cmdlineFd );
+ QT_CLOSE( cmdlineFd );
}
syslog( LOG_ERR | LOG_LOCAL6, "%s // PID:%u // ProgId:%u // Exe:%s // Request:%s // Cmdline:%s",
@@ -834,12 +835,12 @@ QString RequestAnalyzer::analyze( QByteArray *msgQueue )
if ( command_type == QWSCommand::QCopSend )
{
QWSQCopSendCommand *sendCommand = static_cast<QWSQCopSendCommand*>(command);
- request += QString( QLatin1String("/QCop/%1/%2") ).arg( sendCommand->channel ).arg( sendCommand->message );
+ request += QString::fromLatin1("/QCop/%1/%2").arg( sendCommand->channel ).arg( sendCommand->message );
}
if ( command_type == QWSCommand::QCopRegisterChannel )
{
QWSQCopRegisterChannelCommand *registerCommand = static_cast<QWSQCopRegisterChannelCommand*>(command);
- request += QString( QLatin1String("/QCop/RegisterChannel/%1") ).arg( registerCommand->channel );
+ request += QString::fromLatin1("/QCop/RegisterChannel/%1").arg( registerCommand->channel );
}
#endif
dataSize = QWS_PROTOCOL_ITEM_SIZE( *command );
diff --git a/src/gui/embedded/qunixsocket.cpp b/src/gui/embedded/qunixsocket.cpp
index e9cb943..6a6ca24 100644
--- a/src/gui/embedded/qunixsocket.cpp
+++ b/src/gui/embedded/qunixsocket.cpp
@@ -46,6 +46,7 @@
#include <QtCore/qsocketnotifier.h>
#include <QtCore/qqueue.h>
#include <QtCore/qdatetime.h>
+#include "private/qcore_unix_p.h" // overrides QT_OPEN
#ifdef QUNIXSOCKET_DEBUG
#include <QtCore/qdebug.h>
@@ -131,11 +132,11 @@ struct QUnixSocketRightsPrivate : public QSharedData
#ifdef QUNIXSOCKET_DEBUG
int closerv =
#endif
- ::close(fd);
+ QT_CLOSE(fd);
#ifdef QUNIXSOCKET_DEBUG
if(0 != closerv) {
qDebug() << "QUnixSocketRightsPrivate: Unable to close managed"
- " file descriptor (" << ::strerror(errno) << ")";
+ " file descriptor (" << ::strerror(errno) << ')';
}
#endif
}
@@ -162,11 +163,11 @@ QUnixSocketRights::QUnixSocketRights(int fd)
if(-1 == fd) {
d->fd = -1;
} else {
- d->fd = ::dup(fd);
+ d->fd = qt_safe_dup(fd);
#ifdef QUNIXSOCKET_DEBUG
if(-1 == d->fd) {
qDebug() << "QUnixSocketRights: Unable to duplicate fd "
- << fd << " (" << ::strerror(errno) << ")";
+ << fd << " (" << ::strerror(errno) << ')';
}
#endif
}
@@ -232,12 +233,12 @@ int QUnixSocketRights::dupFd() const
{
if(-1 == d->fd) return -1;
- int rv = ::dup(d->fd);
+ int rv = qt_safe_dup(d->fd);
#ifdef QUNIXSOCKET_DEBUG
if(-1 == rv)
qDebug() << "QUnixSocketRights: Unable to duplicate managed file "
- "descriptor (" << ::strerror(errno) << ")";
+ "descriptor (" << ::strerror(errno) << ')';
#endif
return rv;
@@ -825,7 +826,7 @@ public:
int numFds = (h->cmsg_len - CMSG_LEN(0)) / sizeof(int);
for(int ii = 0; ii < numFds; ++ii)
- ::close(fds[ii]);
+ QT_CLOSE(fds[ii]);
}
h = (::cmsghdr *)CMSG_NXTHDR(&(message), h);
@@ -927,7 +928,7 @@ bool QUnixSocket::connect(const QByteArray & path)
int crv;
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Connect requested to '"
- << path << "'";
+ << path << '\'';
#endif
abort(); // Reset any existing connection
@@ -949,7 +950,7 @@ bool QUnixSocket::connect(const QByteArray & path)
if(-1 == d->fd) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to create socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
#endif
d->error = ResourceError;
goto connect_error;
@@ -962,7 +963,7 @@ bool QUnixSocket::connect(const QByteArray & path)
if(-1 == crv) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to configure socket ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
d->error = ResourceError;
@@ -981,7 +982,7 @@ bool QUnixSocket::connect(const QByteArray & path)
if(-1 == crv) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to connect ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
if(ECONNREFUSED == errno)
d->error = ConnectionRefused;
@@ -1017,11 +1018,11 @@ connect_error: // Cleanup failed connection
#ifdef QUNIXSOCKET_DEBUG
int closerv =
#endif
- ::close(d->fd);
+ QT_CLOSE(d->fd);
#ifdef QUNIXSOCKET_DEBUG
if(0 != closerv) {
qDebug() << "QUnixSocket: Unable to close file descriptor after "
- "failed connect (" << ::strerror(errno) << ")";
+ "failed connect (" << ::strerror(errno) << ')';
}
#endif
}
@@ -1065,7 +1066,7 @@ bool QUnixSocket::setSocketDescriptor(int socketDescriptor)
if(-1 == crv) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to configure client provided socket ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
d->error = ResourceError;
@@ -1136,7 +1137,7 @@ void QUnixSocket::abort()
#ifdef QUNIXSOCKET_DEBUG
if(0 != closerv) {
qDebug() << "QUnixSocket: Unable to close socket during abort ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
}
#endif
@@ -1686,11 +1687,11 @@ qint64 QUnixSocketPrivate::writeActivated()
}
#ifdef QUNIXSOCKET_DEBUG
- qDebug() << "QUnixSocket: Transmitting message (length" << m.d->size() << ")";
+ qDebug() << "QUnixSocket: Transmitting message (length" << m.d->size() << ')';
#endif
::ssize_t s = ::sendmsg(fd, &sendmessage, MSG_DONTWAIT | MSG_NOSIGNAL);
#ifdef QUNIXSOCKET_DEBUG
- qDebug() << "QUnixSocket: Transmitted message (" << s << ")";
+ qDebug() << "QUnixSocket: Transmitted message (" << s << ')';
#endif
if(-1 == s) {
@@ -1699,13 +1700,13 @@ qint64 QUnixSocketPrivate::writeActivated()
} else if(EPIPE == errno) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Remote side disconnected during transmit "
- "(" << ::strerror(errno) << ")";
+ "(" << ::strerror(errno) << ')';
#endif
me->abort();
} else {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to transmit data ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
error = (QUnixSocket::SocketError)(QUnixSocket::WriteFailure |
CausedAbort);
@@ -1762,14 +1763,19 @@ void QUnixSocketPrivate::readActivated()
message.msg_controllen = ancillaryBufferCapacity();
message.msg_control = ancillaryBuffer;
- int recvrv = ::recvmsg(fd, &message, 0);
+ int flags = 0;
+#ifdef MSG_CMSG_CLOEXEC
+ flags = MSG_CMSG_CLOEXEC;
+#endif
+
+ int recvrv = ::recvmsg(fd, &message, flags);
#ifdef QUNIXSOCKET_DEBUG
- qDebug() << "QUnixSocket: Received message (" << recvrv << ")";
+ qDebug() << "QUnixSocket: Received message (" << recvrv << ')';
#endif
if(-1 == recvrv) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to receive data ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
error = (QUnixSocket::SocketError)(QUnixSocket::ReadFailure |
CausedAbort);
diff --git a/src/gui/embedded/qunixsocketserver.cpp b/src/gui/embedded/qunixsocketserver.cpp
index 48eb4b1..e56a67e 100644
--- a/src/gui/embedded/qunixsocketserver.cpp
+++ b/src/gui/embedded/qunixsocketserver.cpp
@@ -172,7 +172,7 @@ void QUnixSocketServer::close()
#ifdef QUNIXSOCKET_DEBUG
if(0 != closerv) {
qDebug() << "QUnixSocketServer: Unable to close socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
}
#endif
}
@@ -245,7 +245,7 @@ bool QUnixSocketServer::listen(const QByteArray & path)
if(-1 == d->fd) {
#ifdef QUNIXSOCKETSERVER_DEBUG
qDebug() << "QUnixSocketServer: Unable to create socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
#endif
close();
d->error = ResourceError;
@@ -263,7 +263,7 @@ bool QUnixSocketServer::listen(const QByteArray & path)
if(-1 == ::bind(d->fd, (sockaddr *)&addr, sizeof(sockaddr_un))) {
#ifdef QUNIXSOCKETSERVER_DEBUG
qDebug() << "QUnixSocketServer: Unable to bind socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
#endif
close();
d->error = BindError;
@@ -274,7 +274,7 @@ bool QUnixSocketServer::listen(const QByteArray & path)
if(-1 == ::listen(d->fd, d->maxConns)) {
#ifdef QUNIXSOCKETSERVER_DEBUG
qDebug() << "QUnixSocketServer: Unable to listen socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
#endif
close();
d->error = ListenError;
diff --git a/src/gui/embedded/qwindowsystem_qws.cpp b/src/gui/embedded/qwindowsystem_qws.cpp
index c88280c..e8d7f55 100644
--- a/src/gui/embedded/qwindowsystem_qws.cpp
+++ b/src/gui/embedded/qwindowsystem_qws.cpp
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
+
#include "qwindowsystem_qws.h"
#include "qwsevent_qws.h"
#include "qwscommand_qws_p.h"
@@ -71,24 +73,26 @@
#include <qdebug.h>
-#include <unistd.h>
+#include "qkbddriverfactory_qws.h"
+#include "qmousedriverfactory_qws.h"
+
+#include <qbuffer.h>
+#include <qdir.h>
+
+#include <private/qwindowsurface_qws_p.h>
+#include <private/qfontengine_qpf_p.h>
+
+#include "qwindowsystem_p.h"
+
+
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#ifndef QT_NO_QWS_MULTIPROCESS
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#ifndef Q_OS_DARWIN
-# include <sys/sem.h>
-#endif
#include <sys/param.h>
#include <sys/mount.h>
#endif
-#include <signal.h>
-#include <fcntl.h>
#if !defined(QT_NO_SOUND) && !defined(Q_OS_DARWIN)
#ifdef QT_USE_OLD_QWS_SOUND
@@ -101,17 +105,6 @@
#endif
#endif
-#include "qkbddriverfactory_qws.h"
-#include "qmousedriverfactory_qws.h"
-
-#include <qbuffer.h>
-#include <qdir.h>
-
-#include <private/qwindowsurface_qws_p.h>
-#include <private/qfontengine_qpf_p.h>
-
-#include "qwindowsystem_p.h"
-
//#define QWS_DEBUG_FONTCLEANUP
QT_BEGIN_NAMESPACE
@@ -1304,7 +1297,13 @@ QWSServer::QWSServer(int flags, QObject *parent) :
QObject(*new QWSServerPrivate, parent)
{
Q_D(QWSServer);
- d->initServer(flags);
+ QT_TRY {
+ d->initServer(flags);
+ } QT_CATCH(...) {
+ qwsServer = 0;
+ qwsServerPrivate = 0;
+ QT_RETHROW;
+ }
}
#ifdef QT3_SUPPORT
@@ -1400,7 +1399,7 @@ void QWSServerPrivate::initServer(int flags)
#ifndef QT_NO_QWS_MULTIPROCESS
if (!geteuid()) {
-#if !defined(Q_OS_FREEBSD) && !defined(Q_OS_SOLARIS) && !defined(Q_OS_DARWIN) && !defined(QT_LINUXBASE)
+#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
if(mount(0,"/var/shm", "shm", 0, 0)) {
/* This just confuses people with 2.2 kernels
if (errno != EBUSY)
@@ -1750,21 +1749,29 @@ void QWSServerPrivate::cleanupFonts(bool force)
#if defined(QWS_DEBUG_FONTCLEANUP)
qDebug() << "cleanupFonts()";
#endif
- QMap<QByteArray, int>::Iterator it = fontReferenceCount.begin();
- while (it != fontReferenceCount.end()) {
- if (it.value() && !force) {
- ++it;
- continue;
- }
+ if (!fontReferenceCount.isEmpty()) {
+ QMap<QByteArray, int>::Iterator it = fontReferenceCount.begin();
+ while (it != fontReferenceCount.end()) {
+ if (it.value() && !force) {
+ ++it;
+ continue;
+ }
- const QByteArray &fontName = it.key();
+ const QByteArray &fontName = it.key();
#if defined(QWS_DEBUG_FONTCLEANUP)
- qDebug() << "removing unused font file" << fontName;
+ qDebug() << "removing unused font file" << fontName;
#endif
- QFile::remove(QFile::decodeName(fontName));
- sendFontRemovedEvent(fontName);
-
- it = fontReferenceCount.erase(it);
+ QT_TRY {
+ QFile::remove(QFile::decodeName(fontName));
+ sendFontRemovedEvent(fontName);
+
+ it = fontReferenceCount.erase(it);
+ } QT_CATCH(...) {
+ // so we were not able to remove the font.
+ // don't be angry and just continue with the next ones.
+ ++it;
+ }
+ }
}
if (crashedClientIds.isEmpty())
@@ -2210,7 +2217,7 @@ void QWSServer::sendMouseEvent(const QPoint& pos, int state, int wheel)
{
bool block = qwsServerPrivate->screensaverblockevent(MOUSE, qwsServerPrivate->screensaverinterval, state);
#ifdef EVENT_BLOCK_DEBUG
- qDebug() << "sendMouseEvent" << pos.x() << pos.y() << state << (block?"block":"pass");
+ qDebug() << "sendMouseEvent" << pos.x() << pos.y() << state << (block ? "block" : "pass");
#endif
if (state || wheel)
@@ -3966,7 +3973,8 @@ void QWSServerPrivate::openDisplay()
void QWSServerPrivate::closeDisplay()
{
- qt_screen->shutdownDevice();
+ if (qt_screen)
+ qt_screen->shutdownDevice();
}
/*!
@@ -4065,9 +4073,14 @@ void QWSServer::startup(int flags)
void QWSServer::closedown()
{
- unlink(qws_qtePipeFilename().toLatin1().constData());
- delete qwsServer;
+ QScopedPointer<QWSServer> server(qwsServer);
qwsServer = 0;
+ QT_TRY {
+ unlink(qws_qtePipeFilename().toLatin1().constData());
+ } QT_CATCH(const std::bad_alloc &) {
+ // ### TODO - what to do when we run out of memory
+ // when calling toLatin1?
+ }
}
void QWSServerPrivate::emergency_cleanup()
@@ -4110,7 +4123,7 @@ void QWSServer::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers
block = qwsServerPrivate->screensaverblockevent(KEY, qwsServerPrivate->screensaverinterval, isPress);
#ifdef EVENT_BLOCK_DEBUG
- qDebug() << "processKeyEvent" << unicode << keycode << modifiers << isPress << autoRepeat << (block?"block":"pass");
+ qDebug() << "processKeyEvent" << unicode << keycode << modifiers << isPress << autoRepeat << (block ? "block" : "pass");
#endif
// If we press a key and it's going to be blocked, wake up the screen
diff --git a/src/gui/embedded/qwscommand_qws.cpp b/src/gui/embedded/qwscommand_qws.cpp
index a357c61..6fafd2c 100644
--- a/src/gui/embedded/qwscommand_qws.cpp
+++ b/src/gui/embedded/qwscommand_qws.cpp
@@ -43,7 +43,6 @@
#include "qtransportauth_qws.h"
#include "qtransportauth_qws_p.h"
-#include <sys/uio.h>
#include <unistd.h>
// #define QWSCOMMAND_DEBUG 1 // Uncomment to debug client/server communication
@@ -134,7 +133,7 @@ void QWSHexDump::init()
void QWSHexDump::hexDump()
{
- *outstrm << "(" << dataSize << " bytes):\n" << prefix;
+ *outstrm << '(' << dataSize << " bytes):\n" << prefix;
sprintf(sideviewLayout, " [%%-%us]", wrap);
dataWidth = (2 * wrap) + (wrap / clustering);
@@ -145,7 +144,7 @@ void QWSHexDump::hexDump()
sideview[wrapIndex = i%wrap] = isprint(c) ? c : '.';
if (wrapIndex && (wrapIndex % clustering == 0))
- *outstrm << " ";
+ *outstrm << ' ';
outstrm->setFieldWidth(2);
outstrm->setPadChar('0');
@@ -173,14 +172,14 @@ void QWSHexDump::sideviewDump(int at)
int currentWidth = (2 * at) + (at / clustering) - (at%clustering?0:1);
int missing = qMax(dataWidth - currentWidth, 0);
while (missing--)
- *outstrm << " ";
+ *outstrm << ' ';
*outstrm << " [";
outstrm->setPadChar(' ');
outstrm->setFieldWidth(wrap);
outstrm->setFieldAlignment( QTextStream::AlignLeft );
*outstrm << sideview;
- *outstrm << "]";
+ *outstrm << ']';
}
}
diff --git a/src/gui/embedded/qwscursor_qws.cpp b/src/gui/embedded/qwscursor_qws.cpp
index 4a814e1..93b8de3 100644
--- a/src/gui/embedded/qwscursor_qws.cpp
+++ b/src/gui/embedded/qwscursor_qws.cpp
@@ -531,7 +531,7 @@ void QWSCursor::set(const uchar *data, const uchar *mask,
cursor = QImage(width,height, QImage::Format_Indexed8);
- if (!width || !height || !data || !mask)
+ if (!width || !height || !data || !mask || cursor.isNull())
return;
cursor.setNumColors(3);
diff --git a/src/gui/embedded/qwssignalhandler.cpp b/src/gui/embedded/qwssignalhandler.cpp
index 90f5e98..7b38880 100644
--- a/src/gui/embedded/qwssignalhandler.cpp
+++ b/src/gui/embedded/qwssignalhandler.cpp
@@ -44,8 +44,10 @@
#ifndef QT_NO_QWS_SIGNALHANDLER
#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>
+#ifndef QT_NO_QWS_MULTIPROCESS
+# include <sys/ipc.h>
+# include <sys/sem.h>
+#endif
#include <signal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/embedded/qwsutils_qws.h b/src/gui/embedded/qwsutils_qws.h
index c2f0a16..70973b8 100644
--- a/src/gui/embedded/qwsutils_qws.h
+++ b/src/gui/embedded/qwsutils_qws.h
@@ -44,6 +44,12 @@
#include <QtCore/QIODevice>
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
#ifndef QT_NO_SXE
#define QWS_SOCK_BASE QUnixSocket
#define QWS_SOCK_SERVER_BASE QUnixSocketServer
@@ -58,12 +64,6 @@ class QTcpServer;
class QWSSocket;
class QWSServerSocket;
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Gui)
-
/********************************************************************
*
* Convenient socket functions
diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri
index 02d9bb1..547d7ce 100644
--- a/src/gui/graphicsview/graphicsview.pri
+++ b/src/gui/graphicsview/graphicsview.pri
@@ -1,46 +1,52 @@
# Qt graphicsview module
+HEADERS += graphicsview/qgraphicsgridlayout.h \
+ graphicsview/qgraphicsitem.h \
+ graphicsview/qgraphicsitem_p.h \
+ graphicsview/qgraphicsitemanimation.h \
+ graphicsview/qgraphicslayout.h \
+ graphicsview/qgraphicslayout_p.h \
+ graphicsview/qgraphicslayoutitem.h \
+ graphicsview/qgraphicslayoutitem_p.h \
+ graphicsview/qgraphicslinearlayout.h \
+ graphicsview/qgraphicsproxywidget.h \
+ graphicsview/qgraphicsscene.h \
+ graphicsview/qgraphicsscene_bsp_p.h \
+ graphicsview/qgraphicsscene_p.h \
+ graphicsview/qgraphicsscenebsptreeindex_p.h \
+ graphicsview/qgraphicssceneevent.h \
+ graphicsview/qgraphicssceneindex_p.h \
+ graphicsview/qgraphicsscenelinearindex_p.h \
+ graphicsview/qgraphicstransform.h \
+ graphicsview/qgraphicstransform_p.h \
+ graphicsview/qgraphicsview.h \
+ graphicsview/qgraphicsview_p.h \
+ graphicsview/qgraphicswidget.h \
+ graphicsview/qgraphicswidget_p.h \
+ graphicsview/qgridlayoutengine_p.h \
+ graphicsview/qgraph_p.h \
+ graphicsview/qsimplex_p.h \
+ graphicsview/qgraphicsanchorlayout_p.h \
+ graphicsview/qgraphicsanchorlayout.h
-HEADERS += \
- graphicsview/qgraphicsitem.h \
- graphicsview/qgraphicsitem_p.h \
- graphicsview/qgraphicsitemanimation.h \
- graphicsview/qgraphicsscene.h \
- graphicsview/qgraphicsscene_p.h \
- graphicsview/qgraphicsscene_bsp_p.h \
- graphicsview/qgraphicssceneevent.h \
- graphicsview/qgraphicsview_p.h \
- graphicsview/qgraphicsview.h
-
-SOURCES += \
- graphicsview/qgraphicsitem.cpp \
- graphicsview/qgraphicsitemanimation.cpp \
- graphicsview/qgraphicsscene.cpp \
- graphicsview/qgraphicsscene_bsp.cpp \
- graphicsview/qgraphicssceneevent.cpp \
- graphicsview/qgraphicsview.cpp
-
-# Widgets on the canvas
-
-HEADERS += \
- graphicsview/qgraphicslayout.h \
- graphicsview/qgraphicslayout_p.h \
- graphicsview/qgraphicslayoutitem.h \
- graphicsview/qgraphicslayoutitem_p.h \
- graphicsview/qgraphicslinearlayout.h \
- graphicsview/qgraphicswidget.h \
- graphicsview/qgraphicswidget_p.h \
- graphicsview/qgridlayoutengine_p.h \
- graphicsview/qgraphicsproxywidget.h \
- graphicsview/qgraphicsgridlayout.h
-
-SOURCES += \
- graphicsview/qgraphicslayout.cpp \
- graphicsview/qgraphicslayout_p.cpp \
- graphicsview/qgraphicslayoutitem.cpp \
- graphicsview/qgraphicslinearlayout.cpp \
- graphicsview/qgraphicswidget.cpp \
- graphicsview/qgraphicswidget_p.cpp \
- graphicsview/qgridlayoutengine.cpp \
- graphicsview/qgraphicsproxywidget.cpp \
- graphicsview/qgraphicsgridlayout.cpp
-
+SOURCES += graphicsview/qgraphicsgridlayout.cpp \
+ graphicsview/qgraphicsitem.cpp \
+ graphicsview/qgraphicsitemanimation.cpp \
+ graphicsview/qgraphicslayout.cpp \
+ graphicsview/qgraphicslayout_p.cpp \
+ graphicsview/qgraphicslayoutitem.cpp \
+ graphicsview/qgraphicslinearlayout.cpp \
+ graphicsview/qgraphicsproxywidget.cpp \
+ graphicsview/qgraphicsscene.cpp \
+ graphicsview/qgraphicsscene_bsp.cpp \
+ graphicsview/qgraphicsscenebsptreeindex.cpp \
+ graphicsview/qgraphicssceneevent.cpp \
+ graphicsview/qgraphicssceneindex.cpp \
+ graphicsview/qgraphicsscenelinearindex.cpp \
+ graphicsview/qgraphicstransform.cpp \
+ graphicsview/qgraphicsview.cpp \
+ graphicsview/qgraphicswidget.cpp \
+ graphicsview/qgraphicswidget_p.cpp \
+ graphicsview/qgridlayoutengine.cpp \
+ graphicsview/qsimplex_p.cpp \
+ graphicsview/qgraphicsanchorlayout_p.cpp \
+ graphicsview/qgraphicsanchorlayout.cpp
diff --git a/src/gui/graphicsview/qgraph_p.h b/src/gui/graphicsview/qgraph_p.h
new file mode 100644
index 0000000..895ee0c
--- /dev/null
+++ b/src/gui/graphicsview/qgraph_p.h
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPH_P_H
+#define QGRAPH_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/QHash>
+#include <QtCore/QQueue>
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+
+#include <float.h>
+
+QT_BEGIN_NAMESPACE
+
+template <typename Vertex, typename EdgeData>
+class Graph
+{
+public:
+ Graph() {}
+
+ class const_iterator {
+ public:
+ const_iterator(const Graph *graph, bool begin) : g(graph){
+ if (begin) {
+ row = g->m_graph.constBegin();
+ //test if the graph is empty
+ if (row != g->m_graph.constEnd())
+ {
+ column = (*row)->constBegin();
+ }
+ } else {
+ row = g->m_graph.constEnd();
+ }
+ }
+
+ inline Vertex *operator*() {
+ return column.key();
+ }
+
+ inline Vertex *from() const {
+ return row.key();
+ }
+
+ inline Vertex *to() const {
+ return column.key();
+ }
+
+ inline bool operator==(const const_iterator &o) const { return !(*this != o); }
+ inline bool operator!=(const const_iterator &o) const {
+ if (row == g->m_graph.end()) {
+ return row != o.row;
+ } else {
+ return row != o.row || column != o.column;
+ }
+ }
+ inline const_iterator& operator=(const const_iterator &o) const { row = o.row; column = o.column; return *this;}
+
+ // prefix
+ const_iterator &operator++() {
+ if (row != g->m_graph.constEnd()) {
+ ++column;
+ if (column == (*row)->constEnd()) {
+ ++row;
+ if (row != g->m_graph.constEnd()) {
+ column = (*row)->constBegin();
+ }
+ }
+ }
+ return *this;
+ }
+
+ private:
+ const Graph *g;
+ Q_TYPENAME QHash<Vertex *, QHash<Vertex *, EdgeData *> * >::const_iterator row;
+ Q_TYPENAME QHash<Vertex *, EdgeData *>::const_iterator column;
+ };
+
+ const_iterator constBegin() const {
+ return const_iterator(this,true);
+ }
+
+ const_iterator constEnd() const {
+ return const_iterator(this,false);
+ }
+
+ /*!
+ * \internal
+ *
+ * If there is an edge between \a first and \a second, it will return a structure
+ * containing the data associated with the edge, otherwise it will return 0.
+ *
+ */
+ EdgeData *edgeData(Vertex* first, Vertex* second) {
+ QHash<Vertex *, EdgeData *> *row = m_graph.value(first);
+ return row ? row->value(second) : 0;
+ }
+
+ void createEdge(Vertex *first, Vertex *second, EdgeData *data)
+ {
+ // Creates a bidirectional edge
+#if defined(QT_DEBUG) && 0
+ qDebug("Graph::createEdge(): %s",
+ qPrintable(QString::fromAscii("%1-%2")
+ .arg(first->toString()).arg(second->toString())));
+#endif
+ if (edgeData(first, second)) {
+#ifdef QT_DEBUG
+ qWarning("%s-%s already has an edge", qPrintable(first->toString()), qPrintable(second->toString()));
+#endif
+ }
+ createDirectedEdge(first, second, data);
+ createDirectedEdge(second, first, data);
+ }
+
+ void removeEdge(Vertex *first, Vertex *second)
+ {
+ // Removes a bidirectional edge
+#if defined(QT_DEBUG) && 0
+ qDebug("Graph::removeEdge(): %s",
+ qPrintable(QString::fromAscii("%1-%2")
+ .arg(first->toString()).arg(second->toString())));
+#endif
+ EdgeData *data = edgeData(first, second);
+ removeDirectedEdge(first, second);
+ removeDirectedEdge(second, first);
+ if (data) delete data;
+ }
+
+ EdgeData *takeEdge(Vertex* first, Vertex* second)
+ {
+#if defined(QT_DEBUG) && 0
+ qDebug("Graph::takeEdge(): %s",
+ qPrintable(QString::fromAscii("%1-%2")
+ .arg(first->toString()).arg(second->toString())));
+#endif
+ // Removes a bidirectional edge
+ EdgeData *data = edgeData(first, second);
+ if (data) {
+ removeDirectedEdge(first, second);
+ removeDirectedEdge(second, first);
+ }
+ return data;
+ }
+
+ QList<Vertex *> adjacentVertices(Vertex *vertex) const
+ {
+ QHash<Vertex *, EdgeData *> *row = m_graph.value(vertex);
+ QList<Vertex *> l;
+ if (row)
+ l = row->keys();
+ return l;
+ }
+
+ void setRootVertex(Vertex *vertex)
+ {
+ userVertex = vertex;
+ }
+
+ QSet<Vertex*> vertices() const {
+ QSet<Vertex *> setOfVertices;
+ for (const_iterator it = constBegin(); it != constEnd(); ++it) {
+ setOfVertices.insert(*it);
+ }
+ return setOfVertices;
+ }
+
+ QList<QPair<Vertex*, Vertex*> > connections() const {
+ QList<QPair<Vertex*, Vertex*> > conns;
+ for (const_iterator it = constBegin(); it != constEnd(); ++it) {
+ Vertex *from = it.from();
+ Vertex *to = it.to();
+ // do not return (from,to) *and* (to,from)
+ if (from < to) {
+ conns.append(qMakePair(from, to));
+ }
+ }
+ return conns;
+ }
+
+#if defined(QT_DEBUG)
+ QString serializeToDot() { // traversal
+ QString strVertices;
+ QString edges;
+
+ QSet<Vertex *> setOfVertices = vertices();
+ for (Q_TYPENAME QSet<Vertex*>::const_iterator it = setOfVertices.begin(); it != setOfVertices.end(); ++it) {
+ Vertex *v = *it;
+ QList<Vertex*> adjacents = adjacentVertices(v);
+ for (int i = 0; i < adjacents.count(); ++i) {
+ Vertex *v1 = adjacents.at(i);
+ EdgeData *data = edgeData(v, v1);
+ bool forward = data->from == v;
+ if (forward) {
+ edges += QString::fromAscii("%1->%2 [label=\"[%3,%4,%5]\" dir=both color=\"#000000:#a0a0a0\"] \n")
+ .arg(v->toString())
+ .arg(v1->toString())
+ .arg(data->minSize)
+ .arg(data->prefSize)
+ .arg(data->maxSize)
+ ;
+ }
+ }
+ strVertices += QString::fromAscii("%1 [label=\"%2\"]\n").arg(v->toString()).arg(v->toString());
+ }
+ return QString::fromAscii("%1\n%2\n").arg(strVertices).arg(edges);
+ }
+#endif
+
+ Vertex *rootVertex() const
+ {
+ return userVertex;
+ }
+
+protected:
+ void createDirectedEdge(Vertex *from, Vertex *to, EdgeData *data)
+ {
+ QHash<Vertex *, EdgeData *> *adjacentToFirst = m_graph.value(from);
+ if (!adjacentToFirst) {
+ adjacentToFirst = new QHash<Vertex *, EdgeData *>();
+ m_graph.insert(from, adjacentToFirst);
+ }
+ adjacentToFirst->insert(to, data);
+ }
+
+ void removeDirectedEdge(Vertex *from, Vertex *to)
+ {
+ QHash<Vertex *, EdgeData *> *adjacentToFirst = m_graph.value(from);
+ Q_ASSERT(adjacentToFirst);
+
+ adjacentToFirst->remove(to);
+ if (adjacentToFirst->isEmpty()) {
+ //nobody point to 'from' so we can remove it from the graph
+ m_graph.remove(from);
+ delete adjacentToFirst;
+ }
+ }
+
+private:
+ Vertex *userVertex;
+
+ QHash<Vertex *, QHash<Vertex *, EdgeData *> *> m_graph;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
new file mode 100644
index 0000000..95561b7
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
@@ -0,0 +1,477 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QGraphicsAnchorLayout
+ \brief The QGraphicsAnchorLayout class provides a layout where one can anchor widgets
+ together in Graphics View.
+ \since 4.6
+ \ingroup appearance
+ \ingroup geomanagement
+ \ingroup graphicsview-api
+
+ The anchor layout is a layout where one can specify how widgets should be placed relative to
+ each other. The specification is called an anchor, and it is set up by calling anchor().
+ Anchors are always set up between edges of an item, where the "center" is also considered to
+ be an edge. Considering this example:
+ \code
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ QGraphicsWidget *a = new QGraphicsWidget;
+ QGraphicsWidget *b = new QGraphicsWidget;
+ l->anchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+ \endcode
+
+ Here is the right edge of item A anchored to the left edge of item B, with the result that
+ item B will be placed to the right of item A, with a spacing between A and B. If the
+ spacing is negative, the items will overlap to some extent. Items that are anchored are
+ automatically added to the layout, and if items are removed, all their anchors will be
+ automatically removed
+
+ \section1 Size Hints and Size Policies in QGraphicsAnchorLayout
+
+ QGraphicsAnchorLayout respects each item's size hints and size policies. However it does
+ not respect stretch factors currently. This might change in the future, so please refrain
+ from using stretch factors in anchor layout to avoid any future regressions.
+
+ \section1 Spacing within QGraphicsAnchorLayout
+
+ Between the items, the layout can distribute some space. If the spacing has not been
+ explicitly specified, the actual amount of space will usually be 0, but if the first edge
+ is the "opposite" of the second edge (i.e. Right is anchored to Left or vice-versa), the
+ size of the anchor will be queried from the style through the pixelMetric
+ PM_LayoutHorizontalSpacing (or PM_LayoutVerticalSpacing for vertical anchors).
+*/
+
+#include "qgraphicsanchorlayout_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs a QGraphicsAnchorLayout instance. \a parent is passed to
+ QGraphicsLayout's constructor.
+ */
+QGraphicsAnchorLayout::QGraphicsAnchorLayout(QGraphicsLayoutItem *parent)
+ : QGraphicsLayout(*new QGraphicsAnchorLayoutPrivate(), parent)
+{
+ Q_D(QGraphicsAnchorLayout);
+ d->createLayoutEdges();
+}
+
+/*!
+ Destroys the QGraphicsAnchorLayout object.
+*/
+QGraphicsAnchorLayout::~QGraphicsAnchorLayout()
+{
+ Q_D(QGraphicsAnchorLayout);
+
+ for (int i = count() - 1; i >= 0; --i) {
+ QGraphicsLayoutItem *item = d->items.at(i);
+ removeAt(i);
+ if (item) {
+ if (item->ownedByLayout())
+ delete item;
+ }
+ }
+
+ d->removeCenterConstraints(this, QGraphicsAnchorLayoutPrivate::Horizontal);
+ d->removeCenterConstraints(this, QGraphicsAnchorLayoutPrivate::Vertical);
+ d->deleteLayoutEdges();
+
+ Q_ASSERT(d->itemCenterConstraints[0].isEmpty());
+ Q_ASSERT(d->itemCenterConstraints[1].isEmpty());
+ Q_ASSERT(d->items.isEmpty());
+ Q_ASSERT(d->m_vertexList.isEmpty());
+}
+
+/*!
+ * Creates an anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge
+ * of item \a secondItem. The magnitude of the anchor is picked up from the style. Anchors
+ * between a layout edge and an item edge will have a size of 0.
+ * If there is already an anchor between the edges, the the new anchor will replace the old one.
+ *
+ * \a firstItem and \a secondItem are automatically added to the layout if they are not part
+ * of the layout. This means that count() can increase with up to 2.
+ *
+ * The spacing an anchor will get depends on the type of anchor. For instance, anchors from the
+ * Right edge of one item to the Left edge of another (or vice versa) will use the default
+ * horizontal spacing. The same behaviour applies to Bottom to Top anchors, (but they will use
+ * the default vertical spacing). For all other anchor combinations, the spacing will be 0.
+ * All anchoring functions will follow this rule.
+ *
+ * The spacing can also be set manually by using setAnchorSpacing() method.
+ *
+ * \sa removeAnchor(), addCornerAnchors(), addLeftAndRightAnchors(), addTopAndBottomAnchors(),
+ * addAllAnchors()
+ */
+void QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge)
+{
+ Q_D(QGraphicsAnchorLayout);
+ d->anchor(firstItem, firstEdge, secondItem, secondEdge);
+ invalidate();
+}
+
+/*!
+ * Creates two anchors between \a firstItem and \a secondItem, where one is for the horizontal
+ * edge and another one for the vertical edge that the corners \a firstCorner and \a
+ * secondCorner specifies.
+ * The magnitude of the anchors is picked up from the style.
+ *
+ * This is a convenience function, since anchoring corners can be expressed as anchoring two edges.
+ * For instance,
+ * \code
+ * layout->addAnchor(layout, Qt::AnchorTop, b, Qt::AnchorTop);
+ * layout->addAnchor(layout, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ * \endcode
+ *
+ * has the same effect as
+ *
+ * \code
+ * layout->addCornerAnchors(layout, Qt::TopLeft, b, Qt::TopLeft);
+ * \endcode
+ *
+ * If there is already an anchor between the edge pairs, it will be replaced by the anchors that
+ * this function specifies.
+ *
+ * \a firstItem and \a secondItem are automatically added to the layout if they are not part
+ * of the layout. This means that count() can increase with up to 2.
+ */
+void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem,
+ Qt::Corner firstCorner,
+ QGraphicsLayoutItem *secondItem,
+ Qt::Corner secondCorner)
+{
+ Q_D(QGraphicsAnchorLayout);
+
+ // Horizontal anchor
+ Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft);
+ Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft);
+ d->anchor(firstItem, firstEdge, secondItem, secondEdge);
+
+ // Vertical anchor
+ firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop);
+ secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop);
+ d->anchor(firstItem, firstEdge, secondItem, secondEdge);
+
+ invalidate();
+}
+
+/*!
+ \fn QGraphicsAnchorLayout::addLeftAndRightAnchors(QGraphicsLayoutItem *firstItem, QGraphicsLayoutItem *secondItem)
+
+ Anchors the left and right edges of \a firstItem to the same edges of
+ \a secondItem.
+
+ This convenience function is equivalent to calling
+ \code
+ l->addAnchor(firstItem, Qt::AnchorLeft, secondItem, Qt::AnchorLeft);
+ l->addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight);
+ \endcode
+*/
+
+/*!
+ \fn QGraphicsAnchorLayout::addTopAndBottomAnchors(QGraphicsLayoutItem *firstItem, QGraphicsLayoutItem *secondItem)
+
+ Anchors the top and bottom edges of \a firstItem to the same edges of
+ \a secondItem.
+
+ This convenience function is equivalent to calling
+ \code
+ l->addAnchor(firstItem, Qt::AnchorTop, secondItem, Qt::AnchorTop);
+ l->addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom);
+ \endcode
+*/
+
+/*!
+ \fn QGraphicsAnchorLayout::addAllAnchors(QGraphicsLayoutItem *firstItem, QGraphicsLayoutItem *secondItem)
+
+ Anchors all edges (left, right, top and bottom) of \a firstItem to the same edges of
+ \a secondItem.
+
+ This convenience function is equivalent to calling
+ \code
+ l->addLeftAndRightAnchors(firstItem, secondItem);
+ l->addTopAndBottomAnchors(firstItem, secondItem);
+ \endcode
+*/
+
+/*!
+ Set the spacing between the anchor point defined by \a firstItem and \a firstEdge and
+ \a secondItem and \a secondEdge to be \a spacing.
+*/
+void QGraphicsAnchorLayout::setAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge,
+ qreal spacing)
+{
+ Q_D(QGraphicsAnchorLayout);
+
+ if (!d->setAnchorSize(firstItem, firstEdge, secondItem, secondEdge, &spacing)) {
+ qWarning("setAnchorSpacing: The anchor does not exist.");
+ return;
+ }
+ invalidate();
+}
+
+/*!
+ Returns the spacing between the anchor point defined by \a firstItem and \a firstEdge and
+ \a secondItem and \a secondEdge. The anchor must exist.
+*/
+qreal QGraphicsAnchorLayout::anchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) const
+{
+ Q_D(const QGraphicsAnchorLayout);
+ qreal size = 0;
+ if (!d->anchorSize(firstItem, firstEdge, secondItem, secondEdge, 0, &size)) {
+ qWarning("anchorSpacing: The anchor does not exist.");
+ }
+ return size;
+}
+
+/*!
+ Resets the spacing between the anchor point defined by \a firstItem and \a firstEdge and
+ \a secondItem and \a secondEdge to be the default spacing. Depending on the anchor type, the
+ default spacing is either 0 or a value returned from the style.
+
+ \sa setAnchorSpacing(), anchorSpacing(), addAnchor()
+*/
+void QGraphicsAnchorLayout::unsetAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge)
+{
+ Q_D(QGraphicsAnchorLayout);
+
+ if (!d->setAnchorSize(firstItem, firstEdge, secondItem, secondEdge, 0)) {
+ qWarning("unsetAnchorSpacing: The anchor does not exist.");
+ }
+ invalidate();
+}
+
+/*!
+ Removes the anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge
+ of item \a secondItem. If such an anchor does not exist, the layout will be left unchanged.
+*/
+void QGraphicsAnchorLayout::removeAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge)
+{
+ Q_D(QGraphicsAnchorLayout);
+ if ((firstItem == 0) || (secondItem == 0)) {
+ qWarning("QGraphicsAnchorLayout::removeAnchor: "
+ "Cannot remove anchor between NULL items");
+ return;
+ }
+
+ if (firstItem == secondItem) {
+ qWarning("QGraphicsAnchorLayout::removeAnchor: "
+ "Cannot remove anchor from the item to itself");
+ return;
+ }
+
+ if (d->edgeOrientation(secondEdge) != d->edgeOrientation(firstEdge)) {
+ qWarning("QGraphicsAnchorLayout::removeAnchor: "
+ "Cannot remove anchor from edges of different orientations");
+ return;
+ }
+
+ d->removeAnchor(firstItem, firstEdge, secondItem, secondEdge);
+ invalidate();
+}
+
+/*!
+ Sets the default horizontal spacing for the anchor layout to \a spacing.
+
+ \sa horizontalSpacing(), setVerticalSpacing(), setSpacing()
+*/
+void QGraphicsAnchorLayout::setHorizontalSpacing(qreal spacing)
+{
+ Q_D(QGraphicsAnchorLayout);
+ d->spacings[0] = spacing;
+ invalidate();
+}
+
+/*!
+ Sets the default vertical spacing for the anchor layout to \a spacing.
+
+ \sa verticalSpacing(), setHorizontalSpacing(), setSpacing()
+*/
+void QGraphicsAnchorLayout::setVerticalSpacing(qreal spacing)
+{
+ Q_D(QGraphicsAnchorLayout);
+ d->spacings[1] = spacing;
+ invalidate();
+}
+
+/*!
+ Sets the default horizontal and the default vertical spacing for the anchor layout to \a spacing.
+
+ If an item is anchored with no spacing associated with the anchor, it will use the default
+ spacing.
+ \sa setHorizontalSpacing(), setVerticalSpacing()
+*/
+void QGraphicsAnchorLayout::setSpacing(qreal spacing)
+{
+ Q_D(QGraphicsAnchorLayout);
+ d->spacings[0] = d->spacings[1] = spacing;
+ invalidate();
+}
+
+/*!
+ Returns the default horizontal spacing for the anchor layout.
+
+ \sa verticalSpacing(), setHorizontalSpacing()
+*/
+qreal QGraphicsAnchorLayout::horizontalSpacing() const
+{
+ Q_D(const QGraphicsAnchorLayout);
+ return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Horizontal);
+}
+
+/*!
+ Returns the default vertical spacing for the anchor layout.
+
+ \sa horizontalSpacing(), setVerticalSpacing()
+*/
+qreal QGraphicsAnchorLayout::verticalSpacing() const
+{
+ Q_D(const QGraphicsAnchorLayout);
+ return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Vertical);
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsAnchorLayout::setGeometry(const QRectF &geom)
+{
+ Q_D(QGraphicsAnchorLayout);
+
+ QGraphicsLayout::setGeometry(geom);
+ d->calculateVertexPositions(QGraphicsAnchorLayoutPrivate::Horizontal);
+ d->calculateVertexPositions(QGraphicsAnchorLayoutPrivate::Vertical);
+ d->setItemsGeometries();
+}
+
+/*!
+ Removes the layout item at \a index without destroying it. Ownership of
+ the item is transferred to the caller.
+
+ Removing an item will also remove any of the anchors associated with it.
+
+ \sa itemAt(), count()
+*/
+void QGraphicsAnchorLayout::removeAt(int index)
+{
+ Q_D(QGraphicsAnchorLayout);
+ QGraphicsLayoutItem *item = d->items.value(index);
+
+ if (!item)
+ return;
+
+ // Removing an item affects both horizontal and vertical graphs
+ d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Horizontal);
+ d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Vertical);
+
+ d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Horizontal);
+ d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Vertical);
+ d->removeAnchors(item);
+ d->items.remove(index);
+
+ item->setParentLayoutItem(0);
+ invalidate();
+}
+
+/*!
+ \reimp
+*/
+int QGraphicsAnchorLayout::count() const
+{
+ Q_D(const QGraphicsAnchorLayout);
+ return d->items.size();
+}
+
+/*!
+ \reimp
+*/
+QGraphicsLayoutItem *QGraphicsAnchorLayout::itemAt(int index) const
+{
+ Q_D(const QGraphicsAnchorLayout);
+ return d->items.value(index);
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsAnchorLayout::invalidate()
+{
+ Q_D(QGraphicsAnchorLayout);
+ QGraphicsLayout::invalidate();
+ d->calculateGraphCacheDirty = 1;
+}
+
+/*!
+ \reimp
+*/
+QSizeF QGraphicsAnchorLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which);
+ Q_UNUSED(constraint);
+ Q_D(const QGraphicsAnchorLayout);
+
+ // Some setup calculations are delayed until the information is
+ // actually needed, avoiding unnecessary recalculations when
+ // adding multiple anchors.
+
+ // sizeHint() / effectiveSizeHint() already have a cache
+ // mechanism, using invalidate() to force recalculation. However
+ // sizeHint() is called three times after invalidation (for max,
+ // min and pref), but we just need do our setup once.
+
+ const_cast<QGraphicsAnchorLayoutPrivate *>(d)->calculateGraphs();
+
+ // ### apply constraint!
+ QSizeF engineSizeHint(
+ d->sizeHints[QGraphicsAnchorLayoutPrivate::Horizontal][which],
+ d->sizeHints[QGraphicsAnchorLayoutPrivate::Vertical][which]);
+
+ qreal left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+
+ return engineSizeHint + QSizeF(left + right, top + bottom);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h
new file mode 100644
index 0000000..4b3dbc6
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsanchorlayout.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSANCHORLAYOUT_H
+#define QGRAPHICSANCHORLAYOUT_H
+
+#include <QtGui/qgraphicsitem.h>
+#include <QtGui/qgraphicslayout.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
+
+class QGraphicsAnchorLayoutPrivate;
+
+class Q_GUI_EXPORT QGraphicsAnchorLayout : public QGraphicsLayout
+{
+public:
+ QGraphicsAnchorLayout(QGraphicsLayoutItem *parent = 0);
+ virtual ~QGraphicsAnchorLayout();
+
+ void addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge);
+
+ void addCornerAnchors(QGraphicsLayoutItem *firstItem, Qt::Corner firstCorner,
+ QGraphicsLayoutItem *secondItem, Qt::Corner secondCorner);
+
+ inline void addLeftAndRightAnchors(QGraphicsLayoutItem *firstItem,
+ QGraphicsLayoutItem *secondItem);
+
+ inline void addTopAndBottomAnchors(QGraphicsLayoutItem *firstItem,
+ QGraphicsLayoutItem *secondItem);
+
+ inline void addAllAnchors(QGraphicsLayoutItem *firstItem,
+ QGraphicsLayoutItem *secondItem);
+
+ void setAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge,
+ qreal spacing);
+
+ qreal anchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) const;
+
+ void unsetAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge);
+
+ void removeAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge);
+
+ void setHorizontalSpacing(qreal spacing);
+ void setVerticalSpacing(qreal spacing);
+ void setSpacing(qreal spacing);
+ qreal horizontalSpacing() const;
+ qreal verticalSpacing() const;
+
+ void removeAt(int index);
+ void setGeometry(const QRectF &rect);
+ int count() const;
+ QGraphicsLayoutItem *itemAt(int index) const;
+
+ void invalidate();
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+
+private:
+ Q_DISABLE_COPY(QGraphicsAnchorLayout)
+ Q_DECLARE_PRIVATE(QGraphicsAnchorLayout)
+};
+
+
+void QGraphicsAnchorLayout::addLeftAndRightAnchors(QGraphicsLayoutItem *firstItem,
+ QGraphicsLayoutItem *secondItem)
+{
+ addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft);
+ addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight);
+}
+
+void QGraphicsAnchorLayout::addTopAndBottomAnchors(QGraphicsLayoutItem *firstItem,
+ QGraphicsLayoutItem *secondItem)
+{
+ addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop);
+ addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom);
+}
+
+void QGraphicsAnchorLayout::addAllAnchors(QGraphicsLayoutItem *firstItem,
+ QGraphicsLayoutItem *secondItem)
+{
+ addLeftAndRightAnchors(firstItem, secondItem);
+ addTopAndBottomAnchors(firstItem, secondItem);
+}
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
new file mode 100644
index 0000000..d4afa5b
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -0,0 +1,2104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qwidget.h>
+#include <QtCore/qlinkedlist.h>
+#include <QtCore/qstack.h>
+
+#ifdef QT_DEBUG
+#include <QtCore/qfile.h>
+#endif
+
+#include "qgraphicsanchorlayout_p.h"
+
+QT_BEGIN_NAMESPACE
+
+void AnchorData::refreshSizeHints(qreal effectiveSpacing)
+{
+ if (!isLayoutAnchor && from->m_item == to->m_item) {
+ bool hasCenter = false;
+ QGraphicsLayoutItem *item = from->m_item;
+
+ if (QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge)
+ == QGraphicsAnchorLayoutPrivate::Horizontal) {
+ minSize = item->minimumWidth();
+ prefSize = item->preferredWidth();
+ maxSize = item->maximumWidth();
+ hasCenter = (from->m_edge == Qt::AnchorHorizontalCenter
+ || to->m_edge == Qt::AnchorHorizontalCenter);
+ } else {
+ minSize = item->minimumHeight();
+ prefSize = item->preferredHeight();
+ maxSize = item->maximumHeight();
+ hasCenter = (from->m_edge == Qt::AnchorVerticalCenter
+ || to->m_edge == Qt::AnchorVerticalCenter);
+ }
+
+ if (hasCenter) {
+ minSize /= 2;
+ prefSize /= 2;
+ maxSize /= 2;
+ }
+
+ // Set the anchor effective sizes to preferred.
+ //
+ // Note: The idea here is that all items should remain at their
+ // preferred size unless where that's impossible. In cases where
+ // the item is subject to restrictions (anchored to the layout
+ // edges, for instance), the simplex solver will be run to
+ // recalculate and override the values we set here.
+ sizeAtMinimum = prefSize;
+ sizeAtPreferred = prefSize;
+ sizeAtMaximum = prefSize;
+
+ } else if (!hasSize) {
+ // Anchor has no size defined, use given default information
+ minSize = effectiveSpacing;
+ prefSize = effectiveSpacing;
+ maxSize = effectiveSpacing;
+
+ sizeAtMinimum = prefSize;
+ sizeAtPreferred = prefSize;
+ sizeAtMaximum = prefSize;
+ }
+}
+
+void ParallelAnchorData::updateChildrenSizes()
+{
+ firstEdge->sizeAtMinimum = secondEdge->sizeAtMinimum = sizeAtMinimum;
+ firstEdge->sizeAtPreferred = secondEdge->sizeAtPreferred = sizeAtPreferred;
+ firstEdge->sizeAtMaximum = secondEdge->sizeAtMaximum = sizeAtMaximum;
+
+ firstEdge->updateChildrenSizes();
+ secondEdge->updateChildrenSizes();
+}
+
+void ParallelAnchorData::refreshSizeHints(qreal effectiveSpacing)
+{
+ // First refresh children information
+ firstEdge->refreshSizeHints(effectiveSpacing);
+ secondEdge->refreshSizeHints(effectiveSpacing);
+
+ // ### should we warn if the parallel connection is invalid?
+ // e.g. 1-2-3 with 10-20-30, the minimum of the latter is
+ // bigger than the maximum of the former.
+
+ minSize = qMax(firstEdge->minSize, secondEdge->minSize);
+ maxSize = qMin(firstEdge->maxSize, secondEdge->maxSize);
+
+ prefSize = qMax(firstEdge->prefSize, secondEdge->prefSize);
+ prefSize = qMin(prefSize, maxSize);
+
+ // See comment in AnchorData::refreshSizeHints() about sizeAt* values
+ sizeAtMinimum = prefSize;
+ sizeAtPreferred = prefSize;
+ sizeAtMaximum = prefSize;
+}
+
+/*!
+ \internal
+ returns the factor in the interval [-1, 1].
+ -1 is at Minimum
+ 0 is at Preferred
+ 1 is at Maximum
+*/
+static qreal getFactor(qreal value, qreal min, qreal pref, qreal max)
+{
+ // ### Maybe remove some of the assertions? (since outside is asserting us)
+ Q_ASSERT(value > min || qFuzzyCompare(value, min));
+ Q_ASSERT(value < max || qFuzzyCompare(value, max));
+
+ if (qFuzzyCompare(value, min)) {
+ return -1.0;
+ } else if (qFuzzyCompare(value, pref)) {
+ return 0.0;
+ } else if (qFuzzyCompare(value, max)) {
+ return 1.0;
+ } else if (value < pref) {
+ // Since value < pref and value != pref and min <= value,
+ // we can assert that min < pref.
+ Q_ASSERT(min < pref);
+ return (value - min) / (pref - min) - 1;
+ } else {
+ // Since value > pref and value != pref and max >= value,
+ // we can assert that max > pref.
+ Q_ASSERT(max > pref);
+ return (value - pref) / (max - pref);
+ }
+}
+
+void SequentialAnchorData::updateChildrenSizes()
+{
+ // ### REMOVE ME
+ // ### check whether we are guarantee to get those or we need to warn stuff at this
+ // point.
+ Q_ASSERT(sizeAtMinimum > minSize || qFuzzyCompare(sizeAtMinimum, minSize));
+ Q_ASSERT(sizeAtMinimum < maxSize || qFuzzyCompare(sizeAtMinimum, maxSize));
+ Q_ASSERT(sizeAtPreferred > minSize || qFuzzyCompare(sizeAtPreferred, minSize));
+ Q_ASSERT(sizeAtPreferred < maxSize || qFuzzyCompare(sizeAtPreferred, maxSize));
+ Q_ASSERT(sizeAtMaximum > minSize || qFuzzyCompare(sizeAtMaximum, minSize));
+ Q_ASSERT(sizeAtMaximum < maxSize || qFuzzyCompare(sizeAtMaximum, maxSize));
+
+ // Band here refers if the value is in the Minimum To Preferred
+ // band (the lower band) or the Preferred To Maximum (the upper band).
+
+ qreal minFactor = getFactor(sizeAtMinimum, minSize, prefSize, maxSize);
+ qreal prefFactor = getFactor(sizeAtPreferred, minSize, prefSize, maxSize);
+ qreal maxFactor = getFactor(sizeAtMaximum, minSize, prefSize, maxSize);
+
+ for (int i = 0; i < m_edges.count(); ++i) {
+ AnchorData *e = m_edges.at(i);
+
+ qreal bandSize = minFactor > 0 ? e->maxSize - e->prefSize : e->prefSize - e->minSize;
+ e->sizeAtMinimum = e->prefSize + bandSize * minFactor;
+
+ bandSize = prefFactor > 0 ? e->maxSize - e->prefSize : e->prefSize - e->minSize;
+ e->sizeAtPreferred = e->prefSize + bandSize * prefFactor;
+
+ bandSize = maxFactor > 0 ? e->maxSize - e->prefSize : e->prefSize - e->minSize;
+ e->sizeAtMaximum = e->prefSize + bandSize * maxFactor;
+
+ e->updateChildrenSizes();
+ }
+}
+
+void SequentialAnchorData::refreshSizeHints(qreal effectiveSpacing)
+{
+ minSize = 0;
+ prefSize = 0;
+ maxSize = 0;
+
+ for (int i = 0; i < m_edges.count(); ++i) {
+ AnchorData *edge = m_edges.at(i);
+
+ // First refresh children information
+ edge->refreshSizeHints(effectiveSpacing);
+
+ minSize += edge->minSize;
+ prefSize += edge->prefSize;
+ maxSize += edge->maxSize;
+ }
+
+ // See comment in AnchorData::refreshSizeHints() about sizeAt* values
+ sizeAtMinimum = prefSize;
+ sizeAtPreferred = prefSize;
+ sizeAtMaximum = prefSize;
+}
+
+#ifdef QT_DEBUG
+void AnchorData::dump(int indent) {
+ if (type == Parallel) {
+ qDebug("%*s type: parallel:", indent, "");
+ ParallelAnchorData *p = static_cast<ParallelAnchorData *>(this);
+ p->firstEdge->dump(indent+2);
+ p->secondEdge->dump(indent+2);
+ } else if (type == Sequential) {
+ SequentialAnchorData *s = static_cast<SequentialAnchorData *>(this);
+ int kids = s->m_edges.count();
+ qDebug("%*s type: sequential(%d):", indent, "", kids);
+ for (int i = 0; i < kids; ++i) {
+ s->m_edges.at(i)->dump(indent+2);
+ }
+ } else {
+ qDebug("%*s type: Normal:", indent, "");
+ }
+}
+
+#endif
+
+QSimplexConstraint *GraphPath::constraint(const GraphPath &path) const
+{
+ // Calculate
+ QSet<AnchorData *> cPositives;
+ QSet<AnchorData *> cNegatives;
+ QSet<AnchorData *> intersection;
+
+ cPositives = positives + path.negatives;
+ cNegatives = negatives + path.positives;
+
+ intersection = cPositives & cNegatives;
+
+ cPositives -= intersection;
+ cNegatives -= intersection;
+
+ // Fill
+ QSimplexConstraint *c = new QSimplexConstraint;
+ QSet<AnchorData *>::iterator i;
+ for (i = cPositives.begin(); i != cPositives.end(); ++i)
+ c->variables.insert(*i, 1.0);
+
+ for (i = cNegatives.begin(); i != cNegatives.end(); ++i)
+ c->variables.insert(*i, -1.0);
+
+ return c;
+}
+
+#ifdef QT_DEBUG
+QString GraphPath::toString() const
+{
+ QString string(QLatin1String("Path: "));
+ foreach(AnchorData *edge, positives)
+ string += QString::fromAscii(" (+++) %1").arg(edge->toString());
+
+ foreach(AnchorData *edge, negatives)
+ string += QString::fromAscii(" (---) %1").arg(edge->toString());
+
+ return string;
+}
+#endif
+
+QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate()
+ : calculateGraphCacheDirty(1)
+{
+ for (int i = 0; i < NOrientations; ++i) {
+ spacings[i] = -1;
+ graphSimplified[i] = false;
+ }
+}
+
+Qt::AnchorPoint QGraphicsAnchorLayoutPrivate::oppositeEdge(Qt::AnchorPoint edge)
+{
+ switch (edge) {
+ case Qt::AnchorLeft:
+ edge = Qt::AnchorRight;
+ break;
+ case Qt::AnchorRight:
+ edge = Qt::AnchorLeft;
+ break;
+ case Qt::AnchorTop:
+ edge = Qt::AnchorBottom;
+ break;
+ case Qt::AnchorBottom:
+ edge = Qt::AnchorTop;
+ break;
+ default:
+ break;
+ }
+ return edge;
+}
+
+
+/*!
+ * \internal
+ *
+ * helper function in order to avoid overflowing anchor sizes
+ * the returned size will never be larger than FLT_MAX
+ *
+ */
+inline static qreal checkAdd(qreal a, qreal b)
+{
+ if (FLT_MAX - b < a)
+ return FLT_MAX;
+ return a + b;
+}
+
+/*!
+ * \internal
+ *
+ * Takes the sequence of vertices described by (\a before, \a vertices, \a after) and replaces
+ * all anchors connected to the vertices in \a vertices with one simplified anchor between
+ * \a before and \a after. The simplified anchor will be a placeholder for all the previous
+ * anchors between \a before and \a after, and can be restored back to the anchors it is a
+ * placeholder for.
+ */
+static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph,
+ AnchorVertex *before,
+ const QVector<AnchorVertex*> &vertices,
+ AnchorVertex *after)
+{
+ int i;
+#if defined(QT_DEBUG) && 0
+ QString strVertices;
+ for (i = 0; i < vertices.count(); ++i)
+ strVertices += QString::fromAscii("%1 - ").arg(vertices.at(i)->toString());
+ QString strPath = QString::fromAscii("%1 - %2%3").arg(before->toString(), strVertices, after->toString());
+ qDebug("simplifying [%s] to [%s - %s]", qPrintable(strPath), qPrintable(before->toString()), qPrintable(after->toString()));
+#endif
+
+ qreal min = 0;
+ qreal pref = 0;
+ qreal max = 0;
+
+ SequentialAnchorData *sequence = new SequentialAnchorData;
+ AnchorVertex *prev = before;
+ AnchorData *data;
+ for (i = 0; i <= vertices.count(); ++i) {
+ AnchorVertex *next = (i < vertices.count()) ? vertices.at(i) : after;
+ data = graph->takeEdge(prev, next);
+ min += data->minSize;
+ pref += data->prefSize;
+ max = checkAdd(max, data->maxSize);
+ sequence->m_edges.append(data);
+ prev = next;
+ }
+
+ // insert new
+ sequence->minSize = min;
+ sequence->prefSize = pref;
+ sequence->maxSize = max;
+
+ // Unless these values are overhidden by the simplex solver later-on,
+ // anchors will keep their own preferred size.
+ sequence->sizeAtMinimum = pref;
+ sequence->sizeAtPreferred = pref;
+ sequence->sizeAtMaximum = pref;
+
+ sequence->setVertices(vertices);
+
+ sequence->from = before;
+ sequence->to = after;
+
+ // data here is the last edge in the sequence
+ // ### this seems to be here for supporting reverse order sequences,
+ // but doesnt seem to be used right now
+ if (data->from != vertices.last())
+ qSwap(sequence->from, sequence->to);
+
+ // Note that since layout 'edges' can't be simplified away from
+ // the graph, it's safe to assume that if there's a layout
+ // 'edge', it'll be in the boundaries of the sequence.
+ sequence->isLayoutAnchor = (sequence->m_edges.first()->isLayoutAnchor
+ || sequence->m_edges.last()->isLayoutAnchor);
+
+ AnchorData *newAnchor = sequence;
+ if (AnchorData *oldAnchor = graph->takeEdge(before, after)) {
+ newAnchor = new ParallelAnchorData(oldAnchor, sequence);
+
+ newAnchor->isLayoutAnchor = (oldAnchor->isLayoutAnchor
+ || sequence->isLayoutAnchor);
+
+ min = qMax(oldAnchor->minSize, sequence->minSize);
+ max = qMin(oldAnchor->maxSize, sequence->maxSize);
+
+ pref = qMax(oldAnchor->prefSize, sequence->prefSize);
+ pref = qMin(pref, max);
+
+ newAnchor->minSize = min;
+ newAnchor->prefSize = pref;
+ newAnchor->maxSize = max;
+
+ // Same as above, by default, keep preferred size.
+ newAnchor->sizeAtMinimum = pref;
+ newAnchor->sizeAtPreferred = pref;
+ newAnchor->sizeAtMaximum = pref;
+ }
+ graph->createEdge(before, after, newAnchor);
+
+ // True if we created a parallel anchor
+ return newAnchor != sequence;
+}
+
+/*!
+ \internal
+
+ The purpose of this function is to simplify the graph.
+ Simplification serves two purposes:
+ 1. Reduce the number of edges in the graph, (thus the number of variables to the equation
+ solver is reduced, and the solver performs better).
+ 2. Be able to do distribution of sequences of edges more intelligently (esp. with sequential
+ anchors)
+
+ It is essential that it must be possible to restore simplified anchors back to their "original"
+ form. This is done by restoreSimplifiedAnchor().
+
+ There are two types of simplification that can be done:
+ 1. Sequential simplification
+ Sequential simplification means that all sequences of anchors will be merged into one single
+ anchor. Only anhcors that points in the same direction will be merged.
+ 2. Parallel simplification
+ If a simplified sequential anchor is about to be inserted between two vertices in the graph
+ and there already exist an anchor between those two vertices, a parallel anchor will be
+ created that serves as a placeholder for the sequential anchor and the anchor that was
+ already between the two vertices.
+
+ The process of simplification can be described as:
+
+ 1. Simplify all sequences of anchors into one anchor.
+ If no further simplification was done, go to (3)
+ - If there already exist an anchor where the sequential anchor is supposed to be inserted,
+ take that anchor out of the graph
+ - Then create a parallel anchor that holds the sequential anchor and the anchor just taken
+ out of the graph.
+ 2. Go to (1)
+ 3. Done
+
+
+ * Gathering sequential anchors *
+ The algorithm walks the graph in depth-first order, and only collects vertices that has two
+ edges connected to it. If the vertex does not have two edges or if it is a layout edge,
+ it will take all the previously collected vertices and try to create a simplified sequential
+ anchor representing all the previously collected vertices.
+ Once the simplified anchor is inserted, the collected list is cleared in order to find the next
+ sequence to simplify.
+ Note that there are some catches to this that are not covered by the above explanation.
+*/
+void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation)
+{
+ static bool noSimplification = !qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty();
+ if (noSimplification)
+ return;
+
+ if (graphSimplified[orientation])
+ return;
+ graphSimplified[orientation] = true;
+
+#if 0
+ qDebug("Simplifying Graph for %s",
+ orientation == Horizontal ? "Horizontal" : "Vertical");
+#endif
+
+ AnchorVertex *rootVertex = graph[orientation].rootVertex();
+
+ if (!rootVertex)
+ return;
+
+ bool dirty;
+ do {
+ dirty = simplifyGraphIteration(orientation);
+ } while (dirty);
+}
+
+bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutPrivate::Orientation orientation)
+{
+ Q_Q(QGraphicsAnchorLayout);
+ Graph<AnchorVertex, AnchorData> &g = graph[orientation];
+ AnchorVertex *v = g.rootVertex();
+
+ QSet<AnchorVertex *> visited;
+ QStack<AnchorVertex *> stack;
+ stack.push(v);
+ QVector<AnchorVertex*> candidates;
+
+ const Qt::AnchorPoint centerEdge = pickEdge(Qt::AnchorHorizontalCenter, orientation);
+ const Qt::AnchorPoint layoutEdge = oppositeEdge(v->m_edge);
+
+ bool dirty = false;
+
+ // walk depth-first.
+ while (!stack.isEmpty()) {
+ v = stack.pop();
+ QList<AnchorVertex *> vertices = g.adjacentVertices(v);
+ const int count = vertices.count();
+ bool endOfSequence = (v->m_item == q && v->m_edge == layoutEdge) || count != 2;
+ if (count == 2 && v->m_item != q) {
+ candidates.append(v);
+ if (visited.contains(vertices.first()) && visited.contains(vertices.last())) {
+ // in case of a cycle
+ endOfSequence = true;
+ }
+ }
+ if (endOfSequence && candidates.count() >= 2) {
+ int i;
+ AnchorVertex *afterSequence= 0;
+ QList<AnchorVertex *> adjacentOfSecondLastVertex = g.adjacentVertices(candidates.last());
+ Q_ASSERT(adjacentOfSecondLastVertex.count() == 2);
+ if (adjacentOfSecondLastVertex.first() == candidates.at(candidates.count() - 2))
+ afterSequence = adjacentOfSecondLastVertex.last();
+ else
+ afterSequence = adjacentOfSecondLastVertex.first();
+
+ AnchorVertex *beforeSequence = 0;
+ QList<AnchorVertex *> adjacentOfSecondVertex = g.adjacentVertices(candidates.first());
+ Q_ASSERT(adjacentOfSecondVertex.count() == 2);
+ if (adjacentOfSecondVertex.first() == candidates.at(1))
+ beforeSequence = adjacentOfSecondVertex.last();
+ else
+ beforeSequence = adjacentOfSecondVertex.first();
+ // The complete path of the sequence to simplify is: beforeSequence, <candidates>, afterSequence
+ // where beforeSequence and afterSequence are the endpoints where the anchor is inserted
+ // between.
+#if defined(QT_DEBUG) && 0
+ // ### DEBUG
+ QString strCandidates;
+ for (i = 0; i < candidates.count(); ++i)
+ strCandidates += QString::fromAscii("%1 - ").arg(candidates.at(i)->toString());
+ QString strPath = QString::fromAscii("%1 - %2%3").arg(beforeSequence->toString(), strCandidates, afterSequence->toString());
+ qDebug("candidate list for sequential simplification:\n[%s]", qPrintable(strPath));
+#endif
+
+ bool forward = true;
+ AnchorVertex *prev = beforeSequence;
+ int intervalFrom = 0;
+
+ // Check for directionality (from). We don't want to destroy that information,
+ // thus we only combine anchors with the same direction.
+
+ // "i" is the index *including* the beforeSequence and afterSequence vertices.
+ for (i = 1; i <= candidates.count() + 1; ++i) {
+ bool atVertexAfter = i > candidates.count();
+ AnchorVertex *v1 = atVertexAfter ? afterSequence : candidates.at(i - 1);
+ AnchorData *data = g.edgeData(prev, v1);
+ Q_ASSERT(data);
+ if (i == 1) {
+ forward = (prev == data->from ? true : false);
+ } else if (forward != (prev == data->from) || atVertexAfter) {
+ int intervalTo = i;
+ if (forward != (prev == data->from))
+ --intervalTo;
+
+ // intervalFrom and intervalTo should now be indices to the vertex before and
+ // after the sequential anchor.
+ if (intervalTo - intervalFrom >= 2) {
+ // simplify in the range [intervalFrom, intervalTo]
+
+ // Trim off internal center anchors (Left-Center/Center-Right) from the
+ // start and the end of the sequence. We never want to simplify internal
+ // center anchors where there is an external anchor connected to the center.
+ AnchorVertex *intervalVertexFrom = intervalFrom == 0 ? beforeSequence : candidates.at(intervalFrom - 1);
+ if (intervalVertexFrom->m_edge == centerEdge
+ && intervalVertexFrom->m_item == candidates.at(intervalFrom)->m_item) {
+ ++intervalFrom;
+ intervalVertexFrom = candidates.at(intervalFrom - 1);
+ }
+ AnchorVertex *intervalVertexTo = intervalTo <= candidates.count() ? candidates.at(intervalTo - 1) : afterSequence;
+ if (intervalVertexTo->m_edge == centerEdge
+ && intervalVertexTo->m_item == candidates.at(intervalTo - 2)->m_item) {
+ --intervalTo;
+ intervalVertexTo = candidates.at(intervalTo - 1);
+ }
+
+ QVector<AnchorVertex*> subCandidates;
+ if (forward) {
+ subCandidates = candidates.mid(intervalFrom, intervalTo - intervalFrom - 1);
+ } else {
+ // reverse the order of the candidates.
+ qSwap(intervalVertexFrom, intervalVertexTo);
+ do {
+ ++intervalFrom;
+ subCandidates.prepend(candidates.at(intervalFrom - 1));
+ } while (intervalFrom < intervalTo - 1);
+ }
+ if (simplifySequentialChunk(&g, intervalVertexFrom, subCandidates, intervalVertexTo)) {
+ dirty = true;
+ break;
+ }
+ // finished simplification of chunk with same direction
+ }
+ if (forward == (prev == data->from))
+ --intervalTo;
+ intervalFrom = intervalTo;
+
+ forward = !forward;
+ }
+ prev = v1;
+ }
+
+ if (dirty)
+ break;
+ }
+
+ if (endOfSequence)
+ candidates.clear();
+
+ for (int i = 0; i < count; ++i) {
+ AnchorVertex *next = vertices.at(i);
+ if (next->m_item == q && next->m_edge == centerEdge)
+ continue;
+ if (visited.contains(next))
+ continue;
+ stack.push(next);
+ }
+
+ visited.insert(v);
+ }
+
+ return dirty;
+}
+
+static void restoreSimplifiedAnchor(Graph<AnchorVertex, AnchorData> &g,
+ AnchorData *edge,
+ AnchorVertex *before,
+ AnchorVertex *after)
+{
+ Q_ASSERT(edge->type != AnchorData::Normal);
+#if 0
+ static const char *anchortypes[] = {"Normal",
+ "Sequential",
+ "Parallel"};
+ qDebug("Restoring %s edge.", anchortypes[int(edge->type)]);
+#endif
+ if (edge->type == AnchorData::Sequential) {
+ SequentialAnchorData* seqEdge = static_cast<SequentialAnchorData*>(edge);
+ // restore the sequential anchor
+ AnchorVertex *prev = before;
+ AnchorVertex *last = after;
+ if (edge->from != prev)
+ qSwap(last, prev);
+
+ for (int i = 0; i < seqEdge->m_edges.count(); ++i) {
+ AnchorVertex *v1 = (i < seqEdge->m_children.count()) ? seqEdge->m_children.at(i) : last;
+ AnchorData *data = seqEdge->m_edges.at(i);
+ if (data->type != AnchorData::Normal) {
+ restoreSimplifiedAnchor(g, data, prev, v1);
+ } else {
+ g.createEdge(prev, v1, data);
+ }
+ prev = v1;
+ }
+ } else if (edge->type == AnchorData::Parallel) {
+ ParallelAnchorData* parallelEdge = static_cast<ParallelAnchorData*>(edge);
+ AnchorData *parallelEdges[2] = {parallelEdge->firstEdge,
+ parallelEdge->secondEdge};
+ for (int i = 0; i < 2; ++i) {
+ AnchorData *data = parallelEdges[i];
+ if (data->type == AnchorData::Normal) {
+ g.createEdge(before, after, data);
+ } else {
+ restoreSimplifiedAnchor(g, data, before, after);
+ }
+ }
+ }
+}
+
+void QGraphicsAnchorLayoutPrivate::restoreSimplifiedGraph(Orientation orientation)
+{
+ if (!graphSimplified[orientation])
+ return;
+ graphSimplified[orientation] = false;
+
+#if 0
+ qDebug("Restoring Simplified Graph for %s",
+ orientation == Horizontal ? "Horizontal" : "Vertical");
+#endif
+
+ Graph<AnchorVertex, AnchorData> &g = graph[orientation];
+
+ QList<QPair<AnchorVertex*, AnchorVertex*> > connections = g.connections();
+ for (int i = 0; i < connections.count(); ++i) {
+ AnchorVertex *v1 = connections.at(i).first;
+ AnchorVertex *v2 = connections.at(i).second;
+ AnchorData *edge = g.edgeData(v1, v2);
+ if (edge->type != AnchorData::Normal) {
+ AnchorData *oldEdge = g.takeEdge(v1, v2);
+ restoreSimplifiedAnchor(g, edge, v1, v2);
+ delete oldEdge;
+ }
+ }
+}
+
+QGraphicsAnchorLayoutPrivate::Orientation
+QGraphicsAnchorLayoutPrivate::edgeOrientation(Qt::AnchorPoint edge)
+{
+ return edge > Qt::AnchorRight ? Vertical : Horizontal;
+}
+
+/*!
+ \internal
+
+ Create internal anchors to connect the layout edges (Left to Right and
+ Top to Bottom).
+
+ These anchors doesn't have size restrictions, that will be enforced by
+ other anchors and items in the layout.
+*/
+void QGraphicsAnchorLayoutPrivate::createLayoutEdges()
+{
+ Q_Q(QGraphicsAnchorLayout);
+ QGraphicsLayoutItem *layout = q;
+
+ // Horizontal
+ AnchorData *data = new AnchorData(0, 0, QWIDGETSIZE_MAX);
+ addAnchor(layout, Qt::AnchorLeft, layout,
+ Qt::AnchorRight, data);
+ data->skipInPreferred = 1;
+
+ // Set the Layout Left edge as the root of the horizontal graph.
+ AnchorVertex *v = internalVertex(layout, Qt::AnchorLeft);
+ graph[Horizontal].setRootVertex(v);
+
+ // Vertical
+ data = new AnchorData(0, 0, QWIDGETSIZE_MAX);
+ addAnchor(layout, Qt::AnchorTop, layout,
+ Qt::AnchorBottom, data);
+ data->skipInPreferred = 1;
+
+ // Set the Layout Top edge as the root of the vertical graph.
+ v = internalVertex(layout, Qt::AnchorTop);
+ graph[Vertical].setRootVertex(v);
+}
+
+void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges()
+{
+ Q_Q(QGraphicsAnchorLayout);
+
+ Q_ASSERT(internalVertex(q, Qt::AnchorHorizontalCenter) == NULL);
+ Q_ASSERT(internalVertex(q, Qt::AnchorVerticalCenter) == NULL);
+
+ removeAnchor(q, Qt::AnchorLeft, q, Qt::AnchorRight);
+ removeAnchor(q, Qt::AnchorTop, q, Qt::AnchorBottom);
+}
+
+void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item)
+{
+ Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]);
+
+ items.append(item);
+
+ // Horizontal
+ int minimumSize = item->minimumWidth();
+ int preferredSize = item->preferredWidth();
+ int maximumSize = item->maximumWidth();
+
+ AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize);
+ addAnchor(item, Qt::AnchorLeft, item,
+ Qt::AnchorRight, data);
+
+ // Vertical
+ minimumSize = item->minimumHeight();
+ preferredSize = item->preferredHeight();
+ maximumSize = item->maximumHeight();
+
+ data = new AnchorData(minimumSize, preferredSize, maximumSize);
+ addAnchor(item, Qt::AnchorTop, item,
+ Qt::AnchorBottom, data);
+}
+
+/*!
+ \internal
+
+ By default, each item in the layout is represented internally as
+ a single anchor in each direction. For instance, from Left to Right.
+
+ However, to support anchorage of items to the center of items, we
+ must split this internal anchor into two half-anchors. From Left
+ to Center and then from Center to Right, with the restriction that
+ these anchors must have the same time at all times.
+*/
+void QGraphicsAnchorLayoutPrivate::createCenterAnchors(
+ QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge)
+{
+ Orientation orientation;
+ switch (centerEdge) {
+ case Qt::AnchorHorizontalCenter:
+ orientation = Horizontal;
+ break;
+ case Qt::AnchorVerticalCenter:
+ orientation = Vertical;
+ break;
+ default:
+ // Don't create center edges unless needed
+ return;
+ }
+
+ Q_ASSERT(!graphSimplified[orientation]);
+
+ // Check if vertex already exists
+ if (internalVertex(item, centerEdge))
+ return;
+
+ // Orientation code
+ Qt::AnchorPoint firstEdge;
+ Qt::AnchorPoint lastEdge;
+
+ if (orientation == Horizontal) {
+ firstEdge = Qt::AnchorLeft;
+ lastEdge = Qt::AnchorRight;
+ } else {
+ firstEdge = Qt::AnchorTop;
+ lastEdge = Qt::AnchorBottom;
+ }
+
+ AnchorVertex *first = internalVertex(item, firstEdge);
+ AnchorVertex *last = internalVertex(item, lastEdge);
+ Q_ASSERT(first && last);
+
+ // Create new anchors
+ AnchorData *oldData = graph[orientation].edgeData(first, last);
+
+ int minimumSize = oldData->minSize / 2;
+ int preferredSize = oldData->prefSize / 2;
+ int maximumSize = oldData->maxSize / 2;
+
+ QSimplexConstraint *c = new QSimplexConstraint;
+ AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize);
+ c->variables.insert(data, 1.0);
+ addAnchor(item, firstEdge, item, centerEdge, data);
+
+ data = new AnchorData(minimumSize, preferredSize, maximumSize);
+ c->variables.insert(data, -1.0);
+ addAnchor(item, centerEdge, item, lastEdge, data);
+
+ itemCenterConstraints[orientation].append(c);
+
+ // Remove old one
+ removeAnchor(item, firstEdge, item, lastEdge);
+}
+
+void QGraphicsAnchorLayoutPrivate::removeCenterAnchors(
+ QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge,
+ bool substitute)
+{
+ Orientation orientation;
+ switch (centerEdge) {
+ case Qt::AnchorHorizontalCenter:
+ orientation = Horizontal;
+ break;
+ case Qt::AnchorVerticalCenter:
+ orientation = Vertical;
+ break;
+ default:
+ // Don't remove edges that not the center ones
+ return;
+ }
+
+ Q_ASSERT(!graphSimplified[orientation]);
+
+ // Orientation code
+ Qt::AnchorPoint firstEdge;
+ Qt::AnchorPoint lastEdge;
+
+ if (orientation == Horizontal) {
+ firstEdge = Qt::AnchorLeft;
+ lastEdge = Qt::AnchorRight;
+ } else {
+ firstEdge = Qt::AnchorTop;
+ lastEdge = Qt::AnchorBottom;
+ }
+
+ AnchorVertex *center = internalVertex(item, centerEdge);
+ if (!center)
+ return;
+ AnchorVertex *first = internalVertex(item, firstEdge);
+
+ Q_ASSERT(first);
+ Q_ASSERT(center);
+
+ Graph<AnchorVertex, AnchorData> &g = graph[orientation];
+
+
+ AnchorData *oldData = g.edgeData(first, center);
+ // Remove center constraint
+ for (int i = itemCenterConstraints[orientation].count() - 1; i >= 0; --i) {
+ if (itemCenterConstraints[orientation][i]->variables.contains(oldData)) {
+ delete itemCenterConstraints[orientation].takeAt(i);
+ break;
+ }
+ }
+
+ if (substitute) {
+ // Create the new anchor that should substitute the left-center-right anchors.
+ AnchorData *oldData = g.edgeData(first, center);
+
+ int minimumSize = oldData->minSize * 2;
+ int preferredSize = oldData->prefSize * 2;
+ int maximumSize = oldData->maxSize * 2;
+
+ AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize);
+ addAnchor(item, firstEdge, item, lastEdge, data);
+
+ // Remove old anchors
+ removeAnchor(item, firstEdge, item, centerEdge);
+ removeAnchor(item, centerEdge, item, lastEdge);
+
+ } else {
+ // this is only called from removeAnchors()
+ // first, remove all non-internal anchors
+ QList<AnchorVertex*> adjacents = g.adjacentVertices(center);
+ for (int i = 0; i < adjacents.count(); ++i) {
+ AnchorVertex *v = adjacents.at(i);
+ if (v->m_item != item) {
+ removeAnchor(item, centerEdge, v->m_item, v->m_edge);
+ }
+ }
+ // when all non-internal anchors is removed it will automatically merge the
+ // center anchor into a left-right (or top-bottom) anchor. We must also delete that.
+ // by this time, the center vertex is deleted and merged into a non-centered internal anchor
+ removeAnchor(item, firstEdge, item, lastEdge);
+ }
+}
+
+
+void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem *item,
+ Orientation orientation)
+{
+ Q_ASSERT(!graphSimplified[orientation]);
+
+ // Remove the item center constraints associated to this item
+ // ### This is a temporary solution. We should probably use a better
+ // data structure to hold items and/or their associated constraints
+ // so that we can remove those easily
+
+ AnchorVertex *first = internalVertex(item, orientation == Horizontal ?
+ Qt::AnchorLeft :
+ Qt::AnchorTop);
+ AnchorVertex *center = internalVertex(item, orientation == Horizontal ?
+ Qt::AnchorHorizontalCenter :
+ Qt::AnchorVerticalCenter);
+
+ // Skip if no center constraints exist
+ if (!center)
+ return;
+
+ Q_ASSERT(first);
+ AnchorData *internalAnchor = graph[orientation].edgeData(first, center);
+
+ // Look for our anchor in all item center constraints, then remove it
+ for (int i = 0; i < itemCenterConstraints[orientation].size(); ++i) {
+ if (itemCenterConstraints[orientation][i]->variables.contains(internalAnchor)) {
+ delete itemCenterConstraints[orientation].takeAt(i);
+ break;
+ }
+ }
+}
+
+/*!
+ * \internal
+ *
+ * Helper function that is called from the anchor functions in the public API.
+ * If \a spacing is 0, it will pick up the spacing defined by the style.
+ */
+void QGraphicsAnchorLayoutPrivate::anchor(QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ qreal *spacing)
+{
+ Q_Q(QGraphicsAnchorLayout);
+ if ((firstItem == 0) || (secondItem == 0)) {
+ qWarning("QGraphicsAnchorLayout::addAnchor(): "
+ "Cannot anchor NULL items");
+ return;
+ }
+
+ if (firstItem == secondItem) {
+ qWarning("QGraphicsAnchorLayout::addAnchor(): "
+ "Cannot anchor the item to itself");
+ return;
+ }
+
+ if (edgeOrientation(secondEdge) != edgeOrientation(firstEdge)) {
+ qWarning("QGraphicsAnchorLayout::addAnchor(): "
+ "Cannot anchor edges of different orientations");
+ return;
+ }
+
+ // Guarantee that the graph is no simplified when adding this anchor,
+ // anchor manipulation always happen in the full graph
+ restoreSimplifiedGraph(edgeOrientation(firstEdge));
+
+ // In QGraphicsAnchorLayout, items are represented in its internal
+ // graph as four anchors that connect:
+ // - Left -> HCenter
+ // - HCenter-> Right
+ // - Top -> VCenter
+ // - VCenter -> Bottom
+
+ // Ensure that the internal anchors have been created for both items.
+ if (firstItem != q && !items.contains(firstItem)) {
+ restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal);
+ createItemEdges(firstItem);
+ addChildLayoutItem(firstItem);
+ }
+ if (secondItem != q && !items.contains(secondItem)) {
+ restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal);
+ createItemEdges(secondItem);
+ addChildLayoutItem(secondItem);
+ }
+
+ // Create center edges if needed
+ createCenterAnchors(firstItem, firstEdge);
+ createCenterAnchors(secondItem, secondEdge);
+
+ // Use heuristics to find out what the user meant with this anchor.
+ correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge);
+
+ AnchorData *data;
+ if (!spacing) {
+ // If firstItem or secondItem is the layout itself, the spacing will default to 0.
+ // Otherwise, the following matrix is used (questionmark means that the spacing
+ // is queried from the style):
+ // from
+ // to Left HCenter Right
+ // Left 0 0 ?
+ // HCenter 0 0 0
+ // Right ? 0 0
+ if (firstItem != q
+ && secondItem != q
+ && pickEdge(firstEdge, Horizontal) != Qt::AnchorHorizontalCenter
+ && oppositeEdge(firstEdge) == secondEdge) {
+ data = new AnchorData; // ask the style later
+ } else {
+ data = new AnchorData(0); // spacing should be 0
+ }
+ addAnchor(firstItem, firstEdge, secondItem, secondEdge, data);
+ } else if (*spacing >= 0) {
+ data = new AnchorData(*spacing);
+ addAnchor(firstItem, firstEdge, secondItem, secondEdge, data);
+ } else {
+ data = new AnchorData(-*spacing);
+ addAnchor(secondItem, secondEdge, firstItem, firstEdge, data);
+ }
+}
+
+void QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ AnchorData *data)
+{
+ Q_Q(QGraphicsAnchorLayout);
+
+ // Guarantee that the graph is no simplified when adding this anchor,
+ // anchor manipulation always happen in the full graph
+ restoreSimplifiedGraph(edgeOrientation(firstEdge));
+
+ // Is the Vertex (firstItem, firstEdge) already represented in our
+ // internal structure?
+ AnchorVertex *v1 = addInternalVertex(firstItem, firstEdge);
+ AnchorVertex *v2 = addInternalVertex(secondItem, secondEdge);
+
+ // Remove previous anchor
+ // ### Could we update the existing edgeData rather than creating a new one?
+ if (graph[edgeOrientation(firstEdge)].edgeData(v1, v2))
+ removeAnchor(firstItem, firstEdge, secondItem, secondEdge);
+
+ // Create a bi-directional edge in the sense it can be transversed both
+ // from v1 or v2. "data" however is shared between the two references
+ // so we still know that the anchor direction is from 1 to 2.
+ data->from = v1;
+ data->to = v2;
+#ifdef QT_DEBUG
+ data->name = QString::fromAscii("%1 --to--> %2").arg(v1->toString()).arg(v2->toString());
+#endif
+ // Keep track of anchors that are connected to the layout 'edges'
+ data->isLayoutAnchor = (v1->m_item == q || v2->m_item == q);
+
+ graph[edgeOrientation(firstEdge)].createEdge(v1, v2, data);
+}
+
+void QGraphicsAnchorLayoutPrivate::removeAnchor(QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge)
+{
+ // Guarantee that the graph is no simplified when adding this anchor,
+ // anchor manipulation always happen in the full graph
+ restoreSimplifiedGraph(edgeOrientation(firstEdge));
+
+ // Look for both vertices
+ AnchorVertex *v1 = internalVertex(firstItem, firstEdge);
+ AnchorVertex *v2 = internalVertex(secondItem, secondEdge);
+
+ Q_ASSERT(v1 && v2);
+
+ // Remove edge from graph
+ graph[edgeOrientation(firstEdge)].removeEdge(v1, v2);
+
+ // Decrease vertices reference count (may trigger a deletion)
+ removeInternalVertex(firstItem, firstEdge);
+ removeInternalVertex(secondItem, secondEdge);
+}
+
+bool QGraphicsAnchorLayoutPrivate::setAnchorSize(const QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ const qreal *anchorSize)
+{
+ // ### we can avoid restoration if we really want to, but we would have to
+ // search recursively through all composite anchors
+ restoreSimplifiedGraph(edgeOrientation(firstEdge));
+ AnchorVertex *v1 = internalVertex(firstItem, firstEdge);
+ AnchorVertex *v2 = internalVertex(secondItem, secondEdge);
+
+ AnchorData *data = graph[edgeOrientation(firstEdge)].edgeData(v1, v2);
+ if (data) {
+ if (anchorSize) {
+ data->setFixedSize(*anchorSize);
+ } else {
+ data->unsetSize();
+ }
+ }
+
+ return data;
+}
+
+bool QGraphicsAnchorLayoutPrivate::anchorSize(const QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ qreal *minSize,
+ qreal *prefSize,
+ qreal *maxSize) const
+{
+ Q_ASSERT(minSize || prefSize || maxSize);
+ QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate *>(this);
+ that->restoreSimplifiedGraph(edgeOrientation(firstEdge));
+ AnchorVertex *v1 = internalVertex(firstItem, firstEdge);
+ AnchorVertex *v2 = internalVertex(secondItem, secondEdge);
+
+ AnchorData *data = that->graph[edgeOrientation(firstEdge)].edgeData(v1, v2);
+ if (data) {
+ if (minSize)
+ *minSize = data->minSize;
+ if (prefSize)
+ *prefSize = data->prefSize;
+ if (maxSize)
+ *maxSize = data->maxSize;
+ }
+ return data;
+}
+
+AnchorVertex *QGraphicsAnchorLayoutPrivate::addInternalVertex(QGraphicsLayoutItem *item,
+ Qt::AnchorPoint edge)
+{
+ QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge);
+ QPair<AnchorVertex *, int> v = m_vertexList.value(pair);
+
+ if (!v.first) {
+ Q_ASSERT(v.second == 0);
+ v.first = new AnchorVertex(item, edge);
+ }
+ v.second++;
+ m_vertexList.insert(pair, v);
+ return v.first;
+}
+
+/**
+ * \internal
+ *
+ * returns the AnchorVertex that was dereferenced, also when it was removed.
+ * returns 0 if it did not exist.
+ */
+void QGraphicsAnchorLayoutPrivate::removeInternalVertex(QGraphicsLayoutItem *item,
+ Qt::AnchorPoint edge)
+{
+ QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge);
+ QPair<AnchorVertex *, int> v = m_vertexList.value(pair);
+
+ if (!v.first) {
+ qWarning("This item with this edge is not in the graph");
+ return;
+ }
+
+ v.second--;
+ if (v.second == 0) {
+ // Remove reference and delete vertex
+ m_vertexList.remove(pair);
+ delete v.first;
+ } else {
+ // Update reference count
+ m_vertexList.insert(pair, v);
+
+ if ((v.second == 2) &&
+ ((edge == Qt::AnchorHorizontalCenter) ||
+ (edge == Qt::AnchorVerticalCenter))) {
+ removeCenterAnchors(item, edge, true);
+ }
+ }
+}
+
+void QGraphicsAnchorLayoutPrivate::removeVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge)
+{
+ if (AnchorVertex *v = internalVertex(item, edge)) {
+ Graph<AnchorVertex, AnchorData> &g = graph[edgeOrientation(edge)];
+ const QList<AnchorVertex *> allVertices = graph[edgeOrientation(edge)].adjacentVertices(v);
+ AnchorVertex *v2;
+ foreach (v2, allVertices) {
+ g.removeEdge(v, v2);
+ removeInternalVertex(item, edge);
+ removeInternalVertex(v2->m_item, v2->m_edge);
+ }
+ }
+}
+
+void QGraphicsAnchorLayoutPrivate::removeAnchors(QGraphicsLayoutItem *item)
+{
+ Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]);
+
+ // remove the center anchor first!!
+ removeCenterAnchors(item, Qt::AnchorHorizontalCenter, false);
+ removeVertex(item, Qt::AnchorLeft);
+ removeVertex(item, Qt::AnchorRight);
+
+ removeCenterAnchors(item, Qt::AnchorVerticalCenter, false);
+ removeVertex(item, Qt::AnchorTop);
+ removeVertex(item, Qt::AnchorBottom);
+}
+
+/*!
+ \internal
+
+ Use heuristics to determine the correct orientation of a given anchor.
+
+ After API discussions, we decided we would like expressions like
+ anchor(A, Left, B, Right) to mean the same as anchor(B, Right, A, Left).
+ The problem with this is that anchors could become ambiguous, for
+ instance, what does the anchor A, B of size X mean?
+
+ "pos(B) = pos(A) + X" or "pos(A) = pos(B) + X" ?
+
+ To keep the API user friendly and at the same time, keep our algorithm
+ deterministic, we use an heuristic to determine a direction for each
+ added anchor and then keep it. The heuristic is based on the fact
+ that people usually avoid overlapping items, therefore:
+
+ "A, RIGHT to B, LEFT" means that B is to the LEFT of A.
+ "B, LEFT to A, RIGHT" is corrected to the above anchor.
+
+ Special correction is also applied when one of the items is the
+ layout. We handle Layout Left as if it was another items's Right
+ and Layout Right as another item's Left.
+*/
+void QGraphicsAnchorLayoutPrivate::correctEdgeDirection(QGraphicsLayoutItem *&firstItem,
+ Qt::AnchorPoint &firstEdge,
+ QGraphicsLayoutItem *&secondItem,
+ Qt::AnchorPoint &secondEdge)
+{
+ Q_Q(QGraphicsAnchorLayout);
+
+ Qt::AnchorPoint effectiveFirst = firstEdge;
+ Qt::AnchorPoint effectiveSecond = secondEdge;
+
+ if (firstItem == q)
+ effectiveFirst = QGraphicsAnchorLayoutPrivate::oppositeEdge(firstEdge);
+ if (secondItem == q)
+ effectiveSecond = QGraphicsAnchorLayoutPrivate::oppositeEdge(secondEdge);
+
+ if (effectiveFirst < effectiveSecond) {
+
+ // ### DEBUG
+ /* printf("Swapping Anchor from %s %d --to--> %s %d\n",
+ firstItem->isLayout() ? "<layout>" :
+ qPrintable(static_cast<QGraphicsWidget *>(firstItem)->data(0).toString()),
+ firstEdge,
+ secondItem->isLayout() ? "<layout>" :
+ qPrintable(static_cast<QGraphicsWidget *>(secondItem)->data(0).toString()),
+ secondEdge);
+ */
+ qSwap(firstItem, secondItem);
+ qSwap(firstEdge, secondEdge);
+ }
+}
+
+qreal QGraphicsAnchorLayoutPrivate::effectiveSpacing(Orientation orientation) const
+{
+ Q_Q(const QGraphicsAnchorLayout);
+ qreal s = spacings[orientation];
+ if (s < 0) {
+ // ### make sure behaviour is the same as in QGraphicsGridLayout
+ QGraphicsLayoutItem *parent = q->parentLayoutItem();
+ while (parent && parent->isLayout()) {
+ parent = parent->parentLayoutItem();
+ }
+ if (parent) {
+ QGraphicsItem *parentItem = parent->graphicsItem();
+ if (parentItem && parentItem->isWidget()) {
+ QGraphicsWidget *w = static_cast<QGraphicsWidget*>(parentItem);
+ s = w->style()->pixelMetric(orientation == Horizontal
+ ? QStyle::PM_LayoutHorizontalSpacing
+ : QStyle::PM_LayoutVerticalSpacing);
+ }
+ }
+ }
+ return s;
+}
+
+/*!
+ \internal
+
+ Called on activation. Uses Linear Programming to define minimum, preferred
+ and maximum sizes for the layout. Also calculates the sizes that each item
+ should assume when the layout is in one of such situations.
+*/
+void QGraphicsAnchorLayoutPrivate::calculateGraphs()
+{
+ if (!calculateGraphCacheDirty)
+ return;
+
+ calculateGraphs(Horizontal);
+ calculateGraphs(Vertical);
+
+ calculateGraphCacheDirty = 0;
+}
+
+// ### remove me:
+QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints)
+{
+ QSet<AnchorData *> variableSet;
+ for (int i = 0; i < constraints.count(); ++i) {
+ const QSimplexConstraint *c = constraints[i];
+ foreach (QSimplexVariable *var, c->variables.keys()) {
+ variableSet += static_cast<AnchorData *>(var);
+ }
+ }
+ return variableSet.toList();
+}
+
+/*!
+ \internal
+
+ Calculate graphs is the method that puts together all the helper routines
+ so that the AnchorLayout can calculate the sizes of each item.
+
+ In a nutshell it should do:
+
+ 1) Update anchor nominal sizes, that is, the size that each anchor would
+ have if no other restrictions applied. This is done by quering the
+ layout style and the sizeHints of the items belonging to the layout.
+
+ 2) Simplify the graph by grouping together parallel and sequential anchors
+ into "group anchors". These have equivalent minimum, preferred and maximum
+ sizeHints as the anchors they replace.
+
+ 3) Check if we got to a trivial case. In some cases, the whole graph can be
+ simplified into a single anchor. If so, use this information. If not,
+ then call the Simplex solver to calculate the anchors sizes.
+
+ 4) Once the root anchors had its sizes calculated, propagate that to the
+ anchors they represent.
+*/
+void QGraphicsAnchorLayoutPrivate::calculateGraphs(
+ QGraphicsAnchorLayoutPrivate::Orientation orientation)
+{
+ Q_Q(QGraphicsAnchorLayout);
+
+ // Simplify the graph
+ simplifyGraph(orientation);
+
+ // Reset the nominal sizes of each anchor based on the current item sizes
+ setAnchorSizeHintsFromItems(orientation);
+
+ // Traverse all graph edges and store the possible paths to each vertex
+ findPaths(orientation);
+
+ // From the paths calculated above, extract the constraints that the current
+ // anchor setup impose, to our Linear Programming problem.
+ constraintsFromPaths(orientation);
+
+ // Split the constraints and anchors into groups that should be fed to the
+ // simplex solver independently. Currently we find two groups:
+ //
+ // 1) The "trunk", that is, the set of anchors (items) that are connected
+ // to the two opposite sides of our layout, and thus need to stretch in
+ // order to fit in the current layout size.
+ //
+ // 2) The floating or semi-floating anchors (items) that are those which
+ // are connected to only one (or none) of the layout sides, thus are not
+ // influenced by the layout size.
+ QList<QList<QSimplexConstraint *> > parts;
+ parts = getGraphParts(orientation);
+
+ // Now run the simplex solver to calculate Minimum, Preferred and Maximum sizes
+ // of the "trunk" set of constraints and variables.
+ // ### does trunk always exist? empty = trunk is the layout left->center->right
+ QList<QSimplexConstraint *> trunkConstraints = parts[0];
+ QList<QSimplexConstraint *> sizeHintConstraints;
+ sizeHintConstraints = constraintsFromSizeHints(getVariables(trunkConstraints));
+ trunkConstraints += sizeHintConstraints;
+
+ // For minimum and maximum, use the path between the two layout sides as the
+ // objective function.
+
+ // Retrieve that path
+ AnchorVertex *v = internalVertex(q, pickEdge(Qt::AnchorRight, orientation));
+ GraphPath trunkPath = graphPaths[orientation].value(v);
+
+ if (!trunkConstraints.isEmpty()) {
+#if 0
+ qDebug("Simplex used for trunk of %s",
+ orientation == Horizontal ? "Horizontal" : "Vertical");
+#endif
+
+ // Solve min and max size hints for trunk
+ QPair<qreal, qreal> minMax = solveMinMax(trunkConstraints, trunkPath);
+ sizeHints[orientation][Qt::MinimumSize] = minMax.first;
+ sizeHints[orientation][Qt::MaximumSize] = minMax.second;
+
+ // Solve for preferred. The objective function is calculated from the constraints
+ // and variables internally.
+ solvePreferred(trunkConstraints);
+
+ // Propagate the new sizes down the simplified graph, ie. tell the
+ // group anchors to set their children anchors sizes.
+
+ // ### we calculated variables already a few times, can't we reuse that?
+ QList<AnchorData *> trunkVariables = getVariables(trunkConstraints);
+
+ for (int i = 0; i < trunkVariables.count(); ++i)
+ trunkVariables.at(i)->updateChildrenSizes();
+
+ // Calculate and set the preferred size for the layout from the edge sizes that
+ // were calculated above.
+ qreal pref(0.0);
+ foreach (const AnchorData *ad, trunkPath.positives) {
+ pref += ad->sizeAtPreferred;
+ }
+ foreach (const AnchorData *ad, trunkPath.negatives) {
+ pref -= ad->sizeAtPreferred;
+ }
+ sizeHints[orientation][Qt::PreferredSize] = pref;
+ } else {
+#if 0
+ qDebug("Simplex NOT used for trunk of %s",
+ orientation == Horizontal ? "Horizontal" : "Vertical");
+#endif
+
+ // No Simplex is necessary because the path was simplified all the way to a single
+ // anchor.
+ Q_ASSERT(trunkPath.positives.count() == 1);
+ Q_ASSERT(trunkPath.negatives.count() == 0);
+
+ AnchorData *ad = trunkPath.positives.toList()[0];
+ ad->sizeAtMinimum = ad->minSize;
+ ad->sizeAtPreferred = ad->prefSize;
+ ad->sizeAtMaximum = ad->maxSize;
+
+ // Propagate
+ ad->updateChildrenSizes();
+
+ sizeHints[orientation][Qt::MinimumSize] = ad->sizeAtMinimum;
+ sizeHints[orientation][Qt::PreferredSize] = ad->sizeAtPreferred;
+ sizeHints[orientation][Qt::MaximumSize] = ad->sizeAtMaximum;
+ }
+
+ // Delete the constraints, we won't use them anymore.
+ qDeleteAll(sizeHintConstraints);
+ sizeHintConstraints.clear();
+
+ // For the other parts that not the trunk, solve only for the preferred size
+ // that is the size they will remain at, since they are not stretched by the
+ // layout.
+
+ // Solve the other only for preferred, skip trunk
+ for (int i = 1; i < parts.count(); ++i) {
+ QList<QSimplexConstraint *> partConstraints = parts[i];
+ QList<AnchorData *> partVariables = getVariables(partConstraints);
+ Q_ASSERT(!partVariables.isEmpty());
+
+ sizeHintConstraints = constraintsFromSizeHints(partVariables);
+ partConstraints += sizeHintConstraints;
+ solvePreferred(partConstraints);
+
+ // Propagate size at preferred to other sizes. Semi-floats
+ // always will be in their sizeAtPreferred.
+ for (int j = 0; j < partVariables.count(); ++j) {
+ AnchorData *ad = partVariables[j];
+ Q_ASSERT(ad);
+ ad->sizeAtMinimum = ad->sizeAtPreferred;
+ ad->sizeAtMaximum = ad->sizeAtPreferred;
+ ad->updateChildrenSizes();
+ }
+
+ // Delete the constraints, we won't use them anymore.
+ qDeleteAll(sizeHintConstraints);
+ sizeHintConstraints.clear();
+ }
+
+ // Clean up our data structures. They are not needed anymore since
+ // distribution uses just interpolation.
+ qDeleteAll(constraints[orientation]);
+ constraints[orientation].clear();
+ graphPaths[orientation].clear(); // ###
+}
+
+/*!
+ \internal
+
+ For graph edges ("anchors") that represent items, this method updates their
+ intrinsic size restrictions, based on the item size hints.
+*/
+void QGraphicsAnchorLayoutPrivate::setAnchorSizeHintsFromItems(Orientation orientation)
+{
+ Graph<AnchorVertex, AnchorData> &g = graph[orientation];
+ QList<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections();
+
+ qreal spacing = effectiveSpacing(orientation);
+
+ for (int i = 0; i < vertices.count(); ++i) {
+ AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second);;
+ Q_ASSERT(data->from && data->to);
+ data->refreshSizeHints(spacing);
+ }
+}
+
+/*!
+ \internal
+
+ This method walks the graph using a breadth-first search to find paths
+ between the root vertex and each vertex on the graph. The edges
+ directions in each path are considered and they are stored as a
+ positive edge (left-to-right) or negative edge (right-to-left).
+
+ The list of paths is used later to generate a list of constraints.
+ */
+void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation)
+{
+ QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue;
+
+ QSet<AnchorData *> visited;
+
+ AnchorVertex *root = graph[orientation].rootVertex();
+
+ graphPaths[orientation].insert(root, GraphPath());
+
+ foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) {
+ queue.enqueue(qMakePair(root, v));
+ }
+
+ while(!queue.isEmpty()) {
+ QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue();
+ AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second);
+
+ if (visited.contains(edge))
+ continue;
+
+ visited.insert(edge);
+ GraphPath current = graphPaths[orientation].value(pair.first);
+
+ if (edge->from == pair.first)
+ current.positives.insert(edge);
+ else
+ current.negatives.insert(edge);
+
+ graphPaths[orientation].insert(pair.second, current);
+
+ foreach (AnchorVertex *v,
+ graph[orientation].adjacentVertices(pair.second)) {
+ queue.enqueue(qMakePair(pair.second, v));
+ }
+ }
+}
+
+/*!
+ \internal
+
+ Each vertex on the graph that has more than one path to it
+ represents a contra int to the sizes of the items in these paths.
+
+ This method walks the list of paths to each vertex, generate
+ the constraints and store them in a list so they can be used later
+ by the Simplex solver.
+*/
+void QGraphicsAnchorLayoutPrivate::constraintsFromPaths(Orientation orientation)
+{
+ foreach (AnchorVertex *vertex, graphPaths[orientation].uniqueKeys())
+ {
+ int valueCount = graphPaths[orientation].count(vertex);
+ if (valueCount == 1)
+ continue;
+
+ QList<GraphPath> pathsToVertex = graphPaths[orientation].values(vertex);
+ for (int i = 1; i < valueCount; ++i) {
+ constraints[orientation] += \
+ pathsToVertex[0].constraint(pathsToVertex[i]);
+ }
+ }
+}
+
+/*!
+ \internal
+
+ Create LP constraints for each anchor based on its minimum and maximum
+ sizes, as specified in its size hints
+*/
+QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHints(
+ const QList<AnchorData *> &anchors)
+{
+ QList<QSimplexConstraint *> anchorConstraints;
+ for (int i = 0; i < anchors.size(); ++i) {
+ QSimplexConstraint *c = new QSimplexConstraint;
+ c->variables.insert(anchors[i], 1.0);
+ c->constant = anchors[i]->minSize;
+ c->ratio = QSimplexConstraint::MoreOrEqual;
+ anchorConstraints += c;
+
+ c = new QSimplexConstraint;
+ c->variables.insert(anchors[i], 1.0);
+ c->constant = anchors[i]->maxSize;
+ c->ratio = QSimplexConstraint::LessOrEqual;
+ anchorConstraints += c;
+ }
+
+ return anchorConstraints;
+}
+
+/*!
+ \internal
+*/
+QList< QList<QSimplexConstraint *> >
+QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation)
+{
+ Q_Q(QGraphicsAnchorLayout);
+
+ // Find layout vertices and edges for the current orientation.
+ AnchorVertex *layoutFirstVertex = \
+ internalVertex(q, pickEdge(Qt::AnchorLeft, orientation));
+
+ AnchorVertex *layoutCentralVertex = \
+ internalVertex(q, pickEdge(Qt::AnchorHorizontalCenter, orientation));
+
+ AnchorVertex *layoutLastVertex = \
+ internalVertex(q, pickEdge(Qt::AnchorRight, orientation));
+
+ Q_ASSERT(layoutFirstVertex && layoutLastVertex);
+
+ AnchorData *edgeL1 = NULL;
+ AnchorData *edgeL2 = NULL;
+
+ // The layout may have a single anchor between Left and Right or two half anchors
+ // passing through the center
+ if (layoutCentralVertex) {
+ edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutCentralVertex);
+ edgeL2 = graph[orientation].edgeData(layoutCentralVertex, layoutLastVertex);
+ } else {
+ edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutLastVertex);
+ }
+
+ QLinkedList<QSimplexConstraint *> remainingConstraints;
+ for (int i = 0; i < constraints[orientation].count(); ++i) {
+ remainingConstraints += constraints[orientation][i];
+ }
+ for (int i = 0; i < itemCenterConstraints[orientation].count(); ++i) {
+ remainingConstraints += itemCenterConstraints[orientation][i];
+ }
+
+ QList<QSimplexConstraint *> trunkConstraints;
+ QSet<QSimplexVariable *> trunkVariables;
+
+ trunkVariables += edgeL1;
+ if (edgeL2)
+ trunkVariables += edgeL2;
+
+ bool dirty;
+ do {
+ dirty = false;
+
+ QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin();
+ while (it != remainingConstraints.end()) {
+ QSimplexConstraint *c = *it;
+ bool match = false;
+
+ // Check if this constraint have some overlap with current
+ // trunk variables...
+ foreach (QSimplexVariable *ad, trunkVariables) {
+ if (c->variables.contains(ad)) {
+ match = true;
+ break;
+ }
+ }
+
+ // If so, we add it to trunk, and erase it from the
+ // remaining constraints.
+ if (match) {
+ trunkConstraints += c;
+ trunkVariables += QSet<QSimplexVariable *>::fromList(c->variables.keys());
+ it = remainingConstraints.erase(it);
+ dirty = true;
+ } else {
+ // Note that we don't erase the constraint if it's not
+ // a match, since in a next iteration of a do-while we
+ // can pass on it again and it will be a match.
+ //
+ // For example: if trunk share a variable with
+ // remainingConstraints[1] and it shares with
+ // remainingConstraints[0], we need a second iteration
+ // of the do-while loop to match both.
+ ++it;
+ }
+ }
+ } while (dirty);
+
+ QList< QList<QSimplexConstraint *> > result;
+ result += trunkConstraints;
+
+ if (!remainingConstraints.isEmpty()) {
+ QList<QSimplexConstraint *> nonTrunkConstraints;
+ QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin();
+ while (it != remainingConstraints.end()) {
+ nonTrunkConstraints += *it;
+ ++it;
+ }
+ result += nonTrunkConstraints;
+ }
+
+ return result;
+}
+
+/*!
+ \internal
+
+ Use the current vertices distance to calculate and set the geometry of
+ each item.
+*/
+void QGraphicsAnchorLayoutPrivate::setItemsGeometries()
+{
+ AnchorVertex *firstH, *secondH, *firstV, *secondV;
+
+ foreach (QGraphicsLayoutItem *item, items) {
+ firstH = internalVertex(item, Qt::AnchorLeft);
+ secondH = internalVertex(item, Qt::AnchorRight);
+ firstV = internalVertex(item, Qt::AnchorTop);
+ secondV = internalVertex(item, Qt::AnchorBottom);
+
+ QPointF topLeft(firstH->distance, firstV->distance);
+ QPointF bottomRight(secondH->distance, secondV->distance);
+
+ item->setGeometry(QRectF(topLeft, bottomRight));
+ }
+}
+
+/*!
+ \internal
+
+ Calculate the position of each vertex based on the paths to each of
+ them as well as the current edges sizes.
+*/
+void QGraphicsAnchorLayoutPrivate::calculateVertexPositions(
+ QGraphicsAnchorLayoutPrivate::Orientation orientation)
+{
+ Q_Q(QGraphicsAnchorLayout);
+ QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue;
+ QSet<AnchorVertex *> visited;
+
+ // Get root vertex
+ AnchorVertex *root = graph[orientation].rootVertex();
+
+ qreal widgetMargin;
+ qreal layoutMargin;
+
+ // Initialize the first vertex
+ if (orientation == Horizontal) {
+ widgetMargin = q->geometry().x();
+ q->getContentsMargins(&layoutMargin, 0, 0, 0);
+ } else {
+ // Root position is equal to the top margin
+ widgetMargin = q->geometry().y();
+ q->getContentsMargins(0, &layoutMargin, 0, 0);
+ }
+ root->distance = widgetMargin + layoutMargin;
+ visited.insert(root);
+
+ // Add initial edges to the queue
+ foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) {
+ queue.enqueue(qMakePair(root, v));
+ }
+
+ // Do initial calculation required by "interpolateEdge()"
+ setupEdgesInterpolation(orientation);
+
+ // Traverse the graph and calculate vertex positions, we need to
+ // visit all pairs since each of them could have a sequential
+ // anchor inside, which hides more vertices.
+ while (!queue.isEmpty()) {
+ QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue();
+ AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second);
+
+ // Both vertices were interpolated, and the anchor itself can't have other
+ // anchors inside (it's not a complex anchor).
+ if (edge->type == AnchorData::Normal && visited.contains(pair.second))
+ continue;
+
+ visited.insert(pair.second);
+ interpolateEdge(pair.first, edge, orientation);
+
+ QList<AnchorVertex *> adjacents = graph[orientation].adjacentVertices(pair.second);
+ for (int i = 0; i < adjacents.count(); ++i) {
+ if (!visited.contains(adjacents.at(i)))
+ queue.enqueue(qMakePair(pair.second, adjacents.at(i)));
+ }
+ }
+}
+
+/*!
+ \internal
+
+ Calculate interpolation parameters based on current Layout Size.
+ Must once before calling "interpolateEdgeSize()" for each edge.
+*/
+void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation(
+ Orientation orientation)
+{
+ Q_Q(QGraphicsAnchorLayout);
+ qreal lower, upper, current;
+
+ if (orientation == Horizontal) {
+ current = q->contentsRect().width();
+ } else {
+ current = q->contentsRect().height();
+ }
+
+ if (current < sizeHints[orientation][Qt::PreferredSize]) {
+ interpolationInterval[orientation] = MinToPreferred;
+ lower = sizeHints[orientation][Qt::MinimumSize];
+ upper = sizeHints[orientation][Qt::PreferredSize];
+ } else {
+ interpolationInterval[orientation] = PreferredToMax;
+ lower = sizeHints[orientation][Qt::PreferredSize];
+ upper = sizeHints[orientation][Qt::MaximumSize];
+ }
+
+ if (upper == lower) {
+ interpolationProgress[orientation] = 0;
+ } else {
+ interpolationProgress[orientation] = (current - lower) / (upper - lower);
+ }
+}
+
+/*!
+ \internal
+
+ Calculate the current Edge size based on the current Layout size and the
+ size the edge is supposed to have when:
+
+ - the layout is at its minimum size.
+ - the layout is at its preferred size.
+ - the layout is at its maximum size.
+
+ These three key values are calculated in advance using linear
+ programming (more expensive) or the simplification algorithm, then
+ subsequential resizes of the parent layout require a simple
+ interpolation.
+
+ If the edge is sequential or parallel, it's possible to have more
+ vertices to be initalized, so it calls specialized functions that
+ will recurse back to interpolateEdge().
+ */
+void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base,
+ AnchorData *edge,
+ Orientation orientation)
+{
+ qreal lower, upper;
+
+ if (interpolationInterval[orientation] == MinToPreferred) {
+ lower = edge->sizeAtMinimum;
+ upper = edge->sizeAtPreferred;
+ } else {
+ lower = edge->sizeAtPreferred;
+ upper = edge->sizeAtMaximum;
+ }
+
+ qreal edgeDistance = (interpolationProgress[orientation] * (upper - lower)) + lower;
+
+ Q_ASSERT(edge->from == base || edge->to == base);
+
+ if (edge->from == base)
+ edge->to->distance = base->distance + edgeDistance;
+ else
+ edge->from->distance = base->distance - edgeDistance;
+
+ // Process child anchors
+ if (edge->type == AnchorData::Sequential)
+ interpolateSequentialEdges(edge->from,
+ static_cast<SequentialAnchorData *>(edge),
+ orientation);
+ else if (edge->type == AnchorData::Parallel)
+ interpolateParallelEdges(edge->from,
+ static_cast<ParallelAnchorData *>(edge),
+ orientation);
+}
+
+void QGraphicsAnchorLayoutPrivate::interpolateParallelEdges(
+ AnchorVertex *base, ParallelAnchorData *data, Orientation orientation)
+{
+ // In parallels the boundary vertices are already calculate, we
+ // just need to look for sequential groups inside, because only
+ // them may have new vertices associated.
+
+ // First edge
+ if (data->firstEdge->type == AnchorData::Sequential)
+ interpolateSequentialEdges(base,
+ static_cast<SequentialAnchorData *>(data->firstEdge),
+ orientation);
+ else if (data->firstEdge->type == AnchorData::Parallel)
+ interpolateParallelEdges(base,
+ static_cast<ParallelAnchorData *>(data->firstEdge),
+ orientation);
+
+ // Second edge
+ if (data->secondEdge->type == AnchorData::Sequential)
+ interpolateSequentialEdges(base,
+ static_cast<SequentialAnchorData *>(data->secondEdge),
+ orientation);
+ else if (data->secondEdge->type == AnchorData::Parallel)
+ interpolateParallelEdges(base,
+ static_cast<ParallelAnchorData *>(data->secondEdge),
+ orientation);
+}
+
+void QGraphicsAnchorLayoutPrivate::interpolateSequentialEdges(
+ AnchorVertex *base, SequentialAnchorData *data, Orientation orientation)
+{
+ AnchorVertex *prev = base;
+
+ // ### I'm not sure whether this assumption is safe. If not,
+ // consider that m_edges.last() could be used instead (so
+ // at(0) would be the one to be treated specially).
+ Q_ASSERT(base == data->m_edges.at(0)->to || base == data->m_edges.at(0)->from);
+
+ // Skip the last
+ for (int i = 0; i < data->m_edges.count() - 1; ++i) {
+ AnchorData *child = data->m_edges.at(i);
+ interpolateEdge(prev, child, orientation);
+ prev = child->to;
+ }
+
+ // Treat the last specially, since we already calculated it's end
+ // vertex, so it's only interesting if it's a complex one
+ if (data->m_edges.last()->type != AnchorData::Normal)
+ interpolateEdge(prev, data->m_edges.last(), orientation);
+}
+
+QPair<qreal, qreal>
+QGraphicsAnchorLayoutPrivate::solveMinMax(QList<QSimplexConstraint *> constraints,
+ GraphPath path)
+{
+ QSimplex simplex;
+ simplex.setConstraints(constraints);
+
+ // Obtain the objective constraint
+ QSimplexConstraint objective;
+ QSet<AnchorData *>::const_iterator iter;
+ for (iter = path.positives.constBegin(); iter != path.positives.constEnd(); ++iter)
+ objective.variables.insert(*iter, 1.0);
+
+ for (iter = path.negatives.constBegin(); iter != path.negatives.constEnd(); ++iter)
+ objective.variables.insert(*iter, -1.0);
+
+ simplex.setObjective(&objective);
+
+ // Calculate minimum values
+ qreal min = simplex.solveMin();
+
+ // Save sizeAtMinimum results
+ QList<QSimplexVariable *> variables = simplex.constraintsVariables();
+ for (int i = 0; i < variables.size(); ++i) {
+ AnchorData *ad = static_cast<AnchorData *>(variables[i]);
+ ad->sizeAtMinimum = ad->result;
+ }
+
+ // Calculate maximum values
+ qreal max = simplex.solveMax();
+
+ // Save sizeAtMaximum results
+ for (int i = 0; i < variables.size(); ++i) {
+ AnchorData *ad = static_cast<AnchorData *>(variables[i]);
+ ad->sizeAtMaximum = ad->result;
+ }
+
+ return qMakePair<qreal, qreal>(min, max);
+}
+
+void QGraphicsAnchorLayoutPrivate::solvePreferred(QList<QSimplexConstraint *> constraints)
+{
+ QList<AnchorData *> variables = getVariables(constraints);
+ QList<QSimplexConstraint *> preferredConstraints;
+ QList<QSimplexVariable *> preferredVariables;
+ QSimplexConstraint objective;
+
+ // Fill the objective coefficients for this variable. In the
+ // end the objective function will be
+ //
+ // z = n * (A_shrink + B_shrink + ...) + (A_grower + B_grower + ...)
+ //
+ // where n is the number of variables that have
+ // slacks. Note that here we use the number of variables
+ // as coefficient, this is to mark the "shrinker slack
+ // variable" less likely to get value than the "grower
+ // slack variable".
+
+ // This will fill the values for the structural constraints
+ // and we now fill the values for the slack constraints (one per variable),
+ // which have this form (the constant A_pref was set when creating the slacks):
+ //
+ // A + A_shrinker - A_grower = A_pref
+ //
+ for (int i = 0; i < variables.size(); ++i) {
+ AnchorData *ad = static_cast<AnchorData *>(variables[i]);
+ if (ad->skipInPreferred)
+ continue;
+
+ QSimplexVariable *grower = new QSimplexVariable;
+ QSimplexVariable *shrinker = new QSimplexVariable;
+ QSimplexConstraint *c = new QSimplexConstraint;
+ c->variables.insert(ad, 1.0);
+ c->variables.insert(shrinker, 1.0);
+ c->variables.insert(grower, -1.0);
+ c->constant = ad->prefSize;
+
+ preferredConstraints += c;
+ preferredVariables += grower;
+ preferredVariables += shrinker;
+
+ objective.variables.insert(grower, 1.0);
+ objective.variables.insert(shrinker, variables.size());
+ }
+
+
+ QSimplex *simplex = new QSimplex;
+ simplex->setConstraints(constraints + preferredConstraints);
+ simplex->setObjective(&objective);
+
+ // Calculate minimum values
+ simplex->solveMin();
+
+ // Save sizeAtPreferred results
+ for (int i = 0; i < variables.size(); ++i) {
+ AnchorData *ad = static_cast<AnchorData *>(variables[i]);
+ ad->sizeAtPreferred = ad->result;
+ }
+
+ // Make sure we delete the simplex solver -before- we delete the
+ // constraints used by it.
+ delete simplex;
+
+ // Delete constraints and variables we created.
+ qDeleteAll(preferredConstraints);
+ qDeleteAll(preferredVariables);
+}
+
+#ifdef QT_DEBUG
+void QGraphicsAnchorLayoutPrivate::dumpGraph()
+{
+ QFile file(QString::fromAscii("anchorlayout.dot"));
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
+ qWarning("Could not write to %s", file.fileName().toLocal8Bit().constData());
+
+ QString str = QString::fromAscii("digraph anchorlayout {\nnode [shape=\"rect\"]\n%1}");
+ QString dotContents = graph[0].serializeToDot();
+ dotContents += graph[1].serializeToDot();
+ file.write(str.arg(dotContents).toLocal8Bit());
+
+ file.close();
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
new file mode 100644
index 0000000..1ce6ef5
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
@@ -0,0 +1,493 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSANCHORLAYOUT_P_H
+#define QGRAPHICSANCHORLAYOUT_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 <QGraphicsWidget>
+
+#include "qgraphicslayout_p.h"
+#include "qgraphicsanchorlayout.h"
+#include "qgraph_p.h"
+#include "qsimplex_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ The public QGraphicsAnchorLayout interface represents an anchorage point
+ as a pair of a <QGraphicsLayoutItem *> and a <Qt::AnchorPoint>.
+
+ Internally though, it has a graph of anchorage points (vertices) and
+ anchors (edges), represented by the AnchorVertex and AnchorData structs
+ respectively.
+*/
+
+/*!
+ \internal
+
+ Represents a vertex (anchorage point) in the internal graph
+*/
+struct AnchorVertex {
+ AnchorVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge)
+ : m_item(item), m_edge(edge) {}
+
+ AnchorVertex()
+ : m_item(0), m_edge(Qt::AnchorPoint(0)) {}
+
+#ifdef QT_DEBUG
+ inline QString toString() const;
+#endif
+ QGraphicsLayoutItem *m_item;
+ Qt::AnchorPoint m_edge;
+
+ // Current distance from this vertex to the layout edge (Left or Top)
+ // Value is calculated from the current anchors sizes.
+ qreal distance;
+};
+
+#ifdef QT_DEBUG
+inline QString AnchorVertex::toString() const
+{
+ if (!this || !m_item) {
+ return QLatin1String("NULL");
+ }
+ QString edge;
+ switch (m_edge) {
+ case Qt::AnchorLeft:
+ edge = QLatin1String("Left");
+ break;
+ case Qt::AnchorHorizontalCenter:
+ edge = QLatin1String("HorizontalCenter");
+ break;
+ case Qt::AnchorRight:
+ edge = QLatin1String("Right");
+ break;
+ case Qt::AnchorTop:
+ edge = QLatin1String("Top");
+ break;
+ case Qt::AnchorVerticalCenter:
+ edge = QLatin1String("VerticalCenter");
+ break;
+ case Qt::AnchorBottom:
+ edge = QLatin1String("Bottom");
+ break;
+ default:
+ edge = QLatin1String("None");
+ break;
+ }
+ QString itemName;
+ if (m_item->isLayout()) {
+ itemName = QLatin1String("layout");
+ } else {
+ if (QGraphicsItem *item = m_item->graphicsItem()) {
+ itemName = item->data(0).toString();
+ }
+ }
+ edge.insert(0, QLatin1String("%1_"));
+ return edge.arg(itemName);
+}
+#endif
+
+/*!
+ \internal
+
+ Represents an edge (anchor) in the internal graph.
+*/
+struct AnchorData : public QSimplexVariable {
+ enum Type {
+ Normal = 0,
+ Sequential,
+ Parallel
+ };
+ AnchorData(qreal minimumSize, qreal preferredSize, qreal maximumSize)
+ : QSimplexVariable(), from(0), to(0),
+ minSize(minimumSize), prefSize(preferredSize),
+ maxSize(maximumSize), sizeAtMinimum(preferredSize),
+ sizeAtPreferred(preferredSize), sizeAtMaximum(preferredSize),
+ skipInPreferred(0), type(Normal), hasSize(true),
+ isLayoutAnchor(false) {}
+
+ AnchorData(qreal size)
+ : QSimplexVariable(), from(0), to(0),
+ minSize(size), prefSize(size), maxSize(size),
+ sizeAtMinimum(size), sizeAtPreferred(size), sizeAtMaximum(size),
+ skipInPreferred(0), type(Normal), hasSize(true),
+ isLayoutAnchor(false) {}
+
+ AnchorData()
+ : QSimplexVariable(), from(0), to(0),
+ minSize(0), prefSize(0), maxSize(0),
+ sizeAtMinimum(0), sizeAtPreferred(0), sizeAtMaximum(0),
+ skipInPreferred(0), type(Normal), hasSize(false),
+ isLayoutAnchor(false) {}
+
+ virtual void updateChildrenSizes() { };
+ virtual void refreshSizeHints(qreal effectiveSpacing);
+
+ virtual ~AnchorData() {}
+
+#ifdef QT_DEBUG
+ void dump(int indent = 2);
+ inline QString toString() const;
+ QString name;
+#endif
+
+ inline void setFixedSize(qreal size)
+ {
+ minSize = size;
+ prefSize = size;
+ maxSize = size;
+ sizeAtMinimum = size;
+ sizeAtPreferred = size;
+ sizeAtMaximum = size;
+ hasSize = true;
+ }
+
+ inline void unsetSize()
+ {
+ hasSize = false;
+ }
+
+ // Anchor is semantically directed
+ AnchorVertex *from;
+ AnchorVertex *to;
+
+ // Size restrictions of this edge. For anchors internal to items, these
+ // values are derived from the respective item size hints. For anchors
+ // that were added by users, these values are equal to the specified anchor
+ // size.
+ qreal minSize;
+ qreal prefSize;
+ qreal maxSize;
+
+ // These attributes define which sizes should that anchor be in when the
+ // layout is at its minimum, preferred or maximum sizes. Values are
+ // calculated by the Simplex solver based on the current layout setup.
+ qreal sizeAtMinimum;
+ qreal sizeAtPreferred;
+ qreal sizeAtMaximum;
+
+ uint skipInPreferred : 1;
+ uint type : 2; // either Normal, Sequential or Parallel
+ uint hasSize : 1; // if false, get size from style.
+ uint isLayoutAnchor : 1; // if this anchor is connected to a layout 'edge'
+protected:
+ AnchorData(Type type, qreal size = 0)
+ : QSimplexVariable(), from(0), to(0),
+ minSize(size), prefSize(size),
+ maxSize(size), sizeAtMinimum(size),
+ sizeAtPreferred(size), sizeAtMaximum(size),
+ skipInPreferred(0), type(type), hasSize(true),
+ isLayoutAnchor(false) {}
+};
+
+#ifdef QT_DEBUG
+inline QString AnchorData::toString() const
+{
+ return QString::fromAscii("Anchor(%1)").arg(name);
+}
+#endif
+
+struct SequentialAnchorData : public AnchorData
+{
+ SequentialAnchorData() : AnchorData(AnchorData::Sequential)
+ {
+#ifdef QT_DEBUG
+ name = QLatin1String("SequentialAnchorData");
+#endif
+ }
+
+ virtual void updateChildrenSizes();
+ virtual void refreshSizeHints(qreal effectiveSpacing);
+
+ void setVertices(const QVector<AnchorVertex*> &vertices)
+ {
+ m_children = vertices;
+#ifdef QT_DEBUG
+ name = QString::fromAscii("%1 -- %2").arg(vertices.first()->toString(), vertices.last()->toString());
+#endif
+ }
+
+ QVector<AnchorVertex*> m_children; // list of vertices in the sequence
+ QVector<AnchorData*> m_edges; // keep the list of edges too.
+};
+
+struct ParallelAnchorData : public AnchorData
+{
+ ParallelAnchorData(AnchorData *first, AnchorData *second)
+ : AnchorData(AnchorData::Parallel),
+ firstEdge(first), secondEdge(second)
+ {
+ // ### Those asserts force that both child anchors have the same direction,
+ // but can't we simplify a pair of anchors in opposite directions?
+ Q_ASSERT(first->from == second->from);
+ Q_ASSERT(first->to == second->to);
+ from = first->from;
+ to = first->to;
+#ifdef QT_DEBUG
+ name = QString::fromAscii("%1 | %2").arg(first->toString(), second->toString());
+#endif
+ }
+
+ virtual void updateChildrenSizes();
+ virtual void refreshSizeHints(qreal effectiveSpacing);
+
+ AnchorData* firstEdge;
+ AnchorData* secondEdge;
+};
+
+/*!
+ \internal
+
+ Representation of a valid path for a given vertex in the graph.
+ In this struct, "positives" is the set of anchors that have been
+ traversed in the forward direction, while "negatives" is the set
+ with the ones walked backwards.
+
+ This paths are compared against each other to produce LP Constraints,
+ the exact order in which the anchors were traversed is not relevant.
+*/
+class GraphPath
+{
+public:
+ GraphPath() {};
+
+ QSimplexConstraint *constraint(const GraphPath &path) const;
+#ifdef QT_DEBUG
+ QString toString() const;
+#endif
+ QSet<AnchorData *> positives;
+ QSet<AnchorData *> negatives;
+};
+
+
+/*!
+ \internal
+
+ QGraphicsAnchorLayout private methods and attributes.
+*/
+class QGraphicsAnchorLayoutPrivate : public QGraphicsLayoutPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsAnchorLayout)
+
+public:
+ // When the layout geometry is different from its Minimum, Preferred
+ // or Maximum values, interpolation is used to calculate the geometries
+ // of the items.
+ //
+ // Interval represents which interpolation interval are we operating in.
+ enum Interval {
+ MinToPreferred = 0,
+ PreferredToMax
+ };
+
+ // Several structures internal to the layout are duplicated to handle
+ // both Horizontal and Vertical restrictions.
+ //
+ // Orientation is used to reference the right structure in each context
+ enum Orientation {
+ Horizontal = 0,
+ Vertical,
+ NOrientations
+ };
+
+ QGraphicsAnchorLayoutPrivate();
+
+ static Qt::AnchorPoint oppositeEdge(
+ Qt::AnchorPoint edge);
+
+ static Orientation edgeOrientation(Qt::AnchorPoint edge);
+
+ static Qt::AnchorPoint pickEdge(Qt::AnchorPoint edge, Orientation orientation)
+ {
+ if (orientation == Vertical && int(edge) <= 2)
+ return (Qt::AnchorPoint)(edge + 3);
+ else if (orientation == Horizontal && int(edge) >= 3) {
+ return (Qt::AnchorPoint)(edge - 3);
+ }
+ return edge;
+ }
+
+ // Init methods
+ void createLayoutEdges();
+ void deleteLayoutEdges();
+ void createItemEdges(QGraphicsLayoutItem *item);
+ void createCenterAnchors(QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge);
+ void removeCenterAnchors(QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge, bool substitute = true);
+ void removeCenterConstraints(QGraphicsLayoutItem *item, Orientation orientation);
+
+ // helper function used by the 4 API functions
+ void anchor(QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ qreal *spacing = 0);
+
+ // Anchor Manipulation methods
+ void addAnchor(QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ AnchorData *data);
+
+ void removeAnchor(QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge);
+
+ bool setAnchorSize(const QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ const qreal *anchorSize);
+
+ bool anchorSize(const QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ const QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ qreal *minSize = 0,
+ qreal *prefSize = 0,
+ qreal *maxSize = 0) const;
+
+ void removeAnchors(QGraphicsLayoutItem *item);
+
+ void removeVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge);
+
+ void correctEdgeDirection(QGraphicsLayoutItem *&firstItem,
+ Qt::AnchorPoint &firstEdge,
+ QGraphicsLayoutItem *&secondItem,
+ Qt::AnchorPoint &secondEdge);
+ // for getting the actual spacing (will query the style if the
+ // spacing is not explicitly set).
+ qreal effectiveSpacing(Orientation orientation) const;
+
+ // Activation methods
+ void simplifyGraph(Orientation orientation);
+ bool simplifyGraphIteration(Orientation orientation);
+ void restoreSimplifiedGraph(Orientation orientation);
+
+ void calculateGraphs();
+ void calculateGraphs(Orientation orientation);
+ void setAnchorSizeHintsFromItems(Orientation orientation);
+ void findPaths(Orientation orientation);
+ void constraintsFromPaths(Orientation orientation);
+ QList<QSimplexConstraint *> constraintsFromSizeHints(const QList<AnchorData *> &anchors);
+ QList<QList<QSimplexConstraint *> > getGraphParts(Orientation orientation);
+
+ inline AnchorVertex *internalVertex(const QPair<QGraphicsLayoutItem*, Qt::AnchorPoint> &itemEdge) const
+ {
+ return m_vertexList.value(itemEdge).first;
+ }
+
+ inline AnchorVertex *internalVertex(const QGraphicsLayoutItem *item, Qt::AnchorPoint edge) const
+ {
+ return internalVertex(qMakePair(const_cast<QGraphicsLayoutItem *>(item), edge));
+ }
+
+ AnchorVertex *addInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge);
+ void removeInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge);
+
+ // Geometry interpolation methods
+ void setItemsGeometries();
+
+ void calculateVertexPositions(Orientation orientation);
+ void setupEdgesInterpolation(Orientation orientation);
+ void interpolateEdge(AnchorVertex *base, AnchorData *edge, Orientation orientation);
+ void interpolateSequentialEdges(AnchorVertex *base, SequentialAnchorData *edge,
+ Orientation orientation);
+ void interpolateParallelEdges(AnchorVertex *base, ParallelAnchorData *edge,
+ Orientation orientation);
+
+ // Linear Programming solver methods
+ QPair<qreal, qreal> solveMinMax(QList<QSimplexConstraint *> constraints,
+ GraphPath path);
+ void solvePreferred(QList<QSimplexConstraint *> constraints);
+
+#ifdef QT_DEBUG
+ void dumpGraph();
+#endif
+
+
+ qreal spacings[NOrientations];
+ // Size hints from simplex engine
+ qreal sizeHints[2][3];
+
+ // Items
+ QVector<QGraphicsLayoutItem *> items;
+
+ // Mapping between high level anchorage points (Item, Edge) to low level
+ // ones (Graph Vertices)
+
+ QHash<QPair<QGraphicsLayoutItem*, Qt::AnchorPoint>, QPair<AnchorVertex *, int> > m_vertexList;
+
+ // Internal graph of anchorage points and anchors, for both orientations
+ Graph<AnchorVertex, AnchorData> graph[2];
+
+ // Graph paths and constraints, for both orientations
+ QMultiHash<AnchorVertex *, GraphPath> graphPaths[2];
+ QList<QSimplexConstraint *> constraints[2];
+ QList<QSimplexConstraint *> itemCenterConstraints[2];
+
+ // The interpolation interval and progress based on the current size
+ // as well as the key values (minimum, preferred and maximum)
+ Interval interpolationInterval[2];
+ qreal interpolationProgress[2];
+
+ // ###
+ bool graphSimplified[2];
+
+ uint calculateGraphCacheDirty : 1;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/graphicsview/qgraphicsgridlayout.cpp b/src/gui/graphicsview/qgraphicsgridlayout.cpp
index 119d097..efa9492 100644
--- a/src/gui/graphicsview/qgraphicsgridlayout.cpp
+++ b/src/gui/graphicsview/qgraphicsgridlayout.cpp
@@ -44,7 +44,7 @@
\brief The QGraphicsGridLayout class provides a grid layout for managing
widgets in Graphics View.
\since 4.4
- \ingroup multimedia
+
\ingroup graphicsview-api
The most common way to use QGraphicsGridLayout is to construct an object
@@ -100,7 +100,7 @@ QLayoutStyleInfo QGraphicsGridLayoutPrivate::styleInfo() const
if (!wid)
wid = new QWidget;
QGraphicsItem *item = parentItem();
- QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : qApp->style();
+ QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style();
return QLayoutStyleInfo(style, wid);
}
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index adb1fc0..89b89a8 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -44,7 +44,7 @@
\brief The QGraphicsItem class is the base class for all graphical
items in a QGraphicsScene.
\since 4.2
- \ingroup multimedia
+
\ingroup graphicsview-api
It provides a light-weight foundation for writing your own custom items.
@@ -91,30 +91,33 @@
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 0
- The boundingRect() function has many different purposes. QGraphicsScene
- bases its item index on boundingRect(), and QGraphicsView uses it both for
- culling invisible items, and for determining the area that needs to be
- recomposed when drawing overlapping items. In addition, QGraphicsItem's
- collision detection mechanisms use boundingRect() to provide an efficient
- cut-off. The fine grained collision algorithm in collidesWithItem() is based
- on calling shape(), which returns an accurate outline of the item's shape
- as a QPainterPath.
-
- QGraphicsScene expects all items boundingRect() and shape() to remain
- unchanged unless it is notified. If you want to change an item's geometry
- in any way, you must first call prepareGeometryChange() to allow
- QGraphicsScene to update its bookkeeping.
+ The boundingRect() function has many different purposes.
+ QGraphicsScene bases its item index on boundingRect(), and
+ QGraphicsView uses it both for culling invisible items, and for
+ determining the area that needs to be recomposed when drawing
+ overlapping items. In addition, QGraphicsItem's collision
+ detection mechanisms use boundingRect() to provide an efficient
+ cut-off. The fine grained collision algorithm in
+ collidesWithItem() is based on calling shape(), which returns an
+ accurate outline of the item's shape as a QPainterPath.
+
+ QGraphicsScene expects all items boundingRect() and shape() to
+ remain unchanged unless it is notified. If you want to change an
+ item's geometry in any way, you must first call
+ prepareGeometryChange() to allow QGraphicsScene to update its
+ bookkeeping.
Collision detection can be done in two ways:
\list 1
- \o Reimplement shape() to return an accurate shape for your item, and rely
- on the default implementation of collidesWithItem() to do shape-shape
- intersection. This can be rather expensive if the shapes are complex.
+ \o Reimplement shape() to return an accurate shape for your item,
+ and rely on the default implementation of collidesWithItem() to do
+ shape-shape intersection. This can be rather expensive if the
+ shapes are complex.
- \o Reimplement collidesWithItem() to provide your own custom item and shape
- collision algorithm.
+ \o Reimplement collidesWithItem() to provide your own custom item
+ and shape collision algorithm.
\endlist
@@ -130,21 +133,43 @@
\img graphicsview-parentchild.png
- QGraphicsItem supports affine transformations in addition to its base
- position, pos(). To change the item's transformation, you can either pass
- a transformation matrix to setTransform(), or call one of the convenience
- functions rotate(), scale(), translate(), or shear(). Item transformations
- accumulate from parent to child, so if both a parent and child item are
- rotated 90 degrees, the child's total transformation will be 180 degrees.
- Similarly, if the item's parent is scaled to 2x its original size, its
- children will also be twice as large. An item's transformation does not
- affect its own local geometry; all geometry functions (e.g., contains(),
- update(), and all the mapping functions) still operate in local
- coordinates. For convenience, QGraphicsItem provides the functions
- sceneTransform(), which returns the item's total transformation matrix
- (including its position and all parents' positions and transformations),
- and scenePos(), which returns its position in scene coordinates. To reset
- an item's matrix, call resetTransform().
+ \section1 Transformation
+
+ QGraphicsItem supports projective transformations in addition to its base
+ position, pos(). There are several ways to change an item's transformation.
+ For simple transformations, you can call either of the convenience
+ functions setRotation() or setScale(), or you can pass any transformation
+ matrix to setTransform(). For advanced transformation control you also have
+ the option of setting several combined transformations by calling
+ setTransformations().
+
+ Item transformations accumulate from parent to child, so if both a parent
+ and child item are rotated 90 degrees, the child's total transformation
+ will be 180 degrees. Similarly, if the item's parent is scaled to 2x its
+ original size, its children will also be twice as large. An item's
+ transformation does not affect its own local geometry; all geometry
+ functions (e.g., contains(), update(), and all the mapping functions) still
+ operate in local coordinates. For convenience, QGraphicsItem provides the
+ functions sceneTransform(), which returns the item's total transformation
+ matrix (including its position and all parents' positions and
+ transformations), and scenePos(), which returns its position in scene
+ coordinates. To reset an item's matrix, call resetTransform().
+
+ Certain transformation operations produce a different outcome depending on
+ the order in which they are applied. For example, if you scale an
+ transform, and then rotate it, you may get a different result than if the
+ transform was rotated first. However, the order you set the transformation
+ properties on QGraphicsItem does not affect the resulting transformation;
+ QGraphicsItem always applies the properties in a fixed, defined order:
+
+ \list
+ \o The item's base transform is applied (transform())
+ \o The item's transformations list is applied in order (transformations())
+ \o The item is rotated relative to its transform origin point (rotation(), transformOriginPoint())
+ \o The item is scaled relative to its transform origin point (scale(), transformOriginPoint())
+ \endlist
+
+ \section1 Painting
The paint() function is called by QGraphicsView to paint the item's
contents. The item has no background or default fill of its own; whatever
@@ -161,6 +186,8 @@
high z-values. Stacking order applies to sibling items; parents are always
drawn before their children.
+ \section1 Events
+
QGraphicsItem receives events from QGraphicsScene through the virtual
function sceneEvent(). This function distributes the most common events
to a set of convenience event handlers:
@@ -186,6 +213,8 @@
by the virtual function sceneEventFilter(). You can remove item
event filters by calling removeSceneEventFilter().
+ \section1 Custom Data
+
Sometimes it's useful to register custom data with an item, be it a custom
item, or a standard item. You can call setData() on any item to store data
in it using a key-value pair (the key being an integer, and the value is a
@@ -274,6 +303,45 @@
this flag, the child will be stacked behind it. This flag is useful for
drop shadow effects and for decoration objects that follow the parent
item's geometry without drawing on top of it.
+
+ \value ItemUsesExtendedStyleOption The item makes use of either the
+ exposedRect or matrix member of the QStyleOptionGraphicsItem. Implementers
+ of QGraphicsItem subclasses should set that flag if this data is required.
+ By default, the exposedRect is initialized to the item's boundingRect and
+ the matrix is untransformed. Enable this flag for more fine-grained values.
+ Use QStyleOptionGraphicsItem::levelOfDetailFromTransform() for a more
+ fine-grained value.
+
+ \value ItemHasNoContents The item does not paint anything (i.e., calling
+ paint() on the item has no effect). You should set this flag on items that
+ do not need to be painted to ensure that Graphics View avoids unnecessary
+ painting preparations. This flag was introduced in Qt 4.6.
+
+ \value ItemSendsGeometryChanges The item enables itemChange()
+ notifications for ItemPositionChange, ItemPositionHasChanged,
+ ItemMatrixChange, ItemTransformChange, and ItemTransformHasChanged. For
+ performance reasons, these notifications are disabled by default. You must
+ enable this flag to receive notifications for position and transform
+ changes. This flag was introduced in Qt 4.6.
+
+ \value ItemAcceptsInputMethod The item supports input methods typically
+ used for Asian languages.
+ This flag was introduced in Qt 4.6.
+
+ \value ItemNegativeZStacksBehindParent The item automatically stacks behind
+ it's parent if it's z-value is negative. This flag enables setZValue() to
+ toggle ItemStacksBehindParent.
+
+ \value ItemAutoDetectsFocusProxy The item will assign any child that
+ gains input focus as its focus proxy. See also focusProxy().
+ This flag was introduced in Qt 4.6.
+
+ \value ItemIsPanel. The item is a panel. A panel provides activation and
+ contained focus handling. Only one panel can be active at a time (see
+ QGraphicsItem::isActive()). When no panel is active, QGraphicsScene
+ activates all non-panel items. Window items (i.e.,
+ QGraphicsItem::isWindow() returns true) are panels. This flag was
+ introduced in Qt 4.6.
*/
/*!
@@ -312,33 +380,37 @@
changing. This value is obsolete; you can use ItemTransformChange instead.
\value ItemPositionChange The item's position changes. This notification
- is only sent when the item's local position changes, relative to its
- parent, has changed (i.e., as a result of calling setPos() or
- moveBy()). The value argument is the new position (i.e., a QPointF). You
- can call pos() to get the original position. Do not call setPos() or
- moveBy() in itemChange() as this notification is delivered; instead, you
- can return the new, adjusted position from itemChange(). After this
- notification, QGraphicsItem immediately sends the ItemPositionHasChanged
- notification if the position changed.
+ is sent if the ItemSendsGeometryChanges flag is enabled, and when the
+ item's local position changes, relative to its parent (i.e., as a result
+ of calling setPos() or moveBy()). The value argument is the new position
+ (i.e., a QPointF). You can call pos() to get the original position. Do
+ not call setPos() or moveBy() in itemChange() as this notification is
+ delivered; instead, you can return the new, adjusted position from
+ itemChange(). After this notification, QGraphicsItem immediately sends the
+ ItemPositionHasChanged notification if the position changed.
\value ItemPositionHasChanged The item's position has changed. This
- notification is only sent after the item's local position, relative to its
- parent, has changed. The value argument is the new position (the same as
- pos()), and QGraphicsItem ignores the return value for this notification
- (i.e., a read-only notification).
+ notification is sent if the ItemSendsGeometryChanges flag is enabled, and
+ after the item's local position, relative to its parent, has changed. The
+ value argument is the new position (the same as pos()), and QGraphicsItem
+ ignores the return value for this notification (i.e., a read-only
+ notification).
\value ItemTransformChange The item's transformation matrix changes. This
- notification is only sent when the item's local transformation matrix
- changes (i.e., as a result of calling setTransform(), or one of the
- convenience transformation functions, such as rotate()). The value
- argument is the new matrix (i.e., a QTransform); to get the old matrix,
- call transform(). Do not call setTransform() or any of the transformation
- convenience functions in itemChange() as this notification is delivered;
- instead, you can return the new matrix from itemChange().
+ notification is send if the ItemSendsGeometryChanges flag is enabled, and
+ when the item's local transformation matrix changes (i.e., as a result of
+ calling setTransform(). The value argument is the new matrix (i.e., a
+ QTransform); to get the old matrix, call transform(). Do not call
+ setTransform() or set any of the transformation properties in itemChange()
+ as this notification is delivered; instead, you can return the new matrix
+ from itemChange(). This notification is not sent if you change the
+ transformation properties.
\value ItemTransformHasChanged The item's transformation matrix has
- changed. This notification is only sent after the item's local
- trasformation matrix has changed. The value argument is the new matrix
+ changed either because setTransform is called, or one of the
+ transformation properties is changed. This notification is sent if the
+ ItemSendsGeometryChanges flag is enabled, and after the item's local
+ transformation matrix has changed. The value argument is the new matrix
(same as transform()), and QGraphicsItem ignores the return value for this
notification (i.e., a read-only notification).
@@ -501,6 +573,7 @@
#include "qgraphicsview.h"
#include "qgraphicswidget.h"
#include "qgraphicsproxywidget.h"
+#include "qgraphicsscenebsptreeindex_p.h"
#include <QtCore/qbitarray.h>
#include <QtCore/qdebug.h>
#include <QtCore/qpoint.h>
@@ -515,28 +588,25 @@
#include <QtGui/qpixmapcache.h>
#include <QtGui/qstyleoption.h>
#include <QtGui/qevent.h>
+#include <QtGui/qinputcontext.h>
+#include <QtGui/qgraphicseffect.h>
#include <private/qgraphicsitem_p.h>
#include <private/qgraphicswidget_p.h>
#include <private/qtextcontrol_p.h>
#include <private/qtextdocumentlayout_p.h>
#include <private/qtextengine_p.h>
+#include <private/qwidget_p.h>
+
+#ifdef Q_WS_X11
+#include <private/qt_x11_p.h>
+#include <private/qpixmap_x11_p.h>
+#endif
#include <math.h>
QT_BEGIN_NAMESPACE
-// QRectF::intersects() returns false always if either the source or target
-// rectangle's width or height are 0. This works around that problem.
-static inline void _q_adjustRect(QRectF *rect)
-{
- Q_ASSERT(rect);
- if (!rect->width())
- rect->adjust(-0.00001, 0, 0.00001, 0);
- if (!rect->height())
- rect->adjust(0, -0.00001, 0, 0.00001);
-}
-
static inline void _q_adjustRect(QRect *rect)
{
Q_ASSERT(rect);
@@ -559,29 +629,6 @@ Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore)
/*!
\internal
- Removes the first instance of \a child from \a children. This is a
- heuristic approach that assumes that it's common to remove items from the
- start or end of the list.
-*/
-static void qt_graphicsitem_removeChild(QGraphicsItem *child, QList<QGraphicsItem *> *children)
-{
- const int n = children->size();
- for (int i = 0; i < (n + 1) / 2; ++i) {
- if (children->at(i) == child) {
- children->removeAt(i);
- return;
- }
- int j = n - i - 1;
- if (children->at(j) == child) {
- children->removeAt(j);
- return;
- }
- }
-}
-
-/*!
- \internal
-
Returns a QPainterPath of \a path when stroked with the \a pen.
Ignoring dash pattern.
*/
@@ -621,6 +668,10 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
// For root items only. This is the item that has either enabled or
// disabled \a childFlag, or has been reparented.
switch (int(childFlag)) {
+ case -2:
+ flag = AncestorFiltersChildEvents;
+ enabled = q->filtersChildEvents();
+ break;
case -1:
flag = AncestorHandlesChildEvents;
enabled = q->handlesChildEvents();
@@ -642,7 +693,8 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
// Inherit the enabled-state from our parents.
if ((parent->d_ptr->ancestorFlags & flag)
|| (int(parent->d_ptr->flags & childFlag) == childFlag)
- || (childFlag == -1 && parent->d_ptr->handlesChildEvents)) {
+ || (childFlag == -1 && parent->d_ptr->handlesChildEvents)
+ || (childFlag == -2 && parent->d_ptr->filtersDescendantEvents)) {
enabled = true;
ancestorFlags |= flag;
} else {
@@ -665,7 +717,9 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
ancestorFlags &= ~flag;
// Don't process children if the item has the main flag set on itself.
- if ((childFlag != -1 && int(flags & childFlag) == childFlag) || (int(childFlag) == -1 && handlesChildEvents))
+ if ((childFlag != -1 && int(flags & childFlag) == childFlag)
+ || (int(childFlag) == -1 && handlesChildEvents)
+ || (int(childFlag) == -2 && filtersDescendantEvents))
return;
}
@@ -757,12 +811,79 @@ QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos,
/*!
\internal
- Returns true if this item or any of its ancestors are untransformable.
+ Combines this item's position and transform onto \a transform.
+
+ If you need to change this function (e.g., adding more transformation
+ modes / options), make sure to change all places marked with COMBINE.
+*/
+void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const
+{
+ // COMBINE
+ if (viewTransform && itemIsUntransformable()) {
+ *x = q_ptr->deviceTransform(*viewTransform);
+ } else {
+ if (transformData)
+ *x *= transformData->computedFullTransform();
+ if (!pos.isNull())
+ *x *= QTransform::fromTranslate(pos.x(), pos.y());
+ }
+}
+
+/*!
+ \internal
+
+ Combines this item's position and transform onto \a transform.
+
+ If you need to change this function (e.g., adding more transformation
+ modes / options), make sure to change QGraphicsItem::deviceTransform() as
+ well.
*/
-bool QGraphicsItemPrivate::itemIsUntransformable() const
+void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const
{
- return (flags & QGraphicsItem::ItemIgnoresTransformations)
- || (ancestorFlags & AncestorIgnoresTransformations);
+ // COMBINE
+ if (viewTransform && itemIsUntransformable()) {
+ *x = q_ptr->deviceTransform(*viewTransform);
+ } else {
+ x->translate(pos.x(), pos.y());
+ if (transformData)
+ *x = transformData->computedFullTransform(x);
+ }
+}
+
+void QGraphicsItemPrivate::updateSceneTransformFromParent()
+{
+ if (parent) {
+ Q_ASSERT(!parent->d_ptr->dirtySceneTransform);
+ if (parent->d_ptr->sceneTransformTranslateOnly) {
+ sceneTransform = QTransform::fromTranslate(parent->d_ptr->sceneTransform.dx() + pos.x(),
+ parent->d_ptr->sceneTransform.dy() + pos.y());
+ } else {
+ sceneTransform = parent->d_ptr->sceneTransform;
+ sceneTransform.translate(pos.x(), pos.y());
+ }
+ if (transformData) {
+ sceneTransform = transformData->computedFullTransform(&sceneTransform);
+ sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
+ } else {
+ sceneTransformTranslateOnly = parent->d_ptr->sceneTransformTranslateOnly;
+ }
+ } else if (!transformData) {
+ sceneTransform = QTransform::fromTranslate(pos.x(), pos.y());
+ sceneTransformTranslateOnly = 1;
+ } else if (transformData->onlyTransform) {
+ sceneTransform = transformData->transform;
+ if (!pos.isNull())
+ sceneTransform *= QTransform::fromTranslate(pos.x(), pos.y());
+ sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
+ } else if (pos.isNull()) {
+ sceneTransform = transformData->computedFullTransform();
+ sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
+ } else {
+ sceneTransform = QTransform::fromTranslate(pos.x(), pos.y());
+ sceneTransform = transformData->computedFullTransform(&sceneTransform);
+ sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
+ }
+ dirtySceneTransform = 0;
}
/*!
@@ -784,11 +905,241 @@ QVariant QGraphicsItemPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query
/*!
\internal
+ Make sure not to trigger any pure virtual function calls (e.g.,
+ prepareGeometryChange) if the item is in its destructor, i.e.
+ inDestructor is 1.
+*/
+void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
+{
+ Q_Q(QGraphicsItem);
+ if (newParent == q) {
+ qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
+ return;
+ }
+ if (newParent == parent)
+ return;
+
+ const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange,
+ qVariantFromValue<QGraphicsItem *>(newParent)));
+ newParent = qVariantValue<QGraphicsItem *>(newParentVariant);
+ if (newParent == parent)
+ return;
+
+ if (scene) {
+ // Deliver the change to the index
+ scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant);
+ }
+
+ QGraphicsItem *lastSubFocusItem = subFocusItem;
+ if (subFocusItem) {
+ // Update the child focus chain; when reparenting an item that has a
+ // focus child, ensure that that focus child clears its focus child
+ // chain from our parents before it's reparented.
+ subFocusItem->clearFocus();
+ }
+
+ // We anticipate geometry changes. If the item is deleted, it will be
+ // removed from the index at a later stage, and the whole scene will be
+ // updated.
+ if (!inDestructor)
+ q_ptr->prepareGeometryChange();
+
+ const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(q));
+ if (parent) {
+ // Remove from current parent
+ parent->d_ptr->removeChild(q);
+ parent->itemChange(QGraphicsItem::ItemChildRemovedChange, thisPointerVariant);
+ }
+
+ // Auto-update focus proxy. Any ancestor that has this as focus proxy
+ //needs to be nulled.
+ QGraphicsItem *p = parent;
+ while (p) {
+ if ((p->d_ptr->flags & QGraphicsItem::ItemAutoDetectsFocusProxy) &&
+ (p->focusProxy() == q)) {
+ p->setFocusProxy(0);
+ }
+ p = p->d_ptr->parent;
+ }
+
+ // Update toplevelitem list. If this item is being deleted, its parent
+ // will be 0 but we don't want to register/unregister it in the TLI list.
+ if (scene && !inDestructor) {
+ if (parent && !newParent) {
+ scene->d_func()->registerTopLevelItem(q);
+ } else if (!parent && newParent) {
+ scene->d_func()->unregisterTopLevelItem(q);
+ }
+ }
+
+ if ((parent = newParent)) {
+ bool implicitUpdate = false;
+ if (parent->d_func()->scene && parent->d_func()->scene != scene) {
+ // Move this item to its new parent's scene
+ parent->d_func()->scene->addItem(q);
+ implicitUpdate = true;
+ } else if (!parent->d_func()->scene && scene) {
+ // Remove this item from its former scene
+ scene->removeItem(q);
+ }
+
+ parent->d_ptr->addChild(q);
+ parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant);
+ if (!implicitUpdate && scene) {
+ scene->d_func()->markDirty(q_ptr, QRect(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/true);
+ }
+
+ // Inherit ancestor flags from the new parent.
+ updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
+ updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
+ updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ // Update item visible / enabled.
+ if (parent->isVisible() != visible) {
+ if (!parent->isVisible() || !explicitlyHidden)
+ setVisibleHelper(parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate);
+ }
+ if (parent->isEnabled() != enabled) {
+ if (!parent->isEnabled() || !explicitlyDisabled)
+ setEnabledHelper(parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate);
+ }
+
+ } else {
+ // Inherit ancestor flags from the new parent.
+ updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
+ updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
+ updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ if (!inDestructor) {
+ // Update item visible / enabled.
+ if (!visible && !explicitlyHidden)
+ setVisibleHelper(true, /* explicit = */ false);
+ if (!enabled && !explicitlyDisabled)
+ setEnabledHelper(true, /* explicit = */ false);
+
+ // If the item is being deleted, the whole scene will be updated.
+ if (scene) {
+ scene->d_func()->markDirty(q_ptr, QRect(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/true);
+ }
+ }
+ }
+
+ // Resolve depth.
+ invalidateDepthRecursively();
+ dirtySceneTransform = 1;
+
+ // Restore the sub focus chain.
+ if (lastSubFocusItem)
+ lastSubFocusItem->d_ptr->setSubFocus();
+
+ // Auto-update focus proxy. The closest parent that detects
+ // focus proxies is updated as the proxy gains or loses focus.
+ p = newParent;
+ while (p) {
+ if (p->d_ptr->flags & QGraphicsItem::ItemAutoDetectsFocusProxy) {
+ p->setFocusProxy(q);
+ break;
+ }
+ p = p->d_ptr->parent;
+ }
+
+ // Deliver post-change notification
+ q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
+
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q)->parentChanged();
+}
+
+/*!
+ \internal
+
+ Returns the bounding rect of this item's children (excluding itself).
+*/
+void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect)
+{
+ for (int i = 0; i < children.size(); ++i) {
+ QGraphicsItem *child = children.at(i);
+ QGraphicsItemPrivate *childd = child->d_ptr.data();
+ bool hasPos = !childd->pos.isNull();
+ if (hasPos || childd->transformData) {
+ // COMBINE
+ QTransform matrix = childd->transformToParent();
+ if (x)
+ matrix *= *x;
+ *rect |= matrix.mapRect(child->boundingRect());
+ if (!childd->children.isEmpty())
+ childd->childrenBoundingRectHelper(&matrix, rect);
+ } else {
+ if (x)
+ *rect |= x->mapRect(child->boundingRect());
+ else
+ *rect |= child->boundingRect();
+ if (!childd->children.isEmpty())
+ childd->childrenBoundingRectHelper(x, rect);
+ }
+ }
+}
+
+void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
+ const QRegion &exposedRegion, bool allItems) const
+{
+ Q_ASSERT(option);
+ Q_Q(const QGraphicsItem);
+
+ // Initialize standard QStyleOption values.
+ const QRectF brect = q->boundingRect();
+ option->state = QStyle::State_None;
+ option->rect = brect.toRect();
+ option->levelOfDetail = 1;
+ option->exposedRect = brect;
+ if (selected)
+ option->state |= QStyle::State_Selected;
+ if (enabled)
+ option->state |= QStyle::State_Enabled;
+ if (q->hasFocus())
+ option->state |= QStyle::State_HasFocus;
+ if (scene) {
+ if (scene->d_func()->hoverItems.contains(q_ptr))
+ option->state |= QStyle::State_MouseOver;
+ if (q == scene->mouseGrabberItem())
+ option->state |= QStyle::State_Sunken;
+ }
+
+ if (!(flags & QGraphicsItem::ItemUsesExtendedStyleOption))
+ return;
+
+ // Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect).
+ option->matrix = worldTransform.toAffine(); //### discards perspective
+
+ if (!allItems) {
+ // Determine the item's exposed area
+ option->exposedRect = QRectF();
+ const QTransform reverseMap = worldTransform.inverted();
+ const QVector<QRect> exposedRects(exposedRegion.rects());
+ for (int i = 0; i < exposedRects.size(); ++i) {
+ option->exposedRect |= reverseMap.mapRect(exposedRects.at(i));
+ if (option->exposedRect.contains(brect))
+ break;
+ }
+ option->exposedRect &= brect;
+ }
+}
+
+/*!
+ \internal
+
Empty all cached pixmaps from the pixmap cache.
*/
void QGraphicsItemCache::purge()
{
QPixmapCache::remove(key);
+ key = QPixmapCache::Key();
QMutableMapIterator<QPaintDevice *, DeviceData> it(deviceData);
while (it.hasNext()) {
DeviceData &data = it.next().value();
@@ -853,31 +1204,38 @@ QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent,
Destroys the QGraphicsItem and all its children. If this item is currently
associated with a scene, the item will be removed from the scene before it
is deleted.
+
+ \note It is more efficient to remove the item from the QGraphicsScene before
+ destroying the item.
*/
QGraphicsItem::~QGraphicsItem()
{
- clearFocus();
+ d_ptr->inDestructor = 1;
d_ptr->removeExtraItemCache();
- QVariant variant;
- foreach (QGraphicsItem *child, d_ptr->children) {
- if (QGraphicsItem *parent = child->parentItem()) {
- qVariantSetValue<QGraphicsItem *>(variant, child);
- parent->itemChange(ItemChildRemovedChange, variant);
- }
- delete child;
+ clearFocus();
+ if (!d_ptr->children.isEmpty()) {
+ QList<QGraphicsItem *> oldChildren = d_ptr->children;
+ qDeleteAll(oldChildren);
+ Q_ASSERT(d_ptr->children.isEmpty());
}
- d_ptr->children.clear();
- if (QGraphicsItem *parent = parentItem()) {
- qVariantSetValue<QGraphicsItem *>(variant, this);
- parent->itemChange(ItemChildRemovedChange, variant);
- qt_graphicsitem_removeChild(this, &parent->d_func()->children);
+ if (d_ptr->scene) {
+ d_ptr->scene->d_func()->removeItemHelper(this);
+ } else {
+ d_ptr->resetFocusProxy();
+ d_ptr->setParentItemHelper(0);
}
- if (d_ptr->scene)
- d_ptr->scene->d_func()->_q_removeItemLater(this);
- delete d_ptr;
+ delete d_ptr->graphicsEffect;
+ if (d_ptr->transformData) {
+ for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
+ QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i);
+ static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0;
+ delete t;
+ }
+ }
+ delete d_ptr->transformData;
qt_dataStore()->data.remove(this);
}
@@ -934,7 +1292,7 @@ void QGraphicsItem::setGroup(QGraphicsItemGroup *group)
Returns a pointer to this item's parent item. If this item does not have a
parent, 0 is returned.
- \sa setParentItem(), children()
+ \sa setParentItem(), childItems()
*/
QGraphicsItem *QGraphicsItem::parentItem() const
{
@@ -957,6 +1315,20 @@ QGraphicsItem *QGraphicsItem::topLevelItem() const
}
/*!
+ \since 4.6
+
+ Returns a pointer to the item's parent, cast to a QGraphicsObject. returns 0 if the parent item
+ is not a QGraphicsObject.
+
+ \sa parentItem(), childItems()
+*/
+QGraphicsObject *QGraphicsItem::parentObject() const
+{
+ QGraphicsItem *p = d_ptr->parent;
+ return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : 0;
+}
+
+/*!
\since 4.4
Returns a pointer to the item's parent widget. The item's parent widget is
@@ -998,118 +1370,64 @@ QGraphicsWidget *QGraphicsItem::topLevelWidget() const
*/
QGraphicsWidget *QGraphicsItem::window() const
{
- if (isWidget() && static_cast<const QGraphicsWidget *>(this)->isWindow())
- return static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this));
- if (QGraphicsWidget *parent = parentWidget())
- return parent->window();
+ QGraphicsItem *p = panel();
+ if (p && p->isWindow())
+ return static_cast<QGraphicsWidget *>(p);
return 0;
}
/*!
- Sets this item's parent item to \a parent. If this item already has a
- parent, it is first removed from the previous parent. If \a parent is 0,
- this item will become a top-level item.
+ \since 4.6
- Note that this implicitly adds this graphics item to the scene of
- the parent. You should not \l{QGraphicsScene::addItem()}{add} the
- item to the scene yourself.
+ Returns the item's panel, or 0 if this item does not have a panel. If the
+ item is a panel, it will return itself. Otherwise it will return the
+ closest ancestor that is a panel.
- \sa parentItem(), children()
+ \sa isPanel(), ItemIsPanel
*/
-void QGraphicsItem::setParentItem(QGraphicsItem *parent)
+QGraphicsItem *QGraphicsItem::panel() const
{
- if (parent == this) {
- qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
- return;
- }
- if (parent == d_ptr->parent)
- return;
- const QVariant newParentVariant(itemChange(ItemParentChange, qVariantFromValue<QGraphicsItem *>(parent)));
- parent = qVariantValue<QGraphicsItem *>(newParentVariant);
- if (parent == d_ptr->parent)
- return;
-
- if (QGraphicsWidget *w = d_ptr->isWidget ? static_cast<QGraphicsWidget *>(this) : parentWidget()) {
- // Update the child focus chain; when reparenting a widget that has a
- // focus child, ensure that that focus child clears its focus child
- // chain from our parents before it's reparented.
- if (QGraphicsWidget *focusChild = w->focusWidget())
- focusChild->clearFocus();
- }
-
- // We anticipate geometry changes
- prepareGeometryChange();
-
- const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this));
- if (d_ptr->parent) {
- // Remove from current parent
- qt_graphicsitem_removeChild(this, &d_ptr->parent->d_func()->children);
- d_ptr->parent->itemChange(ItemChildRemovedChange, thisPointerVariant);
- }
-
- if ((d_ptr->parent = parent)) {
- bool implicitUpdate = false;
- if (parent->d_func()->scene && parent->d_func()->scene != d_ptr->scene) {
- // Move this item to its new parent's scene
- parent->d_func()->scene->addItem(this);
- implicitUpdate = true;
- } else if (!parent->d_func()->scene && d_ptr->scene) {
- // Remove this item from its former scene
- d_ptr->scene->removeItem(this);
- }
-
- d_ptr->parent->d_func()->children << this;
- d_ptr->parent->itemChange(ItemChildAddedChange, thisPointerVariant);
- if (!implicitUpdate)
- d_ptr->updateHelper(QRectF(), false, true);
-
- // Inherit ancestor flags from the new parent.
- d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
- d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
- d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
-
- // Update item visible / enabled.
- if (d_ptr->parent->isVisible() != d_ptr->visible) {
- if (!d_ptr->parent->isVisible() || !d_ptr->explicitlyHidden)
- d_ptr->setVisibleHelper(d_ptr->parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate);
- }
- if (d_ptr->parent->isEnabled() != d_ptr->enabled) {
- if (!d_ptr->parent->isEnabled() || !d_ptr->explicitlyDisabled)
- d_ptr->setEnabledHelper(d_ptr->parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate);
- }
-
- } else {
- // Inherit ancestor flags from the new parent.
- d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
- d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
- d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
+ if (d_ptr->flags & ItemIsPanel)
+ return const_cast<QGraphicsItem *>(this);
+ return d_ptr->parent ? d_ptr->parent->panel() : 0;
+}
- // Update item visible / enabled.
- if (!d_ptr->visible && !d_ptr->explicitlyHidden)
- d_ptr->setVisibleHelper(true, /* explicit = */ false);
- if (!d_ptr->enabled && !d_ptr->explicitlyDisabled)
- d_ptr->setEnabledHelper(true, /* explicit = */ false);
+/*!
+ \since 4.6
- d_ptr->updateHelper(QRectF(), false, true);
- }
+ Return the graphics item cast to a QGraphicsObject, if the class is actually a
+ graphics object, 0 otherwise.
+*/
+QGraphicsObject *QGraphicsItem::toGraphicsObject()
+{
+ return d_ptr->isObject ? static_cast<QGraphicsObject *>(this) : 0;
+}
- if (d_ptr->scene) {
- // Invalidate any sort caching; arrival of a new item means we need to
- // resort.
- d_ptr->scene->d_func()->invalidateSortCache();
- }
+/*!
+ \since 4.6
- // Resolve opacity.
- d_ptr->updateEffectiveOpacity();
+ Return the graphics item cast to a QGraphicsObject, if the class is actually a
+ graphics object, 0 otherwise.
+*/
+const QGraphicsObject *QGraphicsItem::toGraphicsObject() const
+{
+ return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : 0;
+}
- // Resolve depth.
- d_ptr->resolveDepth(parent ? parent->d_ptr->depth : -1);
+/*!
+ Sets this item's parent item to \a parent. If this item already has a
+ parent, it is first removed from the previous parent. If \a parent is 0,
+ this item will become a top-level item.
- // Invalidate transform cache.
- d_ptr->invalidateSceneTransformCache();
+ Note that this implicitly adds this graphics item to the scene of
+ the parent. You should not \l{QGraphicsScene::addItem()}{add} the
+ item to the scene yourself.
- // Deliver post-change notification
- itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
+ \sa parentItem(), childItems()
+*/
+void QGraphicsItem::setParentItem(QGraphicsItem *parent)
+{
+ d_ptr->setParentItemHelper(parent);
}
/*!
@@ -1160,6 +1478,17 @@ bool QGraphicsItem::isWindow() const
}
/*!
+ \since 4.6
+ Returns true if the item is a panel; otherwise returns false.
+
+ \sa QGraphicsItem::panel(), ItemIsPanel
+*/
+bool QGraphicsItem::isPanel() const
+{
+ return d_ptr->flags & ItemIsPanel;
+}
+
+/*!
Returns this item's flags. The flags describe what configurable features
of the item are enabled and not. For example, if the flags include
ItemIsFocusable, the item can accept input focus.
@@ -1214,24 +1543,31 @@ static void _q_qgraphicsItemSetFlag(QGraphicsItem *item, QGraphicsItem::Graphics
item was selected, and \a flags does not enabled ItemIsSelectable, the
item is automatically unselected.
- By default, no flags are enabled.
+ By default, no flags are enabled. (QGraphicsWidget enables the
+ ItemSendsGeometryChanges flag by default in order to track position
+ changes.)
\sa flags(), setFlag()
*/
void QGraphicsItem::setFlags(GraphicsItemFlags flags)
{
+ if (isWindow())
+ flags |= ItemIsPanel;
+
// Notify change and check for adjustment.
if (quint32(d_ptr->flags) == quint32(flags))
return;
flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt());
if (quint32(d_ptr->flags) == quint32(flags))
return;
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags));
// Flags that alter the geometry of the item (or its children).
const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations);
bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
if (fullUpdate)
- d_ptr->fullUpdateHelper(false, true);
+ d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
// Keep the old flags to compare the diff.
GraphicsItemFlags oldFlags = this->flags();
@@ -1239,11 +1575,6 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
// Update flags.
d_ptr->flags = flags;
- // Reresolve effective opacity if the opacity flags change.
- static const quint32 opacityFlagsMask = ItemIgnoresParentOpacity | ItemDoesntPropagateOpacityToChildren;
- if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask))
- d_ptr->updateEffectiveOpacity();
-
if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
// Clear focus on the item if it has focus when the focusable flag
// is unset.
@@ -1271,8 +1602,30 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
}
- // ### Why updateHelper?
- d_ptr->updateHelper(QRectF(), false, true);
+ if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) {
+ // Ensure child item sorting is up to date when toggling this flag.
+ if (d_ptr->parent)
+ d_ptr->parent->d_ptr->needSortChildren = 1;
+ else if (d_ptr->scene)
+ d_ptr->scene->d_func()->needSortTopLevelItems = 1;
+ }
+
+ if ((flags & ItemAcceptsInputMethod) != (oldFlags & ItemAcceptsInputMethod)) {
+ // Update input method sensitivity in any views.
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
+ }
+
+ if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) {
+ // Update stack-behind.
+ setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0));
+ }
+
+ if (d_ptr->scene) {
+ d_ptr->scene->d_func()->markDirty(this, QRectF(),
+ /*invalidateChildren=*/true,
+ /*maybeDirtyClipPath*/true);
+ }
// Notify change.
itemChange(ItemFlagsHaveChanged, quint32(flags));
@@ -1335,12 +1688,6 @@ void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize)
cache->purge();
if (mode == ItemCoordinateCache) {
- if (cache->key.isEmpty()) {
- // Generate new simple pixmap cache key.
- QString tmp;
- tmp.sprintf("qgv-%p", this);
- cache->key = tmp;
- }
if (lastMode == mode && cache->fixedSize == logicalCacheSize)
noVisualChange = true;
cache->fixedSize = logicalCacheSize;
@@ -1418,7 +1765,9 @@ void QGraphicsItem::setCursor(const QCursor &cursor)
d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue<QCursor>(cursorVariant));
d_ptr->hasCursor = 1;
if (d_ptr->scene) {
+ d_ptr->scene->d_func()->allItemsUseDefaultCursor = false;
foreach (QGraphicsView *view, d_ptr->scene->views()) {
+ view->viewport()->setMouseTracking(true);
// Note: Some of this logic is duplicated in QGraphicsView's mouse events.
if (view->underMouse()) {
foreach (QGraphicsItem *itemUnderCursor, view->items(view->mapFromGlobal(QCursor::pos()))) {
@@ -1542,7 +1891,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
if (c)
c->purge();
- updateHelper(QRectF(), /* force = */ true);
+ if (scene) {
+ scene->d_func()->markDirty(q_ptr, QRectF(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/false,
+ /*force=*/true);
+ }
}
// Certain properties are dropped as an item becomes invisible.
@@ -1554,16 +1908,16 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
q->ungrabKeyboard();
}
if (q_ptr->hasFocus() && scene) {
- // Hiding the closest non-window ancestor of the focus item
+ // Hiding the closest non-panel ancestor of the focus item
QGraphicsItem *focusItem = scene->focusItem();
bool clear = true;
- if (isWidget && !focusItem->isWindow()) {
+ if (isWidget && !focusItem->isPanel()) {
do {
if (focusItem == q_ptr) {
clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
break;
}
- } while ((focusItem = focusItem->parentWidget()) && !focusItem->isWindow());
+ } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
}
if (clear)
q_ptr->clearFocus();
@@ -1571,6 +1925,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
if (q_ptr->isSelected())
q_ptr->setSelected(false);
} else {
+ geometryChanged = 1;
+ paintedViewBoundingRectsNeedRepaint = 1;
if (isWidget && scene) {
QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
if (widget->windowType() == Qt::Popup)
@@ -1595,6 +1951,9 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
// Deliver post-change notification.
q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant);
+
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->visibleChanged();
}
/*!
@@ -1680,17 +2039,17 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo
if (scene && scene->mouseGrabberItem() == q_ptr)
q_ptr->ungrabMouse();
if (q_ptr->hasFocus()) {
- // Disabling the closest non-window ancestor of the focus item
+ // Disabling the closest non-panel ancestor of the focus item
// causes focus to pop to the next item, otherwise it's cleared.
QGraphicsItem *focusItem = scene->focusItem();
bool clear = true;
- if (isWidget && !focusItem->isWindow() && q_ptr->isAncestorOf(focusItem)) {
+ if (isWidget && !focusItem->isPanel() && q_ptr->isAncestorOf(focusItem)) {
do {
if (focusItem == q_ptr) {
clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
break;
}
- } while ((focusItem = focusItem->parentWidget()) && !focusItem->isWindow());
+ } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
}
if (clear)
q_ptr->clearFocus();
@@ -1706,7 +2065,7 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo
// Schedule redraw.
if (update)
- updateHelper();
+ q_ptr->update();
foreach (QGraphicsItem *child, children) {
if (!newEnabled || !child->d_ptr->explicitlyDisabled)
@@ -1715,6 +2074,9 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo
// Deliver post-change notification.
q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant);
+
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->enabledChanged();
}
/*!
@@ -1807,8 +2169,7 @@ void QGraphicsItem::setSelected(bool selected)
return;
d_ptr->selected = newSelected;
- d_ptr->updateHelper();
-
+ update();
if (d_ptr->scene) {
QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func();
if (selected) {
@@ -1845,12 +2206,7 @@ void QGraphicsItem::setSelected(bool selected)
*/
qreal QGraphicsItem::opacity() const
{
- if (d_ptr->hasOpacity) {
- QVariant o = d_ptr->extra(QGraphicsItemPrivate::ExtraOpacity);
- if (!o.isNull())
- return o.toDouble();
- }
- return qreal(1.0);
+ return d_ptr->opacity;
}
/*!
@@ -1866,11 +2222,7 @@ qreal QGraphicsItem::opacity() const
*/
qreal QGraphicsItem::effectiveOpacity() const
{
- if (!d_ptr->hasEffectiveOpacity)
- return qreal(1.0);
-
- QVariant effectiveOpacity = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectiveOpacity);
- return effectiveOpacity.isNull() ? qreal(1.0) : qreal(effectiveOpacity.toDouble());
+ return d_ptr->effectiveOpacity();
}
/*!
@@ -1898,37 +2250,142 @@ qreal QGraphicsItem::effectiveOpacity() const
void QGraphicsItem::setOpacity(qreal opacity)
{
// Notify change.
- const QVariant newOpacityVariant(itemChange(ItemOpacityChange, double(opacity)));
- qreal newOpacity = newOpacityVariant.toDouble();
+ const QVariant newOpacityVariant(itemChange(ItemOpacityChange, opacity));
- // Normalize.
- newOpacity = qBound<qreal>(0.0, newOpacity, 1.0);
+ // Normalized opacity
+ qreal newOpacity = qBound(qreal(0), newOpacityVariant.toReal(), qreal(1));
// No change? Done.
- if (qFuzzyCompare(newOpacity, this->opacity()))
+ if (newOpacity == d_ptr->opacity)
return;
- // Assign local opacity.
- if (qFuzzyCompare(newOpacity, qreal(1.0))) {
- // Opaque, unset opacity.
- d_ptr->hasOpacity = 0;
- d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraOpacity);
+ d_ptr->opacity = newOpacity;
+
+ // Notify change.
+ itemChange(ItemOpacityHasChanged, newOpacityVariant);
+
+ // Update.
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this, QRectF(),
+ /*invalidateChildren=*/true,
+ /*maybeDirtyClipPath=*/false,
+ /*force=*/false,
+ /*ignoreOpacity=*/true);
+
+ if (d_ptr->isObject)
+ emit static_cast<QGraphicsObject *>(this)->opacityChanged();
+}
+
+/*!
+ Returns a pointer to this item's effect if it has one; otherwise 0.
+
+ \since 4.6
+*/
+QGraphicsEffect *QGraphicsItem::graphicsEffect() const
+{
+ return d_ptr->graphicsEffect;
+}
+
+/*!
+ Sets \a effect as the item's effect. If there already is an effect installed
+ on this item, QGraphicsItem will delete the existing effect before installing
+ the new \a effect.
+
+ If \a effect is the installed on a different item, setGraphicsEffect() will remove
+ the effect from the item and install it on this item.
+
+ \note This function will apply the effect on itself and all its children.
+
+ \since 4.6
+*/
+void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
+{
+ if (d_ptr->graphicsEffect == effect)
+ return;
+
+ if (d_ptr->graphicsEffect && effect) {
+ delete d_ptr->graphicsEffect;
+ d_ptr->graphicsEffect = 0;
+ }
+
+ if (!effect) {
+ // Unset current effect.
+ QGraphicsEffectPrivate *oldEffectPrivate = d_ptr->graphicsEffect->d_func();
+ d_ptr->graphicsEffect = 0;
+ if (oldEffectPrivate) {
+ oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source.
+ if (d_ptr->scene) // Update the views directly.
+ d_ptr->scene->d_func()->markDirty(this, QRectF(), false, false, false, false, true);
+ }
} else {
- d_ptr->hasOpacity = 1;
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraOpacity, double(newOpacity));
+ // Set new effect.
+ QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this);
+ QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
+ d_ptr->graphicsEffect = effect;
+ effect->d_func()->setGraphicsEffectSource(source);
}
- // Resolve effective opacity.
- if (QGraphicsItem *p = d_ptr->parent)
- d_ptr->resolveEffectiveOpacity(p->effectiveOpacity());
- else
- d_ptr->resolveEffectiveOpacity(1.0);
+ prepareGeometryChange();
+}
- // Notify change.
- itemChange(ItemOpacityHasChanged, newOpacity);
+/*!
+ \internal
+ \since 4.6
+ Returns the effective bounding rect of the item.
+ If the item has no effect, this is the same as the item's bounding rect.
+ If the item has an effect, the effective rect can be larger than the item's
+ bouding rect, depending on the effect.
- // Update.
- d_ptr->fullUpdateHelper(/*childrenOnly=*/false, /*maybeDirtyClipPath=*/false, /*ignoreOpacity=*/true);
+ \sa boundingRect()
+*/
+QRectF QGraphicsItemPrivate::effectiveBoundingRect() const
+{
+ QGraphicsEffect *effect = graphicsEffect;
+ QRectF brect = effect && effect->isEnabled() ? effect->boundingRect() : q_ptr->boundingRect();
+ if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
+ return brect;
+
+ const QGraphicsItem *effectParent = parent;
+ while (effectParent) {
+ effect = effectParent->d_ptr->graphicsEffect;
+ if (effect && effect->isEnabled())
+ brect = effect->boundingRectFor(brect);
+ if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
+ return brect;
+ effectParent = effectParent->d_ptr->parent;
+ }
+
+ return brect;
+}
+
+/*!
+ \internal
+ \since 4.6
+ Returns the effective bounding rect of this item in scene coordinates,
+ by combining sceneTransform() with boundingRect(), taking into account
+ the effect that the item might have.
+
+ If the item has no effect, this is the same as sceneBoundingRect().
+
+ \sa effectiveBoundingRect(), sceneBoundingRect()
+*/
+QRectF QGraphicsItemPrivate::sceneEffectiveBoundingRect() const
+{
+ // Find translate-only offset
+ // COMBINE
+ QPointF offset;
+ const QGraphicsItem *parentItem = q_ptr;
+ const QGraphicsItemPrivate *itemd;
+ do {
+ itemd = parentItem->d_ptr.data();
+ if (itemd->transformData)
+ break;
+ offset += itemd->pos;
+ } while ((parentItem = itemd->parent));
+
+ QRectF br = effectiveBoundingRect();
+ br.translate(offset);
+ return !parentItem ? br : parentItem->sceneTransform().mapRect(br);
}
/*!
@@ -2041,10 +2498,10 @@ bool QGraphicsItem::acceptsHoverEvents() const
stays "hovered" until the cursor leaves its area, including its
children's areas.
- If a parent item handles child events (setHandlesChildEvents()), it will
- receive hover move, drag move, and drop events as the cursor passes
- through its children, but it does not receive hover enter and hover leave,
- nor drag enter and drag leave events on behalf of its children.
+ If a parent item handles child events, it will receive hover move,
+ drag move, and drop events as the cursor passes through its
+ children, but it does not receive hover enter and hover leave, nor
+ drag enter and drag leave events on behalf of its children.
A QGraphicsWidget with window decorations will accept hover events
regardless of the value of acceptHoverEvents().
@@ -2054,7 +2511,13 @@ bool QGraphicsItem::acceptsHoverEvents() const
*/
void QGraphicsItem::setAcceptHoverEvents(bool enabled)
{
+ if (d_ptr->acceptsHover == quint32(enabled))
+ return;
d_ptr->acceptsHover = quint32(enabled);
+ if (d_ptr->acceptsHover && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreHoverEvents) {
+ d_ptr->scene->d_func()->allItemsIgnoreHoverEvents = false;
+ d_ptr->scene->d_func()->enableMouseTrackingOnViews();
+ }
}
/*!
@@ -2064,10 +2527,78 @@ void QGraphicsItem::setAcceptHoverEvents(bool enabled)
*/
void QGraphicsItem::setAcceptsHoverEvents(bool enabled)
{
- d_ptr->acceptsHover = quint32(enabled);
+ setAcceptHoverEvents(enabled);
+}
+
+/*! \since 4.6
+
+ Returns true if an item accepts \l{QTouchEvent}{touch events};
+ otherwise, returns false. By default, items do not accept touch events.
+
+ \sa setAcceptTouchEvents()
+*/
+bool QGraphicsItem::acceptTouchEvents() const
+{
+ return d_ptr->acceptTouchEvents;
+}
+
+/*!
+ \since 4.6
+
+ If \a enabled is true, this item will accept \l{QTouchEvent}{touch events};
+ otherwise, it will ignore them. By default, items do not accept
+ touch events.
+*/
+void QGraphicsItem::setAcceptTouchEvents(bool enabled)
+{
+ if (d_ptr->acceptTouchEvents == quint32(enabled))
+ return;
+ d_ptr->acceptTouchEvents = quint32(enabled);
+ if (d_ptr->acceptTouchEvents && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreTouchEvents) {
+ d_ptr->scene->d_func()->allItemsIgnoreTouchEvents = false;
+ d_ptr->scene->d_func()->enableTouchEventsOnViews();
+ }
+}
+
+/*!
+ \since 4.6
+
+ Returns true if this item filters child events (i.e., all events
+ intended for any of its children are instead sent to this item);
+ otherwise, false is returned.
+
+ The default value is false; child events are not filtered.
+
+ \sa setFiltersChildEvents()
+*/
+bool QGraphicsItem::filtersChildEvents() const
+{
+ return d_ptr->filtersDescendantEvents;
+}
+
+/*!
+ \since 4.6
+
+ If \a enabled is true, this item is set to filter all events for
+ all its children (i.e., all events intented for any of its
+ children are instead sent to this item); otherwise, if \a enabled
+ is false, this item will only handle its own events. The default
+ value is false.
+
+ \sa filtersChildEvents()
+*/
+void QGraphicsItem::setFiltersChildEvents(bool enabled)
+{
+ if (d_ptr->filtersDescendantEvents == enabled)
+ return;
+
+ d_ptr->filtersDescendantEvents = enabled;
+ d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
}
/*!
+ \obsolete
+
Returns true if this item handles child events (i.e., all events
intended for any of its children are instead sent to this item);
otherwise, false is returned.
@@ -2088,6 +2619,8 @@ bool QGraphicsItem::handlesChildEvents() const
}
/*!
+ \obsolete
+
If \a enabled is true, this item is set to handle all events for
all its children (i.e., all events intented for any of its
children are instead sent to this item); otherwise, if \a enabled
@@ -2113,75 +2646,188 @@ void QGraphicsItem::setHandlesChildEvents(bool enabled)
d_ptr->handlesChildEvents = enabled;
d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
}
+/*!
+ \since 4.6
+ Returns true if this item is active; otherwise returns false.
+
+ An item can only be active if the scene is active. An item is active
+ if it is, or is a descendent of, an active panel. Items in non-active
+ panels are not active.
+
+ Items that are not part of a panel follow scene activation when the
+ scene has no active panel.
+
+ Only active items can gain input focus.
+
+ \sa QGraphicsScene::isActive(), QGraphicsScene::activePanel(), panel(), isPanel()
+*/
+bool QGraphicsItem::isActive() const
+{
+ if (!d_ptr->scene || !d_ptr->scene->isActive())
+ return false;
+ return panel() == d_ptr->scene->activePanel();
+}
/*!
- Returns true if this item has keyboard input focus; otherwise, returns
- false.
+ Returns true if this item is active, and it or its \l{focusProxy()}{focus
+ proxy} has keyboard input focus; otherwise, returns false.
- \sa QGraphicsScene::focusItem(), setFocus(), QGraphicsScene::setFocusItem()
+ \sa focusItem(), setFocus(), QGraphicsScene::setFocusItem(), isActive()
*/
bool QGraphicsItem::hasFocus() const
{
+ if (d_ptr->focusProxy)
+ return d_ptr->focusProxy->hasFocus();
return (d_ptr->scene && d_ptr->scene->focusItem() == this);
}
/*!
Gives keyboard input focus to this item. The \a focusReason argument will
- be passed into any focus event generated by this function; it is used to
- give an explanation of what caused the item to get focus.
+ be passed into any \l{QFocusEvent}{focus event} generated by this function;
+ it is used to give an explanation of what caused the item to get focus.
- Only items that set the ItemIsFocusable flag can accept keyboard focus.
+ Only enabled items that set the ItemIsFocusable flag can accept keyboard
+ focus.
- If this item is not visible (i.e., isVisible() returns false), not
- enabled, not associated with a scene, or if it already has input focus,
- this function will do nothing.
+ If this item is not visible, not active, or not associated with a scene,
+ it will not gain immediate input focus. However, it will be registered as
+ the preferred focus item for its subtree of items, should it later become
+ visible.
- As a result of calling this function, this item will receive a focus in
- event with \a focusReason. If another item already has focus, that item
- will first receive a focus out event indicating that it has lost input
- focus.
+ As a result of calling this function, this item will receive a
+ \l{focusInEvent()}{focus in event} with \a focusReason. If another item
+ already has focus, that item will first receive a \l{focusOutEvent()}
+ {focus out event} indicating that it has lost input focus.
- \sa clearFocus(), hasFocus()
+ \sa clearFocus(), hasFocus(), focusItem(), focusProxy()
*/
void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
{
- if (!d_ptr->scene || !isEnabled() || hasFocus() || !(d_ptr->flags & ItemIsFocusable))
+ // Disabled / unfocusable items cannot accept focus.
+ if (!isEnabled() || !(d_ptr->flags & QGraphicsItem::ItemIsFocusable))
+ return;
+
+ // Find focus proxy.
+ QGraphicsItem *f = this;
+ while (f->d_ptr->focusProxy)
+ f = f->d_ptr->focusProxy;
+
+ // Return if it already has focus.
+ if (d_ptr->scene && d_ptr->scene->focusItem() == f)
return;
- if (isVisible()) {
- // Visible items immediately gain focus from scene.
- d_ptr->scene->setFocusItem(this, focusReason);
- } else if (d_ptr->isWidget) {
- // Just set up subfocus.
- static_cast<QGraphicsWidget *>(this)->d_func()->setFocusWidget();
+
+ // Update the child focus chain.
+ d_ptr->setSubFocus();
+
+ // Update the scene's focus item.
+ if (d_ptr->scene) {
+ QGraphicsItem *p = panel();
+ if (!p || p->isActive()) {
+ // Visible items immediately gain focus from scene.
+ d_ptr->scene->d_func()->setFocusItemHelper(f, focusReason);
+ }
}
}
/*!
Takes keyboard input focus from the item.
- If it has focus, a focus out event is sent to this item to tell it that it
- is about to lose the focus.
+ If it has focus, a \l{focusOutEvent()}{focus out event} is sent to this
+ item to tell it that it is about to lose the focus.
Only items that set the ItemIsFocusable flag, or widgets that set an
appropriate focus policy, can accept keyboard focus.
- \sa setFocus(), QGraphicsWidget::focusPolicy
+ \sa setFocus(), hasFocus(), QGraphicsWidget::focusPolicy
*/
void QGraphicsItem::clearFocus()
{
if (!d_ptr->scene)
return;
- if (d_ptr->isWidget) {
- // Invisible widget items with focus must explicitly clear subfocus.
- static_cast<QGraphicsWidget *>(this)->d_func()->clearFocusWidget();
- }
- if (d_ptr->scene->focusItem() == this) {
+ // Invisible items with focus must explicitly clear subfocus.
+ d_ptr->clearSubFocus();
+ if (hasFocus()) {
// If this item has the scene's input focus, clear it.
d_ptr->scene->setFocusItem(0);
}
}
/*!
+ \since 4.6
+
+ Returns this item's focus proxy, or 0 if this item has no
+ focus proxy.
+
+ \sa setFocusProxy(), ItemAutoDetectsFocusProxy, setFocus(), hasFocus()
+*/
+QGraphicsItem *QGraphicsItem::focusProxy() const
+{
+ return d_ptr->focusProxy;
+}
+
+/*!
+ \since 4.6
+
+ Sets the item's focus proxy to \a item.
+
+ If an item has a focus proxy, the focus proxy will receive
+ input focus when the item gains input focus. The item itself
+ will still have focus (i.e., hasFocus() will return true),
+ but only the focus proxy will receive the keyboard input.
+
+ A focus proxy can itself have a focus proxy, and so on. In
+ such case, keyboard input will be handled by the outermost
+ focus proxy.
+
+ The focus proxy \a item must belong to the same scene as
+ this item.
+
+ \sa focusProxy(), ItemAutoDetectsFocusProxy, setFocus(), hasFocus()
+*/
+void QGraphicsItem::setFocusProxy(QGraphicsItem *item)
+{
+ if (item == d_ptr->focusProxy)
+ return;
+ if (item == this) {
+ qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
+ return;
+ }
+ if (item) {
+ if (item->d_ptr->scene != d_ptr->scene) {
+ qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
+ return;
+ }
+ for (QGraphicsItem *f = item->focusProxy(); f != 0; f = f->focusProxy()) {
+ if (f == this) {
+ qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item);
+ return;
+ }
+ }
+ }
+
+ QGraphicsItem *lastFocusProxy = d_ptr->focusProxy;
+ if (lastFocusProxy)
+ lastFocusProxy->d_ptr->focusProxyRefs.removeOne(&d_ptr->focusProxy);
+ d_ptr->focusProxy = item;
+ if (item)
+ item->d_ptr->focusProxyRefs << &d_ptr->focusProxy;
+}
+
+/*!
+ \since 4.6
+
+ If this item, a child or descendant of this item currently has input
+ focus, this function will return a pointer to that item. If
+ no descendant has input focus, 0 is returned.
+
+ \sa hasFocus(), setFocus(), QWidget::focusWidget()
+*/
+QGraphicsItem *QGraphicsItem::focusItem() const
+{
+ return d_ptr->subFocusItem;
+}
+
+/*!
\since 4.4
Grabs the mouse input.
@@ -2316,7 +2962,7 @@ void QGraphicsItem::ungrabKeyboard()
For convenience, you can also call scenePos() to determine the
item's position in scene coordinates, regardless of its parent.
- \sa x(), y(), setPos(), matrix(), {The Graphics View Coordinate System}
+ \sa x(), y(), setPos(), transform(), {The Graphics View Coordinate System}
*/
QPointF QGraphicsItem::pos() const
{
@@ -2332,6 +2978,19 @@ QPointF QGraphicsItem::pos() const
*/
/*!
+ \since 4.6
+
+ Set's the \a x coordinate of the item's position. Equivalent to
+ calling setPos(x, y()).
+
+ \sa x(), setPos()
+*/
+void QGraphicsItem::setX(qreal x)
+{
+ d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
+}
+
+/*!
\fn QGraphicsItem::y() const
This convenience function is equivalent to calling pos().y().
@@ -2340,6 +2999,19 @@ QPointF QGraphicsItem::pos() const
*/
/*!
+ \since 4.6
+
+ Set's the \a y coordinate of the item's position. Equivalent to
+ calling setPos(x(), y).
+
+ \sa x(), setPos()
+*/
+void QGraphicsItem::setY(qreal y)
+{
+ d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
+}
+
+/*!
Returns the item's position in scene coordinates. This is
equivalent to calling \c mapToScene(0, 0).
@@ -2353,35 +3025,37 @@ QPointF QGraphicsItem::scenePos() const
/*!
\internal
- Sets the position \a pos and notifies the change. If \a update is true,
- the item is also updated; otherwise it is not updated before and after the
- change.
+ Sets the position \a pos.
*/
void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
{
Q_Q(QGraphicsItem);
- if (this->pos == pos)
- return;
-
- // Notify the item that the position is changing.
- const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos));
- QPointF newPos = newPosVariant.toPointF();
- if (newPos == this->pos)
- return;
-
- // Update and repositition.
inSetPosHelper = 1;
- updateCachedClipPathFromSetPosHelper(newPos);
- if (scene) {
- fullUpdateHelper(true);
+ updateCachedClipPathFromSetPosHelper(pos);
+ if (scene)
q->prepareGeometryChange();
+ QPointF oldPos = this->pos;
+ this->pos = pos;
+ dirtySceneTransform = 1;
+ inSetPosHelper = 0;
+ if (isObject) {
+ if (pos.x() != oldPos.x())
+ emit static_cast<QGraphicsObject *>(q_ptr)->xChanged();
+ if (pos.y() != oldPos.y())
+ emit static_cast<QGraphicsObject *>(q_ptr)->yChanged();
}
- this->pos = newPos;
- invalidateSceneTransformCache();
+}
- // Send post-notification.
- q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
- inSetPosHelper = 0;
+/*!
+ \internal
+
+ Sets the transform \a transform.
+*/
+void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform)
+{
+ q_ptr->prepareGeometryChange();
+ transformData->transform = transform;
+ dirtySceneTransform = 1;
}
/*!
@@ -2396,7 +3070,26 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
*/
void QGraphicsItem::setPos(const QPointF &pos)
{
- d_ptr->setPosHelper(pos);
+ if (d_ptr->pos == pos)
+ return;
+
+ // Update and repositition.
+ if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ d_ptr->setPosHelper(pos);
+ return;
+ }
+
+ // Notify the item that the position is changing.
+ const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos)));
+ QPointF newPos = newPosVariant.toPointF();
+ if (newPos == d_ptr->pos)
+ return;
+
+ // Update and repositition.
+ d_ptr->setPosHelper(newPos);
+
+ // Send post-notification.
+ itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
}
/*!
@@ -2469,19 +3162,239 @@ QMatrix QGraphicsItem::matrix() const
/*!
\since 4.3
- Returns this item's transformation matrix. If no matrix has been set, the
- identity matrix is returned.
+ Returns this item's transformation matrix.
+
+ The transformation matrix is combined with the item's rotation(), scale()
+ and transformations() into a combined transformations for the item.
+
+ The default transformation matrix is an identity matrix.
\sa setTransform(), sceneTransform()
*/
QTransform QGraphicsItem::transform() const
{
- if (!d_ptr->hasTransform)
+ if (!d_ptr->transformData)
return QTransform();
- return qVariantValue<QTransform>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform));
+ return d_ptr->transformData->transform;
+}
+
+/*!
+ \since 4.6
+
+ Returns the clockwise rotation, in degrees, around the Z axis. The default
+ value is 0 (i.e., the item is not rotated).
+
+ The rotation is combined with the item's scale(), transform() and
+ transformations() to map the item's coordinate system to the parent item.
+
+ \sa setRotation(), transformOriginPoint(), {Transformations}
+*/
+qreal QGraphicsItem::rotation() const
+{
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->rotation;
+}
+
+/*!
+ \since 4.6
+
+ Sets the clockwise rotation \a angle, in degrees, around the Z axis. The
+ default value is 0 (i.e., the item is not rotated). Assigning a negative
+ value will rotate the item counter-clockwise. Normally the rotation angle
+ is in the range (-360, 360), but it's also possible to assign values
+ outside of this range (e.g., a rotation of 370 degrees is the same as a
+ rotation of 10 degrees).
+
+ The item is rotated around its transform origin point, which by default
+ is (0, 0). You can select a different transformation origin by calling
+ setTransformOriginPoint().
+
+ The rotation is combined with the item's scale(), transform() and
+ transformations() to map the item's coordinate system to the parent item.
+
+ \sa rotation(), setTransformOriginPoint(), {Transformations}
+*/
+void QGraphicsItem::setRotation(qreal angle)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->rotation = angle;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+
+ if (d_ptr->isObject)
+ emit static_cast<QGraphicsObject *>(this)->rotationChanged();
}
/*!
+ \since 4.6
+
+ Returns the scale factor of the item. The default scale factor is 1.0
+ (i.e., the item is not scaled).
+
+ The scale is combined with the item's rotation(), transform() and
+ transformations() to map the item's coordinate system to the parent item.
+
+ \sa setScale(), rotation(), {Transformations}
+*/
+qreal QGraphicsItem::scale() const
+{
+ if (!d_ptr->transformData)
+ return 1.;
+ return d_ptr->transformData->scale;
+}
+
+/*!
+ \since 4.6
+
+ Sets the scale \a factor of the item. The default scale factor is 1.0
+ (i.e., the item is not scaled). A scale factor of 0.0 will collapse the
+ item to a single point. If you provide a negative scale factor, the
+ item will be flipped and mirrored (i.e., rotated 180 degrees).
+
+ The item is scaled around its transform origin point, which by default
+ is (0, 0). You can select a different transformation origin by calling
+ setTransformOriginPoint().
+
+ The scale is combined with the item's rotation(), transform() and
+ transformations() to map the item's coordinate system to the parent item.
+
+ \sa scale(), setTransformOriginPoint(), {Transformations}
+*/
+void QGraphicsItem::setScale(qreal factor)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->scale = factor;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+
+ if (d_ptr->isObject)
+ emit static_cast<QGraphicsObject *>(this)->scaleChanged();
+}
+
+
+/*!
+ \since 4.6
+
+ Returns a list of graphics transforms that currently apply to this item.
+
+ QGraphicsTransform is for applying and controlling a chain of individual
+ transformation operations on an item. It's particularily useful in
+ animations, where each transform operation needs to be interpolated
+ independently, or differently.
+
+ The transformations are combined with the item's rotation(), scale() and
+ transform() to map the item's coordinate system to the parent item.
+
+ \sa scale(), rotation(), transformOriginPoint(), {Transformations}
+*/
+QList<QGraphicsTransform *> QGraphicsItem::transformations() const
+{
+ if (!d_ptr->transformData)
+ return QList<QGraphicsTransform *>();
+ return d_ptr->transformData->graphicsTransforms;
+}
+
+/*!
+ \since 4.6
+
+ Sets a list of graphics \a transformations (QGraphicsTransform) that
+ currently apply to this item.
+
+ If all you want is to rotate or scale an item, you should call setRotation()
+ or setScale() instead. If you want to set an arbitrary transformation on
+ an item, you can call setTransform().
+
+ QGraphicsTransform is for applying and controlling a chain of individual
+ transformation operations on an item. It's particularily useful in
+ animations, where each transform operation needs to be interpolated
+ independently, or differently.
+
+ The transformations are combined with the item's rotation(), scale() and
+ transform() to map the item's coordinate system to the parent item.
+
+ \sa scale(), setTransformOriginPoint(), {Transformations}
+*/
+void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transformations)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->graphicsTransforms = transformations;
+ for (int i = 0; i < transformations.size(); ++i)
+ transformations.at(i)->d_func()->setItem(this);
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \internal
+*/
+void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t)
+{
+ if (!transformData)
+ transformData = new QGraphicsItemPrivate::TransformData;
+ if (!transformData->graphicsTransforms.contains(t))
+ transformData->graphicsTransforms.append(t);
+
+ Q_Q(QGraphicsItem);
+ t->d_func()->setItem(q);
+ transformData->onlyTransform = false;
+ dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ Returns the origin point for the transformation in item coordinates.
+
+ The default is QPointF(0,0).
+
+ \sa setTransformOriginPoint(), {Transformations}
+*/
+QPointF QGraphicsItem::transformOriginPoint() const
+{
+ if (!d_ptr->transformData)
+ return QPointF(0,0);
+ return QPointF(d_ptr->transformData->xOrigin, d_ptr->transformData->yOrigin);
+}
+
+/*!
+ \since 4.6
+
+ Sets the \a origin point for the transformation in item coordinates.
+
+ \sa transformOriginPoint(), {Transformations}
+*/
+void QGraphicsItem::setTransformOriginPoint(const QPointF &origin)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xOrigin = origin.x();
+ d_ptr->transformData->yOrigin = origin.y();
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \fn void QGraphicsItem::setTransformOriginPoint(qreal x, qreal y)
+
+ \since 4.6
+ \overload
+
+ Sets the origin point for the transformation in item coordinates.
+ This is equivalent to calling setTransformOriginPoint(QPointF(\a x, \a y)).
+
+ \sa setTransformOriginPoint(), {Transformations}
+*/
+
+
+/*!
\obsolete
Use sceneTransform() instead.
@@ -2490,7 +3403,8 @@ QTransform QGraphicsItem::transform() const
*/
QMatrix QGraphicsItem::sceneMatrix() const
{
- return sceneTransform().toAffine();
+ d_ptr->ensureSceneTransform();
+ return d_ptr->sceneTransform.toAffine();
}
@@ -2507,51 +3421,14 @@ QMatrix QGraphicsItem::sceneMatrix() const
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 4
Unlike transform(), which returns only an item's local transformation, this
- function includes the item's (and any parents') position.
+ function includes the item's (and any parents') position, and all the transfomation properties.
- \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}
+ \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}, {Transformations}
*/
QTransform QGraphicsItem::sceneTransform() const
{
- // Check if there's any entry in the transform cache.
- QGraphicsScenePrivate *sd = d_ptr->scene ? d_ptr->scene->d_func() : 0;
- int index = d_ptr->sceneTransformIndex;
- if (sd && index != -1 && sd->validTransforms.testBit(index))
- return sd->sceneTransformCache[index];
-
- // Calculate local transform.
- QTransform m;
- if (d_ptr->hasTransform) {
- m = transform();
- if (!d_ptr->pos.isNull())
- m *= QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
- } else if (!d_ptr->pos.isNull()) {
- m = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
- }
-
- // Combine with parent and add to cache.
- if (d_ptr->parent) {
- m *= d_ptr->parent->sceneTransform();
- // Don't cache toplevels
- if (sd) {
- if (index == -1) {
- if (!sd->freeSceneTransformSlots.isEmpty()) {
- index = sd->freeSceneTransformSlots.last();
- sd->freeSceneTransformSlots.pop_back();
- } else {
- index = sd->sceneTransformCache.size();
- }
- d_ptr->sceneTransformIndex = index;
- if (index >= sd->validTransforms.size()) {
- sd->validTransforms.resize(index + 1);
- sd->sceneTransformCache.resize(index + 1);
- }
- }
- sd->validTransforms.setBit(index, 1);
- sd->sceneTransformCache[index] = m;
- }
- }
- return m;
+ d_ptr->ensureSceneTransform();
+ return d_ptr->sceneTransform;
}
/*!
@@ -2580,8 +3457,10 @@ QTransform QGraphicsItem::sceneTransform() const
QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) const
{
// Ensure we return the standard transform if we're not untransformable.
- if (!d_ptr->itemIsUntransformable())
- return sceneTransform() * viewportTransform;
+ if (!d_ptr->itemIsUntransformable()) {
+ d_ptr->ensureSceneTransform();
+ return d_ptr->sceneTransform * viewportTransform;
+ }
// Find the topmost item that ignores view transformations.
const QGraphicsItem *untransformedAncestor = this;
@@ -2600,18 +3479,18 @@ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) c
}
// First translate the base untransformable item.
- QPointF mappedPoint = (untransformedAncestor->sceneTransform() * viewportTransform).map(QPointF(0, 0));
- QTransform matrix;
- matrix.translate(mappedPoint.x(), mappedPoint.y());
- matrix = untransformedAncestor->transform() * matrix;
+ untransformedAncestor->d_ptr->ensureSceneTransform();
+ QPointF mappedPoint = (untransformedAncestor->d_ptr->sceneTransform * viewportTransform).map(QPointF(0, 0));
+
+ // COMBINE
+ QTransform matrix = QTransform::fromTranslate(mappedPoint.x(), mappedPoint.y());
+ if (untransformedAncestor->d_ptr->transformData)
+ matrix = untransformedAncestor->d_ptr->transformData->computedFullTransform(&matrix);
// Then transform and translate all children.
for (int i = 0; i < parents.size(); ++i) {
const QGraphicsItem *parent = parents.at(i);
- QPointF pos = parent->pos();
- QTransform moveMatrix;
- moveMatrix.translate(pos.x(), pos.y());
- matrix = (parent->transform() * moveMatrix) * matrix;
+ parent->d_ptr->combineTransformFromParent(&matrix);
}
return matrix;
@@ -2654,68 +3533,59 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
if (parent == other) {
if (ok)
*ok = true;
- const QPointF &itemPos = d_ptr->pos;
- if (itemPos.isNull())
- return d_ptr->hasTransform ? transform() : QTransform();
- if (d_ptr->hasTransform)
- return transform() * QTransform::fromTranslate(itemPos.x(), itemPos.y());
- return QTransform::fromTranslate(itemPos.x(), itemPos.y());
+ QTransform x;
+ d_ptr->combineTransformFromParent(&x);
+ return x;
}
// This is other's parent
if (otherParent == this) {
const QPointF &otherPos = other->d_ptr->pos;
- if (other->d_ptr->hasTransform) {
- QTransform otherToParent = other->transform();
- if (!otherPos.isNull())
- otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y());
+ if (other->d_ptr->transformData) {
+ QTransform otherToParent;
+ other->d_ptr->combineTransformFromParent(&otherToParent);
return otherToParent.inverted(ok);
- } else {
- if (ok)
- *ok = true;
- return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
}
+ if (ok)
+ *ok = true;
+ return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
}
// Siblings
if (parent == otherParent) {
- bool hasTr = d_ptr->hasTransform;
- bool otherHasTr = other->d_ptr->hasTransform;
+ // COMBINE
const QPointF &itemPos = d_ptr->pos;
const QPointF &otherPos = other->d_ptr->pos;
-
- if (!hasTr && !otherHasTr) {
+ if (!d_ptr->transformData && !other->d_ptr->transformData) {
QPointF delta = itemPos - otherPos;
if (ok)
*ok = true;
return QTransform::fromTranslate(delta.x(), delta.y());
}
- QTransform itemToParent = QTransform::fromTranslate(itemPos.x(), itemPos.y());
- if (hasTr)
- itemToParent = itemPos.isNull() ? transform() : transform() * itemToParent;
-
- QTransform otherToParent = QTransform::fromTranslate(otherPos.x(), otherPos.y());
- if (otherHasTr)
- otherToParent = otherPos.isNull() ? other->transform() : other->transform() * otherToParent;
-
+ QTransform itemToParent;
+ d_ptr->combineTransformFromParent(&itemToParent);
+ QTransform otherToParent;
+ other->d_ptr->combineTransformFromParent(&otherToParent);
return itemToParent * otherToParent.inverted(ok);
}
// Find the closest common ancestor. If the two items don't share an
// ancestor, then the only way is to combine their scene transforms.
const QGraphicsItem *commonAncestor = commonAncestorItem(other);
- if (!commonAncestor)
- return sceneTransform() * other->sceneTransform().inverted(ok);
+ if (!commonAncestor) {
+ d_ptr->ensureSceneTransform();
+ other->d_ptr->ensureSceneTransform();
+ return d_ptr->sceneTransform * other->d_ptr->sceneTransform.inverted(ok);
+ }
// If the two items are cousins (in sibling branches), map both to the
// common ancestor, and combine the two transforms.
bool cousins = other != commonAncestor && this != commonAncestor;
if (cousins) {
bool good = false;
- QTransform thisToScene;
- QTransform otherToScene;
- thisToScene = itemTransform(commonAncestor, &good);
+ QTransform thisToScene = itemTransform(commonAncestor, &good);
+ QTransform otherToScene(Qt::Uninitialized);
if (good)
otherToScene = other->itemTransform(commonAncestor, &good);
if (!good) {
@@ -2734,11 +3604,7 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
QTransform x;
const QGraphicsItem *p = child;
do {
- const QGraphicsItemPrivate *pd = p->d_ptr;
- if (pd->hasTransform)
- x *= p->transform();
- if (!pd->pos.isNull())
- x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y());
+ p->d_ptr.data()->combineTransformToParent(&x);
} while ((p = p->d_ptr->parent) && p != root);
if (parentOfOther)
return x.inverted(ok);
@@ -2756,37 +3622,34 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
Use setTransform() instead.
- \sa transform(), rotate(), scale(), shear(), translate(), {The Graphics View Coordinate System}
+ \sa transform(), {The Graphics View Coordinate System}
*/
void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
{
- QTransform oldTransform = this->transform();
- QTransform newTransform;
- if (!combine)
- newTransform = QTransform(matrix);
- else
- newTransform = QTransform(matrix) * oldTransform;
- if (oldTransform == newTransform)
- return;
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- // Notify the item that the matrix is changing.
- QVariant newTransformVariant(itemChange(ItemMatrixChange,
- qVariantFromValue<QMatrix>(newTransform.toAffine())));
- newTransform = QTransform(qVariantValue<QMatrix>(newTransformVariant));
- if (oldTransform == newTransform)
+ QTransform newTransform(combine ? QTransform(matrix) * d_ptr->transformData->transform : QTransform(matrix));
+ if (d_ptr->transformData->transform == newTransform)
return;
// Update and set the new transformation.
- d_ptr->fullUpdateHelper(true, true);
- prepareGeometryChange();
- d_ptr->hasTransform = !newTransform.isIdentity();
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
- d_ptr->invalidateSceneTransformCache();
+ if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ d_ptr->setTransformHelper(newTransform);
+ return;
+ }
+ // Notify the item that the transformation matrix is changing.
+ const QVariant newMatrixVariant = qVariantFromValue<QMatrix>(newTransform.toAffine());
+ newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant)));
+ if (d_ptr->transformData->transform == newTransform)
+ return;
+
+ // Update and set the new transformation.
+ d_ptr->setTransformHelper(newTransform);
+
// Send post-notification.
- // NB! We have to change the value from QMatrix to QTransform.
- qVariantSetValue<QTransform>(newTransformVariant, newTransform);
- itemChange(ItemTransformHasChanged, newTransformVariant);
+ itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform));
}
/*!
@@ -2804,32 +3667,36 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
to map an item coordiate to a scene coordinate, or mapFromScene() to map
from scene coordinates to item coordinates.
- \sa transform(), rotate(), scale(), shear(), translate(), {The Graphics View Coordinate System}
+ The transformation matrix is combined with the item's rotation(), scale()
+ and transformations() into a combined transformation that maps the item's
+ coordinate system to its parent.
+
+ \sa transform(), setRotation(), setScale(), setTransformOriginPoint(), {The Graphics View Coordinate System}, {Transformations}
*/
void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
{
- QTransform oldTransform = this->transform();
- QTransform newTransform;
- if (!combine)
- newTransform = matrix;
- else
- newTransform = matrix * oldTransform;
- if (oldTransform == newTransform)
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+
+ QTransform newTransform(combine ? matrix * d_ptr->transformData->transform : matrix);
+ if (d_ptr->transformData->transform == newTransform)
return;
+ // Update and set the new transformation.
+ if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ d_ptr->setTransformHelper(newTransform);
+ return;
+ }
+
// Notify the item that the transformation matrix is changing.
const QVariant newTransformVariant(itemChange(ItemTransformChange,
qVariantFromValue<QTransform>(newTransform)));
newTransform = qVariantValue<QTransform>(newTransformVariant);
- if (oldTransform == newTransform)
+ if (d_ptr->transformData->transform == newTransform)
return;
// Update and set the new transformation.
- d_ptr->fullUpdateHelper(true, true);
- prepareGeometryChange();
- d_ptr->hasTransform = !newTransform.isIdentity();
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
- d_ptr->invalidateSceneTransformCache();
+ d_ptr->setTransformHelper(newTransform);
// Send post-notification.
itemChange(ItemTransformHasChanged, newTransformVariant);
@@ -2848,8 +3715,9 @@ void QGraphicsItem::resetMatrix()
/*!
\since 4.3
- Resets this item's transformation matrix to the identity matrix. This is
- equivalent to calling \c setTransform(QTransform()).
+ Resets this item's transformation matrix to the identity matrix or
+ all the transformation properties to their default values.
+ This is equivalent to calling \c setTransform(QTransform()).
\sa setTransform(), transform()
*/
@@ -2859,6 +3727,16 @@ void QGraphicsItem::resetTransform()
}
/*!
+ \obsolete
+
+ Use
+
+ \code
+ setRotation(rotation() + angle);
+ \endcode
+
+ instead.
+
Rotates the current item transformation \a angle degrees clockwise around
its origin. To translate around an arbitrary point (x, y), you need to
combine translation and rotation with setTransform().
@@ -2875,6 +3753,16 @@ void QGraphicsItem::rotate(qreal angle)
}
/*!
+ \obsolete
+
+ Use
+
+ \code
+ setTransform(QTransform::fromScale(sx, sy), true);
+ \endcode
+
+ instead.
+
Scales the current item transformation by (\a sx, \a sy) around its
origin. To scale from an arbitrary point (x, y), you need to combine
translation and scaling with setTransform().
@@ -2883,7 +3771,7 @@ void QGraphicsItem::rotate(qreal angle)
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7
- \sa setTransform(), transform(), rotate(), shear(), translate()
+ \sa setTransform(), transform()
*/
void QGraphicsItem::scale(qreal sx, qreal sy)
{
@@ -2891,9 +3779,19 @@ void QGraphicsItem::scale(qreal sx, qreal sy)
}
/*!
+ \obsolete
+
+ Use
+
+ \code
+ setTransform(QTransform().shear(sh, sv), true);
+ \endcode
+
+ instead.
+
Shears the current item transformation by (\a sh, \a sv).
- \sa setTransform(), transform(), rotate(), scale(), translate()
+ \sa setTransform(), transform()
*/
void QGraphicsItem::shear(qreal sh, qreal sv)
{
@@ -2901,13 +3799,22 @@ void QGraphicsItem::shear(qreal sh, qreal sv)
}
/*!
+ \obsolete
+
+ Use setPos() or setTransformOriginPoint() instead. For identical
+ behavior, use
+
+ \code
+ setTransform(QTransform::fromTranslate(dx, dy), true);
+ \endcode
+
Translates the current item transformation by (\a dx, \a dy).
If all you want is to move an item, you should call moveBy() or
setPos() instead; this function changes the item's translation,
which is conceptually separate from its position.
- \sa setTransform(), transform(), rotate(), scale(), shear()
+ \sa setTransform(), transform()
*/
void QGraphicsItem::translate(qreal dx, qreal dy)
{
@@ -2952,11 +3859,11 @@ qreal QGraphicsItem::zValue() const
/*!
Sets the Z-value, or the elevation, of the item, to \a z. The elevation
decides the stacking order of sibling (neighboring) items. An item of high
- Z-value will be drawn on top of an item with a lower Z-value if they
- share the same parent item. In addition, children of an item will always be drawn
- on top of the parent, regardless of the child's Z-value. Sibling items
- that share the same Z-value will be drawn in an undefined order, although
- the order will stay the same for as long as the items live.
+ Z-value will be drawn on top of an item with a lower Z-value if they share
+ the same parent item. In addition, children of an item will always be
+ drawn on top of the parent, regardless of the child's Z-value. Sibling
+ items that share the same Z-value will be drawn in order of insertion; the
+ last inserted child is stacked above previous children.
\img graphicsview-zorder.png
@@ -2980,20 +3887,32 @@ qreal QGraphicsItem::zValue() const
*/
void QGraphicsItem::setZValue(qreal z)
{
- const QVariant newZVariant(itemChange(ItemZValueChange, double(z)));
- qreal newZ = qreal(newZVariant.toDouble());
+ const QVariant newZVariant(itemChange(ItemZValueChange, z));
+ qreal newZ = newZVariant.toReal();
if (newZ == d_ptr->z)
return;
- d_ptr->z = z;
- d_ptr->fullUpdateHelper();
if (d_ptr->scene) {
- // Invalidate any sort caching; arrival of a new item means we need to
- // resort.
- d_ptr->scene->d_func()->invalidateSortCache();
+ // Z Value has changed, we have to notify the index.
+ d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, newZVariant);
}
+ d_ptr->z = newZ;
+ if (d_ptr->parent)
+ d_ptr->parent->d_ptr->needSortChildren = 1;
+ else if (d_ptr->scene)
+ d_ptr->scene->d_func()->needSortTopLevelItems = 1;
+
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
+
itemChange(ItemZValueHasChanged, newZVariant);
+
+ if (d_ptr->flags & ItemNegativeZStacksBehindParent)
+ setFlag(QGraphicsItem::ItemStacksBehindParent, z < qreal(0.0));
+
+ if (d_ptr->isObject)
+ emit static_cast<QGraphicsObject *>(this)->zChanged();
}
/*!
@@ -3015,15 +3934,13 @@ void QGraphicsItem::setZValue(qreal z)
*/
QRectF QGraphicsItem::childrenBoundingRect() const
{
- QRectF childRect;
- foreach (QGraphicsItem *child, children()) {
- QPointF childPos = child->pos();
- QTransform matrix = child->transform();
- if (!childPos.isNull())
- matrix *= QTransform::fromTranslate(childPos.x(), childPos.y());
- childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect());
- }
- return childRect;
+ if (!d_ptr->dirtyChildrenBoundingRect)
+ return d_ptr->childrenBoundingRect;
+
+ d_ptr->childrenBoundingRect = QRectF();
+ d_ptr->childrenBoundingRectHelper(0, &d_ptr->childrenBoundingRect);
+ d_ptr->dirtyChildrenBoundingRect = 0;
+ return d_ptr->childrenBoundingRect;
}
/*!
@@ -3036,7 +3953,7 @@ QRectF QGraphicsItem::childrenBoundingRect() const
Although the item's shape can be arbitrary, the bounding rect is
always rectangular, and it is unaffected by the items'
- transformation (scale(), rotate(), etc.).
+ transformation.
If you want to change the item's bounding rectangle, you must first call
prepareGeometryChange(). This notifies the scene of the imminent change,
@@ -3068,19 +3985,26 @@ QRectF QGraphicsItem::childrenBoundingRect() const
QRectF QGraphicsItem::sceneBoundingRect() const
{
// Find translate-only offset
+ // COMBINE
QPointF offset;
const QGraphicsItem *parentItem = this;
const QGraphicsItemPrivate *itemd;
do {
- itemd = parentItem->d_ptr;
- if (itemd->hasTransform)
+ itemd = parentItem->d_ptr.data();
+ if (itemd->transformData)
break;
offset += itemd->pos;
} while ((parentItem = itemd->parent));
QRectF br = boundingRect();
br.translate(offset);
- return !parentItem ? br : parentItem->sceneTransform().mapRect(br);
+ if (!parentItem)
+ return br;
+ if (parentItem->d_ptr->hasTranslateOnlySceneTransform()) {
+ br.translate(parentItem->d_ptr->sceneTransform.dx(), parentItem->d_ptr->sceneTransform.dy());
+ return br;
+ }
+ return parentItem->d_ptr->sceneTransform.mapRect(br);
}
/*!
@@ -3455,7 +4379,7 @@ bool QGraphicsItem::isObscuredBy(const QGraphicsItem *item) const
{
if (!item)
return false;
- return QGraphicsScenePrivate::closestItemFirst_withoutCache(item, this)
+ return QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(item, this)
&& qt_QGraphicsItem_isObscured(this, item, boundingRect());
}
@@ -3540,8 +4464,7 @@ QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) c
p.end();
// Transform QRegion back to device space
- QTransform unscale;
- unscale.scale(1 / granularity, 1 / granularity);
+ QTransform unscale = QTransform::fromScale(1 / granularity, 1 / granularity);
QRegion r;
QBitmap colorMask = QBitmap::fromImage(mask.createMaskFromColor(0));
foreach (const QRect &rect, QRegion( colorMask ).rects()) {
@@ -3637,7 +4560,7 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity)
All painting is done in local coordinates.
- \sa setCacheMode(), QPen::width(), {Item Coordinates}
+ \sa setCacheMode(), QPen::width(), {Item Coordinates}, ItemUsesExtendedStyleOption
*/
/*!
@@ -3649,174 +4572,86 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore
{
// No scene, or if the scene is updating everything, means we have nothing
// to do. The only exception is if the scene tracks the growing scene rect.
- return (!visible && !ignoreVisibleBit)
- || (dirty && !ignoreDirtyBit)
- || !scene
- || (scene->d_func()->updateAll && scene->d_func()->hasSceneRect)
+ return !scene
+ || (!visible && !ignoreVisibleBit && !this->ignoreVisible)
+ || (!ignoreDirtyBit && fullUpdatePending)
|| (!ignoreClipping && (childrenClippedToShape() && isClippedAway()))
- || (!ignoreOpacity && childrenCombineOpacity() && isFullyTransparent());
+ || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent());
}
/*!
\internal
-
- Asks the scene to mark this item's scene rect as dirty, requesting a
- redraw. This does not invalidate any cache.
-
- The \a force argument is for the update call in setVisible(), which is the
- only case where the item's background should be marked as dirty even when
- the item isn't visible.
*/
-void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool maybeDirtyClipPath)
+int QGraphicsItemPrivate::depth() const
{
- // No scene, or if the scene is updating everything, means we have nothing
- // to do. The only exception is if the scene tracks the growing scene rect.
- if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/force))
- return;
+ if (itemDepth == -1)
+ const_cast<QGraphicsItemPrivate *>(this)->resolveDepth();
- if (rect.isNull())
- dirty = 1;
- scene->itemUpdated(q_ptr, rect);
+ return itemDepth;
}
/*!
\internal
-
- Propagates updates to \a item and all its children.
*/
-void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyClipPath, bool ignoreOpacity)
+void QGraphicsItemPrivate::invalidateDepthRecursively()
{
- if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/false,
- /*ignoreDirtyBit=*/true, ignoreOpacity)) {
+ if (itemDepth == -1)
return;
- }
- if (!childrenOnly && !dirty) {
- // Effectively the same as updateHelper(QRectF(), false, maybeDirtyClipPath).
- dirty = 1;
- scene->itemUpdated(q_ptr, QRectF());
- }
-
- if (dirtyChildren || childrenClippedToShape()) {
- // Unnecessary to update children as well.
- return;
- }
-
- if (ancestorFlags & AncestorClipsChildren) {
- Q_Q(QGraphicsItem);
- // Check if we can avoid updating all children.
- QGraphicsItem *p = parent;
- QRectF br = q->boundingRect();
- while (p) {
- if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) {
- bool ok;
- QTransform x = q->itemTransform(p, &ok);
- if (!ok)
- break;
- if (x.mapRect(br).contains(p->boundingRect()))
- return;
- }
- p = p->d_ptr->parent;
- if (!p || !(p->d_ptr->ancestorFlags & AncestorClipsChildren))
- break;
- // ### check one level only
- break;
- }
- }
- foreach (QGraphicsItem *child, children)
- child->d_ptr->fullUpdateHelper(false, maybeDirtyClipPath, ignoreOpacity);
- dirtyChildren = 1;
+ itemDepth = -1;
+ for (int i = 0; i < children.size(); ++i)
+ children.at(i)->d_ptr->invalidateDepthRecursively();
}
-static inline bool qt_allChildrenCombineOpacity(QGraphicsItem *parent)
-{
- Q_ASSERT(parent);
- if (parent->flags() & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
- return false;
-
- const QList<QGraphicsItem *> children(parent->childItems());
- for (int i = 0; i < children.size(); ++i) {
- if (children.at(i)->flags() & QGraphicsItem::ItemIgnoresParentOpacity)
- return false;
- }
- return true;
-}
+/*!
+ \internal
-void QGraphicsItemPrivate::updateEffectiveOpacity()
+ Resolves the stacking depth of this object and all its ancestors.
+*/
+void QGraphicsItemPrivate::resolveDepth()
{
- Q_Q(QGraphicsItem);
- if (parent) {
- resolveEffectiveOpacity(parent->effectiveOpacity());
- parent->d_ptr->allChildrenCombineOpacity = qt_allChildrenCombineOpacity(parent);
- } else {
- resolveEffectiveOpacity(1.0);
+ if (!parent)
+ itemDepth = 0;
+ else {
+ if (parent->d_ptr->itemDepth == -1)
+ parent->d_ptr->resolveDepth();
+ itemDepth = parent->d_ptr->itemDepth + 1;
}
- allChildrenCombineOpacity = qt_allChildrenCombineOpacity(q);
}
/*!
\internal
-
- Resolves and propagates this item's effective opacity to its children.
*/
-void QGraphicsItemPrivate::resolveEffectiveOpacity(qreal parentEffectiveOpacity)
+void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
{
- Q_Q(QGraphicsItem);
- QGraphicsItem::GraphicsItemFlags myFlags = q->flags();
- QGraphicsItem::GraphicsItemFlags parentFlags = parent ? parent->flags() : QGraphicsItem::GraphicsItemFlags(0);
-
- // My local opacity is always part of my effective opacity.
- qreal myEffectiveOpacity = q->opacity();
-
- // If I have a parent, and I don't ignore my parent's opacity, and my
- // parent propagates to me, then combine my local opacity with my parent's
- // effective opacity into my effective opacity.
- if (parent
- && !(myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
- && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
- myEffectiveOpacity *= parentEffectiveOpacity;
- }
-
- // Set this item's resolved opacity.
- if (qFuzzyCompare(myEffectiveOpacity, qreal(1.0))) {
- // Opaque, unset effective opacity.
- hasEffectiveOpacity = 0;
- unsetExtra(ExtraEffectiveOpacity);
- } else {
- hasEffectiveOpacity = 1;
- setExtra(ExtraEffectiveOpacity, myEffectiveOpacity);
- }
-
- // Resolve children always.
- for (int i = 0; i < children.size(); ++i)
- children.at(i)->d_ptr->resolveEffectiveOpacity(myEffectiveOpacity);
+ needSortChildren = 1;
+ child->d_ptr->siblingIndex = children.size();
+ children.append(child);
}
/*!
\internal
-
- Resolves the stacking depth of this object and all its children.
*/
-void QGraphicsItemPrivate::resolveDepth(int parentDepth)
+void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
{
- depth = parentDepth + 1;
- for (int i = 0; i < children.size(); ++i)
- children.at(i)->d_ptr->resolveDepth(depth);
+ children.removeOne(child);
+ // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because
+ // the child is not guaranteed to be at the index after the list is sorted.
+ // (see ensureSortedChildren()).
+ child->d_ptr->siblingIndex = -1;
}
/*!
\internal
*/
-void QGraphicsItemPrivate::invalidateSceneTransformCache()
+QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const
{
- if (!scene || (parent && sceneTransformIndex == -1))
- return;
- if (sceneTransformIndex != -1)
- scene->d_func()->validTransforms.setBit(sceneTransformIndex, 0);
- for (int i = 0; i < children.size(); ++i)
- children.at(i)->d_ptr->invalidateSceneTransformCache();
+ return (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
}
+/*!
+ \internal
+*/
QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const
{
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
@@ -3828,6 +4663,9 @@ QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const
return c;
}
+/*!
+ \internal
+*/
void QGraphicsItemPrivate::removeExtraItemCache()
{
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
@@ -3889,17 +4727,13 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n
// Find closest clip ancestor and transform.
Q_Q(QGraphicsItem);
- QTransform thisToParentTransform = hasTransform
- ? q->transform() * QTransform::fromTranslate(newPos.x(), newPos.y())
- : QTransform::fromTranslate(newPos.x(), newPos.y());
+ // COMBINE
+ QTransform thisToParentTransform = QTransform::fromTranslate(newPos.x(), newPos.y());
+ if (transformData)
+ thisToParentTransform = transformData->computedFullTransform(&thisToParentTransform);
QGraphicsItem *clipParent = parent;
while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) {
- if (clipParent->d_ptr->hasTransform)
- thisToParentTransform *= clipParent->transform();
- if (!clipParent->d_ptr->pos.isNull()) {
- thisToParentTransform *= QTransform::fromTranslate(clipParent->d_ptr->pos.x(),
- clipParent->d_ptr->pos.y());
- }
+ thisToParentTransform *= clipParent->d_ptr->transformToParent();
clipParent = clipParent->d_ptr->parent;
}
@@ -3941,6 +4775,89 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n
}
}
+// Traverses all the ancestors up to the top-level and updates the pointer to
+// always point to the top-most item that has a dirty scene transform.
+// It then backtracks to the top-most dirty item and start calculating the
+// scene transform by combining the item's transform (+pos) with the parent's
+// cached scene transform (which we at this point know for sure is valid).
+void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem)
+{
+ Q_ASSERT(topMostDirtyItem);
+
+ if (dirtySceneTransform)
+ *topMostDirtyItem = q_ptr;
+
+ if (parent)
+ parent->d_ptr->ensureSceneTransformRecursive(topMostDirtyItem);
+
+ if (*topMostDirtyItem == q_ptr) {
+ if (!dirtySceneTransform)
+ return; // OK, neither my ancestors nor I have dirty scene transforms.
+ *topMostDirtyItem = 0;
+ } else if (*topMostDirtyItem) {
+ return; // Continue backtrack.
+ }
+
+ // COMBINE my transform with the parent's scene transform.
+ updateSceneTransformFromParent();
+ Q_ASSERT(!dirtySceneTransform);
+}
+
+void QGraphicsItemPrivate::ensureSceneTransform()
+{
+ if (dirtySceneTransform) {
+ // This item and all its descendants have dirty scene transforms.
+ // We're about to validate this item's scene transform, so we have to
+ // invalidate all the children; otherwise there's no way for the descendants
+ // to detect that the ancestor has changed.
+ invalidateChildrenSceneTransform();
+ }
+
+ QGraphicsItem *that = q_func();
+ ensureSceneTransformRecursive(&that);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsItemPrivate::setSubFocus()
+{
+ // Update focus child chain.
+ QGraphicsItem *item = q_ptr;
+ QGraphicsItem *parent = item;
+ bool hidden = !visible;
+ do {
+ parent->d_func()->subFocusItem = item;
+ } while (!parent->isPanel() && (parent = parent->d_ptr->parent) && (!hidden || !parent->d_func()->visible));
+}
+
+/*!
+ \internal
+*/
+void QGraphicsItemPrivate::clearSubFocus()
+{
+ // Reset focus child chain.
+ QGraphicsItem *parent = q_ptr;
+ do {
+ if (parent->d_ptr->subFocusItem != q_ptr)
+ break;
+ parent->d_ptr->subFocusItem = 0;
+ } while (!parent->isPanel() && (parent = parent->d_ptr->parent));
+}
+
+/*!
+ \internal
+
+ Sets the focusProxy pointer to 0 for all items that have this item as their
+ focusProxy. ### Qt 5: Use QPointer instead.
+*/
+void QGraphicsItemPrivate::resetFocusProxy()
+{
+ for (int i = 0; i < focusProxyRefs.size(); ++i)
+ *focusProxyRefs.at(i) = 0;
+ focusProxyRefs.clear();
+}
+
/*!
\internal
@@ -3974,6 +4891,13 @@ void QGraphicsItem::update(const QRectF &rect)
if (rect.isEmpty() && !rect.isNull())
return;
+ // Make sure we notify effects about invalidated source.
+ QGraphicsItem *item = this;
+ do {
+ if (item->d_ptr->graphicsEffect)
+ item->d_ptr->notifyInvalidated = 1;
+ } while ((item = item->d_ptr->parent));
+
if (CacheMode(d_ptr->cacheMode) != NoCache) {
QGraphicsItemCache *cache = d_ptr->extraItemCache();
if (d_ptr->discardUpdateRequest(/* ignoreVisibleBit = */ false,
@@ -3983,25 +4907,62 @@ void QGraphicsItem::update(const QRectF &rect)
}
// Invalidate cache.
- if (rect.isNull()) {
- cache->allExposed = true;
- cache->exposed.clear();
- } else {
- cache->exposed.append(rect);
+ if (!cache->allExposed) {
+ if (rect.isNull()) {
+ cache->allExposed = true;
+ cache->exposed.clear();
+ } else {
+ cache->exposed.append(rect);
+ }
}
// Only invalidate cache; item is already dirty.
- if (d_ptr->dirty)
+ if (d_ptr->fullUpdatePending)
return;
- } else if (d_ptr->discardUpdateRequest()) {
- return;
}
- // Effectively the same as updateHelper(rect);
- if (rect.isNull())
- d_ptr->dirty = 1;
- d_ptr->scene->itemUpdated(this, rect);
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this, rect);
}
+/*!
+ \internal
+
+ Scrolls \a rect in \a pix by \a dx, \a dy.
+
+ ### This can be done much more efficiently by using XCopyArea on X11 with
+ the same dst and src, and through moving pixels in the raster engine. It
+ can probably also be done much better on the other paint engines.
+*/
+void _q_scrollPixmap(QPixmap *pix, const QRect &rect, int dx, int dy)
+{
+#if 0
+ QPainter painter(pix);
+ painter.setClipRect(rect);
+ painter.drawPixmap(rect.translated(dx, dy), *pix, rect);
+ painter.end();
+#elif defined Q_WS_X11
+ GC gc = XCreateGC(X11->display, pix->handle(), 0, 0);
+
+ XRectangle xrect;
+ xrect.x = rect.x();
+ xrect.y = rect.y();
+ xrect.width = rect.width();
+ xrect.height = rect.height();
+ XSetClipRectangles(X11->display, gc, 0, 0, &xrect, 1, YXBanded);
+
+ XCopyArea(X11->display, pix->handle(), pix->handle(), gc,
+ rect.x(), rect.y(), rect.width(), rect.height(),
+ rect.x()+dx, rect.y()+dy);
+ XFreeGC(X11->display, gc);
+#else
+ QPixmap newPix = *pix;
+ QPainter painter(&newPix);
+ painter.setClipRect(rect);
+ painter.drawPixmap(rect.translated(dx, dy), *pix, rect);
+ painter.end();
+ *pix = newPix;
+#endif
+}
/*!
\since 4.4
@@ -4030,11 +4991,45 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect)
if (!d->scene)
return;
if (d->cacheMode != NoCache) {
- // ### This is very slow, and can be done much better. If the cache is
- // local and matches the below criteria for rotation and scaling, we
- // can easily scroll. And if the cache is in device coordinates, we
- // can scroll both the viewport and the cache.
- update(rect);
+ QGraphicsItemCache *c;
+ bool scrollCache = qFuzzyIsNull(dx - int(dx)) && qFuzzyIsNull(dy - int(dy))
+ && (c = (QGraphicsItemCache *)qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraCacheData)))
+ && (d->cacheMode == ItemCoordinateCache && !c->fixedSize.isValid());
+ if (scrollCache) {
+ QPixmap pix;
+ if (QPixmapCache::find(c->key, &pix)) {
+ // Adjust with 2 pixel margin. Notice the loss of precision
+ // when converting to QRect.
+ int adjust = 2;
+ QRectF br = boundingRect().adjusted(-adjust, -adjust, adjust, adjust);
+ QRect irect = rect.toRect().translated(-br.x(), -br.y());
+
+ _q_scrollPixmap(&pix, irect, dx, dy);
+
+ QPixmapCache::replace(c->key, pix);
+
+ // Translate the existing expose.
+ foreach (QRectF exposedRect, c->exposed)
+ c->exposed += exposedRect.translated(dx, dy) & rect;
+
+ // Calculate exposure.
+ QRegion exposed;
+ QRect r = rect.toRect();
+ exposed += r;
+ exposed -= r.translated(dx, dy);
+ foreach (QRect rect, exposed.rects())
+ update(rect);
+ d->scene->d_func()->markDirty(this);
+ } else {
+ update(rect);
+ }
+ } else {
+ // ### This is very slow, and can be done much better. If the cache is
+ // local and matches the below criteria for rotation and scaling, we
+ // can easily scroll. And if the cache is in device coordinates, we
+ // can scroll both the viewport and the cache.
+ update(rect);
+ }
return;
}
@@ -4053,13 +5048,7 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect)
static const QLineF left(0, 0, -1, 0);
static const QLineF right(0, 0, 1, 0);
- QTransform deviceTr;
- if (d->itemIsUntransformable()) {
- deviceTr = deviceTransform(view->viewportTransform());
- } else {
- deviceTr = sceneTransform() * view->viewportTransform();
- }
-
+ QTransform deviceTr = deviceTransform(view->viewportTransform());
QRect deviceScrollRect = deviceTr.mapRect(scrollRect).toRect();
QLineF v1 = deviceTr.map(right);
QLineF v2 = deviceTr.map(down);
@@ -4191,7 +5180,10 @@ QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPointF &point
*/
QPointF QGraphicsItem::mapToParent(const QPointF &point) const
{
- return d_ptr->pos + (d_ptr->hasTransform ? transform().map(point) : point);
+ // COMBINE
+ if (!d_ptr->transformData)
+ return point + d_ptr->pos;
+ return d_ptr->transformToParent().map(point);
}
/*!
@@ -4211,7 +5203,9 @@ QPointF QGraphicsItem::mapToParent(const QPointF &point) const
*/
QPointF QGraphicsItem::mapToScene(const QPointF &point) const
{
- return sceneTransform().map(point);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return QPointF(point.x() + d_ptr->sceneTransform.dx(), point.y() + d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.map(point);
}
/*!
@@ -4256,9 +5250,10 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect
*/
QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const
{
- QPolygonF p = !d_ptr->hasTransform ? rect : transform().map(rect);
- p.translate(d_ptr->pos);
- return p;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(d_ptr->pos);
+ return d_ptr->transformToParent().map(rect);
}
/*!
@@ -4277,7 +5272,9 @@ QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const
*/
QPolygonF QGraphicsItem::mapToScene(const QRectF &rect) const
{
- return sceneTransform().map(rect);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.map(rect);
}
/*!
@@ -4325,8 +5322,10 @@ QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, const QRectF &rec
*/
QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const
{
- QRectF r = !d_ptr->hasTransform ? rect : transform().mapRect(rect);
- return r.translated(d_ptr->pos);
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(d_ptr->pos);
+ return d_ptr->transformToParent().mapRect(rect);
}
/*!
@@ -4348,7 +5347,9 @@ QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const
*/
QRectF QGraphicsItem::mapRectToScene(const QRectF &rect) const
{
- return sceneTransform().mapRect(rect);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.mapRect(rect);
}
/*!
@@ -4397,8 +5398,10 @@ QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, const QRectF &r
*/
QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const
{
- QRectF r = rect.translated(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().mapRect(r) : r;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().mapRect(rect);
}
/*!
@@ -4420,7 +5423,9 @@ QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const
*/
QRectF QGraphicsItem::mapRectFromScene(const QRectF &rect) const
{
- return sceneTransform().inverted().mapRect(rect);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.inverted().mapRect(rect);
}
/*!
@@ -4457,9 +5462,10 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &p
*/
QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const
{
- QPolygonF p = !d_ptr->hasTransform ? polygon : transform().map(polygon);
- p.translate(d_ptr->pos);
- return p;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return polygon.translated(d_ptr->pos);
+ return d_ptr->transformToParent().map(polygon);
}
/*!
@@ -4471,7 +5477,9 @@ QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const
*/
QPolygonF QGraphicsItem::mapToScene(const QPolygonF &polygon) const
{
- return sceneTransform().map(polygon);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return polygon.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.map(polygon);
}
/*!
@@ -4501,10 +5509,10 @@ QPainterPath QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPainterP
*/
QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const
{
- QTransform x = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
- if (d_ptr->hasTransform)
- x = transform() * x;
- return x.map(path);
+ // COMBINE
+ if (!d_ptr->transformData)
+ return path.translated(d_ptr->pos);
+ return d_ptr->transformToParent().map(path);
}
/*!
@@ -4516,7 +5524,9 @@ QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const
*/
QPainterPath QGraphicsItem::mapToScene(const QPainterPath &path) const
{
- return sceneTransform().map(path);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return path.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.map(path);
}
/*!
@@ -4553,8 +5563,9 @@ QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &poi
*/
QPointF QGraphicsItem::mapFromParent(const QPointF &point) const
{
- if (d_ptr->hasTransform)
- return transform().inverted().map(point - d_ptr->pos);
+ // COMBINE
+ if (d_ptr->transformData)
+ return d_ptr->transformToParent().inverted().map(point);
return point - d_ptr->pos;
}
@@ -4576,7 +5587,9 @@ QPointF QGraphicsItem::mapFromParent(const QPointF &point) const
*/
QPointF QGraphicsItem::mapFromScene(const QPointF &point) const
{
- return sceneTransform().inverted().map(point);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return QPointF(point.x() - d_ptr->sceneTransform.dx(), point.y() - d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.inverted().map(point);
}
/*!
@@ -4621,8 +5634,10 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QRectF &re
*/
QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const
{
- QRectF r = rect.translated(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().map(r) : r;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().map(rect);
}
/*!
@@ -4642,7 +5657,9 @@ QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const
*/
QPolygonF QGraphicsItem::mapFromScene(const QRectF &rect) const
{
- return sceneTransform().inverted().map(rect);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.inverted().map(rect);
}
/*!
@@ -4677,9 +5694,10 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPolygonF
*/
QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const
{
- QPolygonF p = polygon;
- p.translate(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().map(p) : p;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return polygon.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().map(polygon);
}
/*!
@@ -4691,7 +5709,9 @@ QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const
*/
QPolygonF QGraphicsItem::mapFromScene(const QPolygonF &polygon) const
{
- return sceneTransform().inverted().map(polygon);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return polygon.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.inverted().map(polygon);
}
/*!
@@ -4719,9 +5739,10 @@ QPainterPath QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPainte
*/
QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const
{
- if (d_ptr->parent)
- return d_ptr->parent->itemTransform(this).map(path);
- return mapFromScene(path);
+ // COMBINE
+ if (!d_ptr->transformData)
+ return path.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().map(path);
}
/*!
@@ -4733,7 +5754,9 @@ QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const
*/
QPainterPath QGraphicsItem::mapFromScene(const QPainterPath &path) const
{
- return sceneTransform().inverted().map(path);
+ if (d_ptr->hasTranslateOnlySceneTransform())
+ return path.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
+ return d_ptr->sceneTransform.inverted().map(path);
}
/*!
@@ -4770,8 +5793,8 @@ QGraphicsItem *QGraphicsItem::commonAncestorItem(const QGraphicsItem *other) con
return const_cast<QGraphicsItem *>(this);
const QGraphicsItem *thisw = this;
const QGraphicsItem *otherw = other;
- int thisDepth = d_ptr->depth;
- int otherDepth = other->d_ptr->depth;
+ int thisDepth = d_ptr->depth();
+ int otherDepth = other->d_ptr->depth();
while (thisDepth > otherDepth) {
thisw = thisw->d_ptr->parent;
--thisDepth;
@@ -5070,6 +6093,17 @@ bool QGraphicsItem::sceneEvent(QEvent *event)
case QEvent::InputMethod:
inputMethodEvent(static_cast<QInputMethodEvent *>(event));
break;
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ // Propagate panel activation.
+ if (d_ptr->scene) {
+ for (int i = 0; i < d_ptr->children.size(); ++i) {
+ QGraphicsItem *child = d_ptr->children.at(i);
+ if (!(child->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents))
+ d_ptr->scene->sendEvent(child, event);
+ }
+ }
+ break;
default:
return false;
}
@@ -5209,22 +6243,24 @@ void QGraphicsItem::dropEvent(QGraphicsSceneDragDropEvent *event)
focus in events for this item. The default implementation calls
ensureVisible().
- \sa focusOutEvent(), sceneEvent()
+ \sa focusOutEvent(), sceneEvent(), setFocus()
*/
void QGraphicsItem::focusInEvent(QFocusEvent *event)
{
Q_UNUSED(event);
+ update();
}
/*!
This event handler, for event \a event, can be reimplemented to receive
focus out events for this item. The default implementation does nothing.
- \sa focusInEvent(), sceneEvent()
+ \sa focusInEvent(), sceneEvent(), setFocus()
*/
void QGraphicsItem::focusOutEvent(QFocusEvent *event)
{
Q_UNUSED(event);
+ update();
}
/*!
@@ -5239,7 +6275,7 @@ void QGraphicsItem::focusOutEvent(QFocusEvent *event)
void QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
- d_ptr->updateHelper();
+ update();
}
/*!
@@ -5267,7 +6303,7 @@ void QGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
- d_ptr->updateHelper();
+ update();
}
/*!
@@ -5604,7 +6640,7 @@ void QGraphicsItem::inputMethodEvent(QInputMethodEvent *event)
surrounding text and reconversions. \a query specifies which
property is queried.
- \sa inputMethodEvent()
+ \sa inputMethodEvent(), QInputMethodEvent, QInputContext
*/
QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const
{
@@ -5620,6 +6656,39 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const
}
/*!
+ Returns the current input method hints of this item.
+
+ Input method hints are only relevant for input items.
+ The hints are used by the input method to indicate how it should operate.
+ For example, if the Qt::ImhNumbersOnly flag is set, the input method may change
+ its visual components to reflect that only numbers can be entered.
+
+ The effect may vary between input method implementations.
+
+ \since 4.6
+
+ \sa setInputMethodHints(), inputMethodQuery(), QInputContext
+*/
+Qt::InputMethodHints QGraphicsItem::inputMethodHints() const
+{
+ Q_D(const QGraphicsItem);
+ return d->imHints;
+}
+
+/*!
+ Sets the current input method hints of this item to \a hints.
+
+ \since 4.6
+
+ \sa inputMethodHints(), inputMethodQuery(), QInputContext
+*/
+void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints)
+{
+ Q_D(QGraphicsItem);
+ d->imHints = hints;
+}
+
+/*!
This virtual function is called by QGraphicsItem to notify custom items
that some part of the item's state changes. By reimplementing this
function, your can react to a change, and in some cases, (depending on \a
@@ -5696,8 +6765,7 @@ void QGraphicsItem::addToIndex()
return;
}
if (d_ptr->scene)
- d_ptr->scene->d_func()->addToIndex(this);
- d_ptr->updateHelper();
+ d_ptr->scene->d_func()->index->addItem(this);
}
/*!
@@ -5713,9 +6781,8 @@ void QGraphicsItem::removeFromIndex()
// ### remove from child index only if applicable
return;
}
- d_ptr->updateHelper();
if (d_ptr->scene)
- d_ptr->scene->d_func()->removeFromIndex(this);
+ d_ptr->scene->d_func()->index->removeItem(this);
}
/*!
@@ -5734,9 +6801,37 @@ void QGraphicsItem::removeFromIndex()
void QGraphicsItem::prepareGeometryChange()
{
if (d_ptr->scene) {
- d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper);
+ d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true;
+ d_ptr->geometryChanged = 1;
+ d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
+ d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper;
+
QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
- scenePrivate->removeFromIndex(this);
+ scenePrivate->index->prepareBoundingRectChange(this);
+ scenePrivate->markDirty(this, QRectF(),
+ /*invalidateChildren=*/true,
+ /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper);
+
+ // For compatibility reasons, we have to update the item's old geometry
+ // if someone is connected to the changed signal or the scene has no views.
+ // Note that this has to be done *after* markDirty to ensure that
+ // _q_processDirtyItems is called before _q_emitUpdated.
+ if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex)
+ || scenePrivate->views.isEmpty()) {
+ if (d_ptr->hasTranslateOnlySceneTransform()) {
+ d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(),
+ d_ptr->sceneTransform.dy()));
+ } else {
+ d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect()));
+ }
+ }
+ }
+
+ QGraphicsItem *parent = this;
+ while ((parent = parent->d_ptr->parent)) {
+ parent->d_ptr->dirtyChildrenBoundingRect = 1;
+ // ### Only do this if the parent's effect applies to the entire subtree.
+ parent->d_ptr->notifyBoundingRectChanged = 1;
}
if (d_ptr->inSetPosHelper)
@@ -5760,7 +6855,7 @@ static void qt_graphicsItem_highlightSelected(
QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option)
{
const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1));
- if (qFuzzyCompare(qMax(murect.width(), murect.height()) + 1, 1))
+ if (qFuzzyIsNull(qMax(murect.width(), murect.height())))
return;
const QRectF mbrect = painter->transform().mapRect(item->boundingRect());
@@ -5810,11 +6905,232 @@ static void qt_graphicsItem_highlightSelected(
}
/*!
+ \class QGraphicsObject
+ \brief The QGraphicsObject class provides a base class for all graphics items that
+ require signals, slots and properties.
+ \since 4.6
+ \ingroup graphicsview-api
+
+ The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms.
+ It maps many of QGraphicsItem's basic setters and getters to properties and adds notification
+ signals for many of them.
+*/
+
+/*!
+ Constructs a QGraphicsObject with \a parent.
+*/
+QGraphicsObject::QGraphicsObject(QGraphicsItem *parent)
+ : QGraphicsItem(parent)
+{
+ QGraphicsItem::d_ptr->isObject = true;
+}
+
+/*!
+ \internal
+*/
+QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene)
+ : QGraphicsItem(dd, parent, scene)
+{
+ QGraphicsItem::d_ptr->isObject = true;
+}
+
+/*!
+ \property QGraphicsObject::parent
+ \brief the parent of the item
+
+ \sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject()
+*/
+
+/*!
+ \property QGraphicsObject::id
+ \brief the id of of the item
+
+ \sa QGraphicsItem::opacity(), QGraphicsItem::setOpacity()
+*/
+
+/*!
+ \property QGraphicsObject::opacity
+ \brief the opacity of the item
+
+ \sa QGraphicsItem::setOpacity(), QGraphicsItem::opacity()
+*/
+
+/*!
+ \fn QGraphicsObject::opacityChanged()
+
+ This signal gets emitted whenever the opacity of the item changes
+
+ \sa QGraphicsItem::opacity()
+*/
+
+/*!
+ \fn QGraphicsObject::parentChanged()
+
+ This signal gets emitted whenever the parent of the item changes
+*/
+
+/*!
+ \property QGraphicsObject::pos
+ \brief the position of the item
+
+ Describes the items position.
+
+ \sa QGraphicsItem::setPos(), QGraphicsItem::pos()
+*/
+
+/*!
+ \property QGraphicsObject::x
+ \brief the x position of the item
+
+ Describes the items x position.
+
+ \sa QGraphicsItem::setX(), setPos(), xChanged()
+*/
+
+/*!
+ \fn QGraphicsObject::xChanged()
+
+ This signal gets emitted whenever the x position of the item changes
+
+ \sa pos()
+*/
+
+/*!
+ \property QGraphicsObject::y
+ \brief the y position of the item
+
+ Describes the items y position.
+
+ \sa QGraphicsItem::setY(), setPos(), yChanged()
+*/
+
+/*!
+ \fn QGraphicsObject::yChanged()
+
+ This signal gets emitted whenever the y position of the item changes.
+
+ \sa pos()
+*/
+
+/*!
+ \property QGraphicsObject::z
+ \brief the z value of the item
+
+ Describes the items z value.
+
+ \sa QGraphicsItem::setZValue(), zValue(), zChanged()
+*/
+
+/*!
+ \fn QGraphicsObject::zChanged()
+
+ This signal gets emitted whenever the z value of the item changes.
+
+ \sa pos()
+*/
+
+/*!
+ \property QGraphicsObject::rotation
+ This property holds the rotation of the item in degrees.
+
+ This specifies how many degrees to rotate the item around its transformOrigin.
+ The default rotation is 0 degrees (i.e. not rotated at all).
+*/
+
+/*!
+ \fn QGraphicsObject::rotationChanged()
+
+ This signal gets emitted whenever the roation of the item changes.
+*/
+
+/*!
+ \property QGraphicsObject::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's transformOrigin.
+*/
+
+/*!
+ \fn void QGraphicsObject::scaleChanged()
+
+ This signal is emitted when the scale of the item changes.
+*/
+
+
+/*!
+ \property QGraphicsObject::enabled
+ \brief whether the item is enabled or not
+
+ This property is declared in QGraphicsItem.
+
+ By default, this property is true.
+
+ \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled()
+ \sa QGraphicsObject::enabledChanged()
+*/
+
+/*!
+ \fn void QGraphicsObject::enabledChanged()
+
+ This signal gets emitted whenever the item get's enabled or disabled.
+
+ \sa isEnabled()
+*/
+
+/*!
+ \property QGraphicsObject::visible
+ \brief whether the item is visible or not
+
+ This property is declared in QGraphicsItem.
+
+ By default, this property is true.
+
+ \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), visibleChanged()
+*/
+
+/*!
+ \fn QGraphicsObject::visibleChanged()
+
+ This signal gets emitted whenever the visibility of the item changes
+
+ \sa visible
+*/
+
+/*!
+ \fn const QObjectList &QGraphicsObject::children() const
+ \internal
+
+ This function returns the same value as QObject::children(). It's
+ provided to differentiate between the obsolete member
+ QGraphicsItem::children() and QObject::children(). QGraphicsItem now
+ provides childItems() instead.
+*/
+
+/*!
+ \property QGraphicsObject::transformOriginPoint
+ \brief the transformation origin
+
+ This property sets a specific point in the items coordiante system as the
+ origin for scale and rotation.
+
+ \sa scale, rotation, QGraphicsItem::transformOriginPoint()
+*/
+
+
+/*!
\class QAbstractGraphicsShapeItem
\brief The QAbstractGraphicsShapeItem class provides a common base for
all path items.
\since 4.2
- \ingroup multimedia
+ \ingroup graphicsview-api
This class does not fully implement an item by itself; in particular, it
does not implement boundingRect() and paint(), which are inherited by
@@ -5949,7 +7265,6 @@ QPainterPath QAbstractGraphicsShapeItem::opaqueArea() const
\brief The QGraphicsPathItem class provides a path item that you
can add to a QGraphicsScene.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
To set the item's path, pass a QPainterPath to QGraphicsPathItem's
@@ -6152,7 +7467,6 @@ QVariant QGraphicsPathItem::extension(const QVariant &variant) const
\brief The QGraphicsRectItem class provides a rectangle item that you
can add to a QGraphicsScene.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
To set the item's rectangle, pass a QRectF to QGraphicsRectItem's
@@ -6397,7 +7711,6 @@ QVariant QGraphicsRectItem::extension(const QVariant &variant) const
\brief The QGraphicsEllipseItem class provides an ellipse item that you
can add to a QGraphicsScene.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
QGraphicsEllipseItem respresents an ellipse with a fill and an outline,
@@ -6714,7 +8027,6 @@ QVariant QGraphicsEllipseItem::extension(const QVariant &variant) const
\brief The QGraphicsPolygonItem class provides a polygon item that you
can add to a QGraphicsScene.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
To set the item's polygon, pass a QPolygonF to
@@ -6948,7 +8260,6 @@ QVariant QGraphicsPolygonItem::extension(const QVariant &variant) const
\brief The QGraphicsLineItem class provides a line item that you can add to a
QGraphicsScene.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
To set the item's line, pass a QLineF to QGraphicsLineItem's
@@ -7210,7 +8521,6 @@ QVariant QGraphicsLineItem::extension(const QVariant &variant) const
\brief The QGraphicsPixmapItem class provides a pixmap item that you can add to
a QGraphicsScene.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
To set the item's pixmap, pass a QPixmap to QGraphicsPixmapItem's
@@ -7399,7 +8709,6 @@ void QGraphicsPixmapItem::setTransformationMode(Qt::TransformationMode mode)
{
Q_D(QGraphicsPixmapItem);
if (mode != d->transformationMode) {
- d_ptr->updateHelper();
d->transformationMode = mode;
update();
}
@@ -7487,9 +8796,7 @@ void QGraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsIte
painter->setRenderHint(QPainter::SmoothPixmapTransform,
(d->transformationMode == Qt::SmoothTransformation));
- QRectF exposed = option->exposedRect.adjusted(-1, -1, 1, 1);
- exposed &= QRectF(d->offset.x(), d->offset.y(), d->pixmap.width(), d->pixmap.height());
- painter->drawPixmap(exposed, d->pixmap, exposed.translated(-d->offset));
+ painter->drawPixmap(d->offset, d->pixmap);
if (option->state & QStyle::State_Selected)
qt_graphicsItem_highlightSelected(this, painter, option);
@@ -7577,7 +8884,6 @@ QVariant QGraphicsPixmapItem::extension(const QVariant &variant) const
\brief The QGraphicsTextItem class provides a text item that you can add to
a QGraphicsScene to display formatted text.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
If you only need to show plain text in an item, consider using QGraphicsSimpleTextItem
@@ -7612,7 +8918,7 @@ class QGraphicsTextItemPrivate
{
public:
QGraphicsTextItemPrivate()
- : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false)
+ : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false), clickCausedFocus(0)
{ }
mutable QTextControl *control;
@@ -7633,9 +8939,12 @@ public:
bool useDefaultImpl;
bool tabChangesFocus;
+ uint clickCausedFocus : 1;
+
QGraphicsTextItem *qq;
};
+
/*!
Constructs a QGraphicsTextItem, using \a text as the default plain
text. \a parent is passed to QGraphicsItem's constructor.
@@ -7648,13 +8957,14 @@ QGraphicsTextItem::QGraphicsTextItem(const QString &text, QGraphicsItem *parent
, QGraphicsScene *scene
#endif
)
- : QGraphicsItem(parent, scene), dd(new QGraphicsTextItemPrivate)
+ : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate)
{
dd->qq = this;
if (!text.isEmpty())
setPlainText(text);
setAcceptDrops(true);
setAcceptHoverEvents(true);
+ setFlags(ItemUsesExtendedStyleOption);
}
/*!
@@ -7669,11 +8979,12 @@ QGraphicsTextItem::QGraphicsTextItem(QGraphicsItem *parent
, QGraphicsScene *scene
#endif
)
- : QGraphicsItem(parent, scene), dd(new QGraphicsTextItemPrivate)
+ : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate)
{
dd->qq = this;
setAcceptDrops(true);
setAcceptHoverEvents(true);
+ setFlag(ItemUsesExtendedStyleOption);
}
/*!
@@ -7935,7 +9246,42 @@ bool QGraphicsTextItem::sceneEvent(QEvent *event)
return true;
}
}
- return QGraphicsItem::sceneEvent(event);
+ bool result = QGraphicsItem::sceneEvent(event);
+
+ // Ensure input context is updated.
+ switch (event->type()) {
+ case QEvent::ContextMenu:
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ case QEvent::GraphicsSceneDragEnter:
+ case QEvent::GraphicsSceneDragLeave:
+ case QEvent::GraphicsSceneDragMove:
+ case QEvent::GraphicsSceneDrop:
+ case QEvent::GraphicsSceneHoverEnter:
+ case QEvent::GraphicsSceneHoverLeave:
+ case QEvent::GraphicsSceneHoverMove:
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ // Reset the focus widget's input context, regardless
+ // of how this item gained or lost focus.
+ if (QWidget *fw = qApp->focusWidget()) {
+ if (QInputContext *qic = fw->inputContext()) {
+ if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut)
+ qic->reset();
+ else
+ qic->update();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return result;
}
/*!
@@ -7944,21 +9290,22 @@ bool QGraphicsTextItem::sceneEvent(QEvent *event)
void QGraphicsTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if ((QGraphicsItem::d_ptr->flags & (ItemIsSelectable | ItemIsMovable))
- && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) {
- // User left-pressed on edge of selectable/movable item, use
- // base impl.
- dd->useDefaultImpl = true;
+ && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) {
+ // User left-pressed on edge of selectable/movable item, use
+ // base impl.
+ dd->useDefaultImpl = true;
} else if (event->buttons() == event->button()
- && dd->control->textInteractionFlags() == Qt::NoTextInteraction) {
- // User pressed first button on non-interactive item.
- dd->useDefaultImpl = true;
+ && dd->control->textInteractionFlags() == Qt::NoTextInteraction) {
+ // User pressed first button on non-interactive item.
+ dd->useDefaultImpl = true;
}
if (dd->useDefaultImpl) {
QGraphicsItem::mousePressEvent(event);
- if (!event->isAccepted())
- dd->useDefaultImpl = false;
+ if (!event->isAccepted())
+ dd->useDefaultImpl = false;
return;
}
+
dd->sendControlEvent(event);
}
@@ -7971,6 +9318,7 @@ void QGraphicsTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
QGraphicsItem::mouseMoveEvent(event);
return;
}
+
dd->sendControlEvent(event);
}
@@ -7981,16 +9329,22 @@ void QGraphicsTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (dd->useDefaultImpl) {
QGraphicsItem::mouseReleaseEvent(event);
- if (dd->control->textInteractionFlags() == Qt::NoTextInteraction
- && !event->buttons()) {
- // User released last button on non-interactive item.
+ if (dd->control->textInteractionFlags() == Qt::NoTextInteraction
+ && !event->buttons()) {
+ // User released last button on non-interactive item.
dd->useDefaultImpl = false;
- } else if ((event->buttons() & Qt::LeftButton) == 0) {
- // User released the left button on an interactive item.
+ } else if ((event->buttons() & Qt::LeftButton) == 0) {
+ // User released the left button on an interactive item.
dd->useDefaultImpl = false;
- }
+ }
return;
}
+
+ QWidget *widget = event->widget();
+ if (widget) {
+ qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), dd->clickCausedFocus);
+ }
+ dd->clickCausedFocus = 0;
dd->sendControlEvent(event);
}
@@ -8042,6 +9396,9 @@ void QGraphicsTextItem::keyReleaseEvent(QKeyEvent *event)
void QGraphicsTextItem::focusInEvent(QFocusEvent *event)
{
dd->sendControlEvent(event);
+ if (event->reason() == Qt::MouseFocusReason) {
+ dd->clickCausedFocus = 1;
+ }
update();
}
@@ -8278,9 +9635,9 @@ bool QGraphicsTextItemPrivate::_q_mouseOnEdge(QGraphicsSceneMouseEvent *event)
Sets the flags \a flags to specify how the text item should react to user
input.
- The default for a QGraphicsTextItem is Qt::NoTextInteraction. Setting a
- value different to Qt::NoTextInteraction will also set the ItemIsFocusable
- QGraphicsItem flag.
+ The default for a QGraphicsTextItem is Qt::NoTextInteraction. This function
+ also affects the ItemIsFocusable QGraphicsItem flag by setting it if \a flags
+ is different from Qt::NoTextInteraction and clearing it otherwise.
By default, the text is read-only. To transform the item into an editor,
set the Qt::TextEditable flag.
@@ -8439,7 +9796,6 @@ void QGraphicsSimpleTextItemPrivate::updateBoundingRect()
\brief The QGraphicsSimpleTextItem class provides a simple text path item
that you can add to a QGraphicsScene.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
To set the item's text, you can either pass a QString to
@@ -8675,7 +10031,6 @@ QVariant QGraphicsSimpleTextItem::extension(const QVariant &variant) const
\brief The QGraphicsItemGroup class provides treating a group of items as
one.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
A QGraphicsItemGroup is a special type of compound item that
@@ -8690,13 +10045,10 @@ QVariant QGraphicsSimpleTextItem::extension(const QVariant &variant) const
setParentItem().
The boundingRect() function of QGraphicsItemGroup returns the
- bounding rectangle of all items in the item group. In addition,
- item groups have handlesChildEvents() enabled by default, so all
- events sent to a member of the group go to the item group (i.e.,
- selecting one item in a group will select them all).
- QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on its
- children (i.e., with respect to the geometry of the group item, the
- children are treated as if they were transformable).
+ bounding rectangle of all items in the item group.
+ QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on
+ its children (i.e., with respect to the geometry of the group
+ item, the children are treated as if they were transformable).
There are two ways to construct an item group. The easiest and
most common approach is to pass a list of items (e.g., all
@@ -8781,19 +10133,26 @@ void QGraphicsItemGroup::addToGroup(QGraphicsItem *item)
return;
}
- QTransform oldSceneMatrix = item->sceneTransform();
+ // COMBINE
+ bool ok;
+ QTransform itemTransform = item->itemTransform(this, &ok);
+
+ if (!ok) {
+ qWarning("QGraphicsItemGroup::addToGroup: could not find a valid transformation from item to group coordinates");
+ return;
+ }
+
+ QTransform newItemTransform(itemTransform);
item->setPos(mapFromItem(item, 0, 0));
item->setParentItem(this);
- QTransform newItemTransform(oldSceneMatrix);
- newItemTransform *= sceneTransform().inverted();
+
+ // removing position from translation component of the new transform
if (!item->pos().isNull())
newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y());
+
item->setTransform(newItemTransform);
item->d_func()->setIsMemberOfGroup(true);
prepareGeometryChange();
- QTransform itemTransform(item->transform());
- if (!item->pos().isNull())
- itemTransform *= QTransform::fromTranslate(item->x(), item->y());
d->itemsBoundingRect |= itemTransform.mapRect(item->boundingRect() | item->childrenBoundingRect());
update();
}
@@ -8876,6 +10235,123 @@ int QGraphicsItemGroup::type() const
return Type;
}
+QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
+{
+ const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
+ if (!info && deviceCoordinates) {
+ // Device coordinates without info not yet supported.
+ qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
+ return QRectF();
+ }
+
+ QRectF rect = item->boundingRect();
+ if (!item->d_ptr->children.isEmpty())
+ rect |= item->childrenBoundingRect();
+
+ if (deviceCoordinates) {
+ Q_ASSERT(info->painter);
+ rect = info->painter->worldTransform().mapRect(rect);
+ }
+
+ return rect;
+}
+
+void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
+{
+ if (!info) {
+ qWarning("QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw");
+ return;
+ }
+
+ Q_ASSERT(item->d_ptr->scene);
+ QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
+ if (painter == info->painter) {
+ scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion,
+ info->widget, info->opacity, info->effectTransform, info->wasDirtySceneTransform,
+ info->drawItem);
+ } else {
+ QTransform effectTransform = info->painter->worldTransform().inverted();
+ effectTransform *= painter->worldTransform();
+ scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion,
+ info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
+ info->drawItem);
+ }
+}
+
+QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
+{
+ const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
+ if (!info && deviceCoordinates) {
+ // Device coordinates without info not yet supported.
+ qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
+ return QPixmap();
+ }
+
+ if (!item->d_ptr->scene)
+ return QPixmap();
+ QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
+
+ const QRectF sourceRect = boundingRect(system);
+ QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
+ if (offset)
+ *offset = effectRect.topLeft();
+
+ if (deviceCoordinates) {
+ // Clip to viewport rect.
+ int left, top, right, bottom;
+ effectRect.getCoords(&left, &top, &right, &bottom);
+ if (left < 0) {
+ if (offset)
+ offset->rx() += -left;
+ effectRect.setX(0);
+ }
+ if (top < 0) {
+ if (offset)
+ offset->ry() += -top;
+ effectRect.setY(0);
+ }
+ // NB! We use +-1 for historical reasons (see QRect documentation).
+ if (right + 1 > info->widget->width())
+ effectRect.setRight(info->widget->width() - 1);
+ if (bottom + 1 > info->widget->height())
+ effectRect.setBottom(info->widget->height() -1);
+ }
+
+ if (effectRect.isEmpty())
+ return QPixmap();
+
+ QPixmap pixmap(effectRect.size());
+ pixmap.fill(Qt::transparent);
+ QPainter pixmapPainter(&pixmap);
+ pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing);
+
+ QTransform effectTransform = QTransform::fromTranslate(-effectRect.x(), -effectRect.y());
+ if (deviceCoordinates && info->effectTransform)
+ effectTransform *= *info->effectTransform;
+
+ if (!info) {
+ // Logical coordinates without info.
+ QTransform sceneTransform = item->sceneTransform();
+ QTransform newEffectTransform = sceneTransform.inverted();
+ newEffectTransform *= effectTransform;
+ scened->draw(item, &pixmapPainter, 0, &sceneTransform, 0, 0, qreal(1.0),
+ &newEffectTransform, false, true);
+ } else if (deviceCoordinates) {
+ // Device coordinates with info.
+ scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion,
+ info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
+ info->drawItem);
+ } else {
+ // Item coordinates with info.
+ QTransform newEffectTransform = info->transformPtr->inverted();
+ newEffectTransform *= effectTransform;
+ scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion,
+ info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform,
+ info->drawItem);
+ }
+ return pixmap;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, QGraphicsItem *item)
{
@@ -8884,17 +10360,11 @@ QDebug operator<<(QDebug debug, QGraphicsItem *item)
return debug;
}
- QStringList flags;
- if (item->isVisible()) flags << QLatin1String("isVisible");
- if (item->isEnabled()) flags << QLatin1String("isEnabled");
- if (item->isSelected()) flags << QLatin1String("isSelected");
- if (item->hasFocus()) flags << QLatin1String("HasFocus");
-
debug << "QGraphicsItem(this =" << ((void*)item)
<< ", parent =" << ((void*)item->parentItem())
<< ", pos =" << item->pos()
- << ", z =" << item->zValue() << ", flags = {"
- << flags.join(QLatin1String("|")) << " })";
+ << ", z =" << item->zValue() << ", flags = "
+ << item->flags() << ")";
return debug;
}
@@ -9019,6 +10489,27 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemStacksBehindParent:
str = "ItemStacksBehindParent";
break;
+ case QGraphicsItem::ItemUsesExtendedStyleOption:
+ str = "ItemUsesExtendedStyleOption";
+ break;
+ case QGraphicsItem::ItemHasNoContents:
+ str = "ItemHasNoContents";
+ break;
+ case QGraphicsItem::ItemSendsGeometryChanges:
+ str = "ItemSendsGeometryChanges";
+ break;
+ case QGraphicsItem::ItemAcceptsInputMethod:
+ str = "ItemAcceptsInputMethod";
+ break;
+ case QGraphicsItem::ItemNegativeZStacksBehindParent:
+ str = "ItemNegativeZStacksBehindParent";
+ break;
+ case QGraphicsItem::ItemAutoDetectsFocusProxy:
+ str = "ItemAutoDetectsFocusProxy";
+ break;
+ case QGraphicsItem::ItemIsPanel:
+ str = "ItemIsPanel";
+ break;
}
debug << str;
return debug;
@@ -9026,17 +10517,17 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags)
{
- debug << "(";
+ debug << '(';
bool f = false;
- for (int i = 0; i < 9; ++i) {
+ for (int i = 0; i < 16; ++i) {
if (flags & (1 << i)) {
if (f)
- debug << "|";
+ debug << '|';
f = true;
debug << QGraphicsItem::GraphicsItemFlag(int(flags & (1 << i)));
}
}
- debug << ")";
+ debug << ')';
return debug;
}
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 920bbfd..04fe0cb 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -46,6 +46,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qvariant.h>
#include <QtCore/qrect.h>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qpainterpath.h>
#include <QtGui/qpixmap.h>
@@ -62,7 +63,9 @@ QT_MODULE(Gui)
class QBrush;
class QCursor;
class QFocusEvent;
+class QGraphicsEffect;
class QGraphicsItemGroup;
+class QGraphicsObject;
class QGraphicsSceneContextMenuEvent;
class QGraphicsSceneDragDropEvent;
class QGraphicsSceneEvent;
@@ -70,6 +73,7 @@ class QGraphicsSceneHoverEvent;
class QGraphicsSceneMouseEvent;
class QGraphicsSceneWheelEvent;
class QGraphicsScene;
+class QGraphicsTransform;
class QGraphicsWidget;
class QInputMethodEvent;
class QKeyEvent;
@@ -94,7 +98,15 @@ public:
ItemIgnoresTransformations = 0x20,
ItemIgnoresParentOpacity = 0x40,
ItemDoesntPropagateOpacityToChildren = 0x80,
- ItemStacksBehindParent = 0x100
+ ItemStacksBehindParent = 0x100,
+ ItemUsesExtendedStyleOption = 0x200,
+ ItemHasNoContents = 0x400,
+ ItemSendsGeometryChanges = 0x800,
+ ItemAcceptsInputMethod = 0x1000,
+ ItemAutoDetectsFocusProxy = 0x2000,
+ ItemNegativeZStacksBehindParent = 0x4000,
+ ItemIsPanel = 0x8000
+ // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
@@ -136,7 +148,7 @@ public:
QGraphicsItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -146,14 +158,20 @@ public:
QGraphicsItem *parentItem() const;
QGraphicsItem *topLevelItem() const;
+ QGraphicsObject *parentObject() const;
QGraphicsWidget *parentWidget() const;
QGraphicsWidget *topLevelWidget() const;
QGraphicsWidget *window() const;
+ QGraphicsItem *panel() const;
void setParentItem(QGraphicsItem *parent);
QList<QGraphicsItem *> children() const; // ### obsolete
QList<QGraphicsItem *> childItems() const;
bool isWidget() const;
bool isWindow() const;
+ bool isPanel() const;
+
+ QGraphicsObject *toGraphicsObject();
+ const QGraphicsObject *toGraphicsObject() const;
QGraphicsItemGroup *group() const;
void setGroup(QGraphicsItemGroup *group);
@@ -196,21 +214,36 @@ public:
qreal effectiveOpacity() const;
void setOpacity(qreal opacity);
+ // Effect
+ QGraphicsEffect *graphicsEffect() const;
+ void setGraphicsEffect(QGraphicsEffect *effect);
+
Qt::MouseButtons acceptedMouseButtons() const;
void setAcceptedMouseButtons(Qt::MouseButtons buttons);
- bool acceptsHoverEvents() const; // obsolete
- void setAcceptsHoverEvents(bool enabled); // obsolete
+ bool acceptsHoverEvents() const; // ### obsolete
+ void setAcceptsHoverEvents(bool enabled); // ### obsolete
bool acceptHoverEvents() const;
void setAcceptHoverEvents(bool enabled);
+ bool acceptTouchEvents() const;
+ void setAcceptTouchEvents(bool enabled);
+
+ bool filtersChildEvents() const;
+ void setFiltersChildEvents(bool enabled);
bool handlesChildEvents() const;
void setHandlesChildEvents(bool enabled);
+ bool isActive() const;
bool hasFocus() const;
void setFocus(Qt::FocusReason focusReason = Qt::OtherFocusReason);
void clearFocus();
+ QGraphicsItem *focusProxy() const;
+ void setFocusProxy(QGraphicsItem *item);
+
+ QGraphicsItem *focusItem() const;
+
void grabMouse();
void ungrabMouse();
void grabKeyboard();
@@ -219,7 +252,9 @@ public:
// Positioning in scene coordinates
QPointF pos() const;
inline qreal x() const { return pos().x(); }
+ void setX(qreal x);
inline qreal y() const { return pos().y(); }
+ void setY(qreal y);
QPointF scenePos() const;
void setPos(const QPointF &pos);
inline void setPos(qreal x, qreal y);
@@ -239,11 +274,26 @@ public:
QTransform itemTransform(const QGraphicsItem *other, bool *ok = 0) const;
void setTransform(const QTransform &matrix, bool combine = false);
void resetTransform();
-
- void rotate(qreal angle);
- void scale(qreal sx, qreal sy);
- void shear(qreal sh, qreal sv);
- void translate(qreal dx, qreal dy);
+
+ void rotate(qreal angle); // ### obsolete
+ void scale(qreal sx, qreal sy); // ### obsolete
+ void shear(qreal sh, qreal sv); // ### obsolete
+ void translate(qreal dx, qreal dy); // ### obsolete
+
+ void setRotation(qreal angle);
+ qreal rotation() const;
+
+ void setScale(qreal scale);
+ qreal scale() const;
+
+ QList<QGraphicsTransform *> transformations() const;
+ void setTransformations(const QList<QGraphicsTransform *> &transformations);
+
+ QPointF transformOriginPoint() const;
+ void setTransformOriginPoint(const QPointF &origin);
+ inline void setTransformOriginPoint(qreal x, qreal y)
+ { setTransformOriginPoint(QPointF(x,y)); }
+
virtual void advance(int phase);
// Stacking order
@@ -336,6 +386,9 @@ public:
QVariant data(int key) const;
void setData(int key, const QVariant &value);
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
+
enum {
Type = 1,
UserType = 65536
@@ -380,7 +433,7 @@ protected:
protected:
QGraphicsItem(QGraphicsItemPrivate &dd,
QGraphicsItem *parent, QGraphicsScene *scene);
- QGraphicsItemPrivate *d_ptr;
+ QScopedPointer<QGraphicsItemPrivate> d_ptr;
void addToIndex();
void removeFromIndex();
@@ -393,17 +446,25 @@ private:
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
friend class QGraphicsSceneFindItemBspTreeVisitor;
+ friend class QGraphicsSceneBspTree;
friend class QGraphicsView;
friend class QGraphicsViewPrivate;
friend class QGraphicsWidget;
friend class QGraphicsWidgetPrivate;
friend class QGraphicsProxyWidgetPrivate;
+ friend class QGraphicsSceneIndex;
+ friend class QGraphicsSceneIndexPrivate;
+ friend class QGraphicsSceneBspTreeIndex;
+ friend class QGraphicsSceneBspTreeIndexPrivate;
+ friend class QGraphicsItemEffectSourcePrivate;
+ friend class QGraphicsTransformPrivate;
friend class ::tst_QGraphicsItem;
friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *);
friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsItem::GraphicsItemFlags)
+Q_DECLARE_INTERFACE(QGraphicsItem, "com.trolltech.Qt.QGraphicsItem")
inline void QGraphicsItem::setPos(qreal ax, qreal ay)
{ setPos(QPointF(ax, ay)); }
@@ -450,13 +511,59 @@ inline QRectF QGraphicsItem::mapRectFromParent(qreal ax, qreal ay, qreal w, qrea
inline QRectF QGraphicsItem::mapRectFromScene(qreal ax, qreal ay, qreal w, qreal h) const
{ return mapRectFromScene(QRectF(ax, ay, w, h)); }
+
+class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QGraphicsObject * parent READ parentObject WRITE setParentItem NOTIFY parentChanged DESIGNABLE false)
+ Q_PROPERTY(QString id READ objectName WRITE setObjectName)
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
+ Q_PROPERTY(QPointF pos READ pos WRITE setPos)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+ Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged)
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
+ Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
+ Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint)
+ Q_INTERFACES(QGraphicsItem)
+public:
+ QGraphicsObject(QGraphicsItem *parent = 0);
+
+ // ### Qt 5: Disambiguate
+#ifdef Q_NO_USING_KEYWORD
+ const QObjectList &children() const { return QObject::children(); }
+#else
+ using QObject::children;
+#endif
+
+Q_SIGNALS:
+ void parentChanged();
+ void opacityChanged();
+ void visibleChanged();
+ void enabledChanged();
+ void xChanged();
+ void yChanged();
+ void zChanged();
+ void rotationChanged();
+ void scaleChanged();
+
+protected:
+ QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene);
+private:
+ friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
+};
+
+
class QAbstractGraphicsShapeItemPrivate;
class Q_GUI_EXPORT QAbstractGraphicsShapeItem : public QGraphicsItem
{
public:
QAbstractGraphicsShapeItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -486,13 +593,13 @@ class Q_GUI_EXPORT QGraphicsPathItem : public QAbstractGraphicsShapeItem
public:
QGraphicsPathItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsPathItem(const QPainterPath &path, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -529,19 +636,19 @@ class Q_GUI_EXPORT QGraphicsRectItem : public QAbstractGraphicsShapeItem
public:
QGraphicsRectItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsRectItem(const QRectF &rect, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsRectItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -582,19 +689,19 @@ class Q_GUI_EXPORT QGraphicsEllipseItem : public QAbstractGraphicsShapeItem
public:
QGraphicsEllipseItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsEllipseItem(const QRectF &rect, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsEllipseItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -641,14 +748,14 @@ class Q_GUI_EXPORT QGraphicsPolygonItem : public QAbstractGraphicsShapeItem
public:
QGraphicsPolygonItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsPolygonItem(const QPolygonF &polygon,
QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -688,19 +795,19 @@ class Q_GUI_EXPORT QGraphicsLineItem : public QGraphicsItem
public:
QGraphicsLineItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsLineItem(const QLineF &line, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsLineItem(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -748,13 +855,13 @@ public:
QGraphicsPixmapItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -801,7 +908,7 @@ inline void QGraphicsPixmapItem::setOffset(qreal ax, qreal ay)
class QGraphicsTextItemPrivate;
class QTextDocument;
class QTextCursor;
-class Q_GUI_EXPORT QGraphicsTextItem : public QObject, public QGraphicsItem
+class Q_GUI_EXPORT QGraphicsTextItem : public QGraphicsObject
{
Q_OBJECT
QDOC_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks)
@@ -810,13 +917,13 @@ class Q_GUI_EXPORT QGraphicsTextItem : public QObject, public QGraphicsItem
public:
QGraphicsTextItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsTextItem(const QString &text, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -911,13 +1018,13 @@ class Q_GUI_EXPORT QGraphicsSimpleTextItem : public QAbstractGraphicsShapeItem
public:
QGraphicsSimpleTextItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsSimpleTextItem(const QString &text, QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -957,7 +1064,7 @@ class Q_GUI_EXPORT QGraphicsItemGroup : public QGraphicsItem
public:
QGraphicsItemGroup(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -1013,4 +1120,3 @@ QT_END_NAMESPACE
QT_END_HEADER
#endif // QGRAPHICSITEM_H
-
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 3a0ad82..2bc876c 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -47,13 +47,22 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
#include "qgraphicsitem.h"
+#include "qset.h"
+#include "qpixmapcache.h"
+#include <private/qgraphicsview_p.h>
+#include "qgraphicstransform.h"
+#include <private/qgraphicstransform_p.h>
+
+#include <private/qgraphicseffect_p.h>
+
+#include <QtCore/qpoint.h>
#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
@@ -69,13 +78,14 @@ public:
// ItemCoordinateCache only
QRect boundingRect;
QSize fixedSize;
- QString key;
+ QPixmapCache::Key key;
// DeviceCoordinateCache only
struct DeviceData {
+ DeviceData() {}
QTransform lastTransform;
QPoint cacheIndent;
- QString key;
+ QPixmapCache::Key key;
};
QMap<QPaintDevice *, DeviceData> deviceData;
@@ -87,34 +97,39 @@ public:
void purge();
};
-class Q_AUTOTEST_EXPORT QGraphicsItemPrivate
+class Q_GUI_EXPORT QGraphicsItemPrivate
{
Q_DECLARE_PUBLIC(QGraphicsItem)
public:
enum Extra {
- ExtraTransform,
ExtraToolTip,
ExtraCursor,
ExtraCacheData,
ExtraMaxDeviceCoordCacheSize,
- ExtraBoundingRegionGranularity,
- ExtraOpacity,
- ExtraEffectiveOpacity
+ ExtraBoundingRegionGranularity
};
enum AncestorFlag {
NoFlag = 0,
AncestorHandlesChildEvents = 0x1,
AncestorClipsChildren = 0x2,
- AncestorIgnoresTransformations = 0x4
+ AncestorIgnoresTransformations = 0x4,
+ AncestorFiltersChildEvents = 0x8
};
inline QGraphicsItemPrivate()
: z(0),
+ opacity(1.),
scene(0),
parent(0),
+ transformData(0),
+ graphicsEffect(0),
index(-1),
- depth(0),
+ siblingIndex(-1),
+ itemDepth(-1),
+ focusProxy(0),
+ subFocusItem(0),
+ imHints(Qt::ImhNone),
acceptedMouseButtons(0x1f),
visible(1),
explicitlyHidden(0),
@@ -126,14 +141,10 @@ public:
isMemberOfGroup(0),
handlesChildEvents(0),
itemDiscovered(0),
- hasTransform(0),
hasCursor(0),
ancestorFlags(0),
cacheMode(0),
hasBoundingRegionGranularity(0),
- flags(0),
- hasOpacity(0),
- hasEffectiveOpacity(0),
isWidget(0),
dirty(0),
dirtyChildren(0),
@@ -141,9 +152,26 @@ public:
dirtyClipPath(1),
emptyClipPath(0),
inSetPosHelper(0),
- allChildrenCombineOpacity(1),
+ needSortChildren(1),
+ allChildrenDirty(0),
+ fullUpdatePending(0),
+ flags(0),
+ dirtyChildrenBoundingRect(1),
+ paintedViewBoundingRectsNeedRepaint(0),
+ dirtySceneTransform(1),
+ geometryChanged(1),
+ inDestructor(0),
+ isObject(0),
+ ignoreVisible(0),
+ ignoreOpacity(0),
+ acceptTouchEvents(0),
+ acceptedTouchBeginEvent(0),
+ filtersDescendantEvents(0),
+ sceneTransformTranslateOnly(0),
+ notifyBoundingRectChanged(0),
+ notifyInvalidated(0),
+ mouseSetsFocus(1),
globalStackingOrder(-1),
- sceneTransformIndex(-1),
q_ptr(0)
{
}
@@ -151,28 +179,52 @@ public:
inline virtual ~QGraphicsItemPrivate()
{ }
+ static const QGraphicsItemPrivate *get(const QGraphicsItem *item)
+ {
+ return item->d_ptr.data();
+ }
+ static QGraphicsItemPrivate *get(QGraphicsItem *item)
+ {
+ return item->d_ptr.data();
+ }
+
void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
AncestorFlag flag = NoFlag, bool enabled = false, bool root = true);
void setIsMemberOfGroup(bool enabled);
void remapItemPos(QEvent *event, QGraphicsItem *item);
QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const;
- bool itemIsUntransformable() const;
+ inline bool itemIsUntransformable() const
+ {
+ return (flags & QGraphicsItem::ItemIgnoresTransformations)
+ || (ancestorFlags & AncestorIgnoresTransformations);
+ }
+
+ void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const;
+ void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const;
+ virtual void updateSceneTransformFromParent();
// ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4.
virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const;
static bool movableAncestorIsSelected(const QGraphicsItem *item);
- void setPosHelper(const QPointF &pos);
+ virtual void setPosHelper(const QPointF &pos);
+ void setTransformHelper(const QTransform &transform);
+ void appendGraphicsTransform(QGraphicsTransform *t);
void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true);
bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false,
bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
- void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false);
- void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false, bool ignoreOpacity = false);
- void updateEffectiveOpacity();
- void resolveEffectiveOpacity(qreal effectiveParentOpacity);
- void resolveDepth(int parentDepth);
- void invalidateSceneTransformCache();
+ int depth() const;
+ void invalidateDepthRecursively();
+ void resolveDepth();
+ void addChild(QGraphicsItem *child);
+ void removeChild(QGraphicsItem *child);
+ void setParentItemHelper(QGraphicsItem *parent);
+ void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
+ void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
+ const QRegion &exposedRegion, bool allItems = false) const;
+ QRectF effectiveBoundingRect() const;
+ QRectF sceneEffectiveBoundingRect() const;
virtual void resolveFont(uint inheritedMask)
{
@@ -236,8 +288,10 @@ public:
bool operator<(Extra extra) const
{ return type < extra; }
};
+
QList<ExtraStruct> extras;
+ QGraphicsItemCache *maybeExtraItemCache() const;
QGraphicsItemCache *extraItemCache() const;
void removeExtraItemCache();
@@ -261,12 +315,83 @@ public:
void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF());
void updateCachedClipPathFromSetPosHelper(const QPointF &newPos);
+ void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem);
+ void ensureSceneTransform();
+
+ inline bool hasTranslateOnlySceneTransform()
+ {
+ ensureSceneTransform();
+ return sceneTransformTranslateOnly;
+ }
+
+ inline void invalidateChildrenSceneTransform()
+ {
+ for (int i = 0; i < children.size(); ++i)
+ children.at(i)->d_ptr->dirtySceneTransform = 1;
+ }
+
+ inline qreal calcEffectiveOpacity() const
+ {
+ qreal o = opacity;
+ QGraphicsItem *p = parent;
+ int myFlags = flags;
+ while (p) {
+ int parentFlags = p->d_ptr->flags;
+
+ // If I have a parent, and I don't ignore my parent's opacity, and my
+ // parent propagates to me, then combine my local opacity with my parent's
+ // effective opacity into my effective opacity.
+ if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
+ || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
+ break;
+ }
+
+ o *= p->d_ptr->opacity;
+ p = p->d_ptr->parent;
+ myFlags = parentFlags;
+ }
+ return o;
+ }
inline bool isFullyTransparent() const
- { return hasEffectiveOpacity && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0)); }
+ {
+ if (opacity < 0.001)
+ return true;
+ if (!parent)
+ return false;
+
+ return calcEffectiveOpacity() < 0.001;
+ }
+
+ inline qreal effectiveOpacity() const {
+ if (!parent || !opacity)
+ return opacity;
+
+ return calcEffectiveOpacity();
+ }
+
+ inline qreal combineOpacityFromParent(qreal parentOpacity) const
+ {
+ if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity)
+ && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
+ return parentOpacity * opacity;
+ }
+ return opacity;
+ }
inline bool childrenCombineOpacity() const
- { return allChildrenCombineOpacity || children.isEmpty(); }
+ {
+ if (!children.size())
+ return true;
+ if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
+ return false;
+
+ for (int i = 0; i < children.size(); ++i) {
+ if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)
+ return false;
+ }
+ return true;
+ }
inline bool isClippedAway() const
{ return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); }
@@ -281,16 +406,36 @@ public:
|| (childrenCombineOpacity() && isFullyTransparent());
}
+ void setSubFocus();
+ void clearSubFocus();
+ void resetFocusProxy();
+
+ inline QTransform transformToParent() const;
+ inline void ensureSortedChildren();
+
QPainterPath cachedClipPath;
+ QRectF childrenBoundingRect;
+ QRectF needsRepaint;
+ QMap<QWidget *, QRect> paintedViewBoundingRects;
QPointF pos;
qreal z;
+ qreal opacity;
QGraphicsScene *scene;
QGraphicsItem *parent;
QList<QGraphicsItem *> children;
+ struct TransformData;
+ TransformData *transformData;
+ QGraphicsEffect *graphicsEffect;
+ QTransform sceneTransform;
int index;
- int depth;
-
- // Packed 32 bytes
+ int siblingIndex;
+ int itemDepth; // Lazily calculated when calling depth().
+ QGraphicsItem *focusProxy;
+ QList<QGraphicsItem **> focusProxyRefs;
+ QGraphicsItem *subFocusItem;
+ Qt::InputMethodHints imHints;
+
+ // Packed 32 bits
quint32 acceptedMouseButtons : 5;
quint32 visible : 1;
quint32 explicitlyHidden : 1;
@@ -302,32 +447,193 @@ public:
quint32 isMemberOfGroup : 1;
quint32 handlesChildEvents : 1;
quint32 itemDiscovered : 1;
- quint32 hasTransform : 1;
quint32 hasCursor : 1;
- quint32 ancestorFlags : 3;
+ quint32 ancestorFlags : 4;
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
- quint32 flags : 9;
-
- // New 32 bytes
- quint32 hasOpacity : 1;
- quint32 hasEffectiveOpacity : 1;
quint32 isWidget : 1;
- quint32 dirty : 1;
- quint32 dirtyChildren : 1;
+ quint32 dirty : 1;
+ quint32 dirtyChildren : 1;
quint32 localCollisionHack : 1;
quint32 dirtyClipPath : 1;
quint32 emptyClipPath : 1;
quint32 inSetPosHelper : 1;
- quint32 allChildrenCombineOpacity : 1;
+ quint32 needSortChildren : 1;
+ quint32 allChildrenDirty : 1;
+
+ // New 32 bits
+ quint32 fullUpdatePending : 1;
+ quint32 flags : 16;
+ quint32 dirtyChildrenBoundingRect : 1;
+ quint32 paintedViewBoundingRectsNeedRepaint : 1;
+ quint32 dirtySceneTransform : 1;
+ quint32 geometryChanged : 1;
+ quint32 inDestructor : 1;
+ quint32 isObject : 1;
+ quint32 ignoreVisible : 1;
+ quint32 ignoreOpacity : 1;
+ quint32 acceptTouchEvents : 1;
+ quint32 acceptedTouchBeginEvent : 1;
+ quint32 filtersDescendantEvents : 1;
+ quint32 sceneTransformTranslateOnly : 1;
+ quint32 notifyBoundingRectChanged : 1;
+ quint32 notifyInvalidated : 1;
+ quint32 mouseSetsFocus : 1;
// Optional stacking order
int globalStackingOrder;
- int sceneTransformIndex;
-
QGraphicsItem *q_ptr;
};
+struct QGraphicsItemPrivate::TransformData
+{
+ QTransform transform;
+ qreal scale;
+ qreal rotation;
+ qreal xOrigin;
+ qreal yOrigin;
+ QList<QGraphicsTransform *> graphicsTransforms;
+ bool onlyTransform;
+
+ TransformData() :
+ scale(1.0), rotation(0.0),
+ xOrigin(0.0), yOrigin(0.0),
+ onlyTransform(true)
+ { }
+
+ QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const
+ {
+ if (onlyTransform) {
+ if (!postmultiplyTransform || postmultiplyTransform->isIdentity())
+ return transform;
+ if (transform.isIdentity())
+ return *postmultiplyTransform;
+ return transform * *postmultiplyTransform;
+ }
+
+ QMatrix4x4 x(transform);
+ for (int i = 0; i < graphicsTransforms.size(); ++i)
+ graphicsTransforms.at(i)->applyTo(&x);
+ x.translate(xOrigin, yOrigin);
+ x.rotate(rotation, 0, 0, 1);
+ x.scale(scale);
+ x.translate(-xOrigin, -yOrigin);
+ QTransform t = x.toTransform(); // project the 3D matrix back to 2D.
+ if (postmultiplyTransform)
+ t *= *postmultiplyTransform;
+ return t;
+ }
+};
+
+struct QGraphicsItemPaintInfo
+{
+ inline QGraphicsItemPaintInfo(const QTransform *const xform1, const QTransform *const xform2,
+ const QTransform *const xform3,
+ QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt,
+ QPainter *p, qreal o, bool b1, bool b2)
+ : viewTransform(xform1), transformPtr(xform2), effectTransform(xform3), exposedRegion(r), widget(w),
+ option(opt), painter(p), opacity(o), wasDirtySceneTransform(b1), drawItem(b2)
+ {}
+
+ const QTransform *viewTransform;
+ const QTransform *transformPtr;
+ const QTransform *effectTransform;
+ QRegion *exposedRegion;
+ QWidget *widget;
+ QStyleOptionGraphicsItem *option;
+ QPainter *painter;
+ qreal opacity;
+ quint32 wasDirtySceneTransform : 1;
+ quint32 drawItem : 1;
+};
+
+class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate
+{
+public:
+ QGraphicsItemEffectSourcePrivate(QGraphicsItem *i)
+ : QGraphicsEffectSourcePrivate(), item(i), info(0)
+ {}
+
+ inline void detach()
+ { item->setGraphicsEffect(0); }
+
+ inline const QGraphicsItem *graphicsItem() const
+ { return item; }
+
+ inline const QWidget *widget() const
+ { return 0; }
+
+ inline void update()
+ { item->update(); }
+
+ inline bool isPixmap() const
+ {
+ return (item->type() == QGraphicsPixmapItem::Type);
+ //|| (item->d_ptr->isObject && qobject_cast<QFxImage *>(q_func()));
+ }
+
+ inline const QStyleOption *styleOption() const
+ { return info ? info->option : 0; }
+
+ inline QRect deviceRect() const
+ {
+ if (!info || !info->widget) {
+ qWarning("QGraphicsEffectSource::deviceRect: Not yet implemented, lacking device context");
+ return QRect();
+ }
+ return info->widget->rect();
+ }
+
+ QRectF boundingRect(Qt::CoordinateSystem system) const;
+ void draw(QPainter *);
+ QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const;
+
+ QGraphicsItem *item;
+ QGraphicsItemPaintInfo *info;
+};
+
+
+/*!
+ \internal
+*/
+inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
+{
+ // Return true if sibling item1 is on top of item2.
+ const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
+ const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
+ bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent;
+ bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent;
+ if (f1 != f2)
+ return f2;
+ if (d1->z != d2->z)
+ return d1->z > d2->z;
+ return d1->siblingIndex > d2->siblingIndex;
+}
+
+/*!
+ \internal
+*/
+static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
+{ return qt_closestLeaf(item2, item1); }
+
+/*
+ return the full transform of the item to the parent. This include the position and all the transform data
+*/
+inline QTransform QGraphicsItemPrivate::transformToParent() const
+{
+ QTransform matrix;
+ combineTransformToParent(&matrix);
+ return matrix;
+}
+
+inline void QGraphicsItemPrivate::ensureSortedChildren()
+{
+ if (needSortChildren) {
+ qSort(children.begin(), children.end(), qt_notclosestLeaf);
+ needSortChildren = 0;
+ }
+}
+
QT_END_NAMESPACE
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicsitemanimation.cpp b/src/gui/graphicsview/qgraphicsitemanimation.cpp
index 0785f0c..a101f1c 100644
--- a/src/gui/graphicsview/qgraphicsitemanimation.cpp
+++ b/src/gui/graphicsview/qgraphicsitemanimation.cpp
@@ -44,7 +44,6 @@
\brief The QGraphicsItemAnimation class provides simple animation
support for QGraphicsItem.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
The QGraphicsItemAnimation class animates a QGraphicsItem. You can
diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp
index 22df8a9..e816eee 100644
--- a/src/gui/graphicsview/qgraphicslayout.cpp
+++ b/src/gui/graphicsview/qgraphicslayout.cpp
@@ -57,7 +57,6 @@ QT_BEGIN_NAMESPACE
\brief The QGraphicsLayout class provides the base class for all layouts
in Graphics View.
\since 4.4
- \ingroup multimedia
\ingroup graphicsview-api
QGraphicsLayout is an abstract class that defines a virtual API for
@@ -391,8 +390,10 @@ void QGraphicsLayout::widgetEvent(QEvent *e)
QGraphicsLayout to return a pointer to the item at index \a i. The
reimplementation can assume that \a i is valid (i.e., it respects the
value of count()).
+ Together with count(), it is provided as a means of iterating over all items in a layout.
- The subclass is free to decide how to store the items.
+ The subclass is free to decide how to store the items, and the visual arrangement
+ does not have to be reflected through this function.
\sa count(), removeAt()
*/
diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h
index 591e69b..9530068 100644
--- a/src/gui/graphicsview/qgraphicslayout.h
+++ b/src/gui/graphicsview/qgraphicslayout.h
@@ -85,6 +85,8 @@ private:
friend class QGraphicsWidget;
};
+Q_DECLARE_INTERFACE(QGraphicsLayout, "com.trolltech.Qt.QGraphicsLayout")
+
#endif
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp
index 8a0208a..0091718 100644
--- a/src/gui/graphicsview/qgraphicslayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicslayout_p.cpp
@@ -120,8 +120,8 @@ static bool removeLayoutItemFromLayout(QGraphicsLayout *lay, QGraphicsLayoutItem
if (!lay)
return false;
- QGraphicsLayoutItem *child;
- for (int i = 0; (child = lay->itemAt(i)); ++i) {
+ for (int i = lay->count() - 1; i >= 0; --i) {
+ QGraphicsLayoutItem *child = lay->itemAt(i);
if (child && child->isLayout()) {
if (removeLayoutItemFromLayout(static_cast<QGraphicsLayout*>(child), layoutItem))
return true;
diff --git a/src/gui/graphicsview/qgraphicslayout_p.h b/src/gui/graphicsview/qgraphicslayout_p.h
index 89377d6..a892a44 100644
--- a/src/gui/graphicsview/qgraphicslayout_p.h
+++ b/src/gui/graphicsview/qgraphicslayout_p.h
@@ -47,8 +47,8 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp
index d0892c2..ee04ab3 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.cpp
+++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp
@@ -108,13 +108,22 @@ static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qre
\internal
*/
QGraphicsLayoutItemPrivate::QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *par, bool layout)
- : parent(par), isLayout(layout), ownedByLayout(false), graphicsItem(0)
+ : parent(par), userSizeHints(0), isLayout(layout), ownedByLayout(false), graphicsItem(0)
{
}
/*!
\internal
*/
+QGraphicsLayoutItemPrivate::~QGraphicsLayoutItemPrivate()
+{
+ // Remove any lazily allocated data
+ delete[] userSizeHints;
+}
+
+/*!
+ \internal
+*/
void QGraphicsLayoutItemPrivate::init()
{
sizeHintCacheDirty = true;
@@ -132,7 +141,8 @@ QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint)
for (int i = 0; i < Qt::NSizeHints; ++i) {
cachedSizeHints[i] = constraint;
- combineSize(cachedSizeHints[i], userSizeHints[i]);
+ if (userSizeHints)
+ combineSize(cachedSizeHints[i], userSizeHints[i]);
}
QSizeF &minS = cachedSizeHints[Qt::MinimumSize];
@@ -198,11 +208,62 @@ QGraphicsItem *QGraphicsLayoutItemPrivate::parentItem() const
}
/*!
+ \internal
+
+ Ensures that userSizeHints is allocated.
+ This function must be called before any dereferencing.
+*/
+void QGraphicsLayoutItemPrivate::ensureUserSizeHints()
+{
+ if (!userSizeHints)
+ userSizeHints = new QSizeF[Qt::NSizeHints];
+}
+
+/*!
+ \internal
+
+ Sets the user size hint \a which to \a size. Use an invalid size to unset the size hint.
+ */
+void QGraphicsLayoutItemPrivate::setSize(Qt::SizeHint which, const QSizeF &size)
+{
+ Q_Q(QGraphicsLayoutItem);
+
+ if (userSizeHints) {
+ if (size == userSizeHints[which])
+ return;
+ } else if (!size.isValid()) {
+ return;
+ }
+
+ ensureUserSizeHints();
+ userSizeHints[which] = size;
+ q->updateGeometry();
+}
+
+/*!
+ \internal
+
+ Sets the width of the user size hint \a which to \a width.
+ */
+void QGraphicsLayoutItemPrivate::setSizeComponent(
+ Qt::SizeHint which, SizeComponent component, qreal value)
+{
+ Q_Q(QGraphicsLayoutItem);
+ ensureUserSizeHints();
+ qreal &userValue = (component == Width)
+ ? userSizeHints[which].rwidth()
+ : userSizeHints[which].rheight();
+ if (value == userValue)
+ return;
+ userValue = value;
+ q->updateGeometry();
+}
+
+/*!
\class QGraphicsLayoutItem
\brief The QGraphicsLayoutItem class can be inherited to allow your custom
items to be managed by layouts.
\since 4.4
- \ingroup multimedia
\ingroup graphicsview-api
QGraphicsLayoutItem is an abstract class that defines a set of virtual
@@ -307,7 +368,6 @@ QGraphicsLayoutItem::~QGraphicsLayoutItem()
}
}
}
- delete d_ptr;
}
/*!
@@ -381,12 +441,7 @@ QSizePolicy QGraphicsLayoutItem::sizePolicy() const
*/
void QGraphicsLayoutItem::setMinimumSize(const QSizeF &size)
{
- Q_D(QGraphicsLayoutItem);
- if (size == d->userSizeHints[Qt::MinimumSize])
- return;
-
- d->userSizeHints[Qt::MinimumSize] = size;
- updateGeometry();
+ d_ptr->setSize(Qt::MinimumSize, size);
}
/*!
@@ -416,12 +471,7 @@ QSizeF QGraphicsLayoutItem::minimumSize() const
*/
void QGraphicsLayoutItem::setMinimumWidth(qreal width)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rwidth();
- if (width == userSizeHint)
- return;
- userSizeHint = width;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Width, width);
}
/*!
@@ -431,12 +481,7 @@ void QGraphicsLayoutItem::setMinimumWidth(qreal width)
*/
void QGraphicsLayoutItem::setMinimumHeight(qreal height)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rheight();
- if (height == userSizeHint)
- return;
- userSizeHint = height;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Height, height);
}
@@ -450,12 +495,7 @@ void QGraphicsLayoutItem::setMinimumHeight(qreal height)
*/
void QGraphicsLayoutItem::setPreferredSize(const QSizeF &size)
{
- Q_D(QGraphicsLayoutItem);
- if (size == d->userSizeHints[Qt::PreferredSize])
- return;
-
- d->userSizeHints[Qt::PreferredSize] = size;
- updateGeometry();
+ d_ptr->setSize(Qt::PreferredSize, size);
}
/*!
@@ -485,12 +525,7 @@ QSizeF QGraphicsLayoutItem::preferredSize() const
*/
void QGraphicsLayoutItem::setPreferredHeight(qreal height)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rheight();
- if (height == userSizeHint)
- return;
- userSizeHint = height;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Height, height);
}
/*!
@@ -500,12 +535,7 @@ void QGraphicsLayoutItem::setPreferredHeight(qreal height)
*/
void QGraphicsLayoutItem::setPreferredWidth(qreal width)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rwidth();
- if (width == userSizeHint)
- return;
- userSizeHint = width;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Width, width);
}
/*!
@@ -519,12 +549,7 @@ void QGraphicsLayoutItem::setPreferredWidth(qreal width)
*/
void QGraphicsLayoutItem::setMaximumSize(const QSizeF &size)
{
- Q_D(QGraphicsLayoutItem);
- if (size == d->userSizeHints[Qt::MaximumSize])
- return;
-
- d->userSizeHints[Qt::MaximumSize] = size;
- updateGeometry();
+ d_ptr->setSize(Qt::MaximumSize, size);
}
/*!
@@ -554,12 +579,7 @@ QSizeF QGraphicsLayoutItem::maximumSize() const
*/
void QGraphicsLayoutItem::setMaximumWidth(qreal width)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rwidth();
- if (width == userSizeHint)
- return;
- userSizeHint = width;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Width, width);
}
/*!
@@ -569,12 +589,7 @@ void QGraphicsLayoutItem::setMaximumWidth(qreal width)
*/
void QGraphicsLayoutItem::setMaximumHeight(qreal height)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rheight();
- if (height == userSizeHint)
- return;
- userSizeHint = height;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Height, height);
}
/*!
@@ -732,6 +747,11 @@ QRectF QGraphicsLayoutItem::contentsRect() const
*/
QSizeF QGraphicsLayoutItem::effectiveSizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
+ Q_D(const QGraphicsLayoutItem);
+
+ if (!d->userSizeHints && constraint.isValid())
+ return constraint;
+
// ### should respect size policy???
return d_ptr->effectiveSizeHints(constraint)[which];
}
@@ -786,6 +806,8 @@ bool QGraphicsLayoutItem::isLayout() const
}
/*!
+ \since 4.6
+
Returns whether a layout should delete this item in its destructor.
If its true, then the layout will delete it. If its false, then it is
assumed that another object has the ownership of it, and the layout won't
@@ -812,6 +834,8 @@ bool QGraphicsLayoutItem::ownedByLayout() const
return d_func()->ownedByLayout;
}
/*!
+ \since 4.6
+
Sets whether a layout should delete this item in its destructor or not.
\a ownership must be true to in order for the layout to delete it.
\sa ownedByLayout()
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h
index 3e649d8..7084f01 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.h
+++ b/src/gui/graphicsview/qgraphicslayoutitem.h
@@ -42,6 +42,7 @@
#ifndef QGRAPHICSLAYOUTITEM_H
#define QGRAPHICSLAYOUTITEM_H
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qsizepolicy.h>
#include <QtGui/qevent.h>
@@ -112,7 +113,7 @@ protected:
QGraphicsLayoutItem(QGraphicsLayoutItemPrivate &dd);
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const = 0;
- QGraphicsLayoutItemPrivate *d_ptr;
+ QScopedPointer<QGraphicsLayoutItemPrivate> d_ptr;
private:
QSizeF *effectiveSizeHints(const QSizeF &constraint) const;
@@ -121,6 +122,8 @@ private:
friend class QGraphicsLayout;
};
+Q_DECLARE_INTERFACE(QGraphicsLayoutItem, "com.trolltech.Qt.QGraphicsLayoutItem")
+
inline void QGraphicsLayoutItem::setMinimumSize(qreal aw, qreal ah)
{ setMinimumSize(QSizeF(aw, ah)); }
inline void QGraphicsLayoutItem::setPreferredSize(qreal aw, qreal ah)
diff --git a/src/gui/graphicsview/qgraphicslayoutitem_p.h b/src/gui/graphicsview/qgraphicslayoutitem_p.h
index 2031e04..e23abd8 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem_p.h
+++ b/src/gui/graphicsview/qgraphicslayoutitem_p.h
@@ -47,8 +47,8 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
@@ -63,16 +63,20 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutItemPrivate
{
Q_DECLARE_PUBLIC(QGraphicsLayoutItem)
public:
- virtual ~QGraphicsLayoutItemPrivate() {}
+ virtual ~QGraphicsLayoutItemPrivate();
QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *parent, bool isLayout);
void init();
QSizeF *effectiveSizeHints(const QSizeF &constraint) const;
QGraphicsItem *parentItem() const;
+ void ensureUserSizeHints();
+ void setSize(Qt::SizeHint which, const QSizeF &size);
+ enum SizeComponent { Width, Height };
+ void setSizeComponent(Qt::SizeHint which, SizeComponent component, qreal value);
QSizePolicy sizePolicy;
QGraphicsLayoutItem *parent;
- QSizeF userSizeHints[Qt::NSizeHints];
+ QSizeF *userSizeHints;
mutable QSizeF cachedSizeHints[Qt::NSizeHints];
mutable QSizeF cachedConstraint;
diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp
index 0dbecde..ab2cbfb 100644
--- a/src/gui/graphicsview/qgraphicslinearlayout.cpp
+++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp
@@ -44,7 +44,6 @@
\brief The QGraphicsLinearLayout class provides a horizontal or vertical
layout for managing widgets in Graphics View.
\since 4.4
- \ingroup multimedia
\ingroup graphicsview-api
The default orientation for a linear layout is Qt::Horizontal. You can
@@ -178,7 +177,7 @@ QLayoutStyleInfo QGraphicsLinearLayoutPrivate::styleInfo() const
if (!wid)
wid = new QWidget;
QGraphicsItem *item = parentItem();
- QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : qApp->style();
+ QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style();
return QLayoutStyleInfo(style, wid);
}
@@ -278,7 +277,7 @@ void QGraphicsLinearLayout::insertItem(int index, QGraphicsLayoutItem *item)
Q_ASSERT(item);
d->fixIndex(&index);
d->engine.insertRow(index, d->orientation);
- new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index));
+ new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index), 1, 1, 0, index);
invalidate();
}
@@ -323,7 +322,11 @@ void QGraphicsLinearLayout::removeItem(QGraphicsLayoutItem *item)
void QGraphicsLinearLayout::removeAt(int index)
{
Q_D(QGraphicsLinearLayout);
- if (QGridLayoutItem *gridItem = d->engine.itemAt(d->gridRow(index), d->gridColumn(index))) {
+ if (index < 0 || index >= d->engine.itemCount()) {
+ qWarning("QGraphicsLinearLayout::removeAt: invalid index %d", index);
+ return;
+ }
+ if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) {
if (QGraphicsLayoutItem *layoutItem = gridItem->layoutItem())
layoutItem->setParentLayoutItem(0);
d->removeGridItem(gridItem);
@@ -463,17 +466,22 @@ QSizePolicy::ControlTypes QGraphicsLinearLayout::controlTypes(LayoutSide side) c
int QGraphicsLinearLayout::count() const
{
Q_D(const QGraphicsLinearLayout);
- return d->engine.rowCount(d->orientation);
+ return d->engine.itemCount();
}
/*!
\reimp
+ When iterating from 0 and up, it will return the items in the visual arranged order.
*/
QGraphicsLayoutItem *QGraphicsLinearLayout::itemAt(int index) const
{
Q_D(const QGraphicsLinearLayout);
+ if (index < 0 || index >= d->engine.itemCount()) {
+ qWarning("QGraphicsLinearLayout::itemAt: invalid index %d", index);
+ return 0;
+ }
QGraphicsLayoutItem *item = 0;
- if (QGridLayoutItem *gridItem = d->engine.itemAt(d->gridRow(index), d->gridColumn(index)))
+ if (QGridLayoutItem *gridItem = d->engine.itemAt(index))
item = gridItem->layoutItem();
return item;
}
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index c7b5a69..447fc50 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -67,7 +67,6 @@ QT_BEGIN_NAMESPACE
\brief The QGraphicsProxyWidget class provides a proxy layer for embedding
a QWidget in a QGraphicsScene.
\since 4.4
- \ingroup multimedia
\ingroup graphicsview-api
QGraphicsProxyWidget embeds QWidget-based widgets, for example, a
@@ -275,7 +274,7 @@ void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent
QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber;
QApplicationPrivate::sendMouseEvent(receiver, mouseEvent, alienWidget, widget,
- &embeddedMouseGrabberPtr, lastWidgetUnderMouse);
+ &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous());
embeddedMouseGrabber = embeddedMouseGrabberPtr;
// Handle enter/leave events when last button is released from mouse
@@ -451,6 +450,22 @@ void QGraphicsProxyWidgetPrivate::updateProxyGeometryFromWidget()
/*!
\internal
+*/
+void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget()
+{
+ Q_Q(QGraphicsProxyWidget);
+ if (!widget)
+ return;
+
+ QWidget *focusWidget = widget->focusWidget();
+ if (!focusWidget)
+ focusWidget = widget;
+ q->setFlag(QGraphicsItem::ItemAcceptsInputMethod,
+ focusWidget->testAttribute(Qt::WA_InputMethodEnabled));
+}
+
+/*!
+ \internal
Embeds \a subWin as a subwindow of this proxy widget. \a subWin must be a top-level
widget and a descendant of the widget managed by this proxy. A separate subproxy
@@ -460,7 +475,7 @@ void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin)
{
QWExtra *extra;
if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) {
- QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func());
+ QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags());
subProxy->d_func()->setWidget_helper(subWin, false);
}
}
@@ -544,6 +559,9 @@ QGraphicsProxyWidget::~QGraphicsProxyWidget()
hidden or disabled after embedding is complete. The class documentation
has a full overview over the shared state.
+ QGraphicsProxyWidget's window flags determine whether the widget, after
+ embedding, will be given window decorations or not.
+
After this function returns, QGraphicsProxyWidget will keep its state
synchronized with that of \a widget whenever possible.
@@ -661,10 +679,6 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto
if (newWidget->testAttribute(Qt::WA_SetCursor))
q->setCursor(widget->cursor());
#endif
- Qt::WFlags flags = newWidget->windowFlags();
- if (newWidget->windowType() == Qt::Window)
- flags &= ~Qt::Window;
- q->setWindowFlags(flags);
q->setEnabled(newWidget->isEnabled());
q->setVisible(newWidget->isVisible());
q->setLayoutDirection(newWidget->layoutDirection());
@@ -691,6 +705,8 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto
updateProxyGeometryFromWidget();
+ updateProxyInputMethodAcceptanceFromWidget();
+
// Hook up the event filter to keep the state up to date.
newWidget->installEventFilter(q);
QObject::connect(newWidget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
@@ -977,6 +993,7 @@ void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *even
}
#endif // QT_NO_CONTEXTMENU
+#ifndef QT_NO_DRAGANDDROP
/*!
\reimp
*/
@@ -1097,6 +1114,7 @@ void QGraphicsProxyWidget::dropEvent(QGraphicsSceneDragDropEvent *event)
}
#endif
}
+#endif
/*!
\reimp
@@ -1302,8 +1320,8 @@ void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event)
if (d->widget && d->widget->focusWidget()) {
d->widget->focusWidget()->setFocus(event->reason());
return;
- }
- break;
+ }
+ break;
}
}
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.h b/src/gui/graphicsview/qgraphicsproxywidget.h
index 55e9b69..6a5cf08 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.h
+++ b/src/gui/graphicsview/qgraphicsproxywidget.h
@@ -90,10 +90,12 @@ protected:
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
#endif
+#ifndef QT_NO_DRAGANDDROP
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
+#endif
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
@@ -127,7 +129,7 @@ protected Q_SLOTS:
private:
Q_DISABLE_COPY(QGraphicsProxyWidget)
- Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QGraphicsProxyWidget)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsProxyWidget)
Q_PRIVATE_SLOT(d_func(), void _q_removeWidgetSlot())
friend class QWidget;
diff --git a/src/gui/graphicsview/qgraphicsproxywidget_p.h b/src/gui/graphicsview/qgraphicsproxywidget_p.h
index 1078ab9..85b557f 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget_p.h
+++ b/src/gui/graphicsview/qgraphicsproxywidget_p.h
@@ -47,8 +47,8 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
@@ -102,6 +102,8 @@ public:
void updateWidgetGeometryFromProxy();
void updateProxyGeometryFromWidget();
+ void updateProxyInputMethodAcceptanceFromWidget();
+
QPointF mapToReceiver(const QPointF &pos, const QWidget *receiver) const;
enum ChangeMode {
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index c3795c0..ac30668 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -39,16 +39,13 @@
**
****************************************************************************/
-static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
-
/*!
\class QGraphicsScene
\brief The QGraphicsScene class provides a surface for managing a large
number of 2D graphical items.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
- \mainclass
+
The class serves as a container for QGraphicsItems. It is used together
with QGraphicsView for visualizing graphical items, such as lines,
@@ -219,6 +216,9 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
#include "qgraphicsview_p.h"
#include "qgraphicswidget.h"
#include "qgraphicswidget_p.h"
+#include "qgraphicssceneindex_p.h"
+#include "qgraphicsscenebsptreeindex_p.h"
+#include "qgraphicsscenelinearindex_p.h"
#include <QtCore/qdebug.h>
#include <QtCore/qlist.h>
@@ -242,73 +242,18 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
#include <QtGui/qstyleoption.h>
#include <QtGui/qtooltip.h>
#include <QtGui/qtransform.h>
+#include <QtGui/qgesture.h>
+#include <QtGui/qinputcontext.h>
+#include <QtGui/qgraphicseffect.h>
#include <private/qapplication_p.h>
#include <private/qobject_p.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
#endif
+#include <private/qgraphicseffect_p.h>
QT_BEGIN_NAMESPACE
-static inline bool QRectF_intersects(const QRectF &s, const QRectF &r)
-{
- qreal xp = s.left();
- qreal yp = s.top();
- qreal w = s.width();
- qreal h = s.height();
- qreal l1 = xp;
- qreal r1 = xp;
- if (w < 0)
- l1 += w;
- else
- r1 += w;
-
- qreal l2 = r.left();
- qreal r2 = r.left();
- if (w < 0)
- l2 += r.width();
- else
- r2 += r.width();
-
- if (l1 >= r2 || l2 >= r1)
- return false;
-
- qreal t1 = yp;
- qreal b1 = yp;
- if (h < 0)
- t1 += h;
- else
- b1 += h;
-
- qreal t2 = r.top();
- qreal b2 = r.top();
- if (r.height() < 0)
- t2 += r.height();
- else
- b2 += r.height();
-
- return !(t1 >= b2 || t2 >= b1);
-}
-
-// QRectF::intersects() returns false always if either the source or target
-// rectangle's width or height are 0. This works around that problem.
-static inline void _q_adjustRect(QRectF *rect)
-{
- Q_ASSERT(rect);
- if (!rect->width())
- rect->adjust(-0.00001, 0, 0.00001, 0);
- if (!rect->height())
- rect->adjust(0, -0.00001, 0, 0.00001);
-}
-
-static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
-{
- Q_ASSERT(item);
- QRectF boundingRect(item->boundingRect());
- _q_adjustRect(&boundingRect);
- return boundingRect;
-}
-
static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent)
{
hover->setWidget(mouseEvent->widget());
@@ -322,39 +267,41 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph
hover->setAccepted(mouseEvent->isAccepted());
}
+int QGraphicsScenePrivate::changedSignalIndex;
+
/*!
\internal
*/
QGraphicsScenePrivate::QGraphicsScenePrivate()
- : changedSignalMask(0),
- indexMethod(QGraphicsScene::BspTreeIndex),
- bspTreeDepth(0),
+ : indexMethod(QGraphicsScene::BspTreeIndex),
+ index(0),
lastItemCount(0),
hasSceneRect(false),
+ dirtyGrowingItemsBoundingRect(true),
updateAll(false),
calledEmitUpdated(false),
+ processDirtyItemsEmitted(false),
selectionChanging(0),
- dirtyItemResetPending(false),
- regenerateIndex(true),
- purgePending(false),
- indexTimerId(0),
- restartIndexTimer(false),
+ needSortTopLevelItems(true),
stickyFocus(false),
hasFocus(false),
focusItem(0),
lastFocusItem(0),
tabFocusFirst(0),
- activeWindow(0),
+ activePanel(0),
+ lastActivePanel(0),
activationRefCount(0),
lastMouseGrabberItem(0),
lastMouseGrabberItemHasImplicitMouseGrab(false),
dragDropItem(0),
enterWidget(0),
lastDropAction(Qt::IgnoreAction),
+ allItemsIgnoreHoverEvents(true),
+ allItemsUseDefaultCursor(true),
painterStateProtection(true),
sortCacheEnabled(false),
- updatingSortCache(false),
- style(0)
+ style(0),
+ allItemsIgnoreTouchEvents(true)
{
}
@@ -365,8 +312,12 @@ void QGraphicsScenePrivate::init()
{
Q_Q(QGraphicsScene);
+ index = new QGraphicsSceneBspTreeIndex(q);
+
// Keep this index so we can check for connected slots later on.
- changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList<QRectF>)"));
+ if (!changedSignalIndex) {
+ changedSignalIndex = signalIndex("changed(QList<QRectF>)");
+ }
qApp->d_func()->scene_list.append(q);
q->update();
}
@@ -374,229 +325,31 @@ void QGraphicsScenePrivate::init()
/*!
\internal
*/
-QList<QGraphicsItem *> QGraphicsScenePrivate::estimateItemsInRect(const QRectF &rect) const
-{
- const_cast<QGraphicsScenePrivate *>(this)->purgeRemovedItems();
- const_cast<QGraphicsScenePrivate *>(this)->_q_updateSortCache();
-
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- // ### Only do this once in a while.
- QGraphicsScenePrivate *that = const_cast<QGraphicsScenePrivate *>(this);
-
- // Get items from BSP tree
- QList<QGraphicsItem *> items = that->bspTree.items(rect);
-
- // Fill in with any unindexed items
- for (int i = 0; i < unindexedItems.size(); ++i) {
- if (QGraphicsItem *item = unindexedItems.at(i)) {
- if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
- QRectF boundingRect = item->sceneBoundingRect();
- if (QRectF_intersects(boundingRect, rect)) {
- item->d_ptr->itemDiscovered = 1;
- items << item;
- }
- }
- }
- }
-
- // Reset the discovered state of all discovered items
- for (int i = 0; i < items.size(); ++i)
- items.at(i)->d_func()->itemDiscovered = 0;
- return items;
- }
-
- QList<QGraphicsItem *> itemsInRect;
- for (int i = 0; i < unindexedItems.size(); ++i) {
- if (QGraphicsItem *item = unindexedItems.at(i)) {
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
- continue;
- if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0))
- itemsInRect << item;
- }
- }
- for (int i = 0; i < indexedItems.size(); ++i) {
- if (QGraphicsItem *item = indexedItems.at(i)) {
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
- continue;
- if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0))
- itemsInRect << item;
- }
- }
-
- return itemsInRect;
-}
-
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item)
-{
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- if (item->d_func()->index != -1) {
- bspTree.insertItem(item, item->sceneBoundingRect());
- foreach (QGraphicsItem *child, item->children())
- child->addToIndex();
- } else {
- // The BSP tree is regenerated if the number of items grows to a
- // certain threshold, or if the bounding rect of the graph doubles in
- // size.
- startIndexTimer();
- }
- }
-}
-
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item)
-{
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- int index = item->d_func()->index;
- if (index != -1) {
- bspTree.removeItem(item, item->sceneBoundingRect());
- freeItemIndexes << index;
- indexedItems[index] = 0;
- item->d_func()->index = -1;
- unindexedItems << item;
-
- foreach (QGraphicsItem *child, item->children())
- child->removeFromIndex();
- }
-
- startIndexTimer();
- }
-}
-
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::resetIndex()
-{
- purgeRemovedItems();
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- for (int i = 0; i < indexedItems.size(); ++i) {
- if (QGraphicsItem *item = indexedItems.at(i)) {
- item->d_ptr->index = -1;
- unindexedItems << item;
- }
- }
- indexedItems.clear();
- freeItemIndexes.clear();
- regenerateIndex = true;
- startIndexTimer();
- }
-}
-
-static inline int intmaxlog(int n)
+QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q)
{
- return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0);
+ return q->d_func();
}
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::_q_updateIndex()
+void QGraphicsScenePrivate::_q_emitUpdated()
{
- if (!indexTimerId)
- return;
-
Q_Q(QGraphicsScene);
- q->killTimer(indexTimerId);
- indexTimerId = 0;
-
- purgeRemovedItems();
-
- // Add unindexedItems to indexedItems
- QRectF unindexedItemsBoundingRect;
- for (int i = 0; i < unindexedItems.size(); ++i) {
- if (QGraphicsItem *item = unindexedItems.at(i)) {
- unindexedItemsBoundingRect |= item->sceneBoundingRect();
- if (!freeItemIndexes.isEmpty()) {
- int freeIndex = freeItemIndexes.takeFirst();
- item->d_func()->index = freeIndex;
- indexedItems[freeIndex] = item;
- } else {
- item->d_func()->index = indexedItems.size();
- indexedItems << item;
- }
- }
- }
-
- // Update growing scene rect.
- QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
- growingItemsBoundingRect |= unindexedItemsBoundingRect;
-
- // Determine whether we should regenerate the BSP tree.
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- int depth = bspTreeDepth;
- if (depth == 0) {
- int oldDepth = intmaxlog(lastItemCount);
- depth = intmaxlog(indexedItems.size());
- static const int slack = 100;
- if (bspTree.leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) {
- // ### Crude algorithm.
- regenerateIndex = true;
- }
- }
-
- // Regenerate the tree.
- if (regenerateIndex) {
- regenerateIndex = false;
- bspTree.initialize(sceneRect, depth);
- unindexedItems = indexedItems;
- lastItemCount = indexedItems.size();
- q->update();
-
- // Take this opportunity to reset our largest-item counter for
- // untransformable items. When the items are inserted into the BSP
- // tree, we'll get an accurate calculation.
- largestUntransformableItem = QRectF();
- }
- }
+ calledEmitUpdated = false;
- // Insert all unindexed items into the tree.
- for (int i = 0; i < unindexedItems.size(); ++i) {
- if (QGraphicsItem *item = unindexedItems.at(i)) {
- QRectF rect = item->sceneBoundingRect();
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
- continue;
- if (indexMethod == QGraphicsScene::BspTreeIndex)
- bspTree.insertItem(item, rect);
-
- // If the item ignores view transformations, update our
- // largest-item-counter to ensure that the view can accurately
- // discover untransformable items when drawing.
- if (item->d_ptr->itemIsUntransformable()) {
- QGraphicsItem *topmostUntransformable = item;
- while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags
- & QGraphicsItemPrivate::AncestorIgnoresTransformations)) {
- topmostUntransformable = topmostUntransformable->parentItem();
- }
- // ### Verify that this is the correct largest untransformable rectangle.
- largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect();
- }
+ if (dirtyGrowingItemsBoundingRect) {
+ if (!hasSceneRect) {
+ const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
+ growingItemsBoundingRect |= q->itemsBoundingRect();
+ if (oldGrowingItemsBoundingRect != growingItemsBoundingRect)
+ emit q->sceneRectChanged(growingItemsBoundingRect);
}
+ dirtyGrowingItemsBoundingRect = false;
}
- unindexedItems.clear();
-
- // Notify scene rect changes.
- if (!hasSceneRect && growingItemsBoundingRect != oldGrowingItemsBoundingRect)
- emit q->sceneRectChanged(growingItemsBoundingRect);
-}
-
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::_q_emitUpdated()
-{
- Q_Q(QGraphicsScene);
- calledEmitUpdated = false;
// Ensure all views are connected if anything is connected. This disables
// the optimization that items send updates directly to the views, but it
// needs to happen in order to keep compatibility with the behavior from
// Qt 4.4 and backward.
- if (!views.isEmpty() && (connectedSignals & changedSignalMask)) {
+ if (isSignalConnected(changedSignalIndex)) {
for (int i = 0; i < views.size(); ++i) {
QGraphicsView *view = views.at(i);
if (!view->d_func()->connectedToScene) {
@@ -605,13 +358,16 @@ void QGraphicsScenePrivate::_q_emitUpdated()
views.at(i), SLOT(updateScene(QList<QRectF>)));
}
}
+ } else {
+ updateAll = false;
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->processPendingUpdates();
+ // It's important that we update all views before we dispatch, hence two for-loops.
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->dispatchPendingUpdateRequests();
+ return;
}
- // Ensure all dirty items's current positions are recorded in the list of
- // updated rects.
- for (int i = 0; i < dirtyItems.size(); ++i)
- updatedRects += dirtyItems.at(i)->sceneBoundingRect();
-
// Notify the changes to anybody interested.
QList<QRectF> oldUpdatedRects;
oldUpdatedRects = updateAll ? (QList<QRectF>() << q->sceneRect()) : updatedRects;
@@ -622,15 +378,24 @@ void QGraphicsScenePrivate::_q_emitUpdated()
/*!
\internal
+*/
+void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
+{
+ needSortTopLevelItems = true;
+ item->d_ptr->siblingIndex = topLevelItems.size();
+ topLevelItems.append(item);
+}
- Updates all items in the pending update list. At this point, the list is
- unlikely to contain partially constructed items.
+/*!
+ \internal
*/
-void QGraphicsScenePrivate::_q_updateLater()
+void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item)
{
- foreach (QGraphicsItem *item, pendingUpdateItems)
- item->update();
- pendingUpdateItems.clear();
+ topLevelItems.removeOne(item);
+ // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because
+ // the item is not guaranteed to be at the index after the list is sorted
+ // (see ensureSortedTopLevelItems()).
+ item->d_ptr->siblingIndex = -1;
}
/*!
@@ -652,70 +417,99 @@ void QGraphicsScenePrivate::_q_polishItems()
unpolishedItems.clear();
}
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::_q_resetDirtyItems()
+void QGraphicsScenePrivate::_q_processDirtyItems()
{
- for (int i = 0; i < dirtyItems.size(); ++i) {
- QGraphicsItem *item = dirtyItems.at(i);
- item->d_ptr->dirty = 0;
- item->d_ptr->dirtyChildren = 0;
+ processDirtyItemsEmitted = false;
+
+ if (updateAll) {
+ Q_ASSERT(calledEmitUpdated);
+ // No need for further processing (except resetting the dirty states).
+ // The growingItemsBoundingRect is updated in _q_emitUpdated.
+ for (int i = 0; i < topLevelItems.size(); ++i)
+ resetDirtyItem(topLevelItems.at(i), /*recursive=*/true);
+ return;
}
- dirtyItems.clear();
- dirtyItemResetPending = false;
-}
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::resetDirtyItemsLater()
-{
- Q_Q(QGraphicsScene);
- if (dirtyItemResetPending)
+ const bool wasPendingSceneUpdate = calledEmitUpdated;
+ const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
+
+ // Process items recursively.
+ for (int i = 0; i < topLevelItems.size(); ++i)
+ processDirtyItemsRecursive(topLevelItems.at(i));
+
+ dirtyGrowingItemsBoundingRect = false;
+ if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect)
+ emit q_func()->sceneRectChanged(growingItemsBoundingRect);
+
+ if (wasPendingSceneUpdate)
return;
- // dirtyItems.reserve(indexedItems.size() + unindexedItems.size());
- dirtyItemResetPending = true;
- QMetaObject::invokeMethod(q, "_q_resetDirtyItems", Qt::QueuedConnection);
+
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->processPendingUpdates();
+
+ if (calledEmitUpdated) {
+ // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive
+ // and we cannot wait for the control to reach the eventloop before the
+ // changed signal is emitted, so we emit it now.
+ _q_emitUpdated();
+ }
+
+ // Immediately dispatch all pending update requests on the views.
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->dispatchPendingUpdateRequests();
}
/*!
\internal
Schedules an item for removal. This function leaves some stale indexes
- around in the BSP tree; these will be cleaned up the next time someone
- triggers purgeRemovedItems().
+ around in the BSP tree if called from the item's destructor; these will
+ be cleaned up the next time someone triggers purgeRemovedItems().
- Note: This function is called from QGraphicsItem's destructor. \a item is
+ Note: This function might get called from QGraphicsItem's destructor. \a item is
being destroyed, so we cannot call any pure virtual functions on it (such
as boundingRect()). Also, it is unnecessary to update the item's own state
in any way.
-
- ### Refactoring: This function shares much functionality with removeItem()
*/
-void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
+void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
{
Q_Q(QGraphicsScene);
- // Clear focus on the item to remove any reference in the focusWidget
- // chain.
+ // Clear focus on the item to remove any reference in the focusWidget chain.
item->clearFocus();
- int index = item->d_func()->index;
- if (index != -1) {
- // Important: The index is useless until purgeRemovedItems() is
- // called.
- indexedItems[index] = (QGraphicsItem *)0;
- if (!purgePending) {
- purgePending = true;
- q->update();
+ markDirty(item, QRectF(), false, false, false, false, /*removingItemFromScene=*/true);
+
+ if (item->d_ptr->inDestructor) {
+ // The item is actually in its destructor, we call the special method in the index.
+ index->deleteItem(item);
+ } else {
+ // Can potentially call item->boundingRect() (virtual function), that's why
+ // we only can call this function if the item is not in its destructor.
+ index->removeItem(item);
+ }
+
+ item->d_ptr->clearSubFocus();
+
+ if (!item->d_ptr->inDestructor && item == tabFocusFirst) {
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
+ }
+
+ item->d_func()->scene = 0;
+
+ // Unregister focus proxy.
+ item->d_ptr->resetFocusProxy();
+
+ // Remove from parent, or unregister from toplevels.
+ if (QGraphicsItem *parentItem = item->parentItem()) {
+ if (parentItem->scene()) {
+ Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
+ "Parent item's scene is different from this item's scene");
+ item->d_ptr->setParentItemHelper(0);
}
- removedItems << item;
} else {
- // Recently added items are purged immediately. unindexedItems() never
- // contains stale items.
- unindexedItems.removeAll(item);
- q->update();
+ unregisterTopLevelItem(item);
}
// Reset the mouse grabber and focus item data.
@@ -723,10 +517,12 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
focusItem = 0;
if (item == lastFocusItem)
lastFocusItem = 0;
- if (item == activeWindow) {
+ if (item == activePanel) {
// ### deactivate...
- activeWindow = 0;
+ activePanel = 0;
}
+ if (item == lastActivePanel)
+ lastActivePanel = 0;
// Disable selectionChanged() for individual items
++selectionChanging;
@@ -735,10 +531,9 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
// Update selected & hovered item bookkeeping
selectedItems.remove(item);
hoverItems.removeAll(item);
- pendingUpdateItems.removeAll(item);
cachedItemsUnderMouse.removeAll(item);
unpolishedItems.removeAll(item);
- dirtyItems.removeAll(item);
+ resetDirtyItem(item);
//We remove all references of item from the sceneEventFilter arrays
QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
@@ -749,24 +544,19 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
++iterator;
}
- // Remove from scene transform cache
- int transformIndex = item->d_func()->sceneTransformIndex;
- if (transformIndex != -1) {
- validTransforms.setBit(transformIndex, 0);
- freeSceneTransformSlots.append(transformIndex);
+ if (!item->d_ptr->inDestructor) {
+ // Remove all children recursively
+ for (int i = 0; i < item->d_ptr->children.size(); ++i)
+ q->removeItem(item->d_ptr->children.at(i));
}
- // Remove all children recursively.
- foreach (QGraphicsItem *child, item->children())
- _q_removeItemLater(child);
-
- // Reset the mouse grabber
+ // Reset the mouse grabber and focus item data.
if (mouseGrabberItems.contains(item))
- ungrabMouse(item, /* item is dying */ true);
+ ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor);
// Reset the keyboard grabber
if (keyboardGrabberItems.contains(item))
- ungrabKeyboard(item, /* item is dying */ true);
+ ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor);
// Reset the last mouse grabber item
if (item == lastMouseGrabberItem)
@@ -780,46 +570,66 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
/*!
\internal
-
- Removes stale pointers from all data structures.
*/
-void QGraphicsScenePrivate::purgeRemovedItems()
+void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item,
+ Qt::FocusReason focusReason)
{
Q_Q(QGraphicsScene);
-
- if (!purgePending && removedItems.isEmpty())
+ if (item == focusItem)
return;
- // Remove stale items from the BSP tree.
- if (indexMethod != QGraphicsScene::NoIndex)
- bspTree.removeItems(removedItems);
+ // Clear focus if asked to set focus on something that can't
+ // accept input focus.
+ if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
+ || !item->isVisible() || !item->isEnabled())) {
+ item = 0;
+ }
- // Purge this list.
- removedItems.clear();
- freeItemIndexes.clear();
- for (int i = 0; i < indexedItems.size(); ++i) {
- if (!indexedItems.at(i))
- freeItemIndexes << i;
+ // Set focus on the scene if an item requests focus.
+ if (item) {
+ q->setFocus(focusReason);
+ if (item == focusItem)
+ return;
}
- purgePending = false;
- // No locality info for the items; update the whole scene.
- q->update();
-}
+ // Auto-update focus proxy. The closest parent that detects
+ // focus proxies is updated as the proxy gains or loses focus.
+ if (item) {
+ QGraphicsItem *p = item->d_ptr->parent;
+ while (p) {
+ if (p->d_ptr->flags & QGraphicsItem::ItemAutoDetectsFocusProxy) {
+ p->setFocusProxy(item);
+ break;
+ }
+ p = p->d_ptr->parent;
+ }
+ }
-/*!
- \internal
+ if (focusItem) {
+ QFocusEvent event(QEvent::FocusOut, focusReason);
+ lastFocusItem = focusItem;
+ focusItem = 0;
+ sendEvent(lastFocusItem, &event);
- Starts or restarts the timer used for reindexing unindexed items.
-*/
-void QGraphicsScenePrivate::startIndexTimer()
-{
- Q_Q(QGraphicsScene);
- if (indexTimerId) {
- restartIndexTimer = true;
- } else {
- indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
+ if (lastFocusItem
+ && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
+ // Reset any visible preedit text
+ QInputMethodEvent imEvent;
+ sendEvent(lastFocusItem, &imEvent);
+
+ // Close any external input method panel
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->inputContext()->reset();
+ }
+ }
+
+ if (item) {
+ focusItem = item;
+ QFocusEvent event(QEvent::FocusIn, focusReason);
+ sendEvent(item, &event);
}
+
+ updateInputMethodSensitivityInViews();
}
/*!
@@ -863,8 +673,8 @@ void QGraphicsScenePrivate::removePopup(QGraphicsWidget *widget, bool itemIsDyin
if (focusItem && popupWidgets.isEmpty()) {
QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason);
sendEvent(focusItem, &event);
- } else {
- ungrabKeyboard((QGraphicsItem *)widget, itemIsDying);
+ } else if (keyboardGrabberItems.contains(static_cast<QGraphicsItem *>(widget))) {
+ ungrabKeyboard(static_cast<QGraphicsItem *>(widget), itemIsDying);
}
if (!itemIsDying && widget->isVisible()) {
widget->hide();
@@ -880,11 +690,18 @@ void QGraphicsScenePrivate::grabMouse(QGraphicsItem *item, bool implicit)
{
// Append to list of mouse grabber items, and send a mouse grab event.
if (mouseGrabberItems.contains(item)) {
- if (mouseGrabberItems.last() == item)
- qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
- else
+ if (mouseGrabberItems.last() == item) {
+ Q_ASSERT(!implicit);
+ if (!lastMouseGrabberItemHasImplicitMouseGrab) {
+ qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
+ } else {
+ // Upgrade to an explicit mouse grab
+ lastMouseGrabberItemHasImplicitMouseGrab = false;
+ }
+ } else {
qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p",
mouseGrabberItems.last());
+ }
return;
}
@@ -1036,6 +853,12 @@ void QGraphicsScenePrivate::clearKeyboardGrabber()
ungrabKeyboard(keyboardGrabberItems.first());
}
+void QGraphicsScenePrivate::enableMouseTrackingOnViews()
+{
+ foreach (QGraphicsView *view, views)
+ view->viewport()->setMouseTracking(true);
+}
+
/*!
Returns all items for the screen position in \a event.
*/
@@ -1045,41 +868,20 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre
{
Q_Q(const QGraphicsScene);
QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
- QList<QGraphicsItem *> items;
- if (view)
- items = view->items(view->viewport()->mapFromGlobal(screenPos));
- else
- items = q->items(scenePos);
- return items;
-}
+ if (!view)
+ return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, QTransform());
-/*!
- \internal
+ const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1));
+ if (!view->isTransformed())
+ return q->items(pointRect, Qt::IntersectsItemShape, Qt::AscendingOrder);
- Checks if item collides with the path and mode, but also checks that if it
- doesn't collide, maybe its frame rect will.
-*/
-bool QGraphicsScenePrivate::itemCollidesWithPath(QGraphicsItem *item,
- const QPainterPath &path,
- Qt::ItemSelectionMode mode)
-{
- if (item->collidesWithPath(path, mode))
- return true;
- if (item->isWidget()) {
- // Check if this is a window, and if its frame rect collides.
- QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
- if (widget->isWindow()) {
- QRectF frameRect = widget->windowFrameRect();
- QPainterPath framePath;
- framePath.addRect(frameRect);
- bool intersects = path.intersects(frameRect);
- if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect)
- return intersects || path.contains(frameRect.topLeft())
- || framePath.contains(path.elementAt(0));
- return !intersects && path.contains(frameRect.topLeft());
- }
+ const QTransform viewTransform = view->viewportTransform();
+ if (viewTransform.type() <= QTransform::TxScale) {
+ return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape,
+ Qt::AscendingOrder, viewTransform);
}
- return false;
+ return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape,
+ Qt::AscendingOrder, viewTransform);
}
/*!
@@ -1091,7 +893,7 @@ void QGraphicsScenePrivate::storeMouseButtonsForMouseGrabber(QGraphicsSceneMouse
if (event->buttons() & i) {
mouseGrabberButtonDownPos.insert(Qt::MouseButton(i),
mouseGrabberItems.last()->d_ptr->genericMapFromScene(event->scenePos(),
- event->widget()));
+ event->widget()));
mouseGrabberButtonDownScenePos.insert(Qt::MouseButton(i), event->scenePos());
mouseGrabberButtonDownScreenPos.insert(Qt::MouseButton(i), event->screenPos());
}
@@ -1125,6 +927,24 @@ void QGraphicsScenePrivate::removeSceneEventFilter(QGraphicsItem *watched, QGrap
}
/*!
+ \internal
+*/
+bool QGraphicsScenePrivate::filterDescendantEvent(QGraphicsItem *item, QEvent *event)
+{
+ if (item && (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents)) {
+ QGraphicsItem *parent = item->parentItem();
+ while (parent) {
+ if (parent->d_ptr->filtersDescendantEvents && parent->sceneEventFilter(item, event))
+ return true;
+ if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents))
+ return false;
+ parent = parent->parentItem();
+ }
+ }
+ return false;
+}
+
+/*!
\internal
*/
bool QGraphicsScenePrivate::filterEvent(QGraphicsItem *item, QEvent *event)
@@ -1156,7 +976,9 @@ bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event)
{
if (filterEvent(item, event))
return false;
- return (item && item->isEnabled()) ? item->sceneEvent(event) : false;
+ if (filterDescendantEvent(item, event))
+ return false;
+ return (item && item->isEnabled() ? item->sceneEvent(event) : false);
}
/*!
@@ -1257,14 +1079,15 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
}
// Update window activation.
- QGraphicsWidget *newActiveWindow = windowForItem(cachedItemsUnderMouse.value(0));
- if (newActiveWindow != activeWindow)
+ QGraphicsItem *topItem = cachedItemsUnderMouse.value(0);
+ QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : 0;
+ if (newActiveWindow != q->activeWindow())
q->setActiveWindow(newActiveWindow);
// Set focus on the topmost enabled item that can take focus.
bool setFocus = false;
foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
- if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
+ if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
setFocus = true;
if (item != q->focusItem())
@@ -1293,13 +1116,15 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
// check if the item we are sending to are disabled (before we send the event)
bool disabled = !item->isEnabled();
- bool isWindow = item->isWindow();
- if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick && item != lastMouseGrabberItem) {
+ bool isPanel = item->isPanel();
+ if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
+ && item != lastMouseGrabberItem && lastMouseGrabberItem) {
// If this item is different from the item that received the last
// mouse event, and mouseEvent is a doubleclick event, then the
// event is converted to a press. Known limitation:
// Triple-clicking will not generate a doubleclick, though.
QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
+ mousePress.spont = mouseEvent->spont;
mousePress.accept();
mousePress.setButton(mouseEvent->button());
mousePress.setButtons(mouseEvent->buttons());
@@ -1332,8 +1157,8 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
}
ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
- // Don't propagate through windows.
- if (isWindow)
+ // Don't propagate through panels.
+ if (isPanel)
break;
}
@@ -1355,626 +1180,6 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
}
}
-QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) const
-{
- if (!item)
- return 0;
- do {
- if (item->isWidget())
- return static_cast<const QGraphicsWidget *>(item)->window();
- item = item->parentItem();
- } while (item);
- return 0;
-}
-
-
-QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPointF &pos) const
-{
- QList<QGraphicsItem *> items;
-
- // The index returns a rough estimate of what items are inside the rect.
- // Refine it by iterating through all returned items.
- QRectF adjustedRect = QRectF(pos, QSize(1,1));
- foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) {
- // Find the item's scene transform in a clever way.
- QTransform x = item->sceneTransform();
- bool keep = false;
-
- // ### _q_adjustedRect is only needed because QRectF::intersects,
- // QRectF::contains and QTransform::map() and friends don't work with
- // flat rectangles.
- const QRectF br(adjustedItemBoundingRect(item));
- // Rect intersects/contains item's shape
- if (QRectF_intersects(adjustedRect, x.mapRect(br))) {
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok) {
- if (item->contains(xinv.map(pos))) {
- items << item;
- keep = true;
- }
- }
- }
-
- if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
- // Recurse into children that clip children.
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok)
- childItems_helper(&items, item, xinv.map(pos));
- }
- }
-
- sortItems(&items, Qt::AscendingOrder, sortCacheEnabled);
- return items;
-}
-
-QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QRectF &rect,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const
-{
- QList<QGraphicsItem *> items;
-
- QPainterPath path;
-
- // The index returns a rough estimate of what items are inside the rect.
- // Refine it by iterating through all returned items.
- QRectF adjustedRect(rect);
- _q_adjustRect(&adjustedRect);
- foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) {
- // Find the item's scene transform in a clever way.
- QTransform x = item->sceneTransform();
- bool keep = false;
-
- // ### _q_adjustedRect is only needed because QRectF::intersects,
- // QRectF::contains and QTransform::map() and friends don't work with
- // flat rectangles.
- const QRectF br(adjustedItemBoundingRect(item));
- if (mode >= Qt::ContainsItemBoundingRect) {
- // Rect intersects/contains item's bounding rect
- QRectF mbr = x.mapRect(br);
- if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr))
- || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(mbr))) {
- items << item;
- keep = true;
- }
- } else {
- // Rect intersects/contains item's shape
- if (QRectF_intersects(adjustedRect, x.mapRect(br))) {
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok) {
- if (path.isEmpty())
- path.addRect(rect);
- if (itemCollidesWithPath(item, xinv.map(path), mode)) {
- items << item;
- keep = true;
- }
- }
- }
- }
-
- if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
- // Recurse into children that clip children.
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok) {
- if (x.type() <= QTransform::TxScale) {
- // Rect
- childItems_helper(&items, item, xinv.mapRect(rect), mode);
- } else {
- // Polygon
- childItems_helper(&items, item, xinv.map(rect), mode);
- }
- }
- }
- }
-
- if (order != Qt::SortOrder(-1))
- sortItems(&items, order, sortCacheEnabled);
- return items;
-}
-
-QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPolygonF &polygon,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const
-{
- QList<QGraphicsItem *> items;
-
- QRectF polyRect(polygon.boundingRect());
- _q_adjustRect(&polyRect);
- QPainterPath path;
-
- // The index returns a rough estimate of what items are inside the rect.
- // Refine it by iterating through all returned items.
- foreach (QGraphicsItem *item, estimateItemsInRect(polyRect)) {
- // Find the item's scene transform in a clever way.
- QTransform x = item->sceneTransform();
- bool keep = false;
-
- // ### _q_adjustedRect is only needed because QRectF::intersects,
- // QRectF::contains and QTransform::map() and friends don't work with
- // flat rectangles.
- const QRectF br(adjustedItemBoundingRect(item));
- if (mode >= Qt::ContainsItemBoundingRect) {
- // Polygon contains/intersects item's bounding rect
- if (path == QPainterPath())
- path.addPolygon(polygon);
- if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br)))
- || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) {
- items << item;
- keep = true;
- }
- } else {
- // Polygon contains/intersects item's shape
- if (QRectF_intersects(polyRect, x.mapRect(br))) {
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok) {
- if (path == QPainterPath())
- path.addPolygon(polygon);
- if (itemCollidesWithPath(item, xinv.map(path), mode)) {
- items << item;
- keep = true;
- }
- }
- }
- }
-
- if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
- // Recurse into children that clip children.
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok)
- childItems_helper(&items, item, xinv.map(polygon), mode);
- }
- }
-
- if (order != Qt::SortOrder(-1))
- sortItems(&items, order, sortCacheEnabled);
- return items;
-}
-
-QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPainterPath &path,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const
-{
- QList<QGraphicsItem *> items;
- QRectF pathRect(path.controlPointRect());
- _q_adjustRect(&pathRect);
-
- // The index returns a rough estimate of what items are inside the rect.
- // Refine it by iterating through all returned items.
- foreach (QGraphicsItem *item, estimateItemsInRect(pathRect)) {
- // Find the item's scene transform in a clever way.
- QTransform x = item->sceneTransform();
- bool keep = false;
-
- // ### _q_adjustedRect is only needed because QRectF::intersects,
- // QRectF::contains and QTransform::map() and friends don't work with
- // flat rectangles.
- const QRectF br(adjustedItemBoundingRect(item));
- if (mode >= Qt::ContainsItemBoundingRect) {
- // Path contains/intersects item's bounding rect
- if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br)))
- || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) {
- items << item;
- keep = true;
- }
- } else {
- // Path contains/intersects item's shape
- if (QRectF_intersects(pathRect, x.mapRect(br))) {
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok) {
- if (itemCollidesWithPath(item, xinv.map(path), mode)) {
- items << item;
- keep = true;
- }
- }
- }
- }
-
- if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok)
- childItems_helper(&items, item, xinv.map(path), mode);
- }
- }
-
- if (order != Qt::SortOrder(-1))
- sortItems(&items, order, sortCacheEnabled);
- return items;
-}
-
-void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QPointF &pos) const
-{
- bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
- if (parentClip && parent->d_ptr->isClippedAway())
- return;
- // ### is this needed?
- if (parentClip && !parent->boundingRect().contains(pos))
- return;
-
- QList<QGraphicsItem *> &children = parent->d_ptr->children;
- for (int i = 0; i < children.size(); ++i) {
- QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
- continue;
-
- // Skip invisible items and all their children.
- if (item->d_ptr->isInvisible())
- continue;
-
- bool keep = false;
- if (!item->d_ptr->isClippedAway()) {
- if (item->contains(item->mapFromParent(pos))) {
- items->append(item);
- keep = true;
- }
- }
-
- if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty())
- // Recurse into children.
- childItems_helper(items, item, item->mapFromParent(pos));
- }
-}
-
-
-void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QRectF &rect,
- Qt::ItemSelectionMode mode) const
-{
- bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
- if (parentClip && parent->d_ptr->isClippedAway())
- return;
- QRectF adjustedRect(rect);
- _q_adjustRect(&adjustedRect);
- QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent));
- if (r.isEmpty())
- return;
-
- QPainterPath path;
- QList<QGraphicsItem *> &children = parent->d_ptr->children;
- for (int i = 0; i < children.size(); ++i) {
- QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
- continue;
-
- // Skip invisible items and all their children.
- if (item->d_ptr->isInvisible())
- continue;
-
- bool keep = false;
- if (!item->d_ptr->isClippedAway()) {
- // ### _q_adjustedRect is only needed because QRectF::intersects,
- // QRectF::contains and QTransform::map() and friends don't work with
- // flat rectangles.
- const QRectF br(adjustedItemBoundingRect(item));
- QRectF mbr = item->mapRectToParent(br);
- if (mode >= Qt::ContainsItemBoundingRect) {
- // Rect intersects/contains item's bounding rect
- if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr))
- || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) {
- items->append(item);
- keep = true;
- }
- } else {
- // Rect intersects/contains item's shape
- if (QRectF_intersects(rect, mbr)) {
- if (path == QPainterPath())
- path.addRect(rect);
- if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
- items->append(item);
- keep = true;
- }
- }
- }
- }
-
- if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {
- // Recurse into children.
- if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) {
- // Rect
- childItems_helper(items, item, item->mapRectFromParent(rect), mode);
- } else {
- // Polygon
- childItems_helper(items, item, item->mapFromParent(rect), mode);
- }
- }
- }
-}
-
-
-void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QPolygonF &polygon,
- Qt::ItemSelectionMode mode) const
-{
- bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
- if (parentClip && parent->d_ptr->isClippedAway())
- return;
- QRectF polyRect(polygon.boundingRect());
- _q_adjustRect(&polyRect);
- QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent));
- if (r.isEmpty())
- return;
-
- QPainterPath path;
- QList<QGraphicsItem *> &children = parent->d_ptr->children;
- for (int i = 0; i < children.size(); ++i) {
- QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
- continue;
-
- // Skip invisible items.
- if (item->d_ptr->isInvisible())
- continue;
-
- bool keep = false;
- if (!item->d_ptr->isClippedAway()) {
- // ### _q_adjustedRect is only needed because QRectF::intersects,
- // QRectF::contains and QTransform::map() and friends don't work with
- // flat rectangles.
- const QRectF br(adjustedItemBoundingRect(item));
- if (mode >= Qt::ContainsItemBoundingRect) {
- // Polygon contains/intersects item's bounding rect
- if (path == QPainterPath())
- path.addPolygon(polygon);
- if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br)))
- || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) {
- items->append(item);
- keep = true;
- }
- } else {
- // Polygon contains/intersects item's shape
- if (QRectF_intersects(polyRect, item->mapRectToParent(br))) {
- if (path == QPainterPath())
- path.addPolygon(polygon);
- if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
- items->append(item);
- keep = true;
- }
- }
- }
- }
-
- if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {
- // Recurse into children that clip children.
- childItems_helper(items, item, item->mapFromParent(polygon), mode);
- }
- }
-}
-
-void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QPainterPath &path,
- Qt::ItemSelectionMode mode) const
-{
- bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
- if (parentClip && parent->d_ptr->isClippedAway())
- return;
- QRectF pathRect(path.boundingRect());
- _q_adjustRect(&pathRect);
- QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent));
- if (r.isEmpty())
- return;
-
- QList<QGraphicsItem *> &children = parent->d_ptr->children;
- for (int i = 0; i < children.size(); ++i) {
- QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
- continue;
-
- // Skip invisible items.
- if (item->d_ptr->isInvisible())
- continue;
-
- bool keep = false;
- if (!item->d_ptr->isClippedAway()) {
- // ### _q_adjustedRect is only needed because QRectF::intersects,
- // QRectF::contains and QTransform::map() and friends don't work with
- // flat rectangles.
- const QRectF br(adjustedItemBoundingRect(item));
- if (mode >= Qt::ContainsItemBoundingRect) {
- // Polygon contains/intersects item's bounding rect
- if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br)))
- || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) {
- items->append(item);
- keep = true;
- }
- } else {
- // Path contains/intersects item's shape
- if (QRectF_intersects(pathRect, item->mapRectToParent(br))) {
- if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
- items->append(item);
- keep = true;
- }
- }
- }
- }
-
- if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {
- // Recurse into children that clip children.
- childItems_helper(items, item, item->mapFromParent(path), mode);
- }
- }
-}
-
-void QGraphicsScenePrivate::invalidateSortCache()
-{
- Q_Q(QGraphicsScene);
- if (!sortCacheEnabled || updatingSortCache)
- return;
-
- updatingSortCache = true;
- QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection);
-}
-
-/*!
- \internal
-
- Should not be exported, but we can't change that now.
- ### Qt 5: Remove symbol / make static
-*/
-inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
-{
- // Return true if sibling item1 is on top of item2.
- const QGraphicsItemPrivate *d1 = item1->d_ptr;
- const QGraphicsItemPrivate *d2 = item2->d_ptr;
- bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent;
- bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent;
- if (f1 != f2) return f2;
- qreal z1 = d1->z;
- qreal z2 = d2->z;
- return z1 != z2 ? z1 > z2 : item1 > item2;
-}
-
-/*!
- \internal
-
- Should not be exported, but we can't change that now.
-*/
-inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2)
-{
- return QGraphicsScenePrivate::closestItemFirst_withoutCache(item1, item2);
-}
-
-/*!
- Returns true if \a item1 is on top of \a item2.
-
- \internal
-*/
-bool QGraphicsScenePrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
-{
- // Siblings? Just check their z-values.
- const QGraphicsItemPrivate *d1 = item1->d_ptr;
- const QGraphicsItemPrivate *d2 = item2->d_ptr;
- if (d1->parent == d2->parent)
- return qt_closestLeaf(item1, item2);
-
- // Find common ancestor, and each item's ancestor closest to the common
- // ancestor.
- int item1Depth = d1->depth;
- int item2Depth = d2->depth;
- const QGraphicsItem *p = item1;
- const QGraphicsItem *t1 = item1;
- while (item1Depth > item2Depth && (p = p->d_ptr->parent)) {
- if (p == item2) {
- // item2 is one of item1's ancestors; item1 is on top
- return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
- }
- t1 = p;
- --item1Depth;
- }
- p = item2;
- const QGraphicsItem *t2 = item2;
- while (item2Depth > item1Depth && (p = p->d_ptr->parent)) {
- if (p == item1) {
- // item1 is one of item2's ancestors; item1 is not on top
- return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
- }
- t2 = p;
- --item2Depth;
- }
-
- // item1Ancestor is now at the same level as item2Ancestor, but not the same.
- const QGraphicsItem *a1 = t1;
- const QGraphicsItem *a2 = t2;
- while (a1) {
- const QGraphicsItem *p1 = a1;
- const QGraphicsItem *p2 = a2;
- a1 = a1->parentItem();
- a2 = a2->parentItem();
- if (a1 && a1 == a2)
- return qt_closestLeaf(p1, p2);
- }
-
- // No common ancestor? Then just compare the items' toplevels directly.
- return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem());
-}
-
-/*!
- Returns true if \a item2 is on top of \a item1.
-
- \internal
-*/
-bool QGraphicsScenePrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
-{
- return closestItemFirst_withoutCache(item2, item1);
-}
-
-void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder)
-{
- if (!item->d_ptr->children.isEmpty()) {
- QList<QGraphicsItem *> childList = item->d_ptr->children;
- qSort(childList.begin(), childList.end(), qt_closestLeaf);
- for (int i = 0; i < childList.size(); ++i) {
- QGraphicsItem *item = childList.at(i);
- if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent))
- climbTree(childList.at(i), stackingOrder);
- }
- item->d_ptr->globalStackingOrder = (*stackingOrder)++;
- for (int i = 0; i < childList.size(); ++i) {
- QGraphicsItem *item = childList.at(i);
- if (item->flags() & QGraphicsItem::ItemStacksBehindParent)
- climbTree(childList.at(i), stackingOrder);
- }
- } else {
- item->d_ptr->globalStackingOrder = (*stackingOrder)++;
- }
-}
-
-void QGraphicsScenePrivate::_q_updateSortCache()
-{
- _q_updateIndex();
-
- if (!sortCacheEnabled || !updatingSortCache)
- return;
-
- updatingSortCache = false;
- int stackingOrder = 0;
-
- QList<QGraphicsItem *> topLevels;
-
- for (int i = 0; i < indexedItems.size(); ++i) {
- QGraphicsItem *item = indexedItems.at(i);
- if (item && item->parentItem() == 0)
- topLevels << item;
- }
- for (int i = 0; i < unindexedItems.size(); ++i) {
- QGraphicsItem *item = unindexedItems.at(i);
- if (item->parentItem() == 0)
- topLevels << item;
- }
-
- qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf);
- for (int i = 0; i < topLevels.size(); ++i)
- climbTree(topLevels.at(i), &stackingOrder);
-}
-
-void QGraphicsScenePrivate::sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order,
- bool sortCacheEnabled)
-{
- if (sortCacheEnabled) {
- if (order == Qt::AscendingOrder) {
- qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache);
- } else if (order == Qt::DescendingOrder) {
- qSort(itemList->begin(), itemList->end(), closestItemLast_withCache);
- }
- } else {
- if (order == Qt::AscendingOrder) {
- qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache);
- } else if (order == Qt::DescendingOrder) {
- qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache);
- }
- }
-}
-
/*!
\internal
@@ -1996,7 +1201,7 @@ void QGraphicsScenePrivate::setFont_helper(const QFont &font)
*/
void QGraphicsScenePrivate::resolveFont()
{
- QFont naturalFont = qApp->font();
+ QFont naturalFont = QApplication::font();
naturalFont.resolve(0);
QFont resolvedFont = font.resolve(naturalFont);
updateFont(resolvedFont);
@@ -2052,7 +1257,7 @@ void QGraphicsScenePrivate::setPalette_helper(const QPalette &palette)
*/
void QGraphicsScenePrivate::resolvePalette()
{
- QPalette naturalPalette = qApp->palette();
+ QPalette naturalPalette = QApplication::palette();
naturalPalette.resolve(0);
QPalette resolvedPalette = palette.resolve(naturalPalette);
updatePalette(resolvedPalette);
@@ -2107,8 +1312,8 @@ QGraphicsScene::QGraphicsScene(QObject *parent)
QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent)
: QObject(*new QGraphicsScenePrivate, parent)
{
- setSceneRect(sceneRect);
d_func()->init();
+ setSceneRect(sceneRect);
}
/*!
@@ -2122,8 +1327,8 @@ QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent)
QGraphicsScene::QGraphicsScene(qreal x, qreal y, qreal width, qreal height, QObject *parent)
: QObject(*new QGraphicsScenePrivate, parent)
{
- setSceneRect(x, y, width, height);
d_func()->init();
+ setSceneRect(x, y, width, height);
}
/*!
@@ -2160,8 +1365,19 @@ QGraphicsScene::~QGraphicsScene()
QRectF QGraphicsScene::sceneRect() const
{
Q_D(const QGraphicsScene);
- const_cast<QGraphicsScenePrivate *>(d)->_q_updateIndex();
- return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect;
+ if (d->hasSceneRect)
+ return d->sceneRect;
+
+ if (d->dirtyGrowingItemsBoundingRect) {
+ // Lazily update the growing items bounding rect
+ QGraphicsScenePrivate *thatd = const_cast<QGraphicsScenePrivate *>(d);
+ QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect;
+ thatd->growingItemsBoundingRect |= itemsBoundingRect();
+ thatd->dirtyGrowingItemsBoundingRect = false;
+ if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect)
+ emit const_cast<QGraphicsScene *>(this)->sceneRectChanged(thatd->growingItemsBoundingRect);
+ }
+ return d->growingItemsBoundingRect;
}
void QGraphicsScene::setSceneRect(const QRectF &rect)
{
@@ -2169,8 +1385,7 @@ void QGraphicsScene::setSceneRect(const QRectF &rect)
if (rect != d->sceneRect) {
d->hasSceneRect = !rect.isNull();
d->sceneRect = rect;
- d->resetIndex();
- emit sceneRectChanged(rect);
+ emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect);
}
}
@@ -2211,7 +1426,7 @@ void QGraphicsScene::setSceneRect(const QRectF &rect)
void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source,
Qt::AspectRatioMode aspectRatioMode)
{
- Q_D(QGraphicsScene);
+ // ### Switch to using the recursive rendering algorithm instead.
// Default source rect = scene rect
QRectF sourceRect = source;
@@ -2269,36 +1484,8 @@ void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRect
// Generate the style options
QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems];
- for (int i = 0; i < numItems; ++i) {
- QGraphicsItem *item = itemArray[i];
-
- QStyleOptionGraphicsItem option;
- option.state = QStyle::State_None;
- option.rect = item->boundingRect().toRect();
- if (item->isSelected())
- option.state |= QStyle::State_Selected;
- if (item->isEnabled())
- option.state |= QStyle::State_Enabled;
- if (item->hasFocus())
- option.state |= QStyle::State_HasFocus;
- if (d->hoverItems.contains(item))
- option.state |= QStyle::State_MouseOver;
- if (item == mouseGrabberItem())
- option.state |= QStyle::State_Sunken;
-
- // Calculate a simple level-of-detail metric.
- // ### almost identical code in QGraphicsView::paintEvent()
- // and QGraphicsView::render() - consider refactoring
- QTransform itemToDeviceTransform = item->deviceTransform(painterTransform);
-
- option.levelOfDetail = qSqrt(itemToDeviceTransform.map(v1).length() * itemToDeviceTransform.map(v2).length());
- option.matrix = itemToDeviceTransform.toAffine(); //### discards perspective
-
- option.exposedRect = item->boundingRect();
- option.exposedRect &= itemToDeviceTransform.inverted().mapRect(targetRect);
-
- styleOptionArray[i] = option;
- }
+ for (int i = 0; i < numItems; ++i)
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());
// Render the scene.
drawBackground(painter, sourceRect);
@@ -2335,8 +1522,19 @@ QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const
void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method)
{
Q_D(QGraphicsScene);
- d->resetIndex();
+ if (d->indexMethod == method)
+ return;
+
d->indexMethod = method;
+
+ QList<QGraphicsItem *> oldItems = d->index->items(Qt::AscendingOrder);
+ delete d->index;
+ if (method == BspTreeIndex)
+ d->index = new QGraphicsSceneBspTreeIndex(this);
+ else
+ d->index = new QGraphicsSceneLinearIndex(this);
+ for (int i = oldItems.size() - 1; i >= 0; --i)
+ d->index->addItem(oldItems.at(i));
}
/*!
@@ -2374,35 +1572,32 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method)
int QGraphicsScene::bspTreeDepth() const
{
Q_D(const QGraphicsScene);
- return d->bspTreeDepth;
+ QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
+ return bspTree ? bspTree->bspTreeDepth() : 0;
}
void QGraphicsScene::setBspTreeDepth(int depth)
{
Q_D(QGraphicsScene);
- if (d->bspTreeDepth == depth)
- return;
-
if (depth < 0) {
qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth);
return;
}
- d->bspTreeDepth = depth;
- d->resetIndex();
+ QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
+ if (!bspTree) {
+ qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP");
+ return;
+ }
+ bspTree->setBspTreeDepth(depth);
}
/*!
\property QGraphicsScene::sortCacheEnabled
\brief whether sort caching is enabled
\since 4.5
+ \obsolete
- When enabled, this property adds a cache that speeds up sorting and
- transformations for scenes with deep hierarchies (i.e., items with many
- levels of descendents), at the cost of using more memory (approx. 100 more
- bytes of memory per item).
-
- Items that are not part of a deep hierarchy suffer no penalty from this
- cache.
+ Since Qt 4.6, this property has no effect.
*/
bool QGraphicsScene::isSortCacheEnabled() const
{
@@ -2412,10 +1607,9 @@ bool QGraphicsScene::isSortCacheEnabled() const
void QGraphicsScene::setSortCacheEnabled(bool enabled)
{
Q_D(QGraphicsScene);
- if (enabled == d->sortCacheEnabled)
+ if (d->sortCacheEnabled == enabled)
return;
- if ((d->sortCacheEnabled = enabled))
- d->invalidateSortCache();
+ d->sortCacheEnabled = enabled;
}
/*!
@@ -2427,6 +1621,7 @@ void QGraphicsScene::setSortCacheEnabled(bool enabled)
*/
QRectF QGraphicsScene::itemsBoundingRect() const
{
+ // Does not take untransformable items into account.
QRectF boundingRect;
foreach (QGraphicsItem *item, items())
boundingRect |= item->sceneBoundingRect();
@@ -2441,44 +1636,43 @@ QRectF QGraphicsScene::itemsBoundingRect() const
QList<QGraphicsItem *> QGraphicsScene::items() const
{
Q_D(const QGraphicsScene);
- const_cast<QGraphicsScenePrivate *>(d)->purgeRemovedItems();
+ return d->index->items(Qt::AscendingOrder);
+}
- // If freeItemIndexes is empty, we know there are no holes in indexedItems and
- // unindexedItems.
- if (d->freeItemIndexes.isEmpty()) {
- if (d->unindexedItems.isEmpty())
- return d->indexedItems;
- return d->indexedItems + d->unindexedItems;
- }
+/*!
+ Returns an ordered list of all items on the scene. \a order decides the
+ sorting.
- // Rebuild the list of items to avoid holes. ### We could also just
- // compress the item lists at this point.
- QList<QGraphicsItem *> itemList;
- foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) {
- if (item)
- itemList << item;
- }
- return itemList;
+ \sa addItem(), removeItem()
+*/
+QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsScene);
+ return d->index->items(order);
}
/*!
+ \obsolete
+
Returns all visible items at position \a pos in the scene. The items are
- listed in descending Z order (i.e., the first item in the list is the
+ listed in descending stacking order (i.e., the first item in the list is the
top-most item, and the last item is the bottom-most item).
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
{
Q_D(const QGraphicsScene);
- return d->items_helper(pos);
+ return d->index->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder);
}
-
/*!
- \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
-
\overload
+ \obsolete
Returns all visible items that, depending on \a mode, are either inside or
intersect with the specified \a rectangle.
@@ -2486,23 +1680,47 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a rectangle are returned.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
-QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const
+QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
{
Q_D(const QGraphicsScene);
- return d->items_helper(rect, mode, Qt::AscendingOrder);
+ return d->index->items(rectangle, mode, Qt::AscendingOrder);
}
/*!
\fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
+ \obsolete
\since 4.3
This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).
+
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
*/
/*!
+ \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
\overload
+ \since 4.6
+
+ Returns all visible items that, depending on \a mode, are either inside or
+ intersect with the rectangle defined by \a x, \a y, \a w and \a h, in a list
+ sorted using \a order.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+*/
+
+/*!
+ \overload
+ \obsolete
Returns all visible items that, depending on \a mode, are either inside or
intersect with the polygon \a polygon.
@@ -2510,16 +1728,21 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a polygon are returned.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
{
Q_D(const QGraphicsScene);
- return d->items_helper(polygon, mode, Qt::AscendingOrder);
+ return d->index->items(polygon, mode, Qt::AscendingOrder);
}
/*!
\overload
+ \obsolete
Returns all visible items that, depending on \a path, are either inside or
intersect with the path \a path.
@@ -2527,12 +1750,103 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a path are returned.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
{
Q_D(const QGraphicsScene);
- return d->items_helper(path, mode, Qt::AscendingOrder);
+ return d->index->items(path, mode, Qt::AscendingOrder);
+}
+
+/*!
+ \since 4.6
+
+ Returns all visible items that, depending on \a mode, are at the specified \a pos
+ in a list sorted using \a order.
+
+ The default value for \a mode is Qt::IntersectsItemShape; all items whose
+ exact shape intersects with \a pos are returned.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \sa itemAt()
+*/
+QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsScene);
+ return d->index->items(pos, mode, order, deviceTransform);
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ Returns all visible items that, depending on \a mode, are either inside or
+ intersect with the specified \a rect and return a list sorted using \a order.
+
+ The default value for \a mode is Qt::IntersectsItemShape; all items whose
+ exact shape intersects with or is contained by \a rect are returned.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \sa itemAt()
+*/
+QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsScene);
+ return d->index->items(rect, mode, order, deviceTransform);
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ Returns all visible items that, depending on \a mode, are either inside or
+ intersect with the specified \a polygon and return a list sorted using \a order.
+
+ The default value for \a mode is Qt::IntersectsItemShape; all items whose
+ exact shape intersects with or is contained by \a polygon are returned.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \sa itemAt()
+*/
+QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsScene);
+ return d->index->items(polygon, mode, order, deviceTransform);
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ Returns all visible items that, depending on \a mode, are either inside or
+ intersect with the specified \a path and return a list sorted using \a order.
+
+ The default value for \a mode is Qt::IntersectsItemShape; all items whose
+ exact shape intersects with or is contained by \a path are returned.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \sa itemAt()
+*/
+QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsScene);
+ return d->index->items(path, mode, order, deviceTransform);
}
/*!
@@ -2555,34 +1869,77 @@ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
return QList<QGraphicsItem *>();
}
+ // Does not support ItemIgnoresTransformations.
QList<QGraphicsItem *> tmp;
- foreach (QGraphicsItem *itemInVicinity, d->estimateItemsInRect(item->sceneBoundingRect())) {
+ foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder)) {
if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode))
tmp << itemInVicinity;
}
- d->sortItems(&tmp, Qt::AscendingOrder, d->sortCacheEnabled);
return tmp;
}
/*!
- \fn QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
+ \overload
+ \obsolete
Returns the topmost visible item at the specified \a position, or 0 if
there are no items at this position.
\note The topmost item is the one with the highest Z-value.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa items(), collidingItems(), QGraphicsItem::setZValue()
*/
-QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos) const
+QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
{
- QList<QGraphicsItem *> itemsAtPoint = items(pos);
+ QList<QGraphicsItem *> itemsAtPoint = items(position);
return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
}
/*!
+ \since 4.6
+
+ Returns the topmost visible item at the specified \a position, or 0
+ if there are no items at this position.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \note The topmost item is the one with the highest Z-value.
+
+ \sa items(), collidingItems(), QGraphicsItem::setZValue()
+ */
+QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const
+{
+ QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape,
+ Qt::AscendingOrder, deviceTransform);
+ return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
+}
+
+/*!
+ \fn QGraphicsScene::itemAt(qreal x, qreal y, const QTransform &deviceTransform) const
+ \overload
+ \since 4.6
+
+ Returns the topmost item at the position specified by (\a x, \a
+ y), or 0 if there are no items at this position.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ This convenience function is equivalent to calling \c
+ {itemAt(QPointF(x, y), deviceTransform)}.
+
+ \note The topmost item is the one with the highest Z-value.
+*/
+
+/*!
\fn QGraphicsScene::itemAt(qreal x, qreal y) const
\overload
+ \obsolete
Returns the topmost item at the position specified by (\a x, \a
y), or 0 if there are no items at this position.
@@ -2590,6 +1947,10 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos) const
This convenience function is equivalent to calling \c
{itemAt(QPointF(x, y))}.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\note The topmost item is the one with the highest Z-value.
*/
@@ -2630,21 +1991,42 @@ QPainterPath QGraphicsScene::selectionArea() const
}
/*!
+ \since 4.6
+
Sets the selection area to \a path. All items within this area are
immediately selected, and all items outside are unselected. You can get
the list of all selected items by calling selectedItems().
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
For an item to be selected, it must be marked as \e selectable
(QGraphicsItem::ItemIsSelectable).
\sa clearSelection(), selectionArea()
*/
+void QGraphicsScene::setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform)
+{
+ setSelectionArea(path, Qt::IntersectsItemShape, deviceTransform);
+}
+
+/*!
+ \obsolete
+ \overload
+
+ Sets the selection area to \a path.
+
+ This function is deprecated and leads to incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path)
{
- setSelectionArea(path, Qt::IntersectsItemShape);
+ setSelectionArea(path, Qt::IntersectsItemShape, QTransform());
}
/*!
+ \obsolete
\overload
\since 4.3
@@ -2655,6 +2037,24 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path)
*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode)
{
+ setSelectionArea(path, mode, QTransform());
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ Sets the selection area to \a path using \a mode to determine if items are
+ included in the selection area.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \sa clearSelection(), selectionArea()
+*/
+void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode,
+ const QTransform &deviceTransform)
+{
Q_D(QGraphicsScene);
// Note: with boolean path operations, we can improve performance here
@@ -2670,7 +2070,7 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectio
bool changed = false;
// Set all items in path to selected.
- foreach (QGraphicsItem *item, items(path, mode)) {
+ foreach (QGraphicsItem *item, items(path, mode, Qt::AscendingOrder, deviceTransform)) {
if (item->flags() & QGraphicsItem::ItemIsSelectable) {
if (!item->isSelected())
changed = true;
@@ -2727,27 +2127,16 @@ void QGraphicsScene::clearSelection()
void QGraphicsScene::clear()
{
Q_D(QGraphicsScene);
- // Recursive descent delete
- for (int i = 0; i < d->indexedItems.size(); ++i) {
- if (QGraphicsItem *item = d->indexedItems.at(i)) {
- if (!item->parentItem())
- delete item;
- }
- }
- QList<QGraphicsItem *> unindexedParents;
- for (int i = 0; i < d->unindexedItems.size(); ++i) {
- QGraphicsItem *item = d->unindexedItems.at(i);
- if (!item->parentItem())
- unindexedParents << item;
- }
- d->unindexedItems.clear();
- qDeleteAll(unindexedParents);
-
- d->indexedItems.clear();
- d->freeItemIndexes.clear();
+ // NB! We have to clear the index before deleting items; otherwise the
+ // index might try to access dangling item pointers.
+ d->index->clear();
+ const QList<QGraphicsItem *> items = d->topLevelItems;
+ qDeleteAll(items);
+ Q_ASSERT(d->topLevelItems.isEmpty());
d->lastItemCount = 0;
- d->bspTree.clear();
- d->largestUntransformableItem = QRectF();
+ d->allItemsIgnoreHoverEvents = true;
+ d->allItemsUseDefaultCursor = true;
+ d->allItemsIgnoreTouchEvents = true;
}
/*!
@@ -2837,6 +2226,9 @@ void QGraphicsScene::destroyItemGroup(QGraphicsItemGroup *group)
moved to this scene), QGraphicsScene will send an addition notification as
the item is removed from its previous scene.
+ If the item is a panel, the scene is active, and there is no active panel
+ in the scene, then the item will be activated.
+
\sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(),
addRect(), addText(), addWidget()
*/
@@ -2851,7 +2243,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
qWarning("QGraphicsScene::addItem: item has already been added to this scene");
return;
}
-
// Remove this item from its existing scene
if (QGraphicsScene *oldScene = item->scene())
oldScene->removeItem(item);
@@ -2867,14 +2258,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
return;
}
- // Prevent reusing a recently deleted pointer: purge all removed items
- // from our lists.
- d->purgeRemovedItems();
-
- // Invalidate any sort caching; arrival of a new item means we need to
- // resort.
- d->invalidateSortCache();
-
// Detach this item from its parent if the parent's scene is different
// from this scene.
if (QGraphicsItem *itemParent = item->parentItem()) {
@@ -2885,30 +2268,42 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
// Add the item to this scene
item->d_func()->scene = targetScene;
- // Indexing requires sceneBoundingRect(), but because \a item might
- // not be completely constructed at this point, we need to store it in
- // a temporary list and schedule an indexing for later.
- d->unindexedItems << item;
- item->d_func()->index = -1;
- d->startIndexTimer();
+ // Add the item in the index
+ d->index->addItem(item);
- // Update the scene's sort cache settings.
- item->d_ptr->globalStackingOrder = -1;
- d->invalidateSortCache();
+ // Add to list of toplevels if this item is a toplevel.
+ if (!item->d_ptr->parent)
+ d->registerTopLevelItem(item);
// Add to list of items that require an update. We cannot assume that the
// item is fully constructed, so calling item->update() can lead to a pure
// virtual function call to boundingRect().
- if (!d->updateAll) {
- if (d->pendingUpdateItems.isEmpty())
- QMetaObject::invokeMethod(this, "_q_updateLater", Qt::QueuedConnection);
- d->pendingUpdateItems << item;
- }
+ d->markDirty(item);
+ d->dirtyGrowingItemsBoundingRect = true;
// Disable selectionChanged() for individual items
++d->selectionChanging;
int oldSelectedItemSize = d->selectedItems.size();
+ // Enable mouse tracking if the item accepts hover events or has a cursor set.
+ if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
+ d->allItemsIgnoreHoverEvents = false;
+ d->enableMouseTrackingOnViews();
+ }
+#ifndef QT_NO_CURSOR
+ if (d->allItemsUseDefaultCursor && item->hasCursor()) {
+ d->allItemsUseDefaultCursor = false;
+ if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
+ d->enableMouseTrackingOnViews();
+ }
+#endif //QT_NO_CURSOR
+
+ // Enable touch events if the item accepts touch events.
+ if (d->allItemsIgnoreTouchEvents && item->acceptTouchEvents()) {
+ d->allItemsIgnoreTouchEvents = false;
+ d->enableTouchEventsOnViews();
+ }
+
// Update selection lists
if (item->isSelected())
d->selectedItems << item;
@@ -2955,6 +2350,17 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
// Deliver post-change notification
item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
+
+ // Auto-activate the first inactive panel if the scene is active.
+ if (isActive() && !d->activePanel && item->isPanel())
+ setActivePanel(item);
+
+ // Ensure that newly added items that have subfocus set, gain
+ // focus automatically if there isn't a focus item already.
+ if (!d->focusItem && item->focusItem())
+ item->focusItem()->setFocus();
+
+ d->updateInputMethodSensitivityInViews();
}
/*!
@@ -3226,109 +2632,12 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
return;
}
- // If the item has focus, remove it (and any focusWidget reference).
- item->clearFocus();
-
- // Clear its background
- item->update();
-
- // Note: This will access item's sceneBoundingRect(), which (as this is
- // C++) is why we cannot call removeItem() from QGraphicsItem's
- // destructor.
- d->removeFromIndex(item);
-
- if (item == d->tabFocusFirst) {
- QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
- widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
- }
- // Set the item's scene ptr to 0.
- item->d_func()->scene = 0;
-
- // Detach the item from its parent.
- if (QGraphicsItem *parentItem = item->parentItem()) {
- if (parentItem->scene()) {
- Q_ASSERT_X(parentItem->scene() == this, "QGraphicsScene::removeItem",
- "Parent item's scene is different from this item's scene");
- item->setParentItem(0);
- }
- }
-
- // Remove from our item lists.
- int index = item->d_func()->index;
- if (index != -1) {
- d->freeItemIndexes << index;
- d->indexedItems[index] = 0;
- } else {
- d->unindexedItems.removeAll(item);
- }
-
- // Remove from scene transform cache
- int transformIndex = item->d_func()->sceneTransformIndex;
- if (transformIndex != -1) {
- d->validTransforms.setBit(transformIndex, 0);
- d->freeSceneTransformSlots.append(transformIndex);
- item->d_func()->sceneTransformIndex = -1;
- }
-
- if (item == d->focusItem)
- d->focusItem = 0;
- if (item == d->lastFocusItem)
- d->lastFocusItem = 0;
- if (item == d->activeWindow) {
- // ### deactivate...
- d->activeWindow = 0;
- }
-
- // Disable selectionChanged() for individual items
- ++d->selectionChanging;
- int oldSelectedItemsSize = d->selectedItems.size();
-
- // Update selected & hovered item bookkeeping
- d->selectedItems.remove(item);
- d->hoverItems.removeAll(item);
- d->pendingUpdateItems.removeAll(item);
- d->cachedItemsUnderMouse.removeAll(item);
- d->unpolishedItems.removeAll(item);
- d->dirtyItems.removeAll(item);
-
- //We remove all references of item from the sceneEventFilter arrays
- QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = d->sceneEventFilters.begin();
- while (iterator != d->sceneEventFilters.end()) {
- if (iterator.value() == item || iterator.key() == item)
- iterator = d->sceneEventFilters.erase(iterator);
- else
- ++iterator;
- }
-
-
- //Ensure dirty flag have the correct default value so the next time it will be added it will receive updates
- item->d_func()->dirty = 0;
- item->d_func()->dirtyChildren = 0;
-
- // Remove all children recursively
- foreach (QGraphicsItem *child, item->children())
- removeItem(child);
-
- // Reset the mouse grabber and focus item data.
- if (d->mouseGrabberItems.contains(item))
- d->ungrabMouse(item);
-
- // Reset the keyboard grabber
- if (d->keyboardGrabberItems.contains(item))
- item->ungrabKeyboard();
-
- // Reset the last mouse grabber item
- if (item == d->lastMouseGrabberItem)
- d->lastMouseGrabberItem = 0;
-
- // Reenable selectionChanged() for individual items
- --d->selectionChanging;
-
- if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemsSize)
- emit selectionChanged();
+ d->removeItemHelper(item);
// Deliver post-change notification
item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
+
+ d->updateInputMethodSensitivityInViews();
}
/*!
@@ -3365,36 +2674,10 @@ QGraphicsItem *QGraphicsScene::focusItem() const
void QGraphicsScene::setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason)
{
Q_D(QGraphicsScene);
- if (item == d->focusItem)
- return;
- if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
- || !item->isVisible() || !item->isEnabled())) {
- item = 0;
- }
-
- if (item) {
- setFocus(focusReason);
- if (item == d->focusItem)
- return;
- }
-
- if (d->focusItem) {
- QFocusEvent event(QEvent::FocusOut, focusReason);
- d->lastFocusItem = d->focusItem;
- d->focusItem = 0;
- d->sendEvent(d->lastFocusItem, &event);
- }
-
- if (item) {
- if (item->isWidget()) {
- // Update focus child chain.
- static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget();
- }
-
- d->focusItem = item;
- QFocusEvent event(QEvent::FocusIn, focusReason);
- d->sendEvent(item, &event);
- }
+ if (item)
+ item->setFocus(focusReason);
+ else
+ d->setFocusItemHelper(item, focusReason);
}
/*!
@@ -3449,13 +2732,17 @@ void QGraphicsScene::clearFocus()
/*!
\property QGraphicsScene::stickyFocus
- \brief whether or not clicking the scene will clear focus
+ \brief whether clicking into the scene background will clear focus
+
+ \since 4.6
+
+ In a QGraphicsScene with stickyFocus set to true, focus will remain
+ unchanged when the user clicks into the scene background or on an item
+ that does not accept focus. Otherwise, focus will be cleared.
- If this property is false (the default), then clicking on the scene
- background or on an item that does not accept focus, will clear
- focus. Otherwise, focus will remain unchanged.
+ By default, this property is false.
- The focus change happens in response to a mouse press. You can reimplement
+ Focus changes in response to a mouse press. You can reimplement
mousePressEvent() in a subclass of QGraphicsScene to toggle this property
based on where the user has clicked.
@@ -3578,7 +2865,7 @@ void QGraphicsScene::setForegroundBrush(const QBrush &brush)
QVariant QGraphicsScene::inputMethodQuery(Qt::InputMethodQuery query) const
{
Q_D(const QGraphicsScene);
- if (!d->focusItem)
+ if (!d->focusItem || !(d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
return QVariant();
const QTransform matrix = d->focusItem->sceneTransform();
QVariant value = d->focusItem->inputMethodQuery(query);
@@ -3607,14 +2894,14 @@ void QGraphicsScene::update(const QRectF &rect)
// Check if anyone's connected; if not, we can send updates directly to
// the views. Otherwise or if there are no views, use old behavior.
- bool directUpdates = !(d->connectedSignals & d->changedSignalMask) && !d->views.isEmpty();
+ bool directUpdates = !(d->isSignalConnected(d->changedSignalIndex)) && !d->views.isEmpty();
if (rect.isNull()) {
d->updateAll = true;
d->updatedRects.clear();
if (directUpdates) {
// Update all views.
for (int i = 0; i < d->views.size(); ++i)
- d->views.at(i)->d_func()->updateAll();
+ d->views.at(i)->d_func()->fullUpdatePending = true;
}
} else {
if (directUpdates) {
@@ -3628,7 +2915,7 @@ void QGraphicsScene::update(const QRectF &rect)
}
}
- if (!directUpdates && !d->calledEmitUpdated) {
+ if (!d->calledEmitUpdated) {
d->calledEmitUpdated = true;
QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection);
}
@@ -3739,11 +3026,16 @@ bool QGraphicsScene::event(QEvent *event)
case QEvent::GraphicsSceneHoverEnter:
case QEvent::GraphicsSceneHoverLeave:
case QEvent::GraphicsSceneHoverMove:
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
// Reset the under-mouse list to ensure that this event gets fresh
// item-under-mouse data. Be careful about this list; if people delete
// items from inside event handlers, this list can quickly end up
// having stale pointers in it. We need to clear it before dispatching
// events that use it.
+ // ### this should only be cleared if we received a new mouse move event,
+ // which relies on us fixing the replay mechanism in QGraphicsView.
d->cachedItemsUnderMouse.clear();
default:
break;
@@ -3833,40 +3125,43 @@ bool QGraphicsScene::event(QEvent *event)
case QEvent::InputMethod:
inputMethodEvent(static_cast<QInputMethodEvent *>(event));
break;
- case QEvent::WindowActivate: {
+ case QEvent::WindowActivate:
if (!d->activationRefCount++) {
- // Notify all non-window widgets.
- foreach (QGraphicsItem *item, items()) {
- if (item->isWidget() && item->isVisible() && !item->isWindow() && !item->parentWidget()) {
- QEvent event(QEvent::WindowActivate);
- QApplication::sendEvent(static_cast<QGraphicsWidget *>(item), &event);
+ if (d->lastActivePanel) {
+ // Activate the last panel.
+ setActivePanel(d->lastActivePanel);
+ } else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) {
+ // Activate the panel of the first item in the tab focus
+ // chain.
+ setActivePanel(d->tabFocusFirst);
+ } else {
+ // Activate all toplevel items.
+ QEvent event(QEvent::WindowActivate);
+ foreach (QGraphicsItem *item, items()) {
+ if (item->isVisible() && !item->isPanel() && !item->parentItem())
+ sendEvent(item, &event);
}
}
-
- // Restore window activation.
- QGraphicsItem *nextFocusItem = d->focusItem ? d->focusItem : d->lastFocusItem;
- if (nextFocusItem && nextFocusItem->window())
- setActiveWindow(static_cast<QGraphicsWidget *>(nextFocusItem));
- else if (d->tabFocusFirst && d->tabFocusFirst->isWindow())
- setActiveWindow(d->tabFocusFirst);
}
break;
- }
- case QEvent::WindowDeactivate: {
+ case QEvent::WindowDeactivate:
if (!--d->activationRefCount) {
- // Remove window activation.
- setActiveWindow(0);
-
- // Notify all non-window widgets.
- foreach (QGraphicsItem *item, items()) {
- if (item->isWidget() && item->isVisible() && !item->isWindow() && !item->parentWidget()) {
- QEvent event(QEvent::WindowDeactivate);
- QApplication::sendEvent(static_cast<QGraphicsWidget *>(item), &event);
+ if (d->activePanel) {
+ // Deactivate the active panel (but keep it so we can
+ // reactivate it later).
+ QGraphicsItem *lastActivePanel = d->activePanel;
+ setActivePanel(0);
+ d->lastActivePanel = lastActivePanel;
+ } else {
+ // Activate all toplevel items.
+ QEvent event(QEvent::WindowDeactivate);
+ foreach (QGraphicsItem *item, items()) {
+ if (item->isVisible() && !item->isPanel() && !item->parentItem())
+ sendEvent(item, &event);
}
}
}
break;
- }
case QEvent::ApplicationFontChange: {
// Resolve the existing scene font.
d->resolveFont();
@@ -3890,16 +3185,11 @@ bool QGraphicsScene::event(QEvent *event)
// geometries that do not have an explicit style set.
update();
break;
- case QEvent::Timer:
- if (d->indexTimerId && static_cast<QTimerEvent *>(event)->timerId() == d->indexTimerId) {
- if (d->restartIndexTimer) {
- d->restartIndexTimer = false;
- } else {
- // this call will kill the timer
- d->_q_updateIndex();
- }
- }
- // Fallthrough intended - support timers in subclasses.
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ d->touchEventHandler(static_cast<QTouchEvent *>(event));
+ break;
default:
return QObject::event(event);
}
@@ -3919,10 +3209,10 @@ bool QGraphicsScene::eventFilter(QObject *watched, QEvent *event)
switch (event->type()) {
case QEvent::ApplicationPaletteChange:
- qApp->postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
+ QApplication::postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
break;
case QEvent::ApplicationFontChange:
- qApp->postEvent(this, new QEvent(QEvent::ApplicationFontChange));
+ QApplication::postEvent(this, new QEvent(QEvent::ApplicationFontChange));
break;
default:
break;
@@ -4188,7 +3478,7 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent)
text = toolTipItem->toolTip();
point = helpEvent->screenPos();
}
- QToolTip::showText(point, text);
+ QToolTip::showText(point, text, helpEvent->widget());
helpEvent->setAccepted(!text.isEmpty());
#endif
}
@@ -4209,6 +3499,9 @@ bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *i
*/
bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
{
+ if (allItemsIgnoreHoverEvents)
+ return false;
+
// Find the first item that accepts hover events, reusing earlier
// calculated data is possible.
if (cachedItemsUnderMouse.isEmpty()) {
@@ -4231,8 +3524,8 @@ bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEv
QGraphicsItem *commonAncestorItem = (item && !hoverItems.isEmpty()) ? item->commonAncestorItem(hoverItems.last()) : 0;
while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem))
commonAncestorItem = commonAncestorItem->parentItem();
- if (commonAncestorItem && commonAncestorItem->window() != item->window()) {
- // The common ancestor isn't in the same window as the two hovered
+ if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) {
+ // The common ancestor isn't in the same panel as the two hovered
// items.
commonAncestorItem = 0;
}
@@ -4253,8 +3546,8 @@ bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEv
QGraphicsItem *parent = item;
while (parent && parent != commonAncestorItem) {
parents.prepend(parent);
- if (parent->isWindow()) {
- // Stop at the window - we don't deliver beyond this point.
+ if (parent->isPanel()) {
+ // Stop at the panel - we don't deliver beyond this point.
break;
}
parent = parent->parentItem();
@@ -4284,8 +3577,7 @@ void QGraphicsScenePrivate::leaveScene()
{
Q_Q(QGraphicsScene);
#ifndef QT_NO_TOOLTIP
- // Remove any tooltips
- QToolTip::showText(QPoint(), QString());
+ QToolTip::hideText();
#endif
// Send HoverLeave events to all existing hover items, topmost first.
QGraphicsView *senderWidget = qobject_cast<QGraphicsView *>(q->sender());
@@ -4332,7 +3624,7 @@ void QGraphicsScene::keyPressEvent(QKeyEvent *keyEvent)
// is filtered out, stop propagating it.
if (!d->sendEvent(p, keyEvent))
break;
- } while (!keyEvent->isAccepted() && !p->isWindow() && (p = p->parentItem()));
+ } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
} else {
keyEvent->ignore();
}
@@ -4362,7 +3654,7 @@ void QGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent)
// is filtered out, stop propagating it.
if (!d->sendEvent(p, keyEvent))
break;
- } while (!keyEvent->isAccepted() && !p->isWindow() && (p = p->parentItem()));
+ } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
} else {
keyEvent->ignore();
}
@@ -4388,6 +3680,13 @@ void QGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent)
void QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
Q_D(QGraphicsScene);
+ if (d->mouseGrabberItems.isEmpty()) {
+ // Dispatch hover events
+ QGraphicsSceneHoverEvent hover;
+ _q_hoverFromMouseEvent(&hover, mouseEvent);
+ d->dispatchHoverEvent(&hover);
+ }
+
d->mousePressEventHandler(mouseEvent);
}
@@ -4505,7 +3804,8 @@ void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent)
bool hasSetFocus = false;
foreach (QGraphicsItem *item, wheelCandidates) {
- if (!hasSetFocus && item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
+ if (!hasSetFocus && item->isEnabled()
+ && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
if (item->isWidget() && static_cast<QGraphicsWidget *>(item)->focusPolicy() == Qt::WheelFocus) {
hasSetFocus = true;
if (item != focusItem())
@@ -4516,9 +3816,9 @@ void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent)
wheelEvent->setPos(item->d_ptr->genericMapFromScene(wheelEvent->scenePos(),
wheelEvent->widget()));
wheelEvent->accept();
- bool isWindow = item->isWindow();
+ bool isPanel = item->isPanel();
d->sendEvent(item, wheelEvent);
- if (isWindow || wheelEvent->isAccepted())
+ if (isPanel || wheelEvent->isAccepted())
break;
}
}
@@ -4528,16 +3828,16 @@ void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent)
subclass to receive input method events for the scene.
The default implementation forwards the event to the focusItem().
- If no item currently has focus, this function does nothing.
+ If no item currently has focus or the current focus item does not
+ accept input methods, this function does nothing.
\sa QGraphicsItem::inputMethodEvent()
*/
void QGraphicsScene::inputMethodEvent(QInputMethodEvent *event)
{
Q_D(QGraphicsScene);
- if (!d->focusItem)
- return;
- d->sendEvent(d->focusItem, event);
+ if (d->focusItem && (d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
+ d->sendEvent(d->focusItem, event);
}
/*!
@@ -4608,7 +3908,7 @@ static void _q_paintItem(QGraphicsItem *item, QPainter *painter,
? proxy->widget()->windowOpacity() : 1.0;
const qreal oldPainterOpacity = painter->opacity();
- if (qFuzzyCompare(windowOpacity + 1, qreal(1.0)))
+ if (qFuzzyIsNull(windowOpacity))
return;
// Set new painter opacity.
if (windowOpacity < 1.0)
@@ -4687,7 +3987,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
const QStyleOptionGraphicsItem *option, QWidget *widget,
bool painterStateProtection)
{
- QGraphicsItemPrivate *itemd = item->d_ptr;
+ QGraphicsItemPrivate *itemd = item->d_ptr.data();
QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode);
// Render directly, using no cache.
@@ -4717,8 +4017,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
return;
// Fetch the off-screen transparent buffer and exposed area info.
- QString pixmapKey;
+ QPixmapCache::Key pixmapKey;
QPixmap pix;
+ bool pixmapFound;
QGraphicsItemCache *itemCache = itemd->extraItemCache();
if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
if (itemCache->boundingRect != brect.toRect()) {
@@ -4728,17 +4029,11 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
pixmapKey = itemCache->key;
} else {
- if ((pixmapKey = itemCache->deviceData.value(widget).key).isEmpty()) {
- pixmapKey.sprintf("qgv-%p-%p", item, widget);
- QGraphicsItemCache::DeviceData data;
- data.key = pixmapKey;
- itemCache->deviceData.insert(widget, data);
- }
+ pixmapKey = itemCache->deviceData.value(widget).key;
}
// Find pixmap in cache.
- if (!itemCache->allExposed)
- QPixmapCache::find(pixmapKey, pix);
+ pixmapFound = QPixmapCache::find(pixmapKey, &pix);
// Render using item coordinate cache mode.
if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
@@ -4763,6 +4058,12 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Redraw any newly exposed areas.
if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
+
+ //We know that we will modify the pixmap, removing it from the cache
+ //will detach the one we have and avoid a deep copy
+ if (pixmapFound)
+ QPixmapCache::remove(pixmapKey);
+
// Fit the item's bounding rect into the pixmap's coordinates.
QTransform itemToPixmap;
if (fixedCacheSize) {
@@ -4773,7 +4074,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Generate the item's exposedRect and map its list of expose
// rects to device coordinates.
- QStyleOptionGraphicsItem cacheOption = *option;
+ styleOptionTmp = *option;
QRegion pixmapExposed;
QRectF exposedRect;
if (!itemCache->allExposed) {
@@ -4785,14 +4086,14 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
} else {
exposedRect = brect;
}
- cacheOption.exposedRect = exposedRect;
+ styleOptionTmp.exposedRect = exposedRect;
// Render.
_q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
- &cacheOption, painterStateProtection);
+ &styleOptionTmp, painterStateProtection);
- // Reinsert this pixmap into the cache.
- QPixmapCache::insert(pixmapKey, pix);
+ // insert this pixmap into the cache.
+ itemCache->key = QPixmapCache::insert(pix);
// Reset expose data.
itemCache->allExposed = false;
@@ -4858,7 +4159,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
bool allowPartialCacheExposure = !viewRect.contains(deviceRect);
#else
// Only if deviceRect is 20% taller or wider than the desktop.
- QRect desktopRect = qApp->desktop()->availableGeometry(widget);
+ QRect desktopRect = QApplication::desktop()->availableGeometry(widget);
bool allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width()
|| desktopRect.height() * 1.2 < deviceRect.height());
#endif
@@ -4919,6 +4220,11 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Check for newly invalidated areas.
if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
+ //We know that we will modify the pixmap, removing it from the cache
+ //will detach the one we have and avoid a deep copy
+ if (pixmapFound)
+ QPixmapCache::remove(pixmapKey);
+
// Construct an item-to-pixmap transform.
QPointF p = deviceRect.topLeft();
QTransform itemToPixmap = painter->worldTransform();
@@ -4945,12 +4251,12 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
foreach (QRect r, scrollExposure.rects())
br |= pixmapToItem.mapRect(r);
}
- QStyleOptionGraphicsItem cacheOption = *option;
- cacheOption.exposedRect = br.adjusted(-1, -1, 1, 1);
+ styleOptionTmp = *option;
+ styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
// Render the exposed areas.
_q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
- &cacheOption, painterStateProtection);
+ &styleOptionTmp, painterStateProtection);
// Reset expose data.
pixModified = true;
@@ -4959,8 +4265,8 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
if (pixModified) {
- // Reinsert this pixmap into the cache
- QPixmapCache::insert(pixmapKey, pix);
+ // Insert this pixmap into the cache.
+ deviceData->key = QPixmapCache::insert(pix);
}
// Redraw the exposed area using an untransformed painter. This
@@ -4979,12 +4285,494 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
}
+void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform,
+ QRegion *exposedRegion, QWidget *widget)
+{
+ QRectF exposedSceneRect;
+ if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
+ exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
+ if (viewTransform)
+ exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
+ }
+ const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::DescendingOrder);
+ for (int i = 0; i < tli.size(); ++i)
+ drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget);
+}
+
+void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
+ const QTransform *const viewTransform,
+ QRegion *exposedRegion, QWidget *widget,
+ qreal parentOpacity, const QTransform *const effectTransform)
+{
+ Q_ASSERT(item);
+
+ if (!item->d_ptr->visible)
+ return;
+
+ const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
+ const bool itemHasChildren = !item->d_ptr->children.isEmpty();
+ if (!itemHasContents && !itemHasChildren)
+ return; // Item has neither contents nor children!(?)
+
+ const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
+ const bool itemIsFullyTransparent = (opacity < 0.0001);
+ if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
+ return;
+
+ QTransform transform(Qt::Uninitialized);
+ QTransform *transformPtr = 0;
+ bool translateOnlyTransform = false;
+#define ENSURE_TRANSFORM_PTR \
+ if (!transformPtr) { \
+ Q_ASSERT(!itemIsUntransformable); \
+ if (viewTransform) { \
+ transform = item->d_ptr->sceneTransform; \
+ transform *= *viewTransform; \
+ transformPtr = &transform; \
+ } else { \
+ transformPtr = &item->d_ptr->sceneTransform; \
+ translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \
+ } \
+ }
+
+ // Update the item's scene transform if the item is transformable;
+ // otherwise calculate the full transform,
+ bool wasDirtyParentSceneTransform = false;
+ const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
+ if (itemIsUntransformable) {
+ transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
+ transformPtr = &transform;
+ } else if (item->d_ptr->dirtySceneTransform) {
+ item->d_ptr->updateSceneTransformFromParent();
+ Q_ASSERT(!item->d_ptr->dirtySceneTransform);
+ wasDirtyParentSceneTransform = true;
+ }
+
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ bool drawItem = itemHasContents && !itemIsFullyTransparent;
+ if (drawItem) {
+ const QRectF brect = adjustedItemEffectiveBoundingRect(item);
+ ENSURE_TRANSFORM_PTR
+ QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect()
+ : transformPtr->mapRect(brect).toRect();
+ if (widget)
+ item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
+ viewBoundingRect.adjust(-1, -1, 1, 1);
+ drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty();
+ if (!drawItem) {
+ if (!itemHasChildren)
+ return;
+ if (itemClipsChildrenToShape) {
+ if (wasDirtyParentSceneTransform)
+ item->d_ptr->invalidateChildrenSceneTransform();
+ return;
+ }
+ }
+ } // else we know for sure this item has children we must process.
+
+ if (itemHasChildren && itemClipsChildrenToShape)
+ ENSURE_TRANSFORM_PTR;
+
+ if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) {
+ ENSURE_TRANSFORM_PTR;
+ QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
+ painter, opacity, wasDirtyParentSceneTransform, drawItem);
+ QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
+ QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
+ (source->d_func());
+ sourced->info = &info;
+ const QTransform restoreTransform = painter->worldTransform();
+ if (effectTransform)
+ painter->setWorldTransform(*transformPtr * *effectTransform);
+ else
+ painter->setWorldTransform(*transformPtr);
+ item->d_ptr->graphicsEffect->draw(painter, source);
+ painter->setWorldTransform(restoreTransform);
+ sourced->info = 0;
+ } else {
+ draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
+ effectTransform, wasDirtyParentSceneTransform, drawItem);
+ }
+}
+
+void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
+ const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
+ qreal opacity, const QTransform *effectTransform,
+ bool wasDirtyParentSceneTransform, bool drawItem)
+{
+ const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemHasChildren = !item->d_ptr->children.isEmpty();
+
+ int i = 0;
+ if (itemHasChildren) {
+ item->d_ptr->ensureSortedChildren();
+
+ if (itemClipsChildrenToShape) {
+ painter->save();
+ Q_ASSERT(transformPtr);
+ if (effectTransform)
+ painter->setWorldTransform(*transformPtr * *effectTransform);
+ else
+ painter->setWorldTransform(*transformPtr);
+ painter->setClipPath(item->shape(), Qt::IntersectClip);
+ }
+
+ // Draw children behind
+ for (i = 0; i < item->d_ptr->children.size(); ++i) {
+ QGraphicsItem *child = item->d_ptr->children.at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
+ break;
+ if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
+ continue;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
+ }
+ }
+
+ // Draw item
+ if (drawItem) {
+ Q_ASSERT(!itemIsFullyTransparent);
+ Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents));
+ Q_ASSERT(transformPtr);
+ item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
+ ? *exposedRegion : QRegion(), exposedRegion == 0);
+
+ const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
+ const bool savePainter = itemClipsToShape || painterStateProtection;
+ if (savePainter)
+ painter->save();
+
+ if (!itemHasChildren || !itemClipsChildrenToShape) {
+ if (effectTransform)
+ painter->setWorldTransform(*transformPtr * *effectTransform);
+ else
+ painter->setWorldTransform(*transformPtr);
+ }
+
+ if (itemClipsToShape)
+ painter->setClipPath(item->shape(), Qt::IntersectClip);
+ painter->setOpacity(opacity);
+
+ if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
+ item->paint(painter, &styleOptionTmp, widget);
+ else
+ drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
+
+ if (savePainter)
+ painter->restore();
+ }
+
+ // Draw children in front
+ if (itemHasChildren) {
+ for (; i < item->d_ptr->children.size(); ++i) {
+ QGraphicsItem *child = item->d_ptr->children.at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
+ continue;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
+ }
+ }
+
+ // Restore child clip
+ if (itemHasChildren && itemClipsChildrenToShape)
+ painter->restore();
+}
+
+void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
+ bool maybeDirtyClipPath, bool force, bool ignoreOpacity,
+ bool removingItemFromScene)
+{
+ Q_ASSERT(item);
+ if (updateAll)
+ return;
+
+ if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath,
+ /*ignoreVisibleBit=*/force,
+ /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren,
+ /*ignoreOpacity=*/ignoreOpacity)) {
+ if (item->d_ptr->dirty) {
+ // The item is already marked as dirty and will be processed later. However,
+ // we have to make sure ignoreVisible and ignoreOpacity are set properly;
+ // otherwise things like: item->update(); item->hide() (force is now true)
+ // won't work as expected.
+ if (force)
+ item->d_ptr->ignoreVisible = 1;
+ if (ignoreOpacity)
+ item->d_ptr->ignoreOpacity = 1;
+ }
+ return;
+ }
+
+ const bool fullItemUpdate = rect.isNull();
+ if (!fullItemUpdate && rect.isEmpty())
+ return;
+
+ if (!processDirtyItemsEmitted) {
+ QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
+ processDirtyItemsEmitted = true;
+ }
+
+ if (removingItemFromScene) {
+ // Note that this function can be called from the item's destructor, so
+ // do NOT call any virtual functions on it within this block.
+ if (isSignalConnected(changedSignalIndex) || views.isEmpty()) {
+ // This block of code is kept for compatibility. Since 4.5, by default
+ // QGraphicsView does not connect the signal and we use the below
+ // method of delivering updates.
+ q_func()->update();
+ return;
+ }
+
+ for (int i = 0; i < views.size(); ++i) {
+ QGraphicsViewPrivate *viewPrivate = views.at(i)->d_func();
+ QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
+ rect.translate(viewPrivate->dirtyScrollOffset);
+ viewPrivate->updateRect(rect);
+ }
+ return;
+ }
+
+ bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents;
+ if (!hasNoContents) {
+ item->d_ptr->dirty = 1;
+ if (fullItemUpdate)
+ item->d_ptr->fullUpdatePending = 1;
+ else if (!item->d_ptr->fullUpdatePending)
+ item->d_ptr->needsRepaint |= rect;
+ }
+
+ if (invalidateChildren) {
+ item->d_ptr->allChildrenDirty = 1;
+ item->d_ptr->dirtyChildren = 1;
+ }
+
+ if (force)
+ item->d_ptr->ignoreVisible = 1;
+ if (ignoreOpacity)
+ item->d_ptr->ignoreOpacity = 1;
+
+ QGraphicsItem *p = item->d_ptr->parent;
+ while (p) {
+ p->d_ptr->dirtyChildren = 1;
+ if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) {
+ p->d_ptr->dirty = 1;
+ p->d_ptr->fullUpdatePending = 1;
+ }
+ p = p->d_ptr->parent;
+ }
+}
+
+static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
+ const QRectF &rect, bool itemIsUntransformable)
+{
+ Q_ASSERT(view);
+ Q_ASSERT(item);
+
+ QGraphicsItem *itemq = static_cast<QGraphicsItem *>(item->q_ptr);
+ QGraphicsView *viewq = static_cast<QGraphicsView *>(view->q_ptr);
+
+ if (itemIsUntransformable) {
+ const QTransform xform = itemq->deviceTransform(viewq->viewportTransform());
+ if (!item->hasBoundingRegionGranularity)
+ return view->updateRect(xform.mapRect(rect).toRect());
+ return view->updateRegion(xform.map(QRegion(rect.toRect())));
+ }
+
+ if (item->sceneTransformTranslateOnly && view->identityMatrix) {
+ const qreal dx = item->sceneTransform.dx();
+ const qreal dy = item->sceneTransform.dy();
+ if (!item->hasBoundingRegionGranularity) {
+ QRectF r(rect);
+ r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll());
+ return view->updateRect(r.toRect());
+ }
+ QRegion r(rect.toRect());
+ r.translate(qRound(dx) - view->horizontalScroll(), qRound(dy) - view->verticalScroll());
+ return view->updateRegion(r);
+ }
+
+ if (!viewq->isTransformed()) {
+ if (!item->hasBoundingRegionGranularity)
+ return view->updateRect(item->sceneTransform.mapRect(rect).toRect());
+ return view->updateRegion(item->sceneTransform.map(QRegion(rect.toRect())));
+ }
+
+ QTransform xform = item->sceneTransform;
+ xform *= viewq->viewportTransform();
+ if (!item->hasBoundingRegionGranularity)
+ return view->updateRect(xform.mapRect(rect).toRect());
+ return view->updateRegion(xform.map(QRegion(rect.toRect())));
+}
+
+void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren,
+ qreal parentOpacity)
+{
+ Q_Q(QGraphicsScene);
+ Q_ASSERT(item);
+ Q_ASSERT(!updateAll);
+
+ if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) {
+ resetDirtyItem(item);
+ return;
+ }
+
+ const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
+ if (itemIsHidden) {
+ resetDirtyItem(item, /*recursive=*/true);
+ return;
+ }
+
+ const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
+ const bool itemHasChildren = !item->d_ptr->children.isEmpty();
+ if (!itemHasContents && !itemHasChildren) {
+ resetDirtyItem(item);
+ return; // Item has neither contents nor children!(?)
+ }
+
+ const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
+ const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001;
+ if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
+ resetDirtyItem(item, /*recursive=*/itemHasChildren);
+ return;
+ }
+
+ bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform;
+ const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
+ if (wasDirtyParentSceneTransform && !itemIsUntransformable) {
+ item->d_ptr->updateSceneTransformFromParent();
+ Q_ASSERT(!item->d_ptr->dirtySceneTransform);
+ }
+
+ const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
+ if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) {
+ // Make sure we don't process invisible items or items with no content.
+ item->d_ptr->dirty = 0;
+ item->d_ptr->fullUpdatePending = 0;
+ // Might have a dirty view bounding rect otherwise.
+ if (itemIsFullyTransparent || !itemHasContents)
+ item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
+ }
+
+ if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) {
+ // Update growingItemsBoundingRect.
+ if (item->d_ptr->sceneTransformTranslateOnly) {
+ growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(),
+ item->d_ptr->sceneTransform.dy());
+ } else {
+ growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect());
+ }
+ }
+
+ // Process item.
+ if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
+ const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex);
+ const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item);
+
+ if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) {
+ // This block of code is kept for compatibility. Since 4.5, by default
+ // QGraphicsView does not connect the signal and we use the below
+ // method of delivering updates.
+ if (item->d_ptr->sceneTransformTranslateOnly) {
+ q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(),
+ item->d_ptr->sceneTransform.dy()));
+ } else {
+ q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect));
+ }
+ } else {
+ QRectF dirtyRect;
+ bool uninitializedDirtyRect = true;
+
+ for (int j = 0; j < views.size(); ++j) {
+ QGraphicsView *view = views.at(j);
+ QGraphicsViewPrivate *viewPrivate = view->d_func();
+ QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
+ if (viewPrivate->fullUpdatePending
+ || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) {
+ // Okay, if we have a full update pending or no viewport update, this item's
+ // paintedViewBoundingRect will be updated correctly in the next paintEvent if
+ // it is inside the viewport, but for now we can pretend that it is outside.
+ paintedViewBoundingRect = QRect(-1, -1, -1, -1);
+ continue;
+ }
+
+ if (item->d_ptr->paintedViewBoundingRectsNeedRepaint && !paintedViewBoundingRect.isEmpty()) {
+ paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
+ if (!viewPrivate->updateRect(paintedViewBoundingRect))
+ paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
+ }
+
+ if (!item->d_ptr->dirty)
+ continue;
+
+ if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint
+ && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
+ && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
+ continue; // Outside viewport.
+ }
+
+ if (uninitializedDirtyRect) {
+ dirtyRect = itemBoundingRect;
+ if (!item->d_ptr->fullUpdatePending) {
+ _q_adjustRect(&item->d_ptr->needsRepaint);
+ dirtyRect &= item->d_ptr->needsRepaint;
+ }
+ uninitializedDirtyRect = false;
+ }
+
+ if (dirtyRect.isEmpty())
+ continue; // Discard updates outside the bounding rect.
+
+ if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
+ && item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
+ paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
+ }
+ }
+ }
+ }
+
+ // Process children.
+ if (itemHasChildren && item->d_ptr->dirtyChildren) {
+ if (!dirtyAncestorContainsChildren) {
+ dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
+ && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ }
+ const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
+ const bool parentIgnoresVisible = item->d_ptr->ignoreVisible;
+ const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity;
+ for (int i = 0; i < item->d_ptr->children.size(); ++i) {
+ QGraphicsItem *child = item->d_ptr->children.at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (wasDirtyParentViewBoundingRects)
+ child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
+ if (parentIgnoresVisible)
+ child->d_ptr->ignoreVisible = 1;
+ if (parentIgnoresOpacity)
+ child->d_ptr->ignoreOpacity = 1;
+ if (allChildrenDirty) {
+ child->d_ptr->dirty = 1;
+ child->d_ptr->fullUpdatePending = 1;
+ child->d_ptr->dirtyChildren = 1;
+ child->d_ptr->allChildrenDirty = 1;
+ }
+ processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
+ }
+ } else if (wasDirtyParentSceneTransform) {
+ item->d_ptr->invalidateChildrenSceneTransform();
+ }
+
+ resetDirtyItem(item);
+}
+
/*!
Paints the given \a items using the provided \a painter, after the
background has been drawn, and before the foreground has been
drawn. All painting is done in \e scene coordinates. Before
drawing each item, the painter must be transformed using
- QGraphicsItem::sceneMatrix().
+ QGraphicsItem::sceneTransform().
The \a options parameter is the list of style option objects for
each item in \a items. The \a numItems parameter is the number of
@@ -5010,111 +4798,29 @@ void QGraphicsScene::drawItems(QPainter *painter,
const QStyleOptionGraphicsItem options[], QWidget *widget)
{
Q_D(QGraphicsScene);
-
- // Detect if painter state protection is disabled.
QTransform viewTransform = painter->worldTransform();
- QVarLengthArray<QGraphicsItem *, 16> childClippers;
-
- for (int i = 0; i < numItems; ++i) {
- QGraphicsItem *item = items[i];
- if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
- if (!childClippers.isEmpty()) {
- // Item is not clipped to any ancestor: pop all current clippers.
- for (int i = 0; i < childClippers.size(); ++i)
- painter->restore();
- childClippers.clear();
- }
- } else {
- // Item is clipped to an ancestor, which may or may not be in our
- // child clipper list. Let's start by finding the item's closest
- // clipping ancestor.
- QGraphicsItem *clipParent = item->parentItem();
- while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape))
- clipParent = clipParent->parentItem();
-
- // Pop any in-between clippers. If the clipper is unknown, pop
- // them all. ### QVarLengthArray::lastIndexOf().
- int index = -1;
- for (int n = childClippers.size() - 1; n >= 0; --n) {
- if (childClippers[n] == clipParent) {
- index = n;
- break;
- }
- }
- if (index != -1) {
- int toPop = childClippers.size() - index - 1;
- if (toPop > 0) {
- for (int i = 0; i < toPop; ++i)
- painter->restore();
- childClippers.resize(index + 1);
- }
- }
-
- // Sanity check
- if (!childClippers.isEmpty())
- Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent);
-
- // If the clipper list is empty at this point, but we're still
- // clipped to an ancestor, then we need to build the clip chain
- // ourselves. There is only one case that can produce this issue:
- // This item is stacked behind an ancestor:
- // ItemStacksBehindParent.
- if (childClippers.isEmpty()) {
- Q_ASSERT(clipParent != 0);
- // Build a stack of clippers.
- QVarLengthArray<QGraphicsItem *, 16> clippers;
- QGraphicsItem *p = clipParent;
- do {
- if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)
- clippers.append(p);
- } while ((p = p->parentItem()) && (p->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren));
-
- // ### This code path can also use the itemTransform
- // optimization, but it's hit very rarely.
- for (int i = clippers.size() - 1; i >= 0; --i) {
- QGraphicsItem *clipper = clippers[i];
- painter->setWorldTransform(clipper->deviceTransform(viewTransform), false);
-
- childClippers.append(clipper);
- painter->save();
- painter->setClipPath(clipper->shape(), Qt::IntersectClip);
- }
- Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent);
- }
- }
-
- // Set up the painter transform
- painter->setWorldTransform(item->deviceTransform(viewTransform), false);
+ Q_UNUSED(options);
- // Save painter
- bool saveState = (d->painterStateProtection || (item->flags() & QGraphicsItem::ItemClipsToShape));
- if (saveState)
- painter->save();
-
- // Set local clip
- if (item->flags() & QGraphicsItem::ItemClipsToShape)
- painter->setClipPath(item->shape(), Qt::IntersectClip);
-
- // Setup opacity
- painter->setOpacity(item->effectiveOpacity());
-
- // Draw the item
- d->drawItemHelper(item, painter, &options[i], widget, d->painterStateProtection);
-
- if (saveState)
- painter->restore();
+ // Determine view, expose and flags.
+ QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
+ QRegion *expose = 0;
+ if (view)
+ expose = &view->d_func()->exposedRegion;
- if (item->flags() & QGraphicsItem::ItemClipsChildrenToShape) {
- // Clip descendents to this item's shape, and keep the painter
- // saved.
- childClippers.append(item);
- painter->save();
- painter->setClipPath(item->shape(), Qt::IntersectClip);
+ // Find all toplevels, they are already sorted.
+ QList<QGraphicsItem *> topLevelItems;
+ for (int i = 0; i < numItems; ++i) {
+ QGraphicsItem *item = items[i]->topLevelItem();
+ if (!item->d_ptr->itemDiscovered) {
+ topLevelItems << item;
+ item->d_ptr->itemDiscovered = 1;
+ d->drawSubtreeRecursive(item, painter, &viewTransform, expose, widget);
}
}
- for (int i = 0; i < childClippers.size(); ++i)
- painter->restore();
+ // Reset discovery bits.
+ for (int i = 0; i < topLevelItems.size(); ++i)
+ topLevelItems.at(i)->d_ptr->itemDiscovered = 0;
painter->setWorldTransform(viewTransform);
}
@@ -5171,7 +4877,7 @@ bool QGraphicsScene::focusNextPrevChild(bool next)
if (widget->flags() & QGraphicsItem::ItemIsFocusable
&& widget->isEnabled() && widget->isVisibleTo(0)
&& (widget->focusPolicy() & Qt::TabFocus)
- && (!item || !item->isWindow() || item->isAncestorOf(widget))
+ && (!item || !item->isPanel() || item->isAncestorOf(widget))
) {
setFocusItem(widget, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
return true;
@@ -5226,73 +4932,6 @@ bool QGraphicsScene::focusNextPrevChild(bool next)
*/
/*!
- \internal
-
- This private function is called by QGraphicsItem, which is a friend of
- QGraphicsScene. It is used by QGraphicsScene to record the rectangles that
- need updating. It also launches a single-shot timer to ensure that
- updated() will be emitted later.
-
- The \a item parameter is the item that changed, and \a rect is the
- area of the item that changed given in item coordinates.
-*/
-void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect)
-{
- Q_D(QGraphicsScene);
- // Deliver the actual update.
- if (!d->updateAll) {
- if (d->views.isEmpty() || ((d->connectedSignals & d->changedSignalMask) && !item->d_ptr->itemIsUntransformable()
- && qFuzzyCompare(item->boundingRegionGranularity(), qreal(0.0)))) {
- // This block of code is kept for compatibility. Since 4.5, by default
- // QGraphicsView does not connect the signal and we use the below
- // method of delivering updates.
- update(item->sceneBoundingRect());
- } else {
- // ### Remove _q_adjustedRects().
- QRectF boundingRect(adjustedItemBoundingRect(item));
- if (!rect.isNull()) {
- QRectF adjustedRect(rect);
- _q_adjustRect(&adjustedRect);
- boundingRect &= adjustedRect;
- }
-
- // Update each view directly.
- for (int i = 0; i < d->views.size(); ++i)
- d->views.at(i)->d_func()->itemUpdated(item, boundingRect);
- }
- }
- if (item->d_ptr->dirty) {
- d->dirtyItems << item;
- d->resetDirtyItemsLater();
- }
-
- if (!item->isVisible())
- return; // Hiding an item won't effect the largestUntransformableItem/sceneRect.
-
- // Update d->largestUntransformableItem by mapping this item's bounding
- // rect back to the topmost untransformable item's untransformed
- // coordinate system (which sort of equals the 1:1 coordinate system of an
- // untransformed view).
- if (item->d_ptr->itemIsUntransformable()) {
- QGraphicsItem *parent = item;
- while (parent && (parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations))
- parent = parent->parentItem();
- d->largestUntransformableItem |= item->mapToItem(parent, item->boundingRect()).boundingRect();
- }
-
- // Only track the automatically growing scene rect if the scene has no
- // defined scene rect.
- if (!d->hasSceneRect) {
- QRectF oldGrowingItemsBoundingRect = d->growingItemsBoundingRect;
- QRectF adjustedItemSceneBoundingRect(item->sceneBoundingRect());
- _q_adjustRect(&adjustedItemSceneBoundingRect);
- d->growingItemsBoundingRect |= adjustedItemSceneBoundingRect;
- if (d->growingItemsBoundingRect != oldGrowingItemsBoundingRect)
- emit sceneRectChanged(d->growingItemsBoundingRect);
- }
-}
-
-/*!
\since 4.4
Returns the scene's style, or the same as QApplication::style() if the
@@ -5304,7 +4943,7 @@ QStyle *QGraphicsScene::style() const
{
Q_D(const QGraphicsScene);
// ### This function, and the use of styles in general, is non-reentrant.
- return d->style ? d->style : qApp->style();
+ return d->style ? d->style : QApplication::style();
}
/*!
@@ -5381,7 +5020,7 @@ QFont QGraphicsScene::font() const
void QGraphicsScene::setFont(const QFont &font)
{
Q_D(QGraphicsScene);
- QFont naturalFont = qApp->font();
+ QFont naturalFont = QApplication::font();
naturalFont.resolve(0);
QFont resolvedFont = font.resolve(naturalFont);
d->setFont_helper(resolvedFont);
@@ -5418,92 +5057,411 @@ QPalette QGraphicsScene::palette() const
void QGraphicsScene::setPalette(const QPalette &palette)
{
Q_D(QGraphicsScene);
- QPalette naturalPalette = qApp->palette();
+ QPalette naturalPalette = QApplication::palette();
naturalPalette.resolve(0);
QPalette resolvedPalette = palette.resolve(naturalPalette);
d->setPalette_helper(resolvedPalette);
}
/*!
- \since 4.4
+ \since 4.6
- Returns the current active window, or 0 if there is no window is currently
- active.
+ Returns true if the scene is active (e.g., it's viewed by
+ at least one QGraphicsView that is active); otherwise returns false.
- \sa QGraphicsScene::setActiveWindow()
+ \sa QGraphicsItem::isActive(), QWidget::isActiveWindow()
*/
-QGraphicsWidget *QGraphicsScene::activeWindow() const
+bool QGraphicsScene::isActive() const
{
Q_D(const QGraphicsScene);
- return d->activeWindow;
+ return d->activationRefCount > 0;
}
/*!
- \since 4.4
- Activates \a widget, which must be a widget in this scene. You can also
- pass 0 for \a widget, in which case QGraphicsScene will deactivate any
- currently active window.
+ \since 4.6
+ Returns the current active panel, or 0 if no panel is currently active.
- \sa activeWindow(), QGraphicsWidget::isActiveWindow()
+ \sa QGraphicsScene::setActivePanel()
*/
-void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget)
+QGraphicsItem *QGraphicsScene::activePanel() const
+{
+ Q_D(const QGraphicsScene);
+ return d->activePanel;
+}
+
+/*!
+ \since 4.6
+ Activates \a item, which must be an item in this scene. You
+ can also pass 0 for \a item, in which case QGraphicsScene will
+ deactivate any currently active panel.
+
+ \sa activePanel(), isActive(), QGraphicsItem::isActive()
+*/
+void QGraphicsScene::setActivePanel(QGraphicsItem *item)
{
Q_D(QGraphicsScene);
- if (widget && widget->scene() != this) {
- qWarning("QGraphicsScene::setActiveWindow: widget %p must be part of this scene",
- widget);
+ if (item && item->scene() != this) {
+ qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene",
+ item);
return;
}
- // Activate the widget's window.
- QGraphicsWidget *window = widget ? widget->window() : 0;
- if (window == d->activeWindow)
+ // Find the item's panel.
+ QGraphicsItem *panel = item ? item->panel() : 0;
+ d->lastActivePanel = panel ? d->activePanel : 0;
+ if (panel == d->activePanel)
return;
- // Deactivate the last active window.
- if (d->activeWindow) {
- if (QGraphicsWidget *fw = d->activeWindow->focusWidget()) {
+ // Deactivate the last active panel.
+ if (d->activePanel) {
+ if (QGraphicsItem *fi = d->activePanel->focusItem()) {
// Remove focus from the current focus item.
- if (fw == focusItem())
+ if (fi == focusItem())
setFocusItem(0, Qt::ActiveWindowFocusReason);
}
QEvent event(QEvent::WindowDeactivate);
- QApplication::sendEvent(d->activeWindow, &event);
+ sendEvent(d->activePanel, &event);
+ } else if (panel) {
+ // Deactivate the scene if changing activation to a panel.
+ QEvent event(QEvent::WindowDeactivate);
+ foreach (QGraphicsItem *item, items()) {
+ if (item->isVisible() && !item->isPanel() && !item->parentItem())
+ sendEvent(item, &event);
+ }
}
// Update activate state.
- d->activeWindow = window;
+ d->activePanel = panel;
QEvent event(QEvent::ActivationChange);
QApplication::sendEvent(this, &event);
// Activate
- if (window) {
+ if (panel) {
QEvent event(QEvent::WindowActivate);
- QApplication::sendEvent(window, &event);
+ sendEvent(panel, &event);
+
+ // Set focus on the panel's focus item.
+ if (QGraphicsItem *focusItem = panel->focusItem())
+ focusItem->setFocus(Qt::ActiveWindowFocusReason);
+ } else if (isActive()) {
+ // Activate the scene
+ QEvent event(QEvent::WindowActivate);
+ foreach (QGraphicsItem *item, items()) {
+ if (item->isVisible() && !item->isPanel() && !item->parentItem())
+ sendEvent(item, &event);
+ }
+ }
+}
+
+/*!
+ \since 4.4
+ Returns the current active window, or 0 if there is no window is currently
+ active.
+
+ \sa QGraphicsScene::setActiveWindow()
+*/
+QGraphicsWidget *QGraphicsScene::activeWindow() const
+{
+ Q_D(const QGraphicsScene);
+ if (d->activePanel && d->activePanel->isWindow())
+ return static_cast<QGraphicsWidget *>(d->activePanel);
+ return 0;
+}
+
+/*!
+ \since 4.4
+ Activates \a widget, which must be a widget in this scene. You can also
+ pass 0 for \a widget, in which case QGraphicsScene will deactivate any
+ currently active window.
+
+ \sa activeWindow(), QGraphicsWidget::isActiveWindow()
+*/
+void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget)
+{
+ if (widget && widget->scene() != this) {
+ qWarning("QGraphicsScene::setActiveWindow: widget %p must be part of this scene",
+ widget);
+ return;
+ }
+
+ // Activate the widget's panel (all windows are panels).
+ QGraphicsItem *panel = widget ? widget->panel() : 0;
+ setActivePanel(panel);
+
+ // Raise
+ if (panel) {
QList<QGraphicsItem *> siblingWindows;
- QGraphicsItem *parent = window->parentItem();
+ QGraphicsItem *parent = panel->parentItem();
// Raise ### inefficient for toplevels
foreach (QGraphicsItem *sibling, parent ? parent->children() : items()) {
- if (sibling != window && sibling->isWidget()
- && static_cast<QGraphicsWidget *>(sibling)->isWindow()) {
+ if (sibling != panel && sibling->isWindow())
siblingWindows << sibling;
- }
}
// Find the highest z value.
- qreal z = window->zValue();
+ qreal z = panel->zValue();
for (int i = 0; i < siblingWindows.size(); ++i)
z = qMax(z, siblingWindows.at(i)->zValue());
// This will probably never overflow.
const qreal litt = qreal(0.001);
- window->setZValue(z + litt);
+ panel->setZValue(z + litt);
+ }
+}
+
+/*!
+ \since 4.6
- if (QGraphicsWidget *focusChild = window->focusWidget())
- focusChild->setFocus(Qt::ActiveWindowFocusReason);
+ Sends event \a event to item \a item through possible event filters.
+
+ The event is sent only if the item is enabled.
+
+ Returns \c false if the event was filtered or if the item is disabled.
+ Otherwise returns the value that was returned from the event handler.
+
+ \sa QGraphicsItem::sceneEvent(), QGraphicsItem::sceneEventFilter()
+*/
+bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event)
+{
+ Q_D(QGraphicsScene);
+ if (!item) {
+ qWarning("QGraphicsScene::sendEvent: cannot send event to a null item");
+ return false;
+ }
+ if (item->scene() != this) {
+ qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)"
+ " is different from this scene (%p)",
+ item, item->scene(), this);
+ return false;
+ }
+ return d->sendEvent(item, event);
+}
+
+void QGraphicsScenePrivate::addView(QGraphicsView *view)
+{
+ views << view;
+}
+
+void QGraphicsScenePrivate::removeView(QGraphicsView *view)
+{
+ views.removeAll(view);
+}
+
+void QGraphicsScenePrivate::updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent)
+{
+ QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
+ for (int i = 0; i < touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
+ touchPoint.setRect(item->mapFromScene(touchPoint.sceneRect()).boundingRect());
+ touchPoint.setStartPos(item->d_ptr->genericMapFromScene(touchPoint.startScenePos(), touchEvent->widget()));
+ touchPoint.setLastPos(item->d_ptr->genericMapFromScene(touchPoint.lastScenePos(), touchEvent->widget()));
+ }
+ touchEvent->setTouchPoints(touchPoints);
+}
+
+int QGraphicsScenePrivate::findClosestTouchPointId(const QPointF &scenePos)
+{
+ int closestTouchPointId = -1;
+ qreal closestDistance = qreal(0.);
+ foreach (const QTouchEvent::TouchPoint &touchPoint, sceneCurrentTouchPoints) {
+ qreal distance = QLineF(scenePos, touchPoint.scenePos()).length();
+ if (closestTouchPointId == -1|| distance < closestDistance) {
+ closestTouchPointId = touchPoint.id();
+ closestDistance = distance;
+ }
}
+ return closestTouchPointId;
+}
+
+void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
+{
+ typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints;
+ QHash<QGraphicsItem *, StatesAndTouchPoints> itemsNeedingEvents;
+
+ for (int i = 0; i < sceneTouchEvent->touchPoints().count(); ++i) {
+ const QTouchEvent::TouchPoint &touchPoint = sceneTouchEvent->touchPoints().at(i);
+
+ // update state
+ QGraphicsItem *item = 0;
+ if (touchPoint.state() == Qt::TouchPointPressed) {
+ if (sceneTouchEvent->deviceType() == QTouchEvent::TouchPad) {
+ // on touch-pad devices, send all touch points to the same item
+ item = itemForTouchPointId.isEmpty()
+ ? 0
+ : itemForTouchPointId.constBegin().value();
+ }
+
+ if (!item) {
+ // determine which item this touch point will go to
+ cachedItemsUnderMouse = itemsAtPosition(touchPoint.screenPos().toPoint(),
+ touchPoint.scenePos(),
+ sceneTouchEvent->widget());
+ item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.first();
+ }
+
+ if (sceneTouchEvent->deviceType() == QTouchEvent::TouchScreen) {
+ // on touch-screens, combine this touch point with the closest one we find if it
+ // is a a direct descendent or ancestor (
+ int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePos());
+ QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
+ if (!item
+ || (closestItem
+ && (item->isAncestorOf(closestItem)
+ || closestItem->isAncestorOf(item)))) {
+ item = closestItem;
+ }
+ }
+ if (!item)
+ continue;
+
+ itemForTouchPointId.insert(touchPoint.id(), item);
+ sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
+ } else if (touchPoint.state() == Qt::TouchPointReleased) {
+ item = itemForTouchPointId.take(touchPoint.id());
+ if (!item)
+ continue;
+
+ sceneCurrentTouchPoints.remove(touchPoint.id());
+ } else {
+ item = itemForTouchPointId.value(touchPoint.id());
+ if (!item)
+ continue;
+ Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id()));
+ sceneCurrentTouchPoints[touchPoint.id()] = touchPoint;
+ }
+
+ StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item];
+ statesAndTouchPoints.first |= touchPoint.state();
+ statesAndTouchPoints.second.append(touchPoint);
+ }
+
+ if (itemsNeedingEvents.isEmpty()) {
+ sceneTouchEvent->ignore();
+ return;
+ }
+
+ bool acceptSceneTouchEvent = false;
+ QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin();
+ const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd();
+ for (; it != end; ++it) {
+ QGraphicsItem *item = it.key();
+
+ // determine event type from the state mask
+ QEvent::Type eventType;
+ switch (it.value().first) {
+ case Qt::TouchPointPressed:
+ // all touch points have pressed state
+ eventType = QEvent::TouchBegin;
+ break;
+ case Qt::TouchPointReleased:
+ // all touch points have released state
+ eventType = QEvent::TouchEnd;
+ break;
+ case Qt::TouchPointStationary:
+ // don't send the event if nothing changed
+ continue;
+ default:
+ // all other combinations
+ eventType = QEvent::TouchUpdate;
+ break;
+ }
+
+ QTouchEvent touchEvent(eventType);
+ touchEvent.setWidget(sceneTouchEvent->widget());
+ touchEvent.setDeviceType(sceneTouchEvent->deviceType());
+ touchEvent.setModifiers(sceneTouchEvent->modifiers());
+ touchEvent.setTouchPointStates(it.value().first);
+ touchEvent.setTouchPoints(it.value().second);
+
+ switch (touchEvent.type()) {
+ case QEvent::TouchBegin:
+ {
+ // if the TouchBegin handler recurses, we assume that means the event
+ // has been implicitly accepted and continue to send touch events
+ item->d_ptr->acceptedTouchBeginEvent = true;
+ bool res = sendTouchBeginEvent(item, &touchEvent)
+ && touchEvent.isAccepted();
+ acceptSceneTouchEvent = acceptSceneTouchEvent || res;
+ break;
+ }
+ default:
+ if (item->d_ptr->acceptedTouchBeginEvent) {
+ updateTouchPointsForItem(item, &touchEvent);
+ (void) sendEvent(item, &touchEvent);
+ acceptSceneTouchEvent = true;
+ }
+ break;
+ }
+ }
+ sceneTouchEvent->setAccepted(acceptSceneTouchEvent);
+}
+
+bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent)
+{
+ Q_Q(QGraphicsScene);
+
+ if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.first() != origin) {
+ const QTouchEvent::TouchPoint &firstTouchPoint = touchEvent->touchPoints().first();
+ cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.screenPos().toPoint(),
+ firstTouchPoint.scenePos(),
+ touchEvent->widget());
+ }
+ Q_ASSERT(cachedItemsUnderMouse.first() == origin);
+
+ // Set focus on the topmost enabled item that can take focus.
+ bool setFocus = false;
+ foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
+ if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
+ if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
+ setFocus = true;
+ if (item != q->focusItem())
+ q->setFocusItem(item, Qt::MouseFocusReason);
+ break;
+ }
+ }
+ }
+
+ // If nobody could take focus, clear it.
+ if (!stickyFocus && !setFocus)
+ q->setFocusItem(0, Qt::MouseFocusReason);
+
+ bool res = false;
+ bool eventAccepted = touchEvent->isAccepted();
+ foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
+ // first, try to deliver the touch event
+ updateTouchPointsForItem(item, touchEvent);
+ bool acceptTouchEvents = item->acceptTouchEvents();
+ touchEvent->setAccepted(acceptTouchEvents);
+ res = acceptTouchEvents && sendEvent(item, touchEvent);
+ eventAccepted = touchEvent->isAccepted();
+ item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
+ touchEvent->spont = false;
+ if (res && eventAccepted) {
+ // the first item to accept the TouchBegin gets an implicit grab.
+ for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
+ const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i);
+ itemForTouchPointId[touchPoint.id()] = item;
+ }
+ break;
+ }
+ }
+
+ touchEvent->setAccepted(eventAccepted);
+ return res;
+}
+
+void QGraphicsScenePrivate::enableTouchEventsOnViews()
+{
+ foreach (QGraphicsView *view, views)
+ view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true);
+}
+
+void QGraphicsScenePrivate::updateInputMethodSensitivityInViews()
+{
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->updateInputMethodSensitivity();
}
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index cfa9f8e..e43bb67 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -83,6 +83,7 @@ class QGraphicsSimpleTextItem;
class QGraphicsTextItem;
class QGraphicsView;
class QGraphicsWidget;
+class QGraphicsSceneIndex;
class QHelpEvent;
class QInputMethodEvent;
class QKeyEvent;
@@ -152,22 +153,39 @@ public:
QRectF itemsBoundingRect() const;
QList<QGraphicsItem *> items() const;
- QList<QGraphicsItem *> items(const QPointF &pos) const;
- QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
- QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
- QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
+ QList<QGraphicsItem *> items(Qt::SortOrder order) const; // ### Qt 5: unify
+
+ QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+
+ QList<QGraphicsItem *> items(const QPointF &pos) const; // ### obsolete
+ QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
+ QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
+ QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
+
QList<QGraphicsItem *> collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
- QGraphicsItem *itemAt(const QPointF &pos) const;
+
+ QGraphicsItem *itemAt(const QPointF &pos) const; // ### obsolete
+ QGraphicsItem *itemAt(const QPointF &pos, const QTransform &deviceTransform) const;
inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const
- { return items(QRectF(x, y, w, h), mode); }
- inline QGraphicsItem *itemAt(qreal x, qreal y) const
+ { return items(QRectF(x, y, w, h), mode); } // ### obsolete
+ inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order,
+ const QTransform &deviceTransform = QTransform()) const
+ { return items(QRectF(x, y, w, h), mode, order, deviceTransform); }
+ inline QGraphicsItem *itemAt(qreal x, qreal y) const // ### obsolete
{ return itemAt(QPointF(x, y)); }
+ inline QGraphicsItem *itemAt(qreal x, qreal y, const QTransform &deviceTransform) const
+ { return itemAt(QPointF(x, y), deviceTransform); }
QList<QGraphicsItem *> selectedItems() const;
QPainterPath selectionArea() const;
- void setSelectionArea(const QPainterPath &path);
- void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode);
+ void setSelectionArea(const QPainterPath &path); // ### obsolete
+ void setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform);
+ void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode); // ### obsolete
+ void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, const QTransform &deviceTransform);
QGraphicsItemGroup *createItemGroup(const QList<QGraphicsItem *> &items);
void destroyItemGroup(QGraphicsItemGroup *group);
@@ -189,7 +207,7 @@ public:
inline QGraphicsRectItem *addRect(qreal x, qreal y, qreal w, qreal h, const QPen &pen = QPen(), const QBrush &brush = QBrush())
{ return addRect(QRectF(x, y, w, h), pen, brush); }
void removeItem(QGraphicsItem *item);
-
+
QGraphicsItem *focusItem() const;
void setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason = Qt::OtherFocusReason);
bool hasFocus() const;
@@ -225,9 +243,14 @@ public:
QPalette palette() const;
void setPalette(const QPalette &palette);
+ bool isActive() const;
+ QGraphicsItem *activePanel() const;
+ void setActivePanel(QGraphicsItem *item);
QGraphicsWidget *activeWindow() const;
void setActiveWindow(QGraphicsWidget *widget);
+ bool sendEvent(QGraphicsItem *item, QEvent *event);
+
public Q_SLOTS:
void update(const QRectF &rect = QRectF());
void invalidate(const QRectF &rect = QRectF(), SceneLayers layers = AllLayers);
@@ -271,23 +294,23 @@ Q_SIGNALS:
void selectionChanged();
private:
- void itemUpdated(QGraphicsItem *item, const QRectF &rect);
-
Q_DECLARE_PRIVATE(QGraphicsScene)
Q_DISABLE_COPY(QGraphicsScene)
- Q_PRIVATE_SLOT(d_func(), void _q_updateIndex())
Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated())
- Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item))
- Q_PRIVATE_SLOT(d_func(), void _q_updateLater())
Q_PRIVATE_SLOT(d_func(), void _q_polishItems())
- Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache())
- Q_PRIVATE_SLOT(d_func(), void _q_resetDirtyItems())
+ Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems())
friend class QGraphicsItem;
friend class QGraphicsItemPrivate;
friend class QGraphicsView;
friend class QGraphicsViewPrivate;
friend class QGraphicsWidget;
friend class QGraphicsWidgetPrivate;
+ friend class QGraphicsEffect;
+ friend class QGraphicsSceneIndex;
+ friend class QGraphicsSceneIndexPrivate;
+ friend class QGraphicsSceneBspTreeIndex;
+ friend class QGraphicsSceneBspTreeIndexPrivate;
+ friend class QGraphicsItemEffectSourcePrivate;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers)
diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp
index 00f843a..fb77983 100644
--- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp
+++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp
@@ -70,12 +70,15 @@ class QGraphicsSceneFindItemBspTreeVisitor : public QGraphicsSceneBspTreeVisitor
{
public:
QList<QGraphicsItem *> *foundItems;
+ bool onlyTopLevelItems;
void visit(QList<QGraphicsItem *> *items)
{
for (int i = 0; i < items->size(); ++i) {
QGraphicsItem *item = items->at(i);
- if (!item->d_func()->itemDiscovered && item->isVisible()) {
+ if (onlyTopLevelItems && item->d_ptr->parent)
+ item = item->topLevelItem();
+ if (!item->d_func()->itemDiscovered && item->d_ptr->visible) {
item->d_func()->itemDiscovered = 1;
foundItems->prepend(item);
}
@@ -143,19 +146,15 @@ void QGraphicsSceneBspTree::removeItems(const QSet<QGraphicsItem *> &items)
}
}
-QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect)
+QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect, bool onlyTopLevelItems) const
{
QList<QGraphicsItem *> tmp;
findVisitor->foundItems = &tmp;
+ findVisitor->onlyTopLevelItems = onlyTopLevelItems;
climbTree(findVisitor, rect);
- return tmp;
-}
-
-QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QPointF &pos)
-{
- QList<QGraphicsItem *> tmp;
- findVisitor->foundItems = &tmp;
- climbTree(findVisitor, pos);
+ // Reset discovery bits.
+ for (int i = 0; i < tmp.size(); ++i)
+ tmp.at(i)->d_ptr->itemDiscovered = 0;
return tmp;
}
@@ -235,47 +234,17 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index)
}
}
-void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index)
-{
- if (nodes.isEmpty())
- return;
-
- const Node &node = nodes.at(index);
- int childIndex = firstChildIndex(index);
-
- switch (node.type) {
- case Node::Leaf: {
- visitor->visit(&leaves[node.leafIndex]);
- break;
- }
- case Node::Vertical:
- if (pos.x() < node.offset) {
- climbTree(visitor, pos, childIndex);
- } else {
- climbTree(visitor, pos, childIndex + 1);
- }
- break;
- case Node::Horizontal:
- if (pos.y() < node.offset) {
- climbTree(visitor, pos, childIndex);
- } else {
- climbTree(visitor, pos, childIndex + 1);
- }
- break;
- }
-}
-
-void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index)
+void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) const
{
if (nodes.isEmpty())
return;
const Node &node = nodes.at(index);
- int childIndex = firstChildIndex(index);
+ const int childIndex = firstChildIndex(index);
switch (node.type) {
case Node::Leaf: {
- visitor->visit(&leaves[node.leafIndex]);
+ visitor->visit(const_cast<QList<QGraphicsItem*>*>(&leaves[node.leafIndex]));
break;
}
case Node::Vertical:
@@ -288,7 +257,6 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con
}
break;
case Node::Horizontal:
- int childIndex = firstChildIndex(index);
if (rect.top() < node.offset) {
climbTree(visitor, rect, childIndex);
if (rect.bottom() >= node.offset)
diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h
index e2727b1..2f43d22 100644
--- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h
@@ -92,8 +92,7 @@ public:
void removeItem(QGraphicsItem *item, const QRectF &rect);
void removeItems(const QSet<QGraphicsItem *> &items);
- QList<QGraphicsItem *> items(const QRectF &rect);
- QList<QGraphicsItem *> items(const QPointF &pos);
+ QList<QGraphicsItem *> items(const QRectF &rect, bool onlyTopLevelItems = false) const;
int leafCount() const;
inline int firstChildIndex(int index) const
@@ -106,11 +105,7 @@ public:
private:
void initialize(const QRectF &rect, int depth, int index);
- void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0);
- void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0);
-
- void findItems(QList<QGraphicsItem *> *foundItems, const QRectF &rect, int index);
- void findItems(QList<QGraphicsItem *> *foundItems, const QPointF &pos, int index);
+ void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const;
QRectF rectForIndex(int index) const;
QVector<Node> nodes;
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 8ffa3bc..c1b78ff 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -47,8 +47,8 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
@@ -57,7 +57,9 @@
#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
-#include "qgraphicsscene_bsp_p.h"
+#include "qgraphicssceneevent.h"
+#include "qgraphicsview.h"
+#include "qgraphicsview_p.h"
#include "qgraphicsitem_p.h"
#include <private/qobject_p.h>
@@ -68,9 +70,11 @@
#include <QtGui/qfont.h>
#include <QtGui/qpalette.h>
#include <QtGui/qstyle.h>
+#include <QtGui/qstyleoption.h>
QT_BEGIN_NAMESPACE
+class QGraphicsSceneIndex;
class QGraphicsView;
class QGraphicsWidget;
@@ -81,68 +85,54 @@ public:
QGraphicsScenePrivate();
void init();
- quint32 changedSignalMask;
+ static QGraphicsScenePrivate *get(QGraphicsScene *q);
- QGraphicsScene::ItemIndexMethod indexMethod;
- int bspTreeDepth;
+ static int changedSignalIndex;
- QList<QGraphicsItem *> estimateItemsInRect(const QRectF &rect) const;
- void addToIndex(QGraphicsItem *item);
- void removeFromIndex(QGraphicsItem *item);
- void resetIndex();
+ QGraphicsScene::ItemIndexMethod indexMethod;
+ QGraphicsSceneIndex *index;
- QGraphicsSceneBspTree bspTree;
- void _q_updateIndex();
int lastItemCount;
QRectF sceneRect;
bool hasSceneRect;
+ bool dirtyGrowingItemsBoundingRect;
QRectF growingItemsBoundingRect;
- QRectF largestUntransformableItem;
void _q_emitUpdated();
QList<QRectF> updatedRects;
bool updateAll;
bool calledEmitUpdated;
+ bool processDirtyItemsEmitted;
QPainterPath selectionArea;
int selectionChanging;
QSet<QGraphicsItem *> selectedItems;
- QList<QGraphicsItem *> unindexedItems;
- QList<QGraphicsItem *> indexedItems;
- QList<QGraphicsItem *> dirtyItems;
- QList<QGraphicsItem *> pendingUpdateItems;
QList<QGraphicsItem *> unpolishedItems;
+ QList<QGraphicsItem *> topLevelItems;
+ bool needSortTopLevelItems;
QMap<QGraphicsItem *, QPointF> movingItemsInitialPositions;
+ void registerTopLevelItem(QGraphicsItem *item);
+ void unregisterTopLevelItem(QGraphicsItem *item);
void _q_updateLater();
void _q_polishItems();
- void _q_resetDirtyItems();
- void resetDirtyItemsLater();
- bool dirtyItemResetPending;
+ void _q_processDirtyItems();
- QList<int> freeItemIndexes;
- bool regenerateIndex;
-
- bool purgePending;
- void _q_removeItemLater(QGraphicsItem *item);
- QSet<QGraphicsItem *> removedItems;
- void purgeRemovedItems();
+ void removeItemHelper(QGraphicsItem *item);
QBrush backgroundBrush;
QBrush foregroundBrush;
- int indexTimerId;
- bool restartIndexTimer;
- void startIndexTimer();
-
bool stickyFocus;
bool hasFocus;
QGraphicsItem *focusItem;
QGraphicsItem *lastFocusItem;
QGraphicsWidget *tabFocusFirst;
- QGraphicsWidget *activeWindow;
+ QGraphicsItem *activePanel;
+ QGraphicsItem *lastActivePanel;
int activationRefCount;
+ void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason);
QList<QGraphicsWidget *> popupWidgets;
void addPopup(QGraphicsWidget *widget);
@@ -159,27 +149,33 @@ public:
void grabKeyboard(QGraphicsItem *item);
void ungrabKeyboard(QGraphicsItem *item, bool itemIsDying = false);
void clearKeyboardGrabber();
-
+
QGraphicsItem *dragDropItem;
QGraphicsWidget *enterWidget;
Qt::DropAction lastDropAction;
QList<QGraphicsItem *> cachedItemsUnderMouse;
QList<QGraphicsItem *> hoverItems;
+ bool allItemsIgnoreHoverEvents;
+ bool allItemsUseDefaultCursor;
+ void enableMouseTrackingOnViews();
QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownPos;
QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownScenePos;
QMap<Qt::MouseButton, QPoint> mouseGrabberButtonDownScreenPos;
QList<QGraphicsItem *> itemsAtPosition(const QPoint &screenPos,
const QPointF &scenePos,
QWidget *widget) const;
- static bool itemCollidesWithPath(QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode);
void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event);
QList<QGraphicsView *> views;
+ void addView(QGraphicsView *view);
+ void removeView(QGraphicsView *view);
+
bool painterStateProtection;
QMultiMap<QGraphicsItem *, QGraphicsItem *> sceneEventFilters;
void installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter);
void removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter);
+ bool filterDescendantEvent(QGraphicsItem *item, QEvent *event);
bool filterEvent(QGraphicsItem *item, QEvent *event);
bool sendEvent(QGraphicsItem *item, QEvent *event);
@@ -197,56 +193,66 @@ public:
void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent);
QGraphicsWidget *windowForItem(const QGraphicsItem *item) const;
- QList<QGraphicsItem *> items_helper(const QPointF &pos) const;
- QList<QGraphicsItem *> items_helper(const QRectF &rect,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const;
- QList<QGraphicsItem *> items_helper(const QPolygonF &rect,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const;
- QList<QGraphicsItem *> items_helper(const QPainterPath &rect,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const;
- void childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QPointF &pos) const;
- void childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QRectF &rect,
- Qt::ItemSelectionMode mode) const;
- void childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QPolygonF &polygon,
- Qt::ItemSelectionMode mode) const;
- void childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QPainterPath &path,
- Qt::ItemSelectionMode mode) const;
-
- bool sortCacheEnabled;
- bool updatingSortCache;
- void invalidateSortCache();
- static void climbTree(QGraphicsItem *item, int *stackingOrder);
- void _q_updateSortCache();
-
- static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2);
- static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2);
-
- static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
- {
- return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder;
- }
- static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
- {
- return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder;
- }
-
- static void sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order, bool cached);
+ bool sortCacheEnabled; // for compatibility
void drawItemHelper(QGraphicsItem *item, QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget,
bool painterStateProtection);
-
+
+ void drawItems(QPainter *painter, const QTransform *const viewTransform,
+ QRegion *exposedRegion, QWidget *widget);
+
+ void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const,
+ QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0),
+ const QTransform *const effectTransform = 0);
+ void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const,
+ QRegion *, QWidget *, qreal, const QTransform *const, bool, bool);
+
+ void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false,
+ bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false,
+ bool removingItemFromScene = false);
+ void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false,
+ qreal parentOpacity = qreal(1.0));
+
+ inline void resetDirtyItem(QGraphicsItem *item, bool recursive = false)
+ {
+ Q_ASSERT(item);
+ item->d_ptr->dirty = 0;
+ item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
+ item->d_ptr->geometryChanged = 0;
+ if (!item->d_ptr->dirtyChildren)
+ recursive = false;
+ item->d_ptr->dirtyChildren = 0;
+ item->d_ptr->needsRepaint = QRectF();
+ item->d_ptr->allChildrenDirty = 0;
+ item->d_ptr->fullUpdatePending = 0;
+ item->d_ptr->ignoreVisible = 0;
+ item->d_ptr->ignoreOpacity = 0;
+ QGraphicsEffect::ChangeFlags flags;
+ if (item->d_ptr->notifyBoundingRectChanged) {
+ flags |= QGraphicsEffect::SourceBoundingRectChanged;
+ item->d_ptr->notifyBoundingRectChanged = 0;
+ }
+ if (item->d_ptr->notifyInvalidated) {
+ flags |= QGraphicsEffect::SourceInvalidated;
+ item->d_ptr->notifyInvalidated = 0;
+ }
+ if (recursive) {
+ for (int i = 0; i < item->d_ptr->children.size(); ++i)
+ resetDirtyItem(item->d_ptr->children.at(i), recursive);
+ }
+ if (flags && item->d_ptr->graphicsEffect)
+ item->d_ptr->graphicsEffect->sourceChanged(flags);
+ }
+
+ inline void ensureSortedTopLevelItems()
+ {
+ if (needSortTopLevelItems) {
+ qSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf);
+ needSortTopLevelItems = false;
+ }
+ }
+
QStyle *style;
QFont font;
void setFont_helper(const QFont &font);
@@ -257,11 +263,47 @@ public:
void resolvePalette();
void updatePalette(const QPalette &palette);
- mutable QVector<QTransform> sceneTransformCache;
- mutable QBitArray validTransforms;
- mutable QVector<int> freeSceneTransformSlots;
+ QStyleOptionGraphicsItem styleOptionTmp;
+
+ QMap<int, QTouchEvent::TouchPoint> sceneCurrentTouchPoints;
+ QMap<int, QGraphicsItem *> itemForTouchPointId;
+ static void updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent);
+ int findClosestTouchPointId(const QPointF &scenePos);
+ void touchEventHandler(QTouchEvent *touchEvent);
+ bool sendTouchBeginEvent(QGraphicsItem *item, QTouchEvent *touchEvent);
+ bool allItemsIgnoreTouchEvents;
+ void enableTouchEventsOnViews();
+
+ void updateInputMethodSensitivityInViews();
};
+// QRectF::intersects() returns false always if either the source or target
+// rectangle's width or height are 0. This works around that problem.
+static inline void _q_adjustRect(QRectF *rect)
+{
+ Q_ASSERT(rect);
+ if (!rect->width())
+ rect->adjust(qreal(-0.00001), 0, qreal(0.00001), 0);
+ if (!rect->height())
+ rect->adjust(0, qreal(-0.00001), 0, qreal(0.00001));
+}
+
+static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
+{
+ Q_ASSERT(item);
+ QRectF boundingRect(item->boundingRect());
+ _q_adjustRect(&boundingRect);
+ return boundingRect;
+}
+
+static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item)
+{
+ Q_ASSERT(item);
+ QRectF boundingRect(QGraphicsItemPrivate::get(item)->effectiveBoundingRect());
+ _q_adjustRect(&boundingRect);
+ return boundingRect;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
new file mode 100644
index 0000000..b9c4ed8
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -0,0 +1,783 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QGraphicsSceneBspTreeIndex
+ \brief The QGraphicsSceneBspTreeIndex class provides an implementation of
+ a BSP indexing algorithm for discovering items in QGraphicsScene.
+ \since 4.6
+ \ingroup graphicsview-api
+
+ \internal
+
+ QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning)
+ implementation to discover items quickly. This implementation is
+ very efficient for static scene. It has a depth that you can set.
+ The depth directly affects performance and memory usage; the latter
+ growing exponentially with the depth of the tree. With an optimal tree
+ depth, the index can instantly determine the locality of items, even
+ for scenes with thousands or millions of items. This also greatly improves
+ rendering performance.
+
+ By default, the value is 0, in which case Qt will guess a reasonable
+ default depth based on the size, location and number of items in the
+ scene. If these parameters change frequently, however, you may experience
+ slowdowns as the index retunes the depth internally. You can avoid
+ potential slowdowns by fixating the tree depth through setting this
+ property.
+
+ The depth of the tree and the size of the scene rectangle decide the
+ granularity of the scene's partitioning. The size of each scene segment is
+ determined by the following algorithm:
+
+ The BSP tree has an optimal size when each segment contains between 0 and
+ 10 items.
+
+ \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex
+*/
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_GRAPHICSVIEW
+
+#include <private/qgraphicsscene_p.h>
+#include <private/qgraphicsscenebsptreeindex_p.h>
+#include <private/qgraphicssceneindex_p.h>
+
+#include <QtCore/qmath.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+static inline int intmaxlog(int n)
+{
+ return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0);
+}
+
+/*!
+ Constructs a private scene bsp index.
+*/
+QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene)
+ : QGraphicsSceneIndexPrivate(scene),
+ bspTreeDepth(0),
+ indexTimerId(0),
+ restartIndexTimer(false),
+ regenerateIndex(true),
+ lastItemCount(0),
+ purgePending(false),
+ sortCacheEnabled(false),
+ updatingSortCache(false)
+{
+}
+
+
+/*!
+ This method will update the BSP index by removing the items from the temporary
+ unindexed list and add them in the indexedItems list. This will also
+ update the growingItemsBoundingRect if needed. This will update the BSP
+ implementation as well.
+
+ \internal
+*/
+void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex()
+{
+ Q_Q(QGraphicsSceneBspTreeIndex);
+ if (!indexTimerId)
+ return;
+
+ q->killTimer(indexTimerId);
+ indexTimerId = 0;
+
+ purgeRemovedItems();
+
+ // Add unindexedItems to indexedItems
+ for (int i = 0; i < unindexedItems.size(); ++i) {
+ if (QGraphicsItem *item = unindexedItems.at(i)) {
+ Q_ASSERT(!item->d_ptr->itemDiscovered);
+ if (!freeItemIndexes.isEmpty()) {
+ int freeIndex = freeItemIndexes.takeFirst();
+ item->d_func()->index = freeIndex;
+ indexedItems[freeIndex] = item;
+ } else {
+ item->d_func()->index = indexedItems.size();
+ indexedItems << item;
+ }
+ }
+ }
+
+ // Determine whether we should regenerate the BSP tree.
+ if (bspTreeDepth == 0) {
+ int oldDepth = intmaxlog(lastItemCount);
+ bspTreeDepth = intmaxlog(indexedItems.size());
+ static const int slack = 100;
+ if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - indexedItems.size()) > slack)) {
+ // ### Crude algorithm.
+ regenerateIndex = true;
+ }
+ }
+
+ // Regenerate the tree.
+ if (regenerateIndex) {
+ regenerateIndex = false;
+ bsp.initialize(sceneRect, bspTreeDepth);
+ unindexedItems = indexedItems;
+ lastItemCount = indexedItems.size();
+ }
+
+ // Insert all unindexed items into the tree.
+ for (int i = 0; i < unindexedItems.size(); ++i) {
+ if (QGraphicsItem *item = unindexedItems.at(i)) {
+ if (item->d_ptr->itemIsUntransformable()) {
+ untransformableItems << item;
+ continue;
+ }
+ if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
+ continue;
+
+ bsp.insertItem(item, item->d_ptr->sceneEffectiveBoundingRect());
+ }
+ }
+ unindexedItems.clear();
+}
+
+
+/*!
+ \internal
+
+ Removes stale pointers from all data structures.
+*/
+void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems()
+{
+ if (!purgePending && removedItems.isEmpty())
+ return;
+
+ // Remove stale items from the BSP tree.
+ bsp.removeItems(removedItems);
+ // Purge this list.
+ removedItems.clear();
+ freeItemIndexes.clear();
+ for (int i = 0; i < indexedItems.size(); ++i) {
+ if (!indexedItems.at(i))
+ freeItemIndexes << i;
+ }
+ purgePending = false;
+}
+
+/*!
+ \internal
+
+ Starts or restarts the timer used for reindexing unindexed items.
+*/
+void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer(int interval)
+{
+ Q_Q(QGraphicsSceneBspTreeIndex);
+ if (indexTimerId) {
+ restartIndexTimer = true;
+ } else {
+ indexTimerId = q->startTimer(interval);
+ }
+}
+
+/*!
+ \internal
+*/
+void QGraphicsSceneBspTreeIndexPrivate::resetIndex()
+{
+ purgeRemovedItems();
+ for (int i = 0; i < indexedItems.size(); ++i) {
+ if (QGraphicsItem *item = indexedItems.at(i)) {
+ item->d_ptr->index = -1;
+ Q_ASSERT(!item->d_ptr->itemDiscovered);
+ unindexedItems << item;
+ }
+ }
+ indexedItems.clear();
+ freeItemIndexes.clear();
+ untransformableItems.clear();
+ regenerateIndex = true;
+ startIndexTimer();
+}
+
+/*!
+ \internal
+*/
+void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder)
+{
+ if (!item->d_ptr->children.isEmpty()) {
+ QList<QGraphicsItem *> childList = item->d_ptr->children;
+ qSort(childList.begin(), childList.end(), qt_closestLeaf);
+ for (int i = 0; i < childList.size(); ++i) {
+ QGraphicsItem *item = childList.at(i);
+ if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent))
+ climbTree(childList.at(i), stackingOrder);
+ }
+ item->d_ptr->globalStackingOrder = (*stackingOrder)++;
+ for (int i = 0; i < childList.size(); ++i) {
+ QGraphicsItem *item = childList.at(i);
+ if (item->flags() & QGraphicsItem::ItemStacksBehindParent)
+ climbTree(childList.at(i), stackingOrder);
+ }
+ } else {
+ item->d_ptr->globalStackingOrder = (*stackingOrder)++;
+ }
+}
+
+/*!
+ \internal
+*/
+void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache()
+{
+ Q_Q(QGraphicsSceneBspTreeIndex);
+ _q_updateIndex();
+
+ if (!sortCacheEnabled || !updatingSortCache)
+ return;
+
+ updatingSortCache = false;
+ int stackingOrder = 0;
+
+ QList<QGraphicsItem *> topLevels;
+ const QList<QGraphicsItem *> items = q->items();
+ for (int i = 0; i < items.size(); ++i) {
+ QGraphicsItem *item = items.at(i);
+ if (item && !item->d_ptr->parent)
+ topLevels << item;
+ }
+
+ qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf);
+ for (int i = 0; i < topLevels.size(); ++i)
+ climbTree(topLevels.at(i), &stackingOrder);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache()
+{
+ Q_Q(QGraphicsSceneBspTreeIndex);
+ if (!sortCacheEnabled || updatingSortCache)
+ return;
+
+ updatingSortCache = true;
+ QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection);
+}
+
+void QGraphicsSceneBspTreeIndexPrivate::addItem(QGraphicsItem *item, bool recursive)
+{
+ if (!item)
+ return;
+
+ // Prevent reusing a recently deleted pointer: purge all removed item from our lists.
+ purgeRemovedItems();
+
+ // Invalidate any sort caching; arrival of a new item means we need to resort.
+ // Update the scene's sort cache settings.
+ item->d_ptr->globalStackingOrder = -1;
+ invalidateSortCache();
+
+ // Indexing requires sceneBoundingRect(), but because \a item might
+ // not be completely constructed at this point, we need to store it in
+ // a temporary list and schedule an indexing for later.
+ if (item->d_ptr->index == -1) {
+ Q_ASSERT(!unindexedItems.contains(item));
+ unindexedItems << item;
+ startIndexTimer(0);
+ } else {
+ Q_ASSERT(indexedItems.contains(item));
+ qWarning("QGraphicsSceneBspTreeIndex::addItem: item has already been added to this BSP");
+ }
+
+ if (recursive) {
+ for (int i = 0; i < item->d_ptr->children.size(); ++i)
+ addItem(item->d_ptr->children.at(i), recursive);
+ }
+}
+
+void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool recursive,
+ bool moveToUnindexedItems)
+{
+ if (!item)
+ return;
+
+ if (item->d_ptr->index != -1) {
+ Q_ASSERT(item->d_ptr->index < indexedItems.size());
+ Q_ASSERT(indexedItems.at(item->d_ptr->index) == item);
+ Q_ASSERT(!item->d_ptr->itemDiscovered);
+ freeItemIndexes << item->d_ptr->index;
+ indexedItems[item->d_ptr->index] = 0;
+ item->d_ptr->index = -1;
+
+ if (item->d_ptr->itemIsUntransformable()) {
+ untransformableItems.removeOne(item);
+ } else if (item->d_ptr->inDestructor) {
+ // Avoid virtual function calls from the destructor.
+ purgePending = true;
+ removedItems << item;
+ } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ bsp.removeItem(item, item->d_ptr->sceneEffectiveBoundingRect());
+ }
+ } else {
+ unindexedItems.removeOne(item);
+ }
+ invalidateSortCache(); // ### Only do this when removing from BSP?
+
+ Q_ASSERT(item->d_ptr->index == -1);
+ Q_ASSERT(!indexedItems.contains(item));
+ Q_ASSERT(!unindexedItems.contains(item));
+ Q_ASSERT(!untransformableItems.contains(item));
+
+ if (moveToUnindexedItems)
+ addItem(item);
+
+ if (recursive) {
+ for (int i = 0; i < item->d_ptr->children.size(); ++i)
+ removeItem(item->d_ptr->children.at(i), recursive, moveToUnindexedItems);
+ }
+}
+
+QList<QGraphicsItem *> QGraphicsSceneBspTreeIndexPrivate::estimateItems(const QRectF &rect, Qt::SortOrder order,
+ bool onlyTopLevelItems)
+{
+ Q_Q(QGraphicsSceneBspTreeIndex);
+ if (onlyTopLevelItems && rect.isNull())
+ return q->QGraphicsSceneIndex::estimateTopLevelItems(rect, order);
+
+ purgeRemovedItems();
+ _q_updateSortCache();
+ Q_ASSERT(unindexedItems.isEmpty());
+
+ QList<QGraphicsItem *> rectItems = bsp.items(rect, onlyTopLevelItems);
+ if (onlyTopLevelItems) {
+ for (int i = 0; i < untransformableItems.size(); ++i) {
+ QGraphicsItem *item = untransformableItems.at(i);
+ if (!item->d_ptr->parent) {
+ rectItems << item;
+ } else {
+ item = item->topLevelItem();
+ if (!rectItems.contains(item))
+ rectItems << item;
+ }
+ }
+ } else {
+ rectItems += untransformableItems;
+ }
+
+ sortItems(&rectItems, order, sortCacheEnabled, onlyTopLevelItems);
+ return rectItems;
+}
+
+/*!
+ Returns true if \a item1 is on top of \a item2.
+
+ \internal
+*/
+bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
+{
+ // Siblings? Just check their z-values.
+ const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
+ const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
+ if (d1->parent == d2->parent)
+ return qt_closestLeaf(item1, item2);
+
+ // Find common ancestor, and each item's ancestor closest to the common
+ // ancestor.
+ int item1Depth = d1->depth();
+ int item2Depth = d2->depth();
+ const QGraphicsItem *p = item1;
+ const QGraphicsItem *t1 = item1;
+ while (item1Depth > item2Depth && (p = p->d_ptr->parent)) {
+ if (p == item2) {
+ // item2 is one of item1's ancestors; item1 is on top
+ return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
+ }
+ t1 = p;
+ --item1Depth;
+ }
+ p = item2;
+ const QGraphicsItem *t2 = item2;
+ while (item2Depth > item1Depth && (p = p->d_ptr->parent)) {
+ if (p == item1) {
+ // item1 is one of item2's ancestors; item1 is not on top
+ return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
+ }
+ t2 = p;
+ --item2Depth;
+ }
+
+ // item1Ancestor is now at the same level as item2Ancestor, but not the same.
+ const QGraphicsItem *a1 = t1;
+ const QGraphicsItem *a2 = t2;
+ while (a1) {
+ const QGraphicsItem *p1 = a1;
+ const QGraphicsItem *p2 = a2;
+ a1 = a1->parentItem();
+ a2 = a2->parentItem();
+ if (a1 && a1 == a2)
+ return qt_closestLeaf(p1, p2);
+ }
+
+ // No common ancestor? Then just compare the items' toplevels directly.
+ return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem());
+}
+
+/*!
+ Returns true if \a item2 is on top of \a item1.
+
+ \internal
+*/
+bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
+{
+ return closestItemFirst_withoutCache(item2, item1);
+}
+
+/*!
+ Sort a list of \a itemList in a specific \a order and use the cache if requested.
+
+ \internal
+*/
+void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order,
+ bool sortCacheEnabled, bool onlyTopLevelItems)
+{
+ if (order == Qt::SortOrder(-1))
+ return;
+
+ if (onlyTopLevelItems) {
+ if (order == Qt::AscendingOrder)
+ qSort(itemList->begin(), itemList->end(), qt_closestLeaf);
+ else if (order == Qt::DescendingOrder)
+ qSort(itemList->begin(), itemList->end(), qt_notclosestLeaf);
+ return;
+ }
+
+ if (sortCacheEnabled) {
+ if (order == Qt::AscendingOrder) {
+ qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache);
+ } else if (order == Qt::DescendingOrder) {
+ qSort(itemList->begin(), itemList->end(), closestItemLast_withCache);
+ }
+ } else {
+ if (order == Qt::AscendingOrder) {
+ qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache);
+ } else if (order == Qt::DescendingOrder) {
+ qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache);
+ }
+ }
+}
+
+/*!
+ Constructs a BSP scene index for the given \a scene.
+*/
+QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene)
+ : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene)
+{
+
+}
+
+QGraphicsSceneBspTreeIndex::~QGraphicsSceneBspTreeIndex()
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ for (int i = 0; i < d->indexedItems.size(); ++i) {
+ // Ensure item bits are reset properly.
+ if (QGraphicsItem *item = d->indexedItems.at(i)) {
+ Q_ASSERT(!item->d_ptr->itemDiscovered);
+ item->d_ptr->index = -1;
+ }
+ }
+}
+
+/*!
+ \internal
+ Clear the all the BSP index.
+*/
+void QGraphicsSceneBspTreeIndex::clear()
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ d->bsp.clear();
+ d->lastItemCount = 0;
+ d->freeItemIndexes.clear();
+ for (int i = 0; i < d->indexedItems.size(); ++i) {
+ // Ensure item bits are reset properly.
+ if (QGraphicsItem *item = d->indexedItems.at(i)) {
+ Q_ASSERT(!item->d_ptr->itemDiscovered);
+ item->d_ptr->index = -1;
+ }
+ }
+ d->indexedItems.clear();
+ d->unindexedItems.clear();
+ d->untransformableItems.clear();
+ d->regenerateIndex = true;
+}
+
+/*!
+ Add the \a item into the BSP index.
+*/
+void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ d->addItem(item);
+}
+
+/*!
+ Remove the \a item from the BSP index.
+*/
+void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ d->removeItem(item);
+}
+
+/*!
+ \internal
+ Update the BSP when the \a item 's bounding rect has changed.
+*/
+void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item)
+{
+ if (!item)
+ return;
+
+ if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable()
+ || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ return; // Item is not in BSP tree; nothing to do.
+ }
+
+ Q_D(QGraphicsSceneBspTreeIndex);
+ QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
+ d->removeItem(thatItem, /*recursive=*/false, /*moveToUnindexedItems=*/true);
+ for (int i = 0; i < item->d_ptr->children.size(); ++i) // ### Do we really need this?
+ prepareBoundingRectChange(item->d_ptr->children.at(i));
+}
+
+/*!
+ Returns an estimation visible items that are either inside or
+ intersect with the specified \a rect and return a list sorted using \a order.
+
+ \a deviceTransform is the transformation apply to the view.
+
+*/
+QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsSceneBspTreeIndex);
+ return const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->estimateItems(rect, order);
+}
+
+QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsSceneBspTreeIndex);
+ return const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->estimateItems(rect, order, /*onlyTopLevels=*/true);
+}
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const;
+
+ Return all items in the BSP index and sort them using \a order.
+*/
+QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsSceneBspTreeIndex);
+ const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->purgeRemovedItems();
+ QList<QGraphicsItem *> itemList;
+
+ // If freeItemIndexes is empty, we know there are no holes in indexedItems and
+ // unindexedItems.
+ if (d->freeItemIndexes.isEmpty()) {
+ if (d->unindexedItems.isEmpty()) {
+ itemList = d->indexedItems;
+ } else {
+ itemList = d->indexedItems + d->unindexedItems;
+ }
+ } else {
+ // Rebuild the list of items to avoid holes. ### We could also just
+ // compress the item lists at this point.
+ foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) {
+ if (item)
+ itemList << item;
+ }
+ }
+ if (order != -1) {
+ //We sort descending order
+ d->sortItems(&itemList, order, d->sortCacheEnabled);
+ }
+ return itemList;
+}
+
+/*!
+ \property QGraphicsSceneBspTreeIndex::bspTreeDepth
+ \brief the depth of the BSP index tree
+ \since 4.6
+
+ This value determines the depth of BSP tree. The depth
+ directly affects performance and memory usage; the latter
+ growing exponentially with the depth of the tree. With an optimal tree
+ depth, the index can instantly determine the locality of items, even
+ for scenes with thousands or millions of items. This also greatly improves
+ rendering performance.
+
+ By default, the value is 0, in which case Qt will guess a reasonable
+ default depth based on the size, location and number of items in the
+ scene. If these parameters change frequently, however, you may experience
+ slowdowns as the index retunes the depth internally. You can avoid
+ potential slowdowns by fixating the tree depth through setting this
+ property.
+
+ The depth of the tree and the size of the scene rectangle decide the
+ granularity of the scene's partitioning. The size of each scene segment is
+ determined by the following algorithm:
+
+ The BSP tree has an optimal size when each segment contains between 0 and
+ 10 items.
+
+*/
+int QGraphicsSceneBspTreeIndex::bspTreeDepth()
+{
+ Q_D(const QGraphicsSceneBspTreeIndex);
+ return d->bspTreeDepth;
+}
+
+void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ if (d->bspTreeDepth == depth)
+ return;
+ d->bspTreeDepth = depth;
+ d->resetIndex();
+}
+
+/*!
+ \internal
+
+ This method react to the \a rect change of the scene and
+ reset the BSP tree index.
+*/
+void QGraphicsSceneBspTreeIndex::updateSceneRect(const QRectF &rect)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ d->sceneRect = rect;
+ d->resetIndex();
+}
+
+/*!
+ \internal
+
+ This method react to the \a change of the \a item and use the \a value to
+ update the BSP tree if necessary.
+*/
+void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ switch (change) {
+ case QGraphicsItem::ItemFlagsChange: {
+ // Handle ItemIgnoresTransformations
+ bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations;
+ bool willIgnoreTransform = value.toUInt() & QGraphicsItem::ItemIgnoresTransformations;
+ bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
+ bool willClipChildren = value.toUInt() & QGraphicsItem::ItemClipsChildrenToShape;
+ if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) {
+ QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
+ // Remove item and its descendants from the index and append
+ // them to the list of unindexed items. Then, when the index
+ // is updated, they will be put into the bsp-tree or the list
+ // of untransformable items.
+ d->removeItem(thatItem, /*recursive=*/true, /*moveToUnidexedItems=*/true);
+ }
+ break;
+ }
+ case QGraphicsItem::ItemZValueChange:
+ d->invalidateSortCache();
+ break;
+ case QGraphicsItem::ItemParentChange: {
+ d->invalidateSortCache();
+ // Handle ItemIgnoresTransformations
+ QGraphicsItem *newParent = qVariantValue<QGraphicsItem *>(value);
+ bool ignoredTransform = item->d_ptr->itemIsUntransformable();
+ bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations)
+ || (newParent && newParent->d_ptr->itemIsUntransformable());
+ bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren;
+ bool ancestorWillClipChildren = newParent
+ && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)
+ || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren));
+ if ((ignoredTransform != willIgnoreTransform) || (ancestorClippedChildren != ancestorWillClipChildren)) {
+ QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
+ // Remove item and its descendants from the index and append
+ // them to the list of unindexed items. Then, when the index
+ // is updated, they will be put into the bsp-tree or the list
+ // of untransformable items.
+ d->removeItem(thatItem, /*recursive=*/true, /*moveToUnidexedItems=*/true);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return QGraphicsSceneIndex::itemChange(item, change, value);
+}
+/*!
+ \reimp
+
+ Used to catch the timer event.
+
+ \internal
+*/
+bool QGraphicsSceneBspTreeIndex::event(QEvent *event)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ switch (event->type()) {
+ case QEvent::Timer:
+ if (d->indexTimerId && static_cast<QTimerEvent *>(event)->timerId() == d->indexTimerId) {
+ if (d->restartIndexTimer) {
+ d->restartIndexTimer = false;
+ } else {
+ // this call will kill the timer
+ d->_q_updateIndex();
+ }
+ }
+ // Fallthrough intended - support timers in subclasses.
+ default:
+ return QObject::event(event);
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qgraphicsscenebsptreeindex_p.cpp"
+
+#endif // QT_NO_GRAPHICSVIEW
+
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h
new file mode 100644
index 0000000..5cc8449
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QGRAPHICSBSPTREEINDEX_H
+#define QGRAPHICSBSPTREEINDEX_H
+
+#include <QtCore/qglobal.h>
+
+#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
+
+#include "qgraphicssceneindex_p.h"
+#include "qgraphicsitem_p.h"
+#include "qgraphicsscene_bsp_p.h"
+
+#include <QtCore/qrect.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
+
+class QGraphicsScene;
+class QGraphicsSceneBspTreeIndexPrivate;
+
+class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex
+{
+ Q_OBJECT
+ Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth)
+public:
+ QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0);
+ ~QGraphicsSceneBspTreeIndex();
+
+ QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const;
+ QList<QGraphicsItem *> estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const;
+ QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::AscendingOrder) const;
+
+ int bspTreeDepth();
+ void setBspTreeDepth(int depth);
+
+protected Q_SLOTS:
+ void updateSceneRect(const QRectF &rect);
+
+protected:
+ bool event(QEvent *event);
+ void clear();
+
+ void addItem(QGraphicsItem *item);
+ void removeItem(QGraphicsItem *item);
+ void prepareBoundingRectChange(const QGraphicsItem *item);
+
+ void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value);
+
+private :
+ Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex)
+ Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex)
+ Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateIndex())
+
+ friend class QGraphicsScene;
+ friend class QGraphicsScenePrivate;
+};
+
+class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex)
+public:
+ QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene);
+
+ QGraphicsSceneBspTree bsp;
+ QRectF sceneRect;
+ int bspTreeDepth;
+ int indexTimerId;
+ bool restartIndexTimer;
+ bool regenerateIndex;
+ int lastItemCount;
+
+ QList<QGraphicsItem *> indexedItems;
+ QList<QGraphicsItem *> unindexedItems;
+ QList<QGraphicsItem *> untransformableItems;
+ QList<int> freeItemIndexes;
+
+ bool purgePending;
+ QSet<QGraphicsItem *> removedItems;
+ void purgeRemovedItems();
+
+ void _q_updateIndex();
+ void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
+ void resetIndex();
+
+ void _q_updateSortCache();
+ bool sortCacheEnabled;
+ bool updatingSortCache;
+ void invalidateSortCache();
+ void addItem(QGraphicsItem *item, bool recursive = false);
+ void removeItem(QGraphicsItem *item, bool recursive = false, bool moveToUnindexedItems = false);
+ QList<QGraphicsItem *> estimateItems(const QRectF &, Qt::SortOrder, bool b = false);
+
+ static void climbTree(QGraphicsItem *item, int *stackingOrder);
+ static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2);
+ static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2);
+
+ static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
+ {
+ return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder;
+ }
+ static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
+ {
+ return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder;
+ }
+
+ static void sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order,
+ bool cached, bool onlyTopLevelItems = false);
+};
+
+static inline bool QRectF_intersects(const QRectF &s, const QRectF &r)
+{
+ qreal xp = s.left();
+ qreal yp = s.top();
+ qreal w = s.width();
+ qreal h = s.height();
+ qreal l1 = xp;
+ qreal r1 = xp;
+ if (w < 0)
+ l1 += w;
+ else
+ r1 += w;
+
+ qreal l2 = r.left();
+ qreal r2 = r.left();
+ if (w < 0)
+ l2 += r.width();
+ else
+ r2 += r.width();
+
+ if (l1 >= r2 || l2 >= r1)
+ return false;
+
+ qreal t1 = yp;
+ qreal b1 = yp;
+ if (h < 0)
+ t1 += h;
+ else
+ b1 += h;
+
+ qreal t2 = r.top();
+ qreal b2 = r.top();
+ if (r.height() < 0)
+ t2 += r.height();
+ else
+ b2 += r.height();
+
+ return !(t1 >= b2 || t2 >= b1);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GRAPHICSVIEW
+
+#endif // QGRAPHICSBSPTREEINDEX_H
diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp
index 33af4a2..bd27f6e 100644
--- a/src/gui/graphicsview/qgraphicssceneevent.cpp
+++ b/src/gui/graphicsview/qgraphicssceneevent.cpp
@@ -44,7 +44,6 @@
\brief The QGraphicsSceneEvent class provides a base class for all
graphics view related events.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
When a QGraphicsView receives Qt mouse, keyboard, and drag and
@@ -76,22 +75,23 @@
received by the view (see
\l{QGraphicsSceneMouseEvent::}{lastScreenPos()},
\l{QGraphicsSceneMouseEvent::}{lastScenePos()}, and
- \l{QGraphicsSceneMouseEvent::}{lastPos()}).
+ \l{QGraphicsSceneMouseEvent::}{lastPos()}).
\sa QEvent
*/
/*!
\class QGraphicsSceneMouseEvent
- \brief The QGraphicsSceneMouseEvent class provides mouse events
+ \brief The QGraphicsSceneMouseEvent class provides mouse events
in the graphics view framework.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
- When a QGraphicsView receives a QMouseEvent, it translates it to
- a QGraphicsSceneMouseEvent. The event is then forwarded to the
- QGraphicsScene associated with the view.
+ When a QGraphicsView receives a QMouseEvent, it translates it to a
+ QGraphicsSceneMouseEvent. The event is then forwarded to the
+ QGraphicsScene associated with the view. If the event is not
+ handled by the scene, the view may use it, e.g., for the
+ \l{QGraphicsView::}{DragMode}.
In addition to containing the item, scene, and screen coordinates
of the event (as pos(), scenePos(), and screenPos()), mouse
@@ -106,12 +106,11 @@
/*!
\class QGraphicsSceneWheelEvent
- \brief The QGraphicsSceneWheelEvent class provides wheel events
+ \brief The QGraphicsSceneWheelEvent class provides wheel events
in the graphics view framework.
\brief The QGraphicsSceneWheelEvent class provides wheel events in the
graphics view framework.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
\l{QWheelEvent}{QWheelEvent}s received by a QGraphicsView are translated
@@ -128,7 +127,6 @@
\brief The QGraphicsSceneContextMenuEvent class provides context
menu events in the graphics view framework.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
A QContextMenuEvent received by a QGraphicsView is translated
@@ -157,10 +155,9 @@
/*!
\class QGraphicsSceneHoverEvent
- \brief The QGraphicsSceneHoverEvent class provides hover events
+ \brief The QGraphicsSceneHoverEvent class provides hover events
in the graphics view framework.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
When a QGraphicsView receives a QHoverEvent event, it translates
@@ -173,10 +170,9 @@
/*!
\class QGraphicsSceneHelpEvent
- \brief The QGraphicsSceneHelpEvent class provides events when a
+ \brief The QGraphicsSceneHelpEvent class provides events when a
tooltip is requested.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
When a QGraphicsView receives a QEvent of type
@@ -199,9 +195,8 @@
/*!
\class QGraphicsSceneDragDropEvent
\brief The QGraphicsSceneDragDropEvent class provides events for
- drag and drop in the graphics view framework.
+ drag and drop in the graphics view framework.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
QGraphicsView inherits the drag and drop functionality provided
@@ -226,7 +221,6 @@
\brief The QGraphicsSceneResizeEvent class provides events for widget
resizing in the graphics view framework.
\since 4.4
- \ingroup multimedia
\ingroup graphicsview-api
A QGraphicsWidget sends itself a QGraphicsSceneResizeEvent immediately
@@ -243,7 +237,6 @@
\brief The QGraphicsSceneMoveEvent class provides events for widget
moving in the graphics view framework.
\since 4.4
- \ingroup multimedia
\ingroup graphicsview-api
A QGraphicsWidget sends itself a QGraphicsSceneMoveEvent immediately when
@@ -268,6 +261,10 @@
#include <QtCore/qpoint.h>
#include <QtCore/qsize.h>
#include <QtCore/qstring.h>
+#include "qgraphicsview.h"
+#include "qgraphicsitem.h"
+#include <QtGui/qgesture.h>
+#include <private/qevent_p.h>
QT_BEGIN_NAMESPACE
@@ -313,7 +310,6 @@ QGraphicsSceneEvent::QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type ty
*/
QGraphicsSceneEvent::~QGraphicsSceneEvent()
{
- delete d_ptr;
}
/*!
@@ -522,7 +518,7 @@ void QGraphicsSceneMouseEvent::setLastPos(const QPointF &pos)
}
/*!
- Returns the last recorded mouse cursor position in scene
+ Returns the last recorded mouse cursor position in scene
coordinates. The last recorded position is the position of
the previous mouse event received by the view that created
the event.
@@ -545,7 +541,7 @@ void QGraphicsSceneMouseEvent::setLastScenePos(const QPointF &pos)
}
/*!
- Returns the last recorded mouse cursor position in screen
+ Returns the last recorded mouse cursor position in screen
coordinates. The last recorded position is the position of
the previous mouse event received by the view that created
the event.
@@ -1275,7 +1271,7 @@ QGraphicsSceneDragDropEvent::~QGraphicsSceneDragDropEvent()
/*!
Returns the mouse position of the event relative to the
view that sent the event.
-
+
\sa QGraphicsView, screenPos(), scenePos()
*/
QPointF QGraphicsSceneDragDropEvent::pos() const
@@ -1373,7 +1369,7 @@ void QGraphicsSceneDragDropEvent::setButtons(Qt::MouseButtons buttons)
/*!
Returns the keyboard modifiers that were pressed when the drag
- and drop event was created.
+ and drop event was created.
\sa Qt::KeyboardModifiers
*/
@@ -1428,7 +1424,7 @@ void QGraphicsSceneDragDropEvent::setPossibleActions(Qt::DropActions actions)
The action must be one of the possible actions as defined by
\c possibleActions().
- \sa Qt::DropAction, possibleActions()
+ \sa Qt::DropAction, possibleActions()
*/
Qt::DropAction QGraphicsSceneDragDropEvent::proposedAction() const
@@ -1472,7 +1468,7 @@ void QGraphicsSceneDragDropEvent::acceptProposedAction()
/*!
Returns the action that was performed in this drag and drop.
This should be set by the receiver of the drop and is
- returned by QDrag::start().
+ returned by QDrag::exec().
\sa setDropAction(), acceptProposedAction()
*/
diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h
index efcbacb..d40676d 100644
--- a/src/gui/graphicsview/qgraphicssceneevent.h
+++ b/src/gui/graphicsview/qgraphicssceneevent.h
@@ -44,6 +44,11 @@
#include <QtCore/qcoreevent.h>
#include <QtCore/qpoint.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qrect.h>
+#include <QtGui/qpolygon.h>
+#include <QtCore/qset.h>
+#include <QtCore/qhash.h>
QT_BEGIN_HEADER
@@ -70,7 +75,7 @@ public:
protected:
QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type type = None);
- QGraphicsSceneEventPrivate *d_ptr;
+ QScopedPointer<QGraphicsSceneEventPrivate> d_ptr;
Q_DECLARE_PRIVATE(QGraphicsSceneEvent)
};
diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp
new file mode 100644
index 0000000..feb44bb
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicssceneindex.cpp
@@ -0,0 +1,647 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \class QGraphicsSceneIndex
+ \brief The QGraphicsSceneIndex class provides a base class to implement
+ a custom indexing algorithm for discovering items in QGraphicsScene.
+ \since 4.6
+ \ingroup graphicsview-api
+
+ \internal
+
+ The QGraphicsSceneIndex class provides a base class to implement
+ a custom indexing algorithm for discovering items in QGraphicsScene. You
+ need to subclass it and reimplement addItem, removeItem, estimateItems
+ and items in order to have an functional indexing.
+
+ \sa QGraphicsScene, QGraphicsView
+*/
+
+#include "qdebug.h"
+#include "qgraphicsscene.h"
+#include "qgraphicsitem_p.h"
+#include "qgraphicsscene_p.h"
+#include "qgraphicswidget.h"
+#include "qgraphicssceneindex_p.h"
+#include "qgraphicsscenebsptreeindex_p.h"
+
+#ifndef QT_NO_GRAPHICSVIEW
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector
+{
+public:
+ bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ const QTransform &deviceTransform) const
+ {
+ QRectF brect = item->boundingRect();
+ _q_adjustRect(&brect);
+
+ // ### Add test for this (without making things slower?)
+ Q_UNUSED(exposeRect);
+
+ bool keep = true;
+ const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item);
+ if (itemd->itemIsUntransformable()) {
+ // Untransformable items; map the scene rect to item coordinates.
+ const QTransform transform = item->deviceTransform(deviceTransform);
+ QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect);
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = itemRect.contains(brect) && itemRect != brect;
+ else
+ keep = itemRect.intersects(brect);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath itemPath;
+ itemPath.addRect(itemRect);
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
+ }
+ } else {
+ Q_ASSERT(!itemd->dirtySceneTransform);
+ const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
+ ? brect.translated(itemd->sceneTransform.dx(),
+ itemd->sceneTransform.dy())
+ : itemd->sceneTransform.mapRect(brect);
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = sceneRect != brect && sceneRect.contains(itemSceneBoundingRect);
+ else
+ keep = sceneRect.intersects(itemSceneBoundingRect);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath rectPath;
+ rectPath.addRect(sceneRect);
+ if (itemd->sceneTransformTranslateOnly)
+ rectPath.translate(-itemd->sceneTransform.dx(), -itemd->sceneTransform.dy());
+ else
+ rectPath = itemd->sceneTransform.inverted().map(rectPath);
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, rectPath, mode);
+ }
+ }
+ return keep;
+ }
+
+ QRectF sceneRect;
+};
+
+class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersector
+{
+public:
+ bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ const QTransform &deviceTransform) const
+ {
+ QRectF brect = item->boundingRect();
+ _q_adjustRect(&brect);
+
+ // ### Add test for this (without making things slower?)
+ Q_UNUSED(exposeRect);
+
+ bool keep = false;
+ const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item);
+ if (itemd->itemIsUntransformable()) {
+ // Untransformable items; map the scene point to item coordinates.
+ const QTransform transform = item->deviceTransform(deviceTransform);
+ QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint);
+ keep = brect.contains(itemPoint);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath pointPath;
+ pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1)));
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode);
+ }
+ } else {
+ Q_ASSERT(!itemd->dirtySceneTransform);
+ QRectF sceneBoundingRect = itemd->sceneTransformTranslateOnly
+ ? brect.translated(itemd->sceneTransform.dx(),
+ itemd->sceneTransform.dy())
+ : itemd->sceneTransform.mapRect(brect);
+ keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1)));
+ if (keep) {
+ QPointF p = itemd->sceneTransformTranslateOnly
+ ? QPointF(scenePoint.x() - itemd->sceneTransform.dx(),
+ scenePoint.y() - itemd->sceneTransform.dy())
+ : itemd->sceneTransform.inverted().map(scenePoint);
+ keep = item->contains(p);
+ }
+ }
+
+ return keep;
+ }
+
+ QPointF scenePoint;
+};
+
+class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector
+{
+public:
+ bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ const QTransform &deviceTransform) const
+ {
+ QRectF brect = item->boundingRect();
+ _q_adjustRect(&brect);
+
+ // ### Add test for this (without making things slower?)
+ Q_UNUSED(exposeRect);
+
+ bool keep = true;
+ const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item);
+ if (itemd->itemIsUntransformable()) {
+ // Untransformable items; map the scene rect to item coordinates.
+ const QTransform transform = item->deviceTransform(deviceTransform);
+ QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath);
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = itemPath.contains(brect);
+ else
+ keep = itemPath.intersects(brect);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape))
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
+ } else {
+ Q_ASSERT(!itemd->dirtySceneTransform);
+ const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
+ ? brect.translated(itemd->sceneTransform.dx(),
+ itemd->sceneTransform.dy())
+ : itemd->sceneTransform.mapRect(brect);
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = scenePath.contains(itemSceneBoundingRect);
+ else
+ keep = scenePath.intersects(itemSceneBoundingRect);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath itemPath = itemd->sceneTransformTranslateOnly
+ ? scenePath.translated(-itemd->sceneTransform.dx(),
+ -itemd->sceneTransform.dy())
+ : itemd->sceneTransform.inverted().map(scenePath);
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
+ }
+ }
+ return keep;
+ }
+
+ QPainterPath scenePath;
+};
+
+/*!
+ Constructs a private scene index.
+*/
+QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene)
+{
+ pointIntersector = new QGraphicsSceneIndexPointIntersector;
+ rectIntersector = new QGraphicsSceneIndexRectIntersector;
+ pathIntersector = new QGraphicsSceneIndexPathIntersector;
+}
+
+/*!
+ Destructor of private scene index.
+*/
+QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate()
+{
+ delete pointIntersector;
+ delete rectIntersector;
+ delete pathIntersector;
+}
+
+/*!
+ \internal
+
+ Checks if item collides with the path and mode, but also checks that if it
+ doesn't collide, maybe its frame rect will.
+*/
+bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item,
+ const QPainterPath &path,
+ Qt::ItemSelectionMode mode)
+{
+ if (item->collidesWithPath(path, mode))
+ return true;
+ if (item->isWidget()) {
+ // Check if this is a window, and if its frame rect collides.
+ const QGraphicsWidget *widget = static_cast<const QGraphicsWidget *>(item);
+ if (widget->isWindow()) {
+ QRectF frameRect = widget->windowFrameRect();
+ QPainterPath framePath;
+ framePath.addRect(frameRect);
+ bool intersects = path.intersects(frameRect);
+ if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect)
+ return intersects || path.contains(frameRect.topLeft())
+ || framePath.contains(path.elementAt(0));
+ return !intersects && path.contains(frameRect.topLeft());
+ }
+ }
+ return false;
+}
+
+/*!
+ \internal
+*/
+void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
+ QGraphicsSceneIndexIntersector *intersector,
+ QList<QGraphicsItem *> *items,
+ const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order,
+ qreal parentOpacity) const
+{
+ Q_ASSERT(item);
+ if (!item->d_ptr->visible)
+ return;
+
+ const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
+ const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemHasChildren = !item->d_ptr->children.isEmpty();
+ if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
+ return;
+
+ // Update the item's scene transform if dirty.
+ const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
+ const bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform && !itemIsUntransformable;
+ if (wasDirtyParentSceneTransform) {
+ item->d_ptr->updateSceneTransformFromParent();
+ Q_ASSERT(!item->d_ptr->dirtySceneTransform);
+ }
+
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ bool processItem = !itemIsFullyTransparent;
+ if (processItem) {
+ processItem = intersector->intersect(item, exposeRect, mode, viewTransform);
+ if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) {
+ if (wasDirtyParentSceneTransform)
+ item->d_ptr->invalidateChildrenSceneTransform();
+ return;
+ }
+ } // else we know for sure this item has children we must process.
+
+ int i = 0;
+ if (itemHasChildren) {
+ // Sort children.
+ item->d_ptr->ensureSortedChildren();
+
+ // Clip to shape.
+ if (itemClipsChildrenToShape && !itemIsUntransformable) {
+ QPainterPath mappedShape = item->d_ptr->sceneTransformTranslateOnly
+ ? item->shape().translated(item->d_ptr->sceneTransform.dx(),
+ item->d_ptr->sceneTransform.dy())
+ : item->d_ptr->sceneTransform.map(item->shape());
+ exposeRect &= mappedShape.controlPointRect();
+ }
+
+ // Process children behind
+ for (i = 0; i < item->d_ptr->children.size(); ++i) {
+ QGraphicsItem *child = item->d_ptr->children.at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
+ break;
+ if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
+ continue;
+ recursive_items_helper(child, exposeRect, intersector, items, viewTransform,
+ mode, order, opacity);
+ }
+ }
+
+ // Process item
+ if (processItem)
+ items->append(item);
+
+ // Process children in front
+ if (itemHasChildren) {
+ for (; i < item->d_ptr->children.size(); ++i) {
+ QGraphicsItem *child = item->d_ptr->children.at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
+ continue;
+ recursive_items_helper(child, exposeRect, intersector, items, viewTransform,
+ mode, order, opacity);
+ }
+ }
+}
+
+void QGraphicsSceneIndexPrivate::init()
+{
+ if (!scene)
+ return;
+
+ QObject::connect(scene, SIGNAL(sceneRectChanged(const QRectF&)),
+ q_func(), SLOT(updateSceneRect(const QRectF&)));
+}
+
+/*!
+ Constructs an abstract scene index for a given \a scene.
+*/
+QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene)
+: QObject(*new QGraphicsSceneIndexPrivate(scene), scene)
+{
+ d_func()->init();
+}
+
+/*!
+ \internal
+*/
+QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene)
+ : QObject(dd, scene)
+{
+ d_func()->init();
+}
+
+/*!
+ Destroys the scene index.
+*/
+QGraphicsSceneIndex::~QGraphicsSceneIndex()
+{
+
+}
+
+/*!
+ Returns the scene of this index.
+*/
+QGraphicsScene* QGraphicsSceneIndex::scene() const
+{
+ Q_D(const QGraphicsSceneIndex);
+ return d->scene;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform
+ &deviceTransform) const
+
+ Returns all visible items that, depending on \a mode, are at the specified
+ \a pos and return a list sorted using \a order.
+
+ The default value for \a mode is Qt::IntersectsItemShape; all items whose
+ exact shape intersects with \a pos are returned.
+
+ \a deviceTransform is the transformation apply to the view.
+
+ This method use the estimation of the index (estimateItems) and refine the
+ list to get an exact result. If you want to implement your own refinement
+ algorithm you can reimplement this method.
+
+ \sa estimateItems()
+
+*/
+QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+
+ Q_D(const QGraphicsSceneIndex);
+ QList<QGraphicsItem *> itemList;
+ d->pointIntersector->scenePoint = pos;
+ d->items_helper(QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, deviceTransform, mode, order);
+ return itemList;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform
+ &deviceTransform) const
+
+ \overload
+
+ Returns all visible items that, depending on \a mode, are either inside or
+ intersect with the specified \a rect and return a list sorted using \a order.
+
+ The default value for \a mode is Qt::IntersectsItemShape; all items whose
+ exact shape intersects with or is contained by \a rect are returned.
+
+ \a deviceTransform is the transformation apply to the view.
+
+ This method use the estimation of the index (estimateItems) and refine
+ the list to get an exact result. If you want to implement your own
+ refinement algorithm you can reimplement this method.
+
+ \sa estimateItems()
+
+*/
+QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsSceneIndex);
+ QRectF exposeRect = rect;
+ _q_adjustRect(&exposeRect);
+ QList<QGraphicsItem *> itemList;
+ d->rectIntersector->sceneRect = rect;
+ d->items_helper(exposeRect, d->rectIntersector, &itemList, deviceTransform, mode, order);
+ return itemList;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF
+ &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const
+ QTransform &deviceTransform) const
+
+ \overload
+
+ Returns all visible items that, depending on \a mode, are either inside or
+ intersect with the specified \a polygon and return a list sorted using \a order.
+
+ The default value for \a mode is Qt::IntersectsItemShape; all items whose
+ exact shape intersects with or is contained by \a polygon are returned.
+
+ \a deviceTransform is the transformation apply to the view.
+
+ This method use the estimation of the index (estimateItems) and refine
+ the list to get an exact result. If you want to implement your own
+ refinement algorithm you can reimplement this method.
+
+ \sa estimateItems()
+
+*/
+QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsSceneIndex);
+ QList<QGraphicsItem *> itemList;
+ QRectF exposeRect = polygon.boundingRect();
+ _q_adjustRect(&exposeRect);
+ QPainterPath path;
+ path.addPolygon(polygon);
+ d->pathIntersector->scenePath = path;
+ d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order);
+ return itemList;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath
+ &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform
+ &deviceTransform) const
+
+ \overload
+
+ Returns all visible items that, depending on \a mode, are either inside or
+ intersect with the specified \a path and return a list sorted using \a order.
+
+ The default value for \a mode is Qt::IntersectsItemShape; all items whose
+ exact shape intersects with or is contained by \a path are returned.
+
+ \a deviceTransform is the transformation apply to the view.
+
+ This method use the estimation of the index (estimateItems) and refine
+ the list to get an exact result. If you want to implement your own
+ refinement algorithm you can reimplement this method.
+
+ \sa estimateItems()
+
+*/
+QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsSceneIndex);
+ QList<QGraphicsItem *> itemList;
+ QRectF exposeRect = path.controlPointRect();
+ _q_adjustRect(&exposeRect);
+ d->pathIntersector->scenePath = path;
+ d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order);
+ return itemList;
+}
+
+/*!
+ This virtual function return an estimation of items at position \a point.
+ This method return a list sorted using \a order.
+*/
+QList<QGraphicsItem *> QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order) const
+{
+ return estimateItems(QRectF(point, QSize(1, 1)), order);
+}
+
+QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsSceneIndex);
+ Q_UNUSED(rect);
+ QGraphicsScenePrivate *scened = d->scene->d_func();
+ scened->ensureSortedTopLevelItems();
+ if (order == Qt::AscendingOrder) {
+ QList<QGraphicsItem *> sorted;
+ for (int i = scened->topLevelItems.size() - 1; i >= 0; --i)
+ sorted << scened->topLevelItems.at(i);
+ return sorted;
+ }
+ return scened->topLevelItems;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const
+
+ This pure virtual function all items in the index and sort them using
+ \a order.
+*/
+
+
+/*!
+ Notifies the index that the scene's scene rect has changed. \a rect
+ is thew new scene rect.
+
+ \sa QGraphicsScene::sceneRect()
+*/
+void QGraphicsSceneIndex::updateSceneRect(const QRectF &rect)
+{
+ Q_UNUSED(rect);
+}
+
+/*!
+ This virtual function removes all items in the scene index.
+*/
+void QGraphicsSceneIndex::clear()
+{
+ const QList<QGraphicsItem *> allItems = items();
+ for (int i = 0 ; i < allItems.size(); ++i)
+ removeItem(allItems.at(i));
+}
+
+/*!
+ \fn virtual void QGraphicsSceneIndex::addItem(QGraphicsItem *item) = 0
+
+ This pure virtual function inserts an \a item to the scene index.
+
+ \sa removeItem(), deleteItem()
+*/
+
+/*!
+ \fn virtual void QGraphicsSceneIndex::removeItem(QGraphicsItem *item) = 0
+
+ This pure virtual function removes an \a item to the scene index.
+
+ \sa addItem(), deleteItem()
+*/
+
+/*!
+ This method is called when an \a item has been deleted.
+ The default implementation call removeItem. Be carefull,
+ if your implementation of removeItem use pure virtual method
+ of QGraphicsItem like boundingRect(), then you should reimplement
+ this method.
+
+ \sa addItem(), removeItem()
+*/
+void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item)
+{
+ removeItem(item);
+}
+
+/*!
+ This virtual function is called by QGraphicsItem to notify the index
+ that some part of the \a item 's state changes. By reimplementing this
+ function, your can react to a change, and in some cases, (depending on \a
+ change,) adjustments in the index can be made.
+
+ \a change is the parameter of the item that is changing. \a value is the
+ value that changed; the type of the value depends on \a change.
+
+ The default implementation does nothing.
+
+ \sa QGraphicsItem::GraphicsItemChange
+*/
+void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+{
+ Q_UNUSED(item);
+ Q_UNUSED(change);
+ Q_UNUSED(value);
+}
+
+/*!
+ Notify the index for a geometry change of an \a item.
+
+ \sa QGraphicsItem::prepareGeometryChange()
+*/
+void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item)
+{
+ Q_UNUSED(item);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qgraphicssceneindex_p.cpp"
+
+#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h
new file mode 100644
index 0000000..00e5f89
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicssceneindex_p.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSSCENEINDEX_H
+#define QGRAPHICSSCENEINDEX_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qgraphicsscene_p.h"
+#include "qgraphicsscene.h"
+#include <private/qobject_p.h>
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qtransform.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
+
+class QGraphicsSceneIndexIntersector;
+class QGraphicsSceneIndexPointIntersector;
+class QGraphicsSceneIndexRectIntersector;
+class QGraphicsSceneIndexPathIntersector;
+class QGraphicsSceneIndexPrivate;
+class QPointF;
+class QRectF;
+template<typename T> class QList;
+
+class Q_AUTOTEST_EXPORT QGraphicsSceneIndex : public QObject
+{
+ Q_OBJECT
+
+public:
+ QGraphicsSceneIndex(QGraphicsScene *scene = 0);
+ virtual ~QGraphicsSceneIndex();
+
+ QGraphicsScene *scene() const;
+
+ virtual QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::AscendingOrder) const = 0;
+ virtual QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ virtual QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ virtual QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ virtual QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ virtual QList<QGraphicsItem *> estimateItems(const QPointF &point, Qt::SortOrder order) const;
+ virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const = 0;
+ virtual QList<QGraphicsItem *> estimateTopLevelItems(const QRectF &, Qt::SortOrder order) const;
+
+protected Q_SLOTS:
+ virtual void updateSceneRect(const QRectF &rect);
+
+protected:
+ virtual void clear();
+ virtual void addItem(QGraphicsItem *item) = 0;
+ virtual void removeItem(QGraphicsItem *item) = 0;
+ virtual void deleteItem(QGraphicsItem *item);
+
+ virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value);
+ virtual void prepareBoundingRectChange(const QGraphicsItem *item);
+
+ QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene);
+
+ friend class QGraphicsScene;
+ friend class QGraphicsScenePrivate;
+ friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
+ friend class QGraphicsSceneBspTreeIndex;
+private:
+ Q_DISABLE_COPY(QGraphicsSceneIndex)
+ Q_DECLARE_PRIVATE(QGraphicsSceneIndex)
+};
+
+class QGraphicsSceneIndexPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsSceneIndex)
+public:
+ QGraphicsSceneIndexPrivate(QGraphicsScene *scene);
+ ~QGraphicsSceneIndexPrivate();
+
+ void init();
+ static bool itemCollidesWithPath(const QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode);
+
+ void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
+ QGraphicsSceneIndexIntersector *intersector, QList<QGraphicsItem *> *items,
+ const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const;
+ inline void items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector,
+ QList<QGraphicsItem *> *items, const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order) const;
+
+ QGraphicsScene *scene;
+ QGraphicsSceneIndexPointIntersector *pointIntersector;
+ QGraphicsSceneIndexRectIntersector *rectIntersector;
+ QGraphicsSceneIndexPathIntersector *pathIntersector;
+};
+
+inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector,
+ QList<QGraphicsItem *> *items, const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order) const
+{
+ Q_Q(const QGraphicsSceneIndex);
+ const QList<QGraphicsItem *> tli = q->estimateTopLevelItems(rect, Qt::DescendingOrder);
+ for (int i = 0; i < tli.size(); ++i)
+ recursive_items_helper(tli.at(i), rect, intersector, items, viewTransform, mode, order);
+ if (order == Qt::AscendingOrder) {
+ const int n = items->size();
+ for (int i = 0; i < n / 2; ++i)
+ items->swap(i, n - i - 1);
+ }
+}
+
+class QGraphicsSceneIndexIntersector
+{
+public:
+ QGraphicsSceneIndexIntersector() { }
+ virtual ~QGraphicsSceneIndexIntersector() { }
+ virtual bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ const QTransform &deviceTransform) const = 0;
+};
+
+#endif // QT_NO_GRAPHICSVIEW
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGRAPHICSSCENEINDEX_H
diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp
new file mode 100644
index 0000000..132b1a6
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QGraphicsSceneLinearIndex
+ \brief The QGraphicsSceneLinearIndex class provides an implementation of
+ a linear indexing algorithm for discovering items in QGraphicsScene.
+ \since 4.6
+ \ingroup graphicsview-api
+ \internal
+
+ QGraphicsSceneLinearIndex index is default linear implementation to discover items.
+ It basically store all items in a list and return them to the scene.
+
+ \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex, QGraphicsSceneBspTreeIndex
+*/
+
+#include <private/qgraphicsscenelinearindex_p.h>
+
+/*!
+ \fn QGraphicsSceneLinearIndex::QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0):
+
+ Construct a linear index for the given \a scene.
+*/
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneLinearIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const;
+
+ Return all items in the index and sort them using \a order.
+*/
+
+
+/*!
+ \fn virtual QList<QGraphicsItem *> QGraphicsSceneLinearIndex::estimateItems(const QRectF &rect, Qt::SortOrder order) const
+
+ Returns an estimation visible items that are either inside or
+ intersect with the specified \a rect and return a list sorted using \a order.
+*/
+
+/*!
+ \fn void QGraphicsSceneLinearIndex::clear()
+ \internal
+ Clear the all the BSP index.
+*/
+
+/*!
+ \fn virtual void QGraphicsSceneLinearIndex::addItem(QGraphicsItem *item)
+
+ Add the \a item into the index.
+*/
+
+/*!
+ \fn virtual void QGraphicsSceneLinearIndex::removeItem(QGraphicsItem *item)
+
+ Add the \a item from the index.
+*/
+
diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h
new file mode 100644
index 0000000..6181bf0
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSSCENELINEARINDEX_H
+#define QGRAPHICSSCENELINEARINDEX_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
+
+#include <QtCore/qrect.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qgraphicsitem.h>
+#include <private/qgraphicssceneindex_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex
+{
+ Q_OBJECT
+
+public:
+ QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene)
+ { }
+
+ QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::AscendingOrder) const
+ { Q_UNUSED(order); return m_items; }
+
+ virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const
+ {
+ Q_UNUSED(rect);
+ Q_UNUSED(order);
+ return m_items;
+ }
+
+protected :
+ virtual void clear()
+ { m_items.clear(); }
+
+ virtual void addItem(QGraphicsItem *item)
+ { m_items << item; }
+
+ virtual void removeItem(QGraphicsItem *item)
+ { m_items.removeOne(item); }
+
+private:
+ QList<QGraphicsItem*> m_items;
+};
+
+#endif // QT_NO_GRAPHICSVIEW
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGRAPHICSSCENELINEARINDEX_H
diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp
new file mode 100644
index 0000000..c5653d7
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicstransform.cpp
@@ -0,0 +1,564 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QGraphicsTransform
+ \brief The QGraphicsTransform class is an abstract base class for building
+ advanced transformations on QGraphicsItems.
+ \since 4.6
+ \ingroup graphicsview-api
+
+ As an alternative to QGraphicsItem::transform, QGraphicsTransform lets you
+ create and control advanced transformations that can be configured
+ independently using specialized properties.
+
+ QGraphicsItem allows you to assign any number of QGraphicsTransform
+ instances to one QGraphicsItem. Each QGraphicsTransform is applied in
+ order, one at a time, to the QGraphicsItem it's assigned to.
+
+ QGraphicsTransform is particularily useful for animations. Whereas
+ QGraphicsItem::setTransform() lets you assign any transform directly to an
+ item, there is no direct way to interpolate between two different
+ transformations (e.g., when transitioning between two states, each for
+ which the item has a different arbitrary transform assigned). Using
+ QGraphicsTransform you can interpolate the property values of each
+ independent transformation. The resulting operation is then combined into a
+ single transform which is applied to QGraphicsItem.
+
+ Transformations are computed in true 3D space using QMatrix4x4.
+ When the transformation is applied to a QGraphicsItem, it will be
+ projected back to a 2D QTransform. When multiple QGraphicsTransform
+ objects are applied to a QGraphicsItem, all of the transformations
+ are computed in true 3D space, with the projection back to 2D
+ only occurring after the last QGraphicsTransform is applied.
+
+ If you want to create your own configurable transformation, you can create
+ a subclass of QGraphicsTransform (or any or the existing subclasses), and
+ reimplement the pure virtual applyTo() function, which takes a pointer to a
+ QMatrix4x4. Each operation you would like to apply should be exposed as
+ properties (e.g., customTransform->setVerticalShear(2.5)). Inside you
+ reimplementation of applyTo(), you can modify the provided transform
+ respectively.
+
+ QGraphicsTransform can be used together with QGraphicsItem::setTransform(),
+ QGraphicsItem::setRotation(), and QGraphicsItem::setScale().
+
+ \sa QGraphicsItem::transform(), QGraphicsScale, QGraphicsRotation
+*/
+
+#include "qgraphicstransform.h"
+#include "qgraphicsitem_p.h"
+#include "qgraphicstransform_p.h"
+#include <QDebug>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+void QGraphicsTransformPrivate::setItem(QGraphicsItem *i)
+{
+ if (item == i)
+ return;
+
+ if (item) {
+ Q_Q(QGraphicsTransform);
+ QGraphicsItemPrivate *d_ptr = item->d_ptr.data();
+
+ item->prepareGeometryChange();
+ Q_ASSERT(d_ptr->transformData);
+ d_ptr->transformData->graphicsTransforms.removeAll(q);
+ d_ptr->dirtySceneTransform = 1;
+ item = 0;
+ }
+
+ item = i;
+}
+
+void QGraphicsTransformPrivate::updateItem(QGraphicsItem *item)
+{
+ item->prepareGeometryChange();
+ item->d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ Constructs a new QGraphicsTransform with the given \a parent.
+*/
+QGraphicsTransform::QGraphicsTransform(QObject *parent)
+ : QObject(*new QGraphicsTransformPrivate, parent)
+{
+}
+
+/*!
+ Destroys the graphics transform.
+*/
+QGraphicsTransform::~QGraphicsTransform()
+{
+ Q_D(QGraphicsTransform);
+ d->setItem(0);
+}
+
+/*!
+ \internal
+*/
+QGraphicsTransform::QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent)
+ : QObject(p, parent)
+{
+}
+
+/*!
+ \fn void QGraphicsTransform::applyTo(QMatrix4x4 *matrix) const
+
+ This pure virtual method has to be reimplemented in derived classes.
+
+ It applies this transformation to \a matrix.
+
+ \sa QGraphicsItem::transform(), QMatrix4x4::toTransform()
+*/
+
+/*!
+ Notifies that this transform operation has changed its parameters in such a
+ way that applyTo() will return a different result than before.
+
+ When implementing you own custom graphics transform, you must call this
+ function every time you change a parameter, to let QGraphicsItem know that
+ its transformation needs to be updated.
+
+ \sa applyTo()
+*/
+void QGraphicsTransform::update()
+{
+ Q_D(QGraphicsTransform);
+ if (d->item)
+ d->updateItem(d->item);
+}
+
+/*!
+ \class QGraphicsScale
+ \brief The QGraphicsScale class provides a scale transformation.
+ \since 4.6
+
+ QGraphicsScene provides certain parameters to help control how the scale
+ should be applied.
+
+ The origin is the point that the item is scaled from (i.e., it stays fixed
+ relative to the parent as the rest of the item grows). By default the
+ origin is QPointF(0, 0).
+
+ The parameters xScale, yScale, and zScale describe the scale factors to
+ apply in horizontal, vertical, and depth directions. They can take on any
+ value, including 0 (to collapse the item to a point) or negative value.
+ A negative xScale value will mirror the item horizontally. A negative yScale
+ value will flip the item vertically. A negative zScale will flip the
+ item end for end.
+
+ \sa QGraphicsTransform, QGraphicsItem::setScale(), QTransform::scale()
+*/
+
+class QGraphicsScalePrivate : public QGraphicsTransformPrivate
+{
+public:
+ QGraphicsScalePrivate()
+ : xScale(1), yScale(1), zScale(1) {}
+ QVector3D origin;
+ qreal xScale;
+ qreal yScale;
+ qreal zScale;
+};
+
+/*!
+ Constructs an empty QGraphicsScale object with the given \a parent.
+*/
+QGraphicsScale::QGraphicsScale(QObject *parent)
+ : QGraphicsTransform(*new QGraphicsScalePrivate, parent)
+{
+}
+
+/*!
+ Destroys the graphics scale.
+*/
+QGraphicsScale::~QGraphicsScale()
+{
+}
+
+/*!
+ \property QGraphicsScale::origin
+ \brief the origin of the scale in 3D space.
+
+ All scaling will be done relative to this point (i.e., this point
+ will stay fixed, relative to the parent, when the item is scaled).
+
+ \sa xScale, yScale, zScale
+*/
+QVector3D QGraphicsScale::origin() const
+{
+ Q_D(const QGraphicsScale);
+ return d->origin;
+}
+void QGraphicsScale::setOrigin(const QVector3D &point)
+{
+ Q_D(QGraphicsScale);
+ if (d->origin == point)
+ return;
+ d->origin = point;
+ update();
+ emit originChanged();
+}
+
+/*!
+ \property QGraphicsScale::xScale
+ \brief the horizontal scale factor.
+
+ The scale factor can be any real number; the default value is 1.0. If you
+ set the factor to 0.0, the item will be collapsed to a single point. If you
+ provide a negative value, the item will be mirrored horizontally around its
+ origin.
+
+ \sa yScale, zScale, origin
+*/
+qreal QGraphicsScale::xScale() const
+{
+ Q_D(const QGraphicsScale);
+ return d->xScale;
+}
+void QGraphicsScale::setXScale(qreal scale)
+{
+ Q_D(QGraphicsScale);
+ if (d->xScale == scale)
+ return;
+ d->xScale = scale;
+ update();
+ emit scaleChanged();
+}
+
+/*!
+ \property QGraphicsScale::yScale
+ \brief the vertical scale factor.
+
+ The scale factor can be any real number; the default value is 1.0. If you
+ set the factor to 0.0, the item will be collapsed to a single point. If you
+ provide a negative value, the item will be flipped vertically around its
+ origin.
+
+ \sa xScale, zScale, origin
+*/
+qreal QGraphicsScale::yScale() const
+{
+ Q_D(const QGraphicsScale);
+ return d->yScale;
+}
+void QGraphicsScale::setYScale(qreal scale)
+{
+ Q_D(QGraphicsScale);
+ if (d->yScale == scale)
+ return;
+ d->yScale = scale;
+ update();
+ emit scaleChanged();
+}
+
+/*!
+ \property QGraphicsScale::zScale
+ \brief the depth scale factor.
+
+ The scale factor can be any real number; the default value is 1.0. If you
+ set the factor to 0.0, the item will be collapsed to a single point. If you
+ provide a negative value, the item will be flipped end for end around its
+ origin.
+
+ \sa xScale, yScale, origin
+*/
+qreal QGraphicsScale::zScale() const
+{
+ Q_D(const QGraphicsScale);
+ return d->zScale;
+}
+void QGraphicsScale::setZScale(qreal scale)
+{
+ Q_D(QGraphicsScale);
+ if (d->zScale == scale)
+ return;
+ d->zScale = scale;
+ update();
+ emit scaleChanged();
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsScale::applyTo(QMatrix4x4 *matrix) const
+{
+ Q_D(const QGraphicsScale);
+ matrix->translate(d->origin);
+ matrix->scale(d->xScale, d->yScale, d->zScale);
+ matrix->translate(-d->origin);
+}
+
+/*!
+ \fn QGraphicsScale::originChanged()
+
+ QGraphicsScale emits this signal when its origin changes.
+
+ \sa QGraphicsScale::origin
+*/
+
+/*!
+ \fn QGraphicsScale::scaleChanged()
+
+ This signal is emitted whenever the xScale, yScale, or zScale
+ of the object changes.
+
+ \sa QGraphicsScale::xScale, QGraphicsScale::yScale
+ \sa QGraphicsScale::zScale
+*/
+
+/*!
+ \class QGraphicsRotation
+ \brief The QGraphicsRotation class provides a rotation transformation around
+ a given axis.
+ \since 4.6
+
+ You can provide the desired axis by assigning a QVector3D to the axis property
+ or by passing a member if Qt::Axis to the setAxis convenience function.
+ By default the axis is (0, 0, 1) i.e., rotation around the Z axis.
+
+ The angle property, which is provided by QGraphicsRotation, now
+ describes the number of degrees to rotate around this axis.
+
+ QGraphicsRotation provides certain parameters to help control how the
+ rotation should be applied.
+
+ The origin is the point that the item is rotated around (i.e., it stays
+ fixed relative to the parent as the rest of the item is rotated). By
+ default the origin is QPointF(0, 0).
+
+ The angle property provides the number of degrees to rotate the item
+ clockwise around the origin. This value also be negative, indicating a
+ counter-clockwise rotation. For animation purposes it may also be useful to
+ provide rotation angles exceeding (-360, 360) degrees, for instance to
+ animate how an item rotates several times.
+
+ Note: the final rotation is the combined effect of a rotation in
+ 3D space followed by a projection back to 2D. If several rotations
+ are performed in succession, they will not behave as expected unless
+ they were all around the Z axis.
+
+ \sa QGraphicsTransform, QGraphicsItem::setRotation(), QTransform::rotate()
+*/
+
+class QGraphicsRotationPrivate : public QGraphicsTransformPrivate
+{
+public:
+ QGraphicsRotationPrivate()
+ : angle(0), axis(0, 0, 1) {}
+ QVector3D origin;
+ qreal angle;
+ QVector3D axis;
+};
+
+/*!
+ Constructs a new QGraphicsRotation with the given \a parent.
+*/
+QGraphicsRotation::QGraphicsRotation(QObject *parent)
+ : QGraphicsTransform(*new QGraphicsRotationPrivate, parent)
+{
+}
+
+/*!
+ Destroys the graphics rotation.
+*/
+QGraphicsRotation::~QGraphicsRotation()
+{
+}
+
+/*!
+ \property QGraphicsRotation::origin
+ \brief the origin of the rotation in 3D space.
+
+ All rotations will be done relative to this point (i.e., this point
+ will stay fixed, relative to the parent, when the item is rotated).
+
+ \sa angle
+*/
+QVector3D QGraphicsRotation::origin() const
+{
+ Q_D(const QGraphicsRotation);
+ return d->origin;
+}
+void QGraphicsRotation::setOrigin(const QVector3D &point)
+{
+ Q_D(QGraphicsRotation);
+ if (d->origin == point)
+ return;
+ d->origin = point;
+ update();
+ emit originChanged();
+}
+
+/*!
+ \property QGraphicsRotation::angle
+ \brief the angle for clockwise rotation, in degrees.
+
+ The angle can be any real number; the default value is 0.0. A value of 180
+ will rotate 180 degrees, clockwise. If you provide a negative number, the
+ item will be rotated counter-clockwise. Normally the rotation angle will be
+ in the range (-360, 360), but you can also provide numbers outside of this
+ range (e.g., a angle of 370 degrees gives the same result as 10 degrees).
+
+ \sa origin
+*/
+qreal QGraphicsRotation::angle() const
+{
+ Q_D(const QGraphicsRotation);
+ return d->angle;
+}
+void QGraphicsRotation::setAngle(qreal angle)
+{
+ Q_D(QGraphicsRotation);
+ if (d->angle == angle)
+ return;
+ d->angle = angle;
+ update();
+ emit angleChanged();
+}
+
+/*!
+ \fn QGraphicsRotation::originChanged()
+
+ This signal is emitted whenever the origin has changed.
+
+ \sa QGraphicsRotation::origin
+*/
+
+/*!
+ \fn void QGraphicsRotation::angleChanged()
+
+ This signal is emitted whenever the angle has changed.
+
+ \sa QGraphicsRotation::angle
+*/
+
+/*!
+ \property QGraphicsRotation::axis
+ \brief a rotation axis, specified by a vector in 3D space.
+
+ This can be any axis in 3D space. By default the axis is (0, 0, 1),
+ which is aligned with the Z axis. If you provide another axis,
+ QGraphicsRotation will provide a transformation that rotates
+ around this axis. For example, if you would like to rotate an item
+ around its X axis, you could pass (1, 0, 0) as the axis.
+
+ \sa QTransform, QGraphicsRotation::angle
+*/
+QVector3D QGraphicsRotation::axis() const
+{
+ Q_D(const QGraphicsRotation);
+ return d->axis;
+}
+void QGraphicsRotation::setAxis(const QVector3D &axis)
+{
+ Q_D(QGraphicsRotation);
+ if (d->axis == axis)
+ return;
+ d->axis = axis;
+ update();
+ emit axisChanged();
+}
+
+/*!
+ \fn void QGraphicsRotation::setAxis(Qt::Axis axis)
+
+ Convenience function to set the axis to \a axis.
+
+ Note: the Qt::YAxis rotation for QTransform is inverted from the
+ correct mathematical rotation in 3D space. The QGraphicsRotation
+ class implements a correct mathematical rotation. The following
+ two sequences of code will perform the same transformation:
+
+ \code
+ QTransform t;
+ t.rotate(45, Qt::YAxis);
+
+ QGraphicsRotation r;
+ r.setAxis(Qt::YAxis);
+ r.setAngle(-45);
+ \endcode
+*/
+void QGraphicsRotation::setAxis(Qt::Axis axis)
+{
+ switch (axis)
+ {
+ case Qt::XAxis:
+ setAxis(QVector3D(1, 0, 0));
+ break;
+ case Qt::YAxis:
+ setAxis(QVector3D(0, 1, 0));
+ break;
+ case Qt::ZAxis:
+ setAxis(QVector3D(0, 0, 1));
+ break;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const
+{
+ Q_D(const QGraphicsRotation);
+
+ if (d->angle == 0. || d->axis.isNull())
+ return;
+
+ matrix->translate(d->origin);
+ matrix->rotate(d->angle, d->axis.x(), d->axis.y(), d->axis.z());
+ matrix->translate(-d->origin);
+}
+
+/*!
+ \fn void QGraphicsRotation::axisChanged()
+
+ This signal is emitted whenever the axis of the object changes.
+
+ \sa QGraphicsRotation::axis
+*/
+
+#include "moc_qgraphicstransform.cpp"
+
+QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicstransform.h b/src/gui/graphicsview/qgraphicstransform.h
new file mode 100644
index 0000000..d6d5b79
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicstransform.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSTRANSFORM_H
+#define QGRAPHICSTRANSFORM_H
+
+#include <QtCore/QObject>
+#include <QtGui/QVector3D>
+#include <QtGui/QTransform>
+#include <QtGui/QMatrix4x4>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGraphicsItem;
+class QGraphicsTransformPrivate;
+
+class Q_GUI_EXPORT QGraphicsTransform : public QObject
+{
+ Q_OBJECT
+public:
+ QGraphicsTransform(QObject *parent = 0);
+ ~QGraphicsTransform();
+
+ virtual void applyTo(QMatrix4x4 *matrix) const = 0;
+
+protected Q_SLOTS:
+ void update();
+
+protected:
+ QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent);
+
+private:
+ friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
+ Q_DECLARE_PRIVATE(QGraphicsTransform)
+};
+
+class QGraphicsScalePrivate;
+
+class Q_GUI_EXPORT QGraphicsScale : public QGraphicsTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged)
+ Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY scaleChanged)
+ Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY scaleChanged)
+ Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY scaleChanged)
+public:
+ QGraphicsScale(QObject *parent = 0);
+ ~QGraphicsScale();
+
+ QVector3D origin() const;
+ void setOrigin(const QVector3D &point);
+
+ qreal xScale() const;
+ void setXScale(qreal);
+
+ qreal yScale() const;
+ void setYScale(qreal);
+
+ qreal zScale() const;
+ void setZScale(qreal);
+
+ void applyTo(QMatrix4x4 *matrix) const;
+
+Q_SIGNALS:
+ void originChanged();
+ void scaleChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsScale)
+};
+
+class QGraphicsRotationPrivate;
+
+class Q_GUI_EXPORT QGraphicsRotation : public QGraphicsTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
+ Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged)
+public:
+ QGraphicsRotation(QObject *parent = 0);
+ ~QGraphicsRotation();
+
+ QVector3D origin() const;
+ void setOrigin(const QVector3D &point);
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ QVector3D axis() const;
+ void setAxis(const QVector3D &axis);
+ void setAxis(Qt::Axis axis);
+
+ void applyTo(QMatrix4x4 *matrix) const;
+
+Q_SIGNALS:
+ void originChanged();
+ void angleChanged();
+ void axisChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsRotation)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXTRANSFORM_H
diff --git a/src/gui/graphicsview/qgraphicstransform_p.h b/src/gui/graphicsview/qgraphicstransform_p.h
new file mode 100644
index 0000000..c9b95fd
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicstransform_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSTRANSFORM_P_H
+#define QGRAPHICSTRANSFORM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsItem;
+
+class QGraphicsTransformPrivate : public QObjectPrivate {
+public:
+ Q_DECLARE_PUBLIC(QGraphicsTransform)
+
+ QGraphicsTransformPrivate()
+ : QObjectPrivate(), item(0) {}
+
+ QGraphicsItem *item;
+
+ void setItem(QGraphicsItem *item);
+ static void updateItem(QGraphicsItem *item);
+};
+
+QT_END_NAMESPACE
+
+#endif // QGRAPHICSTRANSFORM_P_H
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index a12eb30..236106b 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -39,8 +39,6 @@
**
****************************************************************************/
-//#define QGRAPHICSVIEW_DEBUG
-
static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50;
static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < 2^9
@@ -50,9 +48,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
\brief The QGraphicsView class provides a widget for displaying the
contents of a QGraphicsScene.
\since 4.2
- \ingroup multimedia
\ingroup graphicsview-api
- \mainclass
+
QGraphicsView visualizes the contents of a QGraphicsScene in a scrollable
viewport. To create a scene with geometrical items, see QGraphicsScene's
@@ -99,8 +96,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport
widget.
- QGraphicsView supports affine transformations, using QMatrix. You can
- either pass a matrix to setMatrix(), or you can call one of the
+ QGraphicsView supports affine transformations, using QTransform. You can
+ either pass a matrix to setTransform(), or you can call one of the
convenience functions rotate(), scale(), translate() or shear(). The most
two common transformations are scaling, which is used to implement
zooming, and rotation. QGraphicsView keeps the center of the view fixed
@@ -200,16 +197,7 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
Note that setting a flag usually imposes a side effect, and this effect
can vary between paint devices and platforms.
- \value DontClipPainter QGraphicsView sometimes clips the painter when
- rendering the scene contents. This can generally improve performance
- (e.g., rendering only small parts of a large pixmap), and protects against
- rendering mistakes (e.g., drawing outside bounding rectangles, or outside
- the exposed area). In some situations, however, the painter clip can slow
- down rendering; especially when all painting is restricted to inside
- exposed areas. By enabling this flag, QGraphicsView will completely
- disable its implicit clipping. Note that rendering artifacts from using a
- semi-transparent foreground or background brush can occur if clipping is
- disabled.
+ \value DontClipPainter This value is obsolete and has no effect.
\value DontSavePainterState When rendering, QGraphicsView protects the
painter state (see QPainter::save()) when rendering the background or
@@ -228,6 +216,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
minimizing the areas that require redrawing, which improves performance. A
common side effect is that items that do draw with antialiasing can leave
painting traces behind on the scene as they are moved.
+
+ \omitvalue IndirectPainting
*/
/*!
@@ -289,12 +279,17 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
#include <QtGui/qpainter.h>
#include <QtGui/qscrollbar.h>
#include <QtGui/qstyleoption.h>
+#include <QtGui/qinputcontext.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
#endif
+#include <private/qevent_p.h>
+
QT_BEGIN_NAMESPACE
+bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
+
inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for single precision
{
if (d <= (qreal) INT_MIN)
@@ -304,6 +299,23 @@ inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for sing
return d >= 0.0 ? int(d + 0.5) : int(d - int(d-1) + 0.5) + int(d-1);
}
+void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent)
+{
+ QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
+ for (int i = 0; i < touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
+ // the scene will set the item local pos, startPos, lastPos, and rect before delivering to
+ // an item, but for now those functions are returning the view's local coordinates
+ touchPoint.setSceneRect(d->mapToScene(touchPoint.rect()));
+ touchPoint.setStartScenePos(d->mapToScene(touchPoint.startPos()));
+ touchPoint.setLastScenePos(d->mapToScene(touchPoint.lastPos()));
+
+ // screenPos, startScreenPos, lastScreenPos, and screenRect are already set
+ }
+
+ touchEvent->setTouchPoints(touchPoints);
+}
+
/*!
\internal
*/
@@ -338,8 +350,6 @@ QGraphicsViewPrivate::QGraphicsViewPrivate()
#endif
lastDragDropEvent(0),
fullUpdatePending(true),
- dirtyRectCount(0),
- updatingLater(false),
updateSceneSlotReimplementedChecked(false)
{
styleOptions.reserve(QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS);
@@ -400,7 +410,7 @@ void QGraphicsViewPrivate::recalculateContentSize()
int left = q_round_bound(viewRect.left());
int right = q_round_bound(viewRect.right() - width);
if (left >= right) {
- q->horizontalScrollBar()->setRange(0, 0);
+ hbar->setRange(0, 0);
switch (alignment & Qt::AlignHorizontal_Mask) {
case Qt::AlignLeft:
@@ -415,9 +425,9 @@ void QGraphicsViewPrivate::recalculateContentSize()
break;
}
} else {
- q->horizontalScrollBar()->setRange(left, right);
- q->horizontalScrollBar()->setPageStep(width);
- q->horizontalScrollBar()->setSingleStep(width / 20);
+ hbar->setRange(left, right);
+ hbar->setPageStep(width);
+ hbar->setSingleStep(width / 20);
leftIndent = 0;
}
@@ -426,7 +436,7 @@ void QGraphicsViewPrivate::recalculateContentSize()
int top = q_round_bound(viewRect.top());
int bottom = q_round_bound(viewRect.bottom() - height);
if (top >= bottom) {
- q->verticalScrollBar()->setRange(0, 0);
+ vbar->setRange(0, 0);
switch (alignment & Qt::AlignVertical_Mask) {
case Qt::AlignTop:
@@ -441,9 +451,9 @@ void QGraphicsViewPrivate::recalculateContentSize()
break;
}
} else {
- q->verticalScrollBar()->setRange(top, bottom);
- q->verticalScrollBar()->setPageStep(height);
- q->verticalScrollBar()->setSingleStep(height / 20);
+ vbar->setRange(top, bottom);
+ vbar->setPageStep(height);
+ vbar->setSingleStep(height / 20);
topIndent = 0;
}
@@ -455,7 +465,7 @@ void QGraphicsViewPrivate::recalculateContentSize()
// scroll instead.
if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) {
dirtyScroll = true;
- q->viewport()->update();
+ updateAll();
} else if (q->isRightToLeft() && !leftIndent) {
// In reverse mode, the horizontal scroll always changes after the content
// size has changed, as the scroll is calculated by summing the min and
@@ -481,9 +491,9 @@ void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor)
if (q->underMouse()) {
// Last scene pos: lastMouseMoveScenePoint
// Current mouse pos:
- QPointF transformationDiff = q->mapToScene(q->viewport()->rect().center())
- - q->mapToScene(q->mapFromGlobal(QCursor::pos()));
- q->centerOn(lastMouseMoveScenePoint + transformationDiff);;
+ QPointF transformationDiff = q->mapToScene(viewport->rect().center())
+ - q->mapToScene(viewport->mapFromGlobal(QCursor::pos()));
+ q->centerOn(lastMouseMoveScenePoint + transformationDiff);
} else {
q->centerOn(lastCenterPoint);
}
@@ -503,7 +513,7 @@ void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor)
void QGraphicsViewPrivate::updateLastCenterPoint()
{
Q_Q(QGraphicsView);
- lastCenterPoint = q->mapToScene(q->viewport()->rect().center());
+ lastCenterPoint = q->mapToScene(viewport->rect().center());
}
/*!
@@ -541,15 +551,15 @@ void QGraphicsViewPrivate::updateScroll()
scrollX = qint64(-leftIndent);
if (q->isRightToLeft()) {
if (!leftIndent) {
- scrollX += q->horizontalScrollBar()->minimum();
- scrollX += q->horizontalScrollBar()->maximum();
- scrollX -= q->horizontalScrollBar()->value();
+ scrollX += hbar->minimum();
+ scrollX += hbar->maximum();
+ scrollX -= hbar->value();
}
} else {
- scrollX += q->horizontalScrollBar()->value();
+ scrollX += hbar->value();
}
- scrollY = qint64(q->verticalScrollBar()->value() - topIndent);
+ scrollY = qint64(vbar->value() - topIndent);
dirtyScroll = false;
}
@@ -589,7 +599,7 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
return;
QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
- mouseEvent.setWidget(q->viewport());
+ mouseEvent.setWidget(viewport);
mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint);
mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint);
mouseEvent.setScenePos(q->mapToScene(event->pos()));
@@ -602,7 +612,10 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
lastMouseMoveScenePoint = mouseEvent.scenePos();
lastMouseMoveScreenPoint = mouseEvent.screenPos();
mouseEvent.setAccepted(false);
- QApplication::sendEvent(scene, &mouseEvent);
+ if (event->spontaneous())
+ qt_sendSpontaneousEvent(scene, &mouseEvent);
+ else
+ QApplication::sendEvent(scene, &mouseEvent);
// Remember whether the last event was accepted or not.
lastMouseEvent.setAccepted(mouseEvent.isAccepted());
@@ -614,6 +627,16 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
}
#ifndef QT_NO_CURSOR
+ // If all the items ignore hover events, we don't look-up any items
+ // in QGraphicsScenePrivate::dispatchHoverEvent, hence the
+ // cachedItemsUnderMouse list will be empty. We therefore do the look-up
+ // for cursor items here if not all items use the default cursor.
+ if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor
+ && scene->d_func()->cachedItemsUnderMouse.isEmpty()) {
+ scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(),
+ mouseEvent.scenePos(),
+ mouseEvent.widget());
+ }
// Find the topmost item under the mouse with a cursor.
foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) {
if (item->hasCursor()) {
@@ -626,7 +649,7 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
if (hasStoredOriginalCursor) {
// Restore the original viewport cursor.
hasStoredOriginalCursor = false;
- q->viewport()->setCursor(originalCursor);
+ viewport->setCursor(originalCursor);
}
#endif
}
@@ -658,8 +681,6 @@ QRegion QGraphicsViewPrivate::rubberBandRegion(const QWidget *widget, const QRec
#ifndef QT_NO_CURSOR
void QGraphicsViewPrivate::_q_setViewportCursor(const QCursor &cursor)
{
- Q_Q(QGraphicsView);
- QWidget *viewport = q->viewport();
if (!hasStoredOriginalCursor) {
hasStoredOriginalCursor = true;
originalCursor = viewport->cursor();
@@ -685,9 +706,9 @@ void QGraphicsViewPrivate::_q_unsetViewportCursor()
// Restore the original viewport cursor.
hasStoredOriginalCursor = false;
if (dragMode == QGraphicsView::ScrollHandDrag)
- q->viewport()->setCursor(Qt::OpenHandCursor);
+ viewport->setCursor(Qt::OpenHandCursor);
else
- q->viewport()->setCursor(originalCursor);
+ viewport->setCursor(originalCursor);
}
#endif
@@ -726,7 +747,7 @@ void QGraphicsViewPrivate::populateSceneDragDropEvent(QGraphicsSceneDragDropEven
dest->setProposedAction(source->proposedAction());
dest->setDropAction(source->dropAction());
dest->setMimeData(source->mimeData());
- dest->setWidget(q->viewport());
+ dest->setWidget(viewport);
dest->setSource(source->source());
#else
Q_UNUSED(dest)
@@ -749,12 +770,13 @@ QRect QGraphicsViewPrivate::mapToViewRect(const QGraphicsItem *item, const QRect
}
// Translate-only
+ // COMBINE
QPointF offset;
const QGraphicsItem *parentItem = item;
const QGraphicsItemPrivate *itemd;
do {
- itemd = parentItem->d_ptr;
- if (itemd->hasTransform)
+ itemd = parentItem->d_ptr.data();
+ if (itemd->transformData)
break;
offset += itemd->pos;
} while ((parentItem = itemd->parent));
@@ -786,241 +808,120 @@ QRegion QGraphicsViewPrivate::mapToViewRegion(const QGraphicsItem *item, const Q
const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
// Accurate bounding region
- QTransform itv = item->sceneTransform() * q->viewportTransform();
+ QTransform itv = item->deviceTransform(q->viewportTransform());
return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect();
}
-// QRectF::intersects() returns false always if either the source or target
-// rectangle's width or height are 0. This works around that problem.
-static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
-{
- Q_ASSERT(item);
- QRectF boundingRect(item->boundingRect());
- if (!boundingRect.width())
- boundingRect.adjust(-0.00001, 0, 0.00001, 0);
- if (!boundingRect.height())
- boundingRect.adjust(0, -0.00001, 0, 0.00001);
- return boundingRect;
-}
-
/*!
\internal
*/
-void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect)
-{
- if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate)
- return;
- if (item->d_ptr->dirty)
- updateLater();
-
- QRectF updateRect = rect;
- if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) {
- updateRect &= adjustedItemBoundingRect(item);
- if (updateRect.isEmpty())
- return;
- }
-
- QGraphicsItem *clipItem = item;
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
- // Minimize unnecessary redraw.
- QGraphicsItem *parent = item;
- while ((parent = parent->d_ptr->parent)) {
- if (parent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) {
- // Map update rect to the current parent and itersect with its bounding rect.
- updateRect = clipItem->itemTransform(parent).mapRect(updateRect)
- & adjustedItemBoundingRect(parent);
- if (updateRect.isEmpty())
- return;
- clipItem = parent;
- }
-
- if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
- break;
- }
- }
-
- // Map update rect from clipItem coordinates to view coordinates.
- Q_ASSERT(clipItem);
- if (!item->d_ptr->hasBoundingRegionGranularity)
- this->updateRect(mapToViewRect(clipItem, updateRect) & viewport->rect());
- else
- updateRegion(mapToViewRegion(clipItem, updateRect) & viewport->rect());
-}
-
-void QGraphicsViewPrivate::updateLater()
-{
- Q_Q(QGraphicsView);
- if (updatingLater)
- return;
- updatingLater = true;
- QMetaObject::invokeMethod(q, "_q_updateLaterSlot", Qt::QueuedConnection);
-}
-
-void QGraphicsViewPrivate::_q_updateLaterSlot()
+void QGraphicsViewPrivate::processPendingUpdates()
{
- Q_Q(QGraphicsView);
if (!scene)
return;
- QRect vr = viewport->rect();
- QTransform viewTransform = q->viewportTransform();
- const QList<QGraphicsItem *> &dirtyItems = scene->d_func()->dirtyItems;
- for (int i = 0; i < dirtyItems.size(); ++i) {
- const QGraphicsItem *item = dirtyItems.at(i);
- if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/false,
- /*ignoreVisibleBit=*/false,
- /*ignoreDirtyBit=*/true)) {
- continue;
- }
- QTransform x = item->sceneTransform() * viewTransform;
- updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr);
- }
-
- dirtyRectCount += dirtyRects.size();
-
- bool noUpdate = !fullUpdatePending && viewportUpdateMode == QGraphicsView::FullViewportUpdate;
- if ((dirtyRectCount > 0 || !dirtyBoundingRect.isEmpty()) && !fullUpdatePending && !noUpdate) {
- if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate
- || (viewportUpdateMode == QGraphicsView::SmartViewportUpdate
- && dirtyRectCount >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD)) {
- if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) {
- viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
- } else {
- viewport->update(dirtyBoundingRect);
- }
- } else {
- // ### Improve this block, which is very slow for complex regions. We
- // need to strike the balance between having an accurate update
- // region, and running fast. The below approach is the simplest way to
- // create a region from a bunch of rects, but we might want to use
- // other approaches; e.g., a grid of a fixed size representing
- // quadrants of the viewport, which we mark as dirty depending on the
- // rectangles in the list. Perhaps this should go into a
- // QRegion::fromRects(rects, how) function.
- QRegion region;
- if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) {
- for (int i = 0; i < dirtyRegions.size(); ++i) {
- QVector<QRect> rects = dirtyRegions.at(i).rects();
- for (int j = 0; j < rects.size(); ++j)
- region += rects.at(j).adjusted(-2, -2, 2, 2);
- }
- for (int i = 0; i < dirtyRects.size(); ++i)
- region += dirtyRects.at(i).adjusted(-2, -2, 2, 2);
- } else {
- for (int i = 0; i < dirtyRegions.size(); ++i)
- region += dirtyRegions.at(i);
- for (int i = 0; i < dirtyRects.size(); ++i)
- region += dirtyRects.at(i);
- }
-
- viewport->update(region);
- }
+ if (fullUpdatePending) {
+ viewport->update();
+ } else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
+ if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
+ viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1));
+ else
+ viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
+ } else {
+ viewport->update(dirtyRegion); // Already adjusted in updateRect/Region.
}
- dirtyRegions.clear();
- dirtyRects.clear();
- dirtyRectCount = 0;
dirtyBoundingRect = QRect();
- updatingLater = false;
+ dirtyRegion = QRegion();
}
-void QGraphicsViewPrivate::updateAll()
+static inline bool intersectsViewport(const QRect &r, int width, int height)
+{ return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); }
+
+static inline bool containsViewport(const QRect &r, int width, int height)
+{ return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; }
+
+static inline void QRect_unite(QRect *rect, const QRect &other)
{
- Q_Q(QGraphicsView);
- q->viewport()->update();
- fullUpdatePending = true;
- dirtyRectCount = 0;
- dirtyBoundingRect = QRect();
- updatingLater = false;
+ if (rect->isEmpty()) {
+ *rect = other;
+ } else {
+ rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()),
+ qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom()));
+ }
}
-void QGraphicsViewPrivate::updateRegion(const QRegion &r)
+bool QGraphicsViewPrivate::updateRegion(const QRegion &r)
{
- if (r.isEmpty())
- return;
+ if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty())
+ return false;
- Q_Q(QGraphicsView);
+ const QRect boundingRect = r.boundingRect();
+ if (!intersectsViewport(boundingRect, viewport->width(), viewport->height()))
+ return false; // Update region outside viewport.
- // Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
- q->viewport()->update();
+ viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
- dirtyBoundingRect |= r.boundingRect();
- if (dirtyBoundingRect == q->viewport()->rect()) {
+ QRect_unite(&dirtyBoundingRect, boundingRect);
+ if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
fullUpdatePending = true;
- q->viewport()->update();
- } else {
- updateLater();
+ viewport->update();
}
break;
- case QGraphicsView::SmartViewportUpdate:
- dirtyBoundingRect |= r.boundingRect();
- if ((dirtyRectCount + r.numRects()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD)
- dirtyRegions << r;
- dirtyRectCount += r.numRects();
- updateLater();
- break;
+ case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
case QGraphicsView::MinimalViewportUpdate:
- dirtyRegions << r;
- dirtyRectCount += r.numRects();
- updateLater();
+ {
+ const QVector<QRect> &rects = r.rects();
+ for (int i = 0; i < rects.size(); ++i) {
+ if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
+ dirtyRegion += rects.at(i).adjusted(-1, -1, 1, 1);
+ else
+ dirtyRegion += rects.at(i).adjusted(-2, -2, 2, 2);
+ }
break;
- case QGraphicsView::NoViewportUpdate:
- // Unreachable
+ }
+ default:
break;
}
- // Compress the regions...
- if (dirtyRectCount > QGRAPHICSVIEW_REGION_RECT_THRESHOLD && dirtyRegions.size() > 1) {
- QRegion masterRegion;
- for (int i=0; i<dirtyRegions.size(); ++i) {
- masterRegion |= dirtyRegions.at(i);
- }
- dirtyRectCount = masterRegion.numRects();
- dirtyRegions.clear();
- dirtyRegions << masterRegion;
- }
+ return true;
}
-void QGraphicsViewPrivate::updateRect(const QRect &r)
+bool QGraphicsViewPrivate::updateRect(const QRect &r)
{
- if (r.isEmpty())
- return;
-
- Q_Q(QGraphicsView);
+ if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
+ || !intersectsViewport(r, viewport->width(), viewport->height())) {
+ return false;
+ }
- // Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
- q->viewport()->update();
+ viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
- dirtyBoundingRect |= r;
- if (dirtyBoundingRect == q->viewport()->rect()) {
+ QRect_unite(&dirtyBoundingRect, r);
+ if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
fullUpdatePending = true;
- q->viewport()->update();
- } else {
- updateLater();
+ viewport->update();
}
break;
- case QGraphicsView::SmartViewportUpdate:
- dirtyBoundingRect |= r;
- if ((dirtyRectCount + dirtyRects.size()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD)
- dirtyRects << r;
- updateLater();
- break;
+ case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
case QGraphicsView::MinimalViewportUpdate:
- dirtyRects << r;
- updateLater();
+ if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
+ dirtyRegion += r.adjusted(-1, -1, 1, 1);
+ else
+ dirtyRegion += r.adjusted(-2, -2, 2, 2);
break;
- case QGraphicsView::NoViewportUpdate:
- // Unreachable
+ default:
break;
}
+
+ return true;
}
QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(int numItems)
@@ -1055,47 +956,32 @@ extern QPainterPath qt_regionToPath(const QRegion &region);
is at risk of painting 1 pixel outside the bounding rect. Therefore we
must search for items with an adjustment of (-1, -1, 1, 1).
*/
-QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const
+QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems,
+ const QTransform &viewTransform) const
{
Q_Q(const QGraphicsView);
// Step 1) If all items are contained within the expose region, then
- // return a list of all visible items.
- const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 2, 2))
+ // return a list of all visible items. ### the scene's growing bounding
+ // rect does not take into account untransformable items.
+ const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1))
.boundingRect();
- if (exposedRegionSceneBounds.contains(scene->d_func()->growingItemsBoundingRect)) {
+ if (exposedRegionSceneBounds.contains(scene->sceneRect())) {
Q_ASSERT(allItems);
*allItems = true;
- // All items are guaranteed within the exposed region, don't bother using the index.
- QList<QGraphicsItem *> itemList(scene->items());
- int i = 0;
- while (i < itemList.size()) {
- const QGraphicsItem *item = itemList.at(i);
- // But we only want to include items that are visible
- // The following check is basically the same as item->d_ptr->isInvisible(), except
- // that we don't check whether the item clips children to shape or propagates its
- // opacity (we loop through all items, so those checks are wrong in this context).
- if (!item->isVisible() || item->d_ptr->isClippedAway() || item->d_ptr->isFullyTransparent())
- itemList.removeAt(i);
- else
- ++i;
- }
-
- // Sort the items.
- QGraphicsScenePrivate::sortItems(&itemList, Qt::DescendingOrder, scene->d_func()->sortCacheEnabled);
- return itemList;
+ // All items are guaranteed within the exposed region.
+ return scene->items(Qt::DescendingOrder);
}
// Step 2) If the expose region is a simple rect and the view is only
// translated or scaled, search for items using
// QGraphicsScene::items(QRectF).
- bool simpleRectLookup = (scene->d_func()->largestUntransformableItem.isNull()
- && exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale);
+ bool simpleRectLookup = exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale;
if (simpleRectLookup) {
- return scene->d_func()->items_helper(exposedRegionSceneBounds,
- Qt::IntersectsItemBoundingRect,
- Qt::DescendingOrder);
+ return scene->items(exposedRegionSceneBounds,
+ Qt::IntersectsItemBoundingRect,
+ Qt::DescendingOrder, viewTransform);
}
// If the region is complex or the view has a complex transform, adjust
@@ -1105,79 +991,25 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg
foreach (const QRect &r, exposedRegion.rects())
adjustedRegion += r.adjusted(-1, -1, 1, 1);
- const QPainterPath exposedPath(qt_regionToPath(adjustedRegion));
- if (scene->d_func()->largestUntransformableItem.isNull()) {
- const QPainterPath exposedScenePath(q->mapToScene(exposedPath));
- return scene->d_func()->items_helper(exposedScenePath,
- Qt::IntersectsItemBoundingRect,
- Qt::DescendingOrder);
- }
-
- // NB! Path must be in viewport coordinates.
- return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder);
-}
-
-void QGraphicsViewPrivate::generateStyleOptions(const QList<QGraphicsItem *> &itemList,
- QGraphicsItem **itemArray,
- QStyleOptionGraphicsItem *styleOptionArray,
- const QTransform &worldTransform,
- bool allItems,
- const QRegion &exposedRegion) const
-{
- // Two unit vectors.
- QLineF v1(0, 0, 1, 0);
- QLineF v2(0, 0, 0, 1);
- QTransform itemToViewportTransform;
- QRectF brect;
- QTransform reverseMap;
-
- for (int i = 0; i < itemList.size(); ++i) {
- QGraphicsItem *item = itemArray[i] = itemList[i];
-
- QStyleOptionGraphicsItem &option = styleOptionArray[i];
- brect = item->boundingRect();
- option.state = QStyle::State_None;
- option.rect = brect.toRect();
- option.exposedRect = QRectF();
- if (item->d_ptr->selected)
- option.state |= QStyle::State_Selected;
- if (item->d_ptr->enabled)
- option.state |= QStyle::State_Enabled;
- if (item->hasFocus())
- option.state |= QStyle::State_HasFocus;
- if (scene->d_func()->hoverItems.contains(item))
- option.state |= QStyle::State_MouseOver;
- if (item == scene->mouseGrabberItem())
- option.state |= QStyle::State_Sunken;
-
- // Calculate a simple level-of-detail metric.
- // ### almost identical code in QGraphicsScene::render()
- // and QGraphicsView::render() - consider refactoring
- itemToViewportTransform = item->deviceTransform(worldTransform);
-
- if (itemToViewportTransform.type() <= QTransform::TxTranslate) {
- // Translation and rotation only? The LOD is 1.
- option.levelOfDetail = 1;
- } else {
- // LOD is the transformed area of a 1x1 rectangle.
- option.levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length());
- }
- option.matrix = itemToViewportTransform.toAffine(); //### discards perspective
-
- if (!allItems) {
- // Determine the item's exposed area
- reverseMap = itemToViewportTransform.inverted();
- foreach (const QRect &rect, exposedRegion.rects()) {
- option.exposedRect |= reverseMap.mapRect(QRectF(rect.adjusted(-1, -1, 1, 1)));
- if (option.exposedRect.contains(brect))
- break;
- }
- option.exposedRect &= brect;
- } else {
- // The whole item is exposed
- option.exposedRect = brect;
- }
- }
+ const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion)));
+ return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect,
+ Qt::DescendingOrder, viewTransform);
+}
+
+/*!
+ \internal
+
+ Enables input methods for the view if and only if the current focus item of
+ the scene accepts input methods. Call function whenever that condition has
+ potentially changed.
+*/
+void QGraphicsViewPrivate::updateInputMethodSensitivity()
+{
+ Q_Q(QGraphicsView);
+ bool enabled = scene && scene->focusItem()
+ && (scene->focusItem()->flags() & QGraphicsItem::ItemAcceptsInputMethod);
+ q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
+ q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled);
}
/*!
@@ -1189,12 +1021,9 @@ QGraphicsView::QGraphicsView(QWidget *parent)
setViewport(0);
setAcceptDrops(true);
setBackgroundRole(QPalette::Base);
-
- // ### Ideally this would be enabled/disabled depending on whether any
- // widgets in the current scene enabled input methods. We could do that
- // using a simple reference count. The same goes for acceptDrops and mouse
- // tracking.
+ // Investigate leaving these disabled by default.
setAttribute(Qt::WA_InputMethodEnabled);
+ viewport()->setAttribute(Qt::WA_InputMethodEnabled);
}
/*!
@@ -1208,7 +1037,9 @@ QGraphicsView::QGraphicsView(QGraphicsScene *scene, QWidget *parent)
setViewport(0);
setAcceptDrops(true);
setBackgroundRole(QPalette::Base);
+ // Investigate leaving these disabled by default.
setAttribute(Qt::WA_InputMethodEnabled);
+ viewport()->setAttribute(Qt::WA_InputMethodEnabled);
}
/*!
@@ -1220,7 +1051,9 @@ QGraphicsView::QGraphicsView(QGraphicsViewPrivate &dd, QWidget *parent)
setViewport(0);
setAcceptDrops(true);
setBackgroundRole(QPalette::Base);
+ // Investigate leaving these disabled by default.
setAttribute(Qt::WA_InputMethodEnabled);
+ viewport()->setAttribute(Qt::WA_InputMethodEnabled);
}
/*!
@@ -1274,7 +1107,7 @@ void QGraphicsView::setRenderHints(QPainter::RenderHints hints)
if (hints == d->renderHints)
return;
d->renderHints = hints;
- viewport()->update();
+ d->updateAll();
}
/*!
@@ -1292,7 +1125,7 @@ void QGraphicsView::setRenderHint(QPainter::RenderHint hint, bool enabled)
else
d->renderHints &= ~hint;
if (oldHints != d->renderHints)
- viewport()->update();
+ d->updateAll();
}
/*!
@@ -1579,7 +1412,7 @@ void QGraphicsView::resetCachedContent()
if (d->cacheMode & CacheBackground) {
// Background caching is enabled.
d->mustResizeBackgroundPixmap = true;
- viewport()->update();
+ d->updateAll();
} else if (d->mustResizeBackgroundPixmap) {
// Background caching is disabled.
// Cleanup, free some resources.
@@ -1668,7 +1501,7 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
return;
// Always update the viewport when the scene changes.
- viewport()->update();
+ d->updateAll();
// Remove the previously assigned scene.
if (d->scene) {
@@ -1676,7 +1509,7 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
this, SLOT(updateScene(QList<QRectF>)));
disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
this, SLOT(updateSceneRect(QRectF)));
- d->scene->d_func()->views.removeAll(this);
+ d->scene->d_func()->removeView(this);
d->connectedToScene = false;
}
@@ -1685,13 +1518,25 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
connect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
this, SLOT(updateSceneRect(QRectF)));
d->updateSceneSlotReimplementedChecked = false;
- d->scene->d_func()->views << this;
+ d->scene->d_func()->addView(this);
d->recalculateContentSize();
d->lastCenterPoint = sceneRect().center();
d->keepLastCenterPoint = true;
+ // We are only interested in mouse tracking if items accept
+ // hover events or use non-default cursors.
+ if (!d->scene->d_func()->allItemsIgnoreHoverEvents
+ || !d->scene->d_func()->allItemsUseDefaultCursor) {
+ d->viewport->setMouseTracking(true);
+ }
+
+ // enable touch events if any items is interested in them
+ if (!d->scene->d_func()->allItemsIgnoreTouchEvents)
+ d->viewport->setAttribute(Qt::WA_AcceptTouchEvents);
} else {
d->recalculateContentSize();
}
+
+ d->updateInputMethodSensitivity();
}
/*!
@@ -1738,7 +1583,7 @@ void QGraphicsView::setSceneRect(const QRectF &rect)
Returns the current transformation matrix for the view. If no current
transformation is set, the identity matrix is returned.
- \sa setMatrix(), rotate(), scale(), shear(), translate()
+ \sa setMatrix(), transform(), rotate(), scale(), shear(), translate()
*/
QMatrix QGraphicsView::matrix() const
{
@@ -1770,7 +1615,7 @@ QMatrix QGraphicsView::matrix() const
a view coordinate to a floating point scene coordinate, or mapFromScene()
to map from floating point scene coordinates to view coordinates.
- \sa matrix(), rotate(), scale(), shear(), translate()
+ \sa matrix(), setTransform(), rotate(), scale(), shear(), translate()
*/
void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine)
{
@@ -1779,6 +1624,8 @@ void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine)
/*!
Resets the view transformation matrix to the identity matrix.
+
+ \sa resetTransform()
*/
void QGraphicsView::resetMatrix()
{
@@ -1788,7 +1635,7 @@ void QGraphicsView::resetMatrix()
/*!
Rotates the current view transformation \a angle degrees clockwise.
- \sa setMatrix(), matrix(), scale(), shear(), translate()
+ \sa setTransform(), transform(), scale(), shear(), translate()
*/
void QGraphicsView::rotate(qreal angle)
{
@@ -1801,7 +1648,7 @@ void QGraphicsView::rotate(qreal angle)
/*!
Scales the current view transformation by (\a sx, \a sy).
- \sa setMatrix(), matrix(), rotate(), shear(), translate()
+ \sa setTransform(), transform(), rotate(), shear(), translate()
*/
void QGraphicsView::scale(qreal sx, qreal sy)
{
@@ -1814,7 +1661,7 @@ void QGraphicsView::scale(qreal sx, qreal sy)
/*!
Shears the current view transformation by (\a sh, \a sv).
- \sa setMatrix(), matrix(), rotate(), scale(), translate()
+ \sa setTransform(), transform(), rotate(), scale(), translate()
*/
void QGraphicsView::shear(qreal sh, qreal sv)
{
@@ -1827,7 +1674,7 @@ void QGraphicsView::shear(qreal sh, qreal sv)
/*!
Translates the current view transformation by (\a dx, \a dy).
- \sa setMatrix(), matrix(), rotate(), shear()
+ \sa setTransform(), transform(), rotate(), shear()
*/
void QGraphicsView::translate(qreal dx, qreal dy)
{
@@ -1985,7 +1832,7 @@ void QGraphicsView::ensureVisible(const QGraphicsItem *item, int xmargin, int ym
If \a rect is empty, or if the viewport is too small, this
function will do nothing.
- \sa setMatrix(), ensureVisible(), centerOn()
+ \sa setTransform(), ensureVisible(), centerOn()
*/
void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
{
@@ -2050,7 +1897,12 @@ void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRati
void QGraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRatioMode)
{
QPainterPath path = item->isClipped() ? item->clipPath() : item->shape();
- fitInView(item->sceneTransform().map(path).boundingRect(), aspectRatioMode);
+ if (item->d_ptr->hasTranslateOnlySceneTransform()) {
+ path.translate(item->d_ptr->sceneTransform.dx(), item->d_ptr->sceneTransform.dy());
+ fitInView(path.boundingRect(), aspectRatioMode);
+ } else {
+ fitInView(item->d_ptr->sceneTransform.map(path).boundingRect(), aspectRatioMode);
+ }
}
/*!
@@ -2076,6 +1928,8 @@ void QGraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode asp
void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect &source,
Qt::AspectRatioMode aspectRatioMode)
{
+ // ### Switch to using the recursive rendering algorithm instead.
+
Q_D(QGraphicsView);
if (!d->scene || !(painter && painter->isActive()))
return;
@@ -2122,48 +1976,17 @@ void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect
itemList.clear();
// Setup painter matrix.
- QTransform moveMatrix;
- moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
+ QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
QTransform painterMatrix = d->matrix * moveMatrix;
painterMatrix *= QTransform()
.translate(targetRect.left(), targetRect.top())
.scale(xratio, yratio)
.translate(-sourceRect.left(), -sourceRect.top());
- // Two unit vectors.
- QLineF v1(0, 0, 1, 0);
- QLineF v2(0, 0, 0, 1);
-
// Generate the style options
QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
- QStyleOptionGraphicsItem* option = styleOptionArray;
- for (int i = 0; i < numItems; ++i, ++option) {
- QGraphicsItem *item = itemArray[i];
-
- option->state = QStyle::State_None;
- option->rect = item->boundingRect().toRect();
- if (item->isSelected())
- option->state |= QStyle::State_Selected;
- if (item->isEnabled())
- option->state |= QStyle::State_Enabled;
- if (item->hasFocus())
- option->state |= QStyle::State_HasFocus;
- if (d->scene->d_func()->hoverItems.contains(item))
- option->state |= QStyle::State_MouseOver;
- if (item == d->scene->mouseGrabberItem())
- option->state |= QStyle::State_Sunken;
-
- // Calculate a simple level-of-detail metric.
- // ### almost identical code in QGraphicsScene::render()
- // and QGraphicsView::paintEvent() - consider refactoring
- QTransform itemToViewportTransform = item->deviceTransform(painterMatrix);
-
- option->levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length());
- option->matrix = itemToViewportTransform.toAffine();
-
- option->exposedRect = item->boundingRect();
- option->exposedRect &= itemToViewportTransform.inverted().mapRect(targetRect);
- }
+ for (int i = 0; i < numItems; ++i)
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect());
painter->save();
@@ -2203,69 +2026,6 @@ QList<QGraphicsItem *> QGraphicsView::items() const
}
/*!
- Returns all items in the area \a path, which is in viewport coordinates,
- also taking untransformable items into consideration. This function is
- considerably slower than just checking the scene directly. There is
- certainly room for improvement.
-*/
-QList<QGraphicsItem *> QGraphicsViewPrivate::itemsInArea(const QPainterPath &path,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const
-{
- Q_Q(const QGraphicsView);
-
- // Determine the size of the largest untransformable subtree of children
- // mapped to scene coordinates.
- QRectF untr = scene->d_func()->largestUntransformableItem;
- QRectF ltri = matrix.inverted().mapRect(untr);
- ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());
-
- QRectF rect = path.controlPointRect();
-
- // Find all possible items in the relevant area.
- // ### Improve this algorithm; it might be searching a too large area.
- QRectF adjustedRect = q->mapToScene(rect.adjusted(-1, -1, 1, 1).toRect()).boundingRect();
- adjustedRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());
-
- // First build a (potentially large) list of all items in the vicinity
- // that might be untransformable.
- QList<QGraphicsItem *> allCandidates = scene->d_func()->estimateItemsInRect(adjustedRect);
-
- // Then find the minimal list of items that are inside \a path, and
- // convert it to a set.
- QList<QGraphicsItem *> regularCandidates = scene->items(q->mapToScene(path), mode);
- QSet<QGraphicsItem *> candSet = QSet<QGraphicsItem *>::fromList(regularCandidates);
-
- QTransform viewMatrix = q->viewportTransform();
-
- QList<QGraphicsItem *> result;
-
- // Run through all candidates and keep all items that are in candSet, or
- // are untransformable and collide with \a path. ### We can improve this
- // algorithm.
- QList<QGraphicsItem *>::Iterator it = allCandidates.begin();
- while (it != allCandidates.end()) {
- QGraphicsItem *item = *it;
- if (item->d_ptr->itemIsUntransformable()) {
- // Check if this untransformable item collides with the
- // original selection rect.
- QTransform itemTransform = item->deviceTransform(viewMatrix);
- if (QGraphicsScenePrivate::itemCollidesWithPath(item, itemTransform.inverted().map(path), mode))
- result << item;
- } else {
- if (candSet.contains(item))
- result << item;
- }
- ++it;
- }
-
- // ### Insertion sort would be faster.
- if (order != Qt::SortOrder(-1))
- QGraphicsScenePrivate::sortItems(&result, order, scene->d_func()->sortCacheEnabled);
- return result;
-}
-
-/*!
Returns a list of all the items at the position \a pos in the view. The
items are listed in descending Z order (i.e., the first item in the list
is the top-most item, and the last item is the bottom-most item). \a pos
@@ -2284,17 +2044,22 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- if (d->scene->d_func()->largestUntransformableItem.isNull()) {
- if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
- QTransform xinv = viewportTransform().inverted();
- return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)));
- }
- return d->scene->items(mapToScene(pos.x(), pos.y(), 2, 2));
+ // ### Unify these two, and use the items(QPointF) version in
+ // QGraphicsScene instead. The scene items function could use the viewport
+ // transform to map the point to a rect/polygon.
+ if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
+ // Use the rect version
+ QTransform xinv = viewportTransform().inverted();
+ return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)),
+ Qt::IntersectsItemShape,
+ Qt::AscendingOrder,
+ viewportTransform());
}
-
- QPainterPath path;
- path.addRect(QRectF(pos.x(), pos.y(), 1, 1));
- return d->itemsInArea(path);
+ // Use the polygon version
+ return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1),
+ Qt::IntersectsItemShape,
+ Qt::AscendingOrder,
+ viewportTransform());
}
/*!
@@ -2321,12 +2086,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelection
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- if (d->scene->d_func()->largestUntransformableItem.isNull())
- return d->scene->items(mapToScene(rect), mode);
-
- QPainterPath path;
- path.addRect(rect);
- return d->itemsInArea(path);
+ return d->scene->items(mapToScene(rect), mode, Qt::AscendingOrder, viewportTransform());
}
/*!
@@ -2354,13 +2114,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSel
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- if (d->scene->d_func()->largestUntransformableItem.isNull())
- return d->scene->items(mapToScene(polygon), mode);
-
- QPainterPath path;
- path.addPolygon(polygon);
- path.closeSubpath();
- return d->itemsInArea(path);
+ return d->scene->items(mapToScene(polygon), mode, Qt::AscendingOrder, viewportTransform());
}
/*!
@@ -2380,9 +2134,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSe
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- if (d->scene->d_func()->largestUntransformableItem.isNull())
- return d->scene->items(mapToScene(path), mode);
- return d->itemsInArea(path);
+ return d->scene->items(mapToScene(path), mode, Qt::AscendingOrder, viewportTransform());
}
/*!
@@ -2451,13 +2203,13 @@ QPolygonF QGraphicsView::mapToScene(const QRect &rect) const
return QPolygonF();
QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
- QPointF tl = scrollOffset + rect.topLeft();
- QPointF tr = scrollOffset + rect.topRight();
- QPointF br = scrollOffset + rect.bottomRight();
- QPointF bl = scrollOffset + rect.bottomLeft();
+ QRect r = rect.adjusted(0, 0, 1, 1);
+ QPointF tl = scrollOffset + r.topLeft();
+ QPointF tr = scrollOffset + r.topRight();
+ QPointF br = scrollOffset + r.bottomRight();
+ QPointF bl = scrollOffset + r.bottomLeft();
- QPolygonF poly;
- poly.resize(4);
+ QPolygonF poly(4);
if (!d->identityMatrix) {
QTransform x = d->matrix.inverted();
poly[0] = x.map(tl);
@@ -2503,9 +2255,9 @@ QPolygonF QGraphicsView::mapToScene(const QPolygon &polygon) const
QPainterPath QGraphicsView::mapToScene(const QPainterPath &path) const
{
Q_D(const QGraphicsView);
- QTransform moveMatrix;
- moveMatrix.translate(d->horizontalScroll(), d->verticalScroll());
- return (moveMatrix * d->matrix.inverted()).map(path);
+ QTransform matrix = QTransform::fromTranslate(d->horizontalScroll(), d->verticalScroll());
+ matrix *= d->matrix.inverted();
+ return matrix.map(path);
}
/*!
@@ -2560,8 +2312,7 @@ QPolygon QGraphicsView::mapFromScene(const QRectF &rect) const
br -= scrollOffset;
bl -= scrollOffset;
- QPolygon poly;
- poly.resize(4);
+ QPolygon poly(4);
poly[0] = tl.toPoint();
poly[1] = tr.toPoint();
poly[2] = br.toPoint();
@@ -2599,9 +2350,9 @@ QPolygon QGraphicsView::mapFromScene(const QPolygonF &polygon) const
QPainterPath QGraphicsView::mapFromScene(const QPainterPath &path) const
{
Q_D(const QGraphicsView);
- QTransform moveMatrix;
- moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
- return (d->matrix * moveMatrix).map(path);
+ QTransform matrix = d->matrix;
+ matrix *= QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
+ return matrix.map(path);
}
/*!
@@ -2647,7 +2398,7 @@ void QGraphicsView::setBackgroundBrush(const QBrush &brush)
{
Q_D(QGraphicsView);
d->backgroundBrush = brush;
- viewport()->update();
+ d->updateAll();
if (d->cacheMode & CacheBackground) {
// Invalidate the background pixmap
@@ -2677,7 +2428,7 @@ void QGraphicsView::setForegroundBrush(const QBrush &brush)
{
Q_D(QGraphicsView);
d->foregroundBrush = brush;
- viewport()->update();
+ d->updateAll();
}
/*!
@@ -2698,9 +2449,11 @@ void QGraphicsView::updateScene(const QList<QRectF> &rects)
// Extract and reset dirty scene rect info.
QVector<QRect> dirtyViewportRects;
- for (int i = 0; i < d->dirtyRegions.size(); ++i)
- dirtyViewportRects += d->dirtyRegions.at(i).rects();
- d->dirtyRegions.clear();
+ const QVector<QRect> &dirtyRects = d->dirtyRegion.rects();
+ for (int i = 0; i < dirtyRects.size(); ++i)
+ dirtyViewportRects += dirtyRects.at(i);
+ d->dirtyRegion = QRegion();
+ d->dirtyBoundingRect = QRect();
bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate;
bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate)
@@ -2784,9 +2537,7 @@ void QGraphicsView::setupViewport(QWidget *widget)
const bool isGLWidget = widget->inherits("QGLWidget");
- d->accelerateScrolling = !(isGLWidget
- || widget->testAttribute(Qt::WA_MSWindowsUseDirect3D)
- || qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault));
+ d->accelerateScrolling = !(isGLWidget);
widget->setFocusPolicy(Qt::StrongFocus);
@@ -2795,7 +2546,17 @@ void QGraphicsView::setupViewport(QWidget *widget)
widget->setAutoFillBackground(true);
}
- widget->setMouseTracking(true);
+ // We are only interested in mouse tracking if items
+ // accept hover events or use non-default cursors.
+ if (d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents
+ || !d->scene->d_func()->allItemsUseDefaultCursor)) {
+ widget->setMouseTracking(true);
+ }
+
+ // enable touch events if any items is interested in them
+ if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents)
+ widget->setAttribute(Qt::WA_AcceptTouchEvents);
+
widget->setAcceptDrops(acceptDrops());
}
@@ -2894,6 +2655,7 @@ bool QGraphicsView::viewportEvent(QEvent *event)
case QEvent::Paint:
// Reset full update
d->fullUpdatePending = false;
+ d->dirtyScrollOffset = QPoint();
if (d->scene) {
// Check if this view reimplements the updateScene slot; if it
// does, we can't do direct update delivery and have to fall back
@@ -2912,6 +2674,23 @@ bool QGraphicsView::viewportEvent(QEvent *event)
d->scene->d_func()->updateAll = false;
}
break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ {
+ if (!isEnabled())
+ return false;
+
+ if (d->scene && d->sceneInteractionAllowed) {
+ // Convert and deliver the touch event to the scene.
+ QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
+ touchEvent->setWidget(viewport());
+ QGraphicsViewPrivate::translateTouchEvent(d, touchEvent);
+ (void) QApplication::sendEvent(d->scene, touchEvent);
+ }
+
+ return true;
+ }
default:
break;
}
@@ -3085,6 +2864,7 @@ void QGraphicsView::dragMoveEvent(QDragMoveEvent *event)
void QGraphicsView::focusInEvent(QFocusEvent *event)
{
Q_D(QGraphicsView);
+ d->updateInputMethodSensitivity();
QAbstractScrollArea::focusInEvent(event);
if (d->scene)
QApplication::sendEvent(d->scene, event);
@@ -3170,7 +2950,10 @@ void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
mouseEvent.setAccepted(false);
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
- QApplication::sendEvent(d->scene, &mouseEvent);
+ if (event->spontaneous())
+ qt_sendSpontaneousEvent(d->scene, &mouseEvent);
+ else
+ QApplication::sendEvent(d->scene, &mouseEvent);
}
/*!
@@ -3209,7 +2992,10 @@ void QGraphicsView::mousePressEvent(QMouseEvent *event)
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
mouseEvent.setAccepted(false);
- QApplication::sendEvent(d->scene, &mouseEvent);
+ if (event->spontaneous())
+ qt_sendSpontaneousEvent(d->scene, &mouseEvent);
+ else
+ QApplication::sendEvent(d->scene, &mouseEvent);
// Update the original mouse event accepted state.
bool isAccepted = mouseEvent.isAccepted();
@@ -3270,7 +3056,7 @@ void QGraphicsView::mouseMoveEvent(QMouseEvent *event)
if (d->viewportUpdateMode != FullViewportUpdate)
viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
else
- viewport()->update();
+ d->updateAll();
}
// Stop rubber banding if the user has let go of all buttons (even
@@ -3292,14 +3078,15 @@ void QGraphicsView::mouseMoveEvent(QMouseEvent *event)
if (d->viewportUpdateMode != FullViewportUpdate)
viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
else
- viewport()->update();
+ d->updateAll();
}
// Set the new selection area
QPainterPath selectionArea;
selectionArea.addPolygon(mapToScene(d->rubberBandRect));
selectionArea.closeSubpath();
if (d->scene)
- d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode);
+ d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode,
+ viewportTransform());
return;
}
} else
@@ -3335,7 +3122,7 @@ void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
if (d->viewportUpdateMode != FullViewportUpdate)
viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
else
- viewport()->update();
+ d->updateAll();
}
d->rubberBanding = false;
d->rubberBandRect = QRect();
@@ -3379,7 +3166,10 @@ void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
mouseEvent.setAccepted(false);
- QApplication::sendEvent(d->scene, &mouseEvent);
+ if (event->spontaneous())
+ qt_sendSpontaneousEvent(d->scene, &mouseEvent);
+ else
+ QApplication::sendEvent(d->scene, &mouseEvent);
// Update the last mouse event selected state.
d->lastMouseEvent.setAccepted(mouseEvent.isAccepted());
@@ -3437,16 +3227,11 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
d->scene->d_func()->painterStateProtection = !(d->optimizationFlags & DontSavePainterState);
// Determine the exposed region
- QRegion exposedRegion = event->region();
- if (!d->accelerateScrolling)
- exposedRegion = viewport()->rect();
- else if (d->viewportUpdateMode == BoundingRectViewportUpdate)
- exposedRegion = event->rect();
- QRectF exposedSceneRect = mapToScene(exposedRegion.boundingRect().adjusted(0, 0, 1, 1)).boundingRect();
+ d->exposedRegion = event->region();
+ QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
// Set up the painter
QPainter painter(viewport());
- QTransform original = painter.worldTransform();
#ifndef QT_NO_RUBBERBAND
if (d->rubberBanding && !d->rubberBandRect.isEmpty())
painter.save();
@@ -3456,23 +3241,12 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
painter.setRenderHints(d->renderHints, true);
// Set up viewport transform
- const QTransform viewTransform = viewportTransform();
- painter.setTransform(viewTransform, true);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- QTime stopWatch;
- stopWatch.start();
- qDebug() << "QGraphicsView::paintEvent(" << exposedRegion << ")";
-#endif
-
- // Find all exposed items
- bool allItems = false;
- QList<QGraphicsItem *> itemList = d->findItems(exposedRegion, &allItems);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- int exposedTime = stopWatch.elapsed();
-#endif
+ const bool viewTransformed = isTransformed();
+ if (viewTransformed)
+ painter.setWorldTransform(viewportTransform());
+ const QTransform viewTransform = painter.worldTransform();
+ // Draw background
if ((d->cacheMode & CacheBackground)
#ifdef Q_WS_X11
&& X11->use_xrender
@@ -3495,16 +3269,21 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
if (!d->backgroundPixmapExposed.isEmpty()) {
QPainter backgroundPainter(&d->backgroundPixmap);
backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip);
- backgroundPainter.setTransform(viewportTransform());
+ if (viewTransformed)
+ backgroundPainter.setTransform(viewTransform);
+ backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source);
drawBackground(&backgroundPainter, exposedSceneRect);
d->backgroundPixmapExposed = QRegion();
}
// Blit the background from the background pixmap
- QTransform oldMatrix = painter.worldTransform();
- painter.setWorldTransform(original);
- painter.drawPixmap(QPoint(), d->backgroundPixmap);
- painter.setWorldTransform(oldMatrix);
+ if (viewTransformed) {
+ painter.setWorldTransform(QTransform());
+ painter.drawPixmap(QPoint(), d->backgroundPixmap);
+ painter.setWorldTransform(viewTransform);
+ } else {
+ painter.drawPixmap(QPoint(), d->backgroundPixmap);
+ }
} else {
if (!(d->optimizationFlags & DontSavePainterState))
painter.save();
@@ -3513,34 +3292,32 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
painter.restore();
}
-#ifdef QGRAPHICSVIEW_DEBUG
- int backgroundTime = stopWatch.elapsed() - exposedTime;
-#endif
-
- // Generate the style options
- QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];
- QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(itemList.size());
-
- d->generateStyleOptions(itemList, itemArray, styleOptionArray, viewTransform,
- allItems, exposedRegion);
-
// Items
- drawItems(&painter, itemList.size(), itemArray, styleOptionArray);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- int itemsTime = stopWatch.elapsed() - exposedTime - backgroundTime;
-#endif
+ if (!(d->optimizationFlags & IndirectPainting)) {
+ d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0,
+ &d->exposedRegion, viewport());
+ } else {
+ // Find all exposed items
+ bool allItems = false;
+ QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform);
+ if (!itemList.isEmpty()) {
+ // Generate the style options.
+ const int numItems = itemList.size();
+ QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
+ QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
+ for (int i = 0; i < numItems; ++i) {
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform,
+ d->exposedRegion, allItems);
+ }
+ // Draw the items.
+ drawItems(&painter, numItems, itemArray, styleOptionArray);
+ d->freeStyleOptionsArray(styleOptionArray);
+ }
+ }
// Foreground
drawForeground(&painter, exposedSceneRect);
- delete [] itemArray;
- d->freeStyleOptionsArray(styleOptionArray);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- int foregroundTime = stopWatch.elapsed() - exposedTime - backgroundTime - itemsTime;
-#endif
-
#ifndef QT_NO_RUBBERBAND
// Rubberband
if (d->rubberBanding && !d->rubberBandRect.isEmpty()) {
@@ -3562,17 +3339,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
painter.end();
-#ifdef QGRAPHICSVIEW_DEBUG
- qDebug() << "\tItem discovery....... " << exposedTime << "msecs (" << itemList.size() << "items,"
- << (exposedTime > 0 ? (itemList.size() * 1000.0 / exposedTime) : -1) << "/ sec )";
- qDebug() << "\tDrawing background... " << backgroundTime << "msecs (" << exposedRegion.numRects() << "segments )";
- qDebug() << "\tDrawing items........ " << itemsTime << "msecs ("
- << (itemsTime > 0 ? (itemList.size() * 1000.0 / itemsTime) : -1) << "/ sec )";
- qDebug() << "\tDrawing foreground... " << foregroundTime << "msecs (" << exposedRegion.numRects() << "segments )";
- qDebug() << "\tTotal rendering time: " << stopWatch.elapsed() << "msecs ("
- << (stopWatch.elapsed() > 0 ? (1000.0 / stopWatch.elapsed()) : -1.0) << "fps )";
-#endif
-
// Restore painter state protection.
d->scene->d_func()->painterStateProtection = true;
}
@@ -3619,10 +3385,6 @@ void QGraphicsView::scrollContentsBy(int dx, int dy)
if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) {
- for (int i = 0; i < d->dirtyRects.size(); ++i)
- d->dirtyRects[i].translate(dx, dy);
- for (int i = 0; i < d->dirtyRegions.size(); ++i)
- d->dirtyRegions[i].translate(dx, dy);
if (d->accelerateScrolling) {
#ifndef QT_NO_RUBBERBAND
// Update new and old rubberband regions
@@ -3632,12 +3394,15 @@ void QGraphicsView::scrollContentsBy(int dx, int dy)
viewport()->update(rubberBandRegion);
}
#endif
+ d->dirtyScrollOffset.rx() += dx;
+ d->dirtyScrollOffset.ry() += dy;
+ d->dirtyRegion.translate(dx, dy);
viewport()->scroll(dx, dy);
} else {
- viewport()->update();
+ d->updateAll();
}
} else {
- viewport()->update();
+ d->updateAll();
}
}
@@ -3648,31 +3413,14 @@ void QGraphicsView::scrollContentsBy(int dx, int dy)
&& X11->use_xrender
#endif
) {
- // Invalidate the background pixmap
- d->backgroundPixmapExposed.translate(dx, 0);
- if (dx > 0) {
- d->backgroundPixmapExposed += QRect(0, 0, dx, viewport()->height());
- } else if (dx < 0) {
- d->backgroundPixmapExposed += QRect(viewport()->width() + dx, 0,
- -dx, viewport()->height());
- }
- d->backgroundPixmapExposed.translate(0, dy);
- if (dy > 0) {
- d->backgroundPixmapExposed += QRect(0, 0, viewport()->width(), dy);
- } else if (dy < 0) {
- d->backgroundPixmapExposed += QRect(0, viewport()->height() + dy,
- viewport()->width(), -dy);
- }
-
// Scroll the background pixmap
- if (!d->backgroundPixmap.isNull()) {
- QPixmap tmp = d->backgroundPixmap.copy();
- QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole());
- if (!bgBrush.isOpaque())
- d->backgroundPixmap.fill(Qt::transparent);
- QPainter painter(&d->backgroundPixmap);
- painter.drawPixmap(dx, dy, tmp);
- }
+ QRegion exposed;
+ if (!d->backgroundPixmap.isNull())
+ d->backgroundPixmap.scroll(dx, dy, d->backgroundPixmap.rect(), &exposed);
+
+ // Invalidate the background pixmap
+ d->backgroundPixmapExposed.translate(dx, dy);
+ d->backgroundPixmapExposed += exposed;
}
// Always replay on scroll.
@@ -3773,8 +3521,10 @@ void QGraphicsView::drawItems(QPainter *painter, int numItems,
const QStyleOptionGraphicsItem options[])
{
Q_D(QGraphicsView);
- if (d->scene)
- d->scene->drawItems(painter, numItems, items, options, viewport());
+ if (d->scene) {
+ QWidget *widget = painter->device() == viewport() ? viewport() : 0;
+ d->scene->drawItems(painter, numItems, items, options, widget);
+ }
}
/*!
@@ -3797,12 +3547,25 @@ QTransform QGraphicsView::transform() const
QTransform QGraphicsView::viewportTransform() const
{
Q_D(const QGraphicsView);
- QTransform moveMatrix;
- moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
+ QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
return d->identityMatrix ? moveMatrix : d->matrix * moveMatrix;
}
/*!
+ \since 4.6
+
+ Returns true if the view is transformed (i.e., a non-identity transform
+ has been assigned, or the scrollbars are adjusted).
+
+ \sa setTransform(), horizontalScrollBar(), verticalScrollBar()
+*/
+bool QGraphicsView::isTransformed() const
+{
+ Q_D(const QGraphicsView);
+ return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll();
+}
+
+/*!
Sets the view's current transformation matrix to \a matrix.
If \a combine is true, then \a matrix is combined with the current matrix;
@@ -3853,7 +3616,7 @@ void QGraphicsView::setTransform(const QTransform &matrix, bool combine )
d->transforming = false;
// Any matrix operation requires a full update.
- viewport()->update();
+ d->updateAll();
}
/*!
@@ -3866,6 +3629,38 @@ void QGraphicsView::resetTransform()
setTransform(QTransform());
}
+QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const
+{
+ QPointF p = point;
+ p.rx() += horizontalScroll();
+ p.ry() += verticalScroll();
+ return identityMatrix ? p : matrix.inverted().map(p);
+}
+
+QRectF QGraphicsViewPrivate::mapToScene(const QRectF &rect) const
+{
+ QPointF scrollOffset(horizontalScroll(), verticalScroll());
+ QPointF tl = scrollOffset + rect.topLeft();
+ QPointF tr = scrollOffset + rect.topRight();
+ QPointF br = scrollOffset + rect.bottomRight();
+ QPointF bl = scrollOffset + rect.bottomLeft();
+
+ QPolygonF poly(4);
+ if (!identityMatrix) {
+ QTransform x = matrix.inverted();
+ poly[0] = x.map(tl);
+ poly[1] = x.map(tr);
+ poly[2] = x.map(br);
+ poly[3] = x.map(bl);
+ } else {
+ poly[0] = tl;
+ poly[1] = tr;
+ poly[2] = br;
+ poly[3] = bl;
+ }
+ return poly.boundingRect();
+}
+
QT_END_NAMESPACE
#include "moc_qgraphicsview.cpp"
diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h
index a107cb2..e26503a 100644
--- a/src/gui/graphicsview/qgraphicsview.h
+++ b/src/gui/graphicsview/qgraphicsview.h
@@ -110,9 +110,10 @@ public:
};
enum OptimizationFlag {
- DontClipPainter = 0x1,
+ DontClipPainter = 0x1, // obsolete
DontSavePainterState = 0x2,
- DontAdjustForAntialiasing = 0x4
+ DontAdjustForAntialiasing = 0x4,
+ IndirectPainting = 0x8
};
Q_DECLARE_FLAGS(OptimizationFlags, OptimizationFlag)
@@ -169,6 +170,7 @@ public:
void resetMatrix();
QTransform transform() const;
QTransform viewportTransform() const;
+ bool isTransformed() const;
void setTransform(const QTransform &matrix, bool combine = false);
void resetTransform();
void rotate(qreal angle);
@@ -273,7 +275,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_setViewportCursor(const QCursor &))
Q_PRIVATE_SLOT(d_func(), void _q_unsetViewportCursor())
#endif
- Q_PRIVATE_SLOT(d_func(), void _q_updateLaterSlot())
friend class QGraphicsSceneWidget;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index b5859731..ad3bb5c 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -47,8 +47,8 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
@@ -58,12 +58,14 @@
#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
#include <QtGui/qevent.h>
+#include <QtCore/qcoreapplication.h>
#include "qgraphicssceneevent.h"
+#include <QtGui/qstyleoption.h>
#include <private/qabstractscrollarea_p.h>
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
+class Q_AUTOTEST_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
{
Q_DECLARE_PUBLIC(QGraphicsView)
public:
@@ -84,16 +86,13 @@ public:
qint64 horizontalScroll() const;
qint64 verticalScroll() const;
- QList<QGraphicsItem *> itemsInArea(const QPainterPath &path,
- Qt::ItemSelectionMode mode = Qt::IntersectsItemShape,
- Qt::SortOrder = Qt::AscendingOrder) const;
-
QPointF mousePressItemPoint;
QPointF mousePressScenePoint;
QPoint mousePressViewPoint;
QPoint mousePressScreenPoint;
QPointF lastMouseMoveScenePoint;
QPoint lastMouseMoveScreenPoint;
+ QPoint dirtyScrollOffset;
Qt::MouseButton mousePressButton;
QTransform matrix;
bool identityMatrix;
@@ -159,28 +158,38 @@ public:
QRect mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const;
QRegion mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const;
- void itemUpdated(QGraphicsItem *item, const QRectF &rect);
bool fullUpdatePending;
- QList<QRect> dirtyRects;
- QList<QRegion> dirtyRegions;
- int dirtyRectCount;
+ QRegion dirtyRegion;
QRect dirtyBoundingRect;
- void updateLater();
- bool updatingLater;
- void _q_updateLaterSlot();
- void updateAll();
- void updateRect(const QRect &rect);
- void updateRegion(const QRegion &region);
+ void processPendingUpdates();
+ inline void updateAll()
+ {
+ viewport->update();
+ fullUpdatePending = true;
+ dirtyBoundingRect = QRect();
+ dirtyRegion = QRegion();
+ }
+
+ inline void dispatchPendingUpdateRequests()
+ {
+ if (qt_widget_private(viewport)->paintOnScreen())
+ QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest);
+ else
+ QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest);
+ }
+
+ bool updateRect(const QRect &rect);
+ bool updateRegion(const QRegion &region);
bool updateSceneSlotReimplementedChecked;
+ QRegion exposedRegion;
- QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems) const;
+ QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems,
+ const QTransform &viewTransform) const;
- void generateStyleOptions(const QList<QGraphicsItem *> &itemList,
- QGraphicsItem **itemArray,
- QStyleOptionGraphicsItem *styleOptionArray,
- const QTransform &worldTransform,
- bool allItems,
- const QRegion &exposedRegion) const;
+ QPointF mapToScene(const QPointF &point) const;
+ QRectF mapToScene(const QRectF &rect) const;
+ static void translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent);
+ void updateInputMethodSensitivity();
};
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index de80181..9972223 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -74,7 +74,6 @@ QT_BEGIN_NAMESPACE
\brief The QGraphicsWidget class is the base class for all widget
items in a QGraphicsScene.
\since 4.4
- \ingroup multimedia
\ingroup graphicsview-api
QGraphicsWidget is an extended base item that provides extra functionality
@@ -169,38 +168,7 @@ QT_BEGIN_NAMESPACE
\sa QGraphicsProxyWidget, QGraphicsItem, {Widgets and Layouts}
*/
-/*!
- \property QGraphicsWidget::enabled
- \brief whether the item is enabled or not
-
- This property is declared in QGraphicsItem.
-
- By default, this property is true.
-
- \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled()
-*/
-
-/*!
- \property QGraphicsWidget::visible
- \brief whether the item is visible or not
-
- This property is declared in QGraphicsItem.
-
- By default, this property is true.
-
- \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), show(),
- hide()
-*/
-
-/*!
- \property QGraphicsWidget::opacity
- \brief the opacity of the widget
-*/
-
-/*!
- \property QGraphicsWidget::pos
- \brief the position of the widget
-*/
+bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
/*!
Constructs a QGraphicsWidget instance. The optional \a parent argument is
@@ -209,7 +177,7 @@ QT_BEGIN_NAMESPACE
window, a tool, a popup, etc).
*/
QGraphicsWidget::QGraphicsWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
- : QGraphicsItem(*new QGraphicsWidgetPrivate, 0, 0), QGraphicsLayoutItem(0, false)
+ : QGraphicsObject(*new QGraphicsWidgetPrivate, 0, 0), QGraphicsLayoutItem(0, false)
{
Q_D(QGraphicsWidget);
d->init(parent, wFlags);
@@ -221,7 +189,7 @@ QGraphicsWidget::QGraphicsWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
Constructs a new QGraphicsWidget, using \a dd as parent.
*/
QGraphicsWidget::QGraphicsWidget(QGraphicsWidgetPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene, Qt::WindowFlags wFlags)
- : QGraphicsItem(dd, 0, scene), QGraphicsLayoutItem(0, false)
+ : QGraphicsObject(dd, 0, scene), QGraphicsLayoutItem(0, false)
{
Q_D(QGraphicsWidget);
d->init(parent, wFlags);
@@ -291,7 +259,7 @@ QGraphicsWidget::~QGraphicsWidget()
//we check if we have a layout previously
if (d->layout) {
- delete d->layout;
+ QGraphicsLayout *temp = d->layout;
foreach (QGraphicsItem * item, childItems()) {
// In case of a custom layout which doesn't remove and delete items, we ensure that
// the parent layout item does not point to the deleted layout. This code is here to
@@ -302,6 +270,8 @@ QGraphicsWidget::~QGraphicsWidget()
widget->setParentLayoutItem(0);
}
}
+ d->layout = 0;
+ delete temp;
}
// Remove this graphics widget from widgetStyles
@@ -366,7 +336,7 @@ void QGraphicsWidget::resize(const QSizeF &size)
void QGraphicsWidget::setGeometry(const QRectF &rect)
{
QGraphicsWidgetPrivate *wd = QGraphicsWidget::d_func();
- QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr;
+ QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr.data();
QRectF newGeom;
QPointF oldPos = d->geom.topLeft();
if (!wd->inSetPos) {
@@ -461,17 +431,19 @@ void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qre
{
Q_D(QGraphicsWidget);
- if (left == d->leftMargin
- && top == d->topMargin
- && right == d->rightMargin
- && bottom == d->bottomMargin) {
+ if (!d->margins && left == 0 && top == 0 && right == 0 && bottom == 0)
+ return;
+ d->ensureMargins();
+ if (left == d->margins[d->Left]
+ && top == d->margins[d->Top]
+ && right == d->margins[d->Right]
+ && bottom == d->margins[d->Bottom])
return;
- }
- d->leftMargin = left;
- d->topMargin = top;
- d->rightMargin = right;
- d->bottomMargin = bottom;
+ d->margins[d->Left] = left;
+ d->margins[d->Top] = top;
+ d->margins[d->Right] = right;
+ d->margins[d->Bottom] = bottom;
if (QGraphicsLayout *l = d->layout)
l->invalidate();
@@ -492,14 +464,16 @@ void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qre
void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
{
Q_D(const QGraphicsWidget);
+ if (left || top || right || bottom)
+ d->ensureMargins();
if (left)
- *left = d->leftMargin;
+ *left = d->margins[d->Left];
if (top)
- *top = d->topMargin;
+ *top = d->margins[d->Top];
if (right)
- *right = d->rightMargin;
+ *right = d->margins[d->Right];
if (bottom)
- *bottom = d->bottomMargin;
+ *bottom = d->margins[d->Bottom];
}
/*!
@@ -515,16 +489,23 @@ void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right,
void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom)
{
Q_D(QGraphicsWidget);
- bool unchanged = left == d->leftWindowFrameMargin && top == d->topWindowFrameMargin
- && right == d->rightWindowFrameMargin && bottom == d->bottomWindowFrameMargin;
+
+ if (!d->windowFrameMargins && left == 0 && top == 0 && right == 0 && bottom == 0)
+ return;
+ d->ensureWindowFrameMargins();
+ bool unchanged =
+ d->windowFrameMargins[d->Left] == left
+ && d->windowFrameMargins[d->Top] == top
+ && d->windowFrameMargins[d->Right] == right
+ && d->windowFrameMargins[d->Bottom] == bottom;
if (d->setWindowFrameMargins && unchanged)
return;
if (!unchanged)
prepareGeometryChange();
- d->leftWindowFrameMargin = left;
- d->topWindowFrameMargin = top;
- d->rightWindowFrameMargin = right;
- d->bottomWindowFrameMargin = bottom;
+ d->windowFrameMargins[d->Left] = left;
+ d->windowFrameMargins[d->Top] = top;
+ d->windowFrameMargins[d->Right] = right;
+ d->windowFrameMargins[d->Bottom] = bottom;
d->setWindowFrameMargins = true;
}
@@ -538,14 +519,16 @@ void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right,
void QGraphicsWidget::getWindowFrameMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
{
Q_D(const QGraphicsWidget);
+ if (left || top || right || bottom)
+ d->ensureWindowFrameMargins();
if (left)
- *left = d->leftWindowFrameMargin;
+ *left = d->windowFrameMargins[d->Left];
if (top)
- *top = d->topWindowFrameMargin;
+ *top = d->windowFrameMargins[d->Top];
if (right)
- *right = d->rightWindowFrameMargin;
+ *right = d->windowFrameMargins[d->Right];
if (bottom)
- *bottom = d->bottomWindowFrameMargin;
+ *bottom = d->windowFrameMargins[d->Bottom];
}
/*!
@@ -579,8 +562,10 @@ void QGraphicsWidget::unsetWindowFrameMargins()
QRectF QGraphicsWidget::windowFrameGeometry() const
{
Q_D(const QGraphicsWidget);
- return geometry().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin,
- d->rightWindowFrameMargin, d->bottomWindowFrameMargin);
+ return d->windowFrameMargins
+ ? geometry().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
+ d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
+ : geometry();
}
/*!
@@ -591,8 +576,10 @@ QRectF QGraphicsWidget::windowFrameGeometry() const
QRectF QGraphicsWidget::windowFrameRect() const
{
Q_D(const QGraphicsWidget);
- return rect().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin,
- d->rightWindowFrameMargin, d->bottomWindowFrameMargin);
+ return d->windowFrameMargins
+ ? rect().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
+ d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
+ : rect();
}
/*!
@@ -701,7 +688,10 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
QSizeF sh;
if (d->layout) {
sh = d->layout->effectiveSizeHint(which, constraint);
- sh += QSizeF(d->leftMargin + d->rightMargin, d->topMargin + d->bottomMargin);
+ if (d->margins) {
+ sh += QSizeF(d->margins[d->Left] + d->margins[d->Right],
+ d->margins[d->Top] + d->margins[d->Bottom]);
+ }
} else {
switch (which) {
case Qt::MinimumSize:
@@ -986,12 +976,18 @@ void QGraphicsWidget::updateGeometry()
deliver events related to state changes in the item. Because of this, it is
very important that subclasses call the base implementation.
- For example, QGraphicsWidget uses ItemVisibleChange to deliver \l Show and
- \l Hide events, ItemPositionHasChanged to deliver \l Move events, and
- ItemParentChange both to deliver \l ParentChange events, and for managing
- the focus chain.
+ \a change specifies the type of change, and \a value is the new value.
- \sa propertyChange()
+ For example, QGraphicsWidget uses ItemVisibleChange to deliver
+ \l{QEvent::Show} {Show} and \l{QEvent::Hide}{Hide} events,
+ ItemPositionHasChanged to deliver \l{QEvent::Move}{Move} events,
+ and ItemParentChange both to deliver \l{QEvent::ParentChange}
+ {ParentChange} events, and for managing the focus chain.
+
+ QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in
+ order to track position changes.
+
+ \sa QGraphicsItem::itemChange()
*/
QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value)
{
@@ -1041,10 +1037,6 @@ QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &
break;
}
case ItemParentHasChanged: {
- // reset window type on parent change in order to automagically remove decorations etc.
- Qt::WindowFlags wflags = d->windowFlags & ~Qt::WindowType_Mask;
- d->adjustWindowFlags(&wflags);
- setWindowFlags(wflags);
// Deliver ParentChange.
QEvent event(QEvent::ParentChange);
QApplication::sendEvent(this, &event);
@@ -1109,7 +1101,11 @@ QVariant QGraphicsWidget::propertyChange(const QString &propertyName, const QVar
*/
bool QGraphicsWidget::sceneEvent(QEvent *event)
{
- return QCoreApplication::sendEvent(this, event) || QGraphicsItem::sceneEvent(event);
+ bool spont = event->spontaneous();
+ if (spont ? qt_sendSpontaneousEvent(this, event) : QApplication::sendEvent(this, event))
+ return true;
+ event->spont = spont;
+ return QGraphicsItem::sceneEvent(event);
}
/*!
@@ -1133,7 +1129,8 @@ bool QGraphicsWidget::windowFrameEvent(QEvent *event)
d->windowFrameMousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
break;
case QEvent::GraphicsSceneMouseMove:
- if (d->grabbedSection != Qt::NoSection) {
+ d->ensureWindowData();
+ if (d->windowData->grabbedSection != Qt::NoSection) {
d->windowFrameMouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
event->accept();
}
@@ -1188,7 +1185,8 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
const qreal cornerMargin = 20;
//### Not sure of this one, it should be the same value for all edges.
- const qreal windowFrameWidth = d->leftWindowFrameMargin;
+ const qreal windowFrameWidth = d->windowFrameMargins
+ ? d->windowFrameMargins[d->Left] : 0;
Qt::WindowFrameSection s = Qt::NoSection;
if (x <= left + cornerMargin) {
@@ -1214,7 +1212,8 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
}
if (s == Qt::NoSection) {
QRectF r1 = r;
- r1.setHeight(d->topWindowFrameMargin);
+ r1.setHeight(d->windowFrameMargins
+ ? d->windowFrameMargins[d->Top] : 0);
if (r1.contains(pos))
s = Qt::TitleBarArea;
}
@@ -1224,7 +1223,8 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
/*!
\reimp
- QGraphicsWidget handles the following events:
+ Handles the \a event. QGraphicsWidget handles the following
+ events:
\table \o Event \o Usage
\row \o Polish
@@ -1285,10 +1285,6 @@ bool QGraphicsWidget::event(QEvent *event)
case QEvent::WindowActivate:
case QEvent::WindowDeactivate:
update();
- foreach (QGraphicsItem *child, childItems()) {
- if (child->isWidget())
- QApplication::sendEvent(static_cast<QGraphicsWidget *>(child), event);
- }
break;
// Taken from QWidget::event
case QEvent::ActivationChange:
@@ -1322,7 +1318,8 @@ bool QGraphicsWidget::event(QEvent *event)
case QEvent::GraphicsSceneMouseMove:
case QEvent::GraphicsSceneMouseRelease:
case QEvent::GraphicsSceneMouseDoubleClick:
- if (d->hasDecoration() && d->grabbedSection != Qt::NoSection)
+ d->ensureWindowData();
+ if (d->hasDecoration() && d->windowData->grabbedSection != Qt::NoSection)
return windowFrameEvent(event);
break;
case QEvent::GraphicsSceneHoverEnter:
@@ -1597,6 +1594,8 @@ void QGraphicsWidget::ungrabKeyboardEvent(QEvent *event)
/*!
Returns the widgets window type.
+
+ \sa windowFlags(), isWindow(), isPanel()
*/
Qt::WindowType QGraphicsWidget::windowType() const
{
@@ -1612,6 +1611,13 @@ Qt::WindowType QGraphicsWidget::windowType() const
is platform-dependent.
By default, this property contains no window flags.
+
+ Windows are panels. If you set the Qt::Window flag, the ItemIsPanel flag
+ will be set automatically. If you clear the Qt::Window flag, the
+ ItemIsPanel flag is also cleared. Note that the ItemIsPanel flag can be
+ set independently of Qt::Window.
+
+ \sa isWindow(), isPanel()
*/
Qt::WindowFlags QGraphicsWidget::windowFlags() const
{
@@ -1625,10 +1631,13 @@ void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags)
return;
bool wasPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup;
+ d->adjustWindowFlags(&wFlags);
d->windowFlags = wFlags;
if (!d->setWindowFrameMargins)
unsetWindowFrameMargins();
+ setFlag(ItemIsPanel, d->windowFlags & Qt::Window);
+
bool isPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup;
if (d->scene && isVisible() && wasPopup != isPopup) {
// Popup state changed; update implicit mouse grab.
@@ -1637,6 +1646,11 @@ void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags)
else
d->scene->d_func()->addPopup(this);
}
+
+ if (d->scene && d->scene->d_func()->allItemsIgnoreHoverEvents && d->hasDecoration()) {
+ d->scene->d_func()->allItemsIgnoreHoverEvents = false;
+ d->scene->d_func()->enableMouseTrackingOnViews();
+ }
}
/*!
@@ -1647,7 +1661,7 @@ void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags)
The active window is the window that either contains a child widget that
currently has input focus, or that itself has input focus.
- \sa QGraphicsScene::activeWindow(), QGraphicsScene::setActiveWindow()
+ \sa QGraphicsScene::activeWindow(), QGraphicsScene::setActiveWindow(), isActive()
*/
bool QGraphicsWidget::isActiveWindow() const
{
@@ -1655,7 +1669,7 @@ bool QGraphicsWidget::isActiveWindow() const
if (!d->scene)
return false;
const QGraphicsWidget *w = window();
- return (!w && d->scene->d_func()->activationRefCount) || (w && d->scene->activeWindow() == w);
+ return (!w && d->scene->isActive()) || (w && d->scene->activeWindow() == w);
}
/*!
@@ -1664,17 +1678,19 @@ bool QGraphicsWidget::isActiveWindow() const
This property is only used for windows.
- By default, if no title has been set, this property contains an empty string.
+ By default, if no title has been set, this property contains an
+ empty string.
*/
void QGraphicsWidget::setWindowTitle(const QString &title)
{
Q_D(QGraphicsWidget);
- d->windowTitle = title;
+ d->ensureWindowData();
+ d->windowData->windowTitle = title;
}
QString QGraphicsWidget::windowTitle() const
{
Q_D(const QGraphicsWidget);
- return d->windowTitle;
+ return d->windowData ? d->windowData->windowTitle : QString();
}
/*!
@@ -1716,17 +1732,18 @@ void QGraphicsWidget::setFocusPolicy(Qt::FocusPolicy policy)
/*!
If this widget, a child or descendant of this widget currently has input
focus, this function will return a pointer to that widget. If
- no descendant has input focus, 0 is returned.
+ no descendant widget has input focus, 0 is returned.
- \sa QWidget::focusWidget()
+ \sa QGraphicsItem::focusItem(), QWidget::focusWidget()
*/
QGraphicsWidget *QGraphicsWidget::focusWidget() const
{
Q_D(const QGraphicsWidget);
- return d->focusChild;
+ if (d->subFocusItem && d->subFocusItem->d_ptr->isWidget)
+ return static_cast<QGraphicsWidget *>(d->subFocusItem);
+ return 0;
}
-
#ifndef QT_NO_SHORTCUT
/*!
\since 4.5
@@ -2112,11 +2129,12 @@ void QGraphicsWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGrap
QStyleOptionTitleBar bar;
bar.QStyleOption::operator=(*option);
d->initStyleOptionTitleBar(&bar); // this clear flags in bar.state
- if (d->buttonMouseOver)
+ d->ensureWindowData();
+ if (d->windowData->buttonMouseOver)
bar.state |= QStyle::State_MouseOver;
else
bar.state &= ~QStyle::State_MouseOver;
- if (d->buttonSunken)
+ if (d->windowData->buttonSunken)
bar.state |= QStyle::State_Sunken;
else
bar.state &= ~QStyle::State_Sunken;
@@ -2251,6 +2269,7 @@ bool QGraphicsWidget::close()
#ifdef Q_NO_USING_KEYWORD
/*!
\fn const QObjectList &QGraphicsWidget::children() const
+ \internal
This function returns the same value as QObject::children(). It's
provided to differentiate between the obsolete member
@@ -2271,7 +2290,7 @@ void QGraphicsWidget::dumpFocusChain()
qWarning("Found a focus chain that is not circular, (next == 0)");
break;
}
- qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromAscii("focusItem:%1").arg(next->hasFocus() ? "1" : "0") << QLatin1String("next:") << next->d_func()->focusNext->data(0) << QLatin1String("prev:") << next->d_func()->focusPrev->data(0);
+ qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromAscii("focusItem:%1").arg(next->hasFocus() ? '1' : '0') << QLatin1String("next:") << next->d_func()->focusNext->data(0) << QLatin1String("prev:") << next->d_func()->focusPrev->data(0);
if (visited.contains(next)) {
qWarning("Already visited this node. However, I expected to dump until I found myself.");
break;
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index 2a7a8bd..5b657a9 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -66,22 +66,18 @@ class QStyleOption;
class QGraphicsWidgetPrivate;
-class Q_GUI_EXPORT QGraphicsWidget : public QObject, public QGraphicsItem, public QGraphicsLayoutItem
+class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLayoutItem
{
Q_OBJECT
+ Q_INTERFACES(QGraphicsItem QGraphicsLayoutItem)
Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
Q_PROPERTY(QFont font READ font WRITE setFont)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
Q_PROPERTY(QSizeF size READ size WRITE resize)
Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy)
- Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
- Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle)
- Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
- Q_PROPERTY(QPointF pos READ pos WRITE setPos)
Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
-
public:
QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
~QGraphicsWidget();
@@ -225,7 +221,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsWidget)
- Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QGraphicsWidget)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsWidget)
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
friend class QGraphicsView;
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index e23d19f..787bbb1 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -66,17 +66,20 @@ void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFl
isWidget = 1; // QGraphicsItem::isWidget() returns true.
focusNext = focusPrev = q;
focusPolicy = Qt::NoFocus;
+
+ adjustWindowFlags(&wFlags);
+ windowFlags = wFlags;
+
q->setParentItem(parentItem);
q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType));
q->setGraphicsItem(q);
resolveLayoutDirection();
-
- if (!parentItem)
- adjustWindowFlags(&wFlags);
- windowFlags = wFlags;
q->unsetWindowFrameMargins();
+ q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
+ q->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
}
+
qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
{
Q_Q(const QGraphicsWidget);
@@ -89,56 +92,57 @@ qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options
return (qreal)height;
}
-void QGraphicsWidgetPrivate::getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
+/*!
+ \internal
+*/
+QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
{
- if (left)
- *left = leftLayoutItemMargin;
- if (top)
- *top = topLayoutItemMargin;
- if (right)
- *right = rightLayoutItemMargin;
- if (bottom)
- *bottom = bottomLayoutItemMargin;
+ // Remove any lazily allocated data
+ delete[] margins;
+ delete[] windowFrameMargins;
+ delete windowData;
}
-void QGraphicsWidgetPrivate::setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom)
-{
- if (leftLayoutItemMargin == left
- && topLayoutItemMargin == top
- && rightLayoutItemMargin == right
- && bottomLayoutItemMargin == bottom)
- return;
+/*!
+ \internal
- Q_Q(QGraphicsWidget);
- leftLayoutItemMargin = left;
- topLayoutItemMargin = top;
- rightLayoutItemMargin = right;
- bottomLayoutItemMargin = bottom;
- q->updateGeometry();
+ Ensures that margins is allocated.
+ This function must be called before any dereferencing.
+*/
+void QGraphicsWidgetPrivate::ensureMargins() const
+{
+ if (!margins) {
+ margins = new qreal[4];
+ for (int i = 0; i < 4; ++i)
+ margins[i] = 0;
+ }
}
-void QGraphicsWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
+/*!
+ \internal
+
+ Ensures that windowFrameMargins is allocated.
+ This function must be called before any dereferencing.
+*/
+void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const
{
- Q_Q(QGraphicsWidget);
- QStyleOption myOpt;
- if (!opt) {
- q->initStyleOption(&myOpt);
- myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
- opt = &myOpt;
+ if (!windowFrameMargins) {
+ windowFrameMargins = new qreal[4];
+ for (int i = 0; i < 4; ++i)
+ windowFrameMargins[i] = 0;
}
+}
- QRect liRect = q->style()->subElementRect(element, opt, /* q */ 0);
- if (liRect.isValid()) {
- leftLayoutItemMargin = (opt->rect.left() - liRect.left());
- topLayoutItemMargin = (opt->rect.top() - liRect.top());
- rightLayoutItemMargin = (liRect.right() - opt->rect.right());
- bottomLayoutItemMargin = (liRect.bottom() - opt->rect.bottom());
- } else {
- leftLayoutItemMargin = 0;
- topLayoutItemMargin = 0;
- rightLayoutItemMargin = 0;
- bottomLayoutItemMargin = 0;
- }
+/*!
+ \internal
+
+ Ensures that windowData is allocated.
+ This function must be called before any dereferencing.
+*/
+void QGraphicsWidgetPrivate::ensureWindowData()
+{
+ if (!windowData)
+ windowData = new WindowData;
}
void QGraphicsWidgetPrivate::setPalette_helper(const QPalette &palette)
@@ -297,11 +301,12 @@ QFont QGraphicsWidgetPrivate::naturalWidgetFont() const
void QGraphicsWidgetPrivate::initStyleOptionTitleBar(QStyleOptionTitleBar *option)
{
Q_Q(QGraphicsWidget);
+ ensureWindowData();
q->initStyleOption(option);
option->rect.setHeight(titleBarHeight(*option));
option->titleBarFlags = windowFlags;
option->subControls = QStyle::SC_TitleBarCloseButton | QStyle::SC_TitleBarLabel | QStyle::SC_TitleBarSysMenu;
- option->activeSubControls = hoveredSubControl;
+ option->activeSubControls = windowData->hoveredSubControl;
bool isActive = q->isActiveWindow();
if (isActive) {
option->state |= QStyle::State_Active;
@@ -313,7 +318,8 @@ void QGraphicsWidgetPrivate::initStyleOptionTitleBar(QStyleOptionTitleBar *optio
}
QFont windowTitleFont = QApplication::font("QWorkspaceTitleBar");
QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel, 0);
- option->text = QFontMetrics(windowTitleFont).elidedText(windowTitle, Qt::ElideRight, textRect.width());
+ option->text = QFontMetrics(windowTitleFont).elidedText(
+ windowData->windowTitle, Qt::ElideRight, textRect.width());
}
void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags)
@@ -341,9 +347,10 @@ void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags)
void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
Q_Q(QGraphicsWidget);
- if (grabbedSection != Qt::NoSection) {
- if (grabbedSection == Qt::TitleBarArea) {
- buttonSunken = false;
+ ensureWindowData();
+ if (windowData->grabbedSection != Qt::NoSection) {
+ if (windowData->grabbedSection == Qt::TitleBarArea) {
+ windowData->buttonSunken = false;
QStyleOptionTitleBar bar;
initStyleOptionTitleBar(&bar);
// make sure that the coordinates (rect and pos) we send to the style are positive.
@@ -351,8 +358,10 @@ void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEve
bar.rect.moveTo(0,0);
bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar));
QPointF pos = event->pos();
- pos.rx() += leftWindowFrameMargin;
- pos.ry() += topWindowFrameMargin;
+ if (windowFrameMargins) {
+ pos.rx() += windowFrameMargins[Left];
+ pos.ry() += windowFrameMargins[Top];
+ }
bar.subControls = QStyle::SC_TitleBarCloseButton;
if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar,
QStyle::SC_TitleBarCloseButton,
@@ -361,7 +370,7 @@ void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEve
}
}
if (!(static_cast<QGraphicsSceneMouseEvent *>(event)->buttons()))
- grabbedSection = Qt::NoSection;
+ windowData->grabbedSection = Qt::NoSection;
event->accept();
}
}
@@ -372,35 +381,16 @@ void QGraphicsWidgetPrivate::windowFrameMousePressEvent(QGraphicsSceneMouseEvent
if (event->button() != Qt::LeftButton)
return;
- startGeometry = q->geometry();
- grabbedSection = q->windowFrameSectionAt(event->pos());
- switch (grabbedSection) {
- case Qt::LeftSection:
- case Qt::TopLeftSection:
- mouseDelta = event->pos() - q->rect().topLeft();
- break;
- case Qt::TopSection:
- case Qt::TopRightSection:
- mouseDelta = event->pos() - q->rect().topRight();
- break;
- case Qt::RightSection:
- case Qt::BottomRightSection:
- mouseDelta = event->pos() - q->rect().bottomRight();
- break;
- case Qt::BottomSection:
- case Qt::BottomLeftSection:
- mouseDelta = event->pos() - q->rect().bottomLeft();
- break;
- case Qt::TitleBarArea:
- if (hoveredSubControl == QStyle::SC_TitleBarCloseButton) {
- buttonSunken = true;
- q->update();
- }
- break;
- case Qt::NoSection:
- break;
+ ensureWindowData();
+ windowData->startGeometry = q->geometry();
+ windowData->grabbedSection = q->windowFrameSectionAt(event->pos());
+ ensureWindowData();
+ if (windowData->grabbedSection == Qt::TitleBarArea
+ && windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton) {
+ windowData->buttonSunken = true;
+ q->update();
}
- event->setAccepted(grabbedSection != Qt::NoSection);
+ event->setAccepted(windowData->grabbedSection != Qt::NoSection);
}
static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
@@ -455,7 +445,8 @@ static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
Q_Q(QGraphicsWidget);
- if (!(event->buttons() & Qt::LeftButton) || hoveredSubControl != QStyle::SC_TitleBarLabel)
+ ensureWindowData();
+ if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel)
return;
QLineF delta(q->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)), event->pos());
@@ -464,49 +455,56 @@ void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent
QLineF parentYDelta(q->mapToParent(QPointF(0, delta.p1().y())), q->mapToParent(QPointF(0, delta.p2().y())));
QRectF newGeometry;
- switch (grabbedSection) {
+ switch (windowData->grabbedSection) {
case Qt::LeftSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()),
- startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentXDelta.dx(), parentXDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
break;
case Qt::TopLeftSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()),
- startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentDelta.dx(), parentDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
break;
case Qt::TopSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()),
- startGeometry.size() - QSizeF(0, delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentYDelta.dx(), parentYDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(0, delta.dy()));
break;
case Qt::TopRightSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()),
- startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentYDelta.dx(), parentYDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
break;
case Qt::RightSection:
- newGeometry = QRectF(startGeometry.topLeft(),
- startGeometry.size() + QSizeF(delta.dx(), 0));
+ newGeometry = QRectF(windowData->startGeometry.topLeft(),
+ windowData->startGeometry.size() + QSizeF(delta.dx(), 0));
break;
case Qt::BottomRightSection:
- newGeometry = QRectF(startGeometry.topLeft(),
- startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft(),
+ windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
break;
case Qt::BottomSection:
- newGeometry = QRectF(startGeometry.topLeft(),
- startGeometry.size() + QSizeF(0, delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft(),
+ windowData->startGeometry.size() + QSizeF(0, delta.dy()));
break;
case Qt::BottomLeftSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()),
- startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentXDelta.dx(), parentXDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
break;
case Qt::TitleBarArea:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()),
- startGeometry.size());
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentDelta.dx(), parentDelta.dy()),
+ windowData->startGeometry.size());
break;
case Qt::NoSection:
break;
}
- if (grabbedSection != Qt::NoSection) {
- _q_boundGeometryToSizeConstraints(startGeometry, &newGeometry, grabbedSection,
+ if (windowData->grabbedSection != Qt::NoSection) {
+ _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry,
+ windowData->grabbedSection,
q->effectiveSizeHint(Qt::MinimumSize),
q->effectiveSizeHint(Qt::MaximumSize));
q->setGeometry(newGeometry);
@@ -519,21 +517,25 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent
if (!hasDecoration())
return;
+ ensureWindowData();
+
if (q->rect().contains(event->pos())) {
- if (buttonMouseOver || hoveredSubControl != QStyle::SC_None)
+ if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None)
windowFrameHoverLeaveEvent(event);
return;
}
- bool wasMouseOver = buttonMouseOver;
- QRect oldButtonRect = buttonRect;
- buttonRect = QRect();
- buttonMouseOver = false;
+ bool wasMouseOver = windowData->buttonMouseOver;
+ QRect oldButtonRect = windowData->buttonRect;
+ windowData->buttonRect = QRect();
+ windowData->buttonMouseOver = false;
QPointF pos = event->pos();
QStyleOptionTitleBar bar;
// make sure that the coordinates (rect and pos) we send to the style are positive.
- pos.rx() += leftWindowFrameMargin;
- pos.ry() += topWindowFrameMargin;
+ if (windowFrameMargins) {
+ pos.rx() += windowFrameMargins[Left];
+ pos.ry() += windowFrameMargins[Top];
+ }
initStyleOptionTitleBar(&bar);
bar.rect = q->windowFrameRect().toRect();
bar.rect.moveTo(0,0);
@@ -559,14 +561,17 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent
cursorShape = Qt::SizeVerCursor;
break;
case Qt::TitleBarArea:
- buttonRect = q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0);
+ windowData->buttonRect = q->style()->subControlRect(
+ QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0);
#ifdef Q_WS_MAC
// On mac we should hover if we are in the 'area' of the buttons
- buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0);
- buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0);
+ windowData->buttonRect |= q->style()->subControlRect(
+ QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0);
+ windowData->buttonRect |= q->style()->subControlRect(
+ QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0);
#endif
- if (buttonRect.contains(pos.toPoint()))
- buttonMouseOver = true;
+ if (windowData->buttonRect.contains(pos.toPoint()))
+ windowData->buttonMouseOver = true;
event->ignore();
break;
default:
@@ -578,15 +583,15 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent
q->setCursor(cursorShape);
#endif
// update buttons if we hover over them
- hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0);
- if (hoveredSubControl != QStyle::SC_TitleBarCloseButton)
- hoveredSubControl = QStyle::SC_TitleBarLabel;
+ windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0);
+ if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton)
+ windowData->hoveredSubControl = QStyle::SC_TitleBarLabel;
- if (buttonMouseOver != wasMouseOver) {
+ if (windowData->buttonMouseOver != wasMouseOver) {
if (!oldButtonRect.isNull())
q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft()));
- if (!buttonRect.isNull())
- q->update(QRectF(buttonRect).translated(q->windowFrameRect().topLeft()));
+ if (!windowData->buttonRect.isNull())
+ q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft()));
}
}
@@ -600,16 +605,19 @@ void QGraphicsWidgetPrivate::windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent
q->unsetCursor();
#endif
+ ensureWindowData();
+
bool needsUpdate = false;
- if (hoveredSubControl == QStyle::SC_TitleBarCloseButton || buttonMouseOver)
+ if (windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton
+ || windowData->buttonMouseOver)
needsUpdate = true;
// update the hover state (of buttons etc...)
- hoveredSubControl = QStyle::SC_None;
- buttonMouseOver = false;
- buttonRect = QRect();
+ windowData->hoveredSubControl = QStyle::SC_None;
+ windowData->buttonMouseOver = false;
+ windowData->buttonRect = QRect();
if (needsUpdate)
- q->update(buttonRect);
+ q->update(windowData->buttonRect);
}
}
@@ -618,34 +626,6 @@ bool QGraphicsWidgetPrivate::hasDecoration() const
return (windowFlags & Qt::Window) && (windowFlags & Qt::WindowTitleHint);
}
-/*!
- \internal
-*/
-void QGraphicsWidgetPrivate::setFocusWidget()
-{
- // Update focus child chain.
- QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
- QGraphicsWidget *parent = widget;
- bool hidden = !visible;
- do {
- parent->d_func()->focusChild = widget;
- } while (!parent->isWindow() && (parent = parent->parentWidget()) && (!hidden || !parent->d_func()->visible));
-}
-
-/*!
- \internal
-*/
-void QGraphicsWidgetPrivate::clearFocusWidget()
-{
- // Reset focus child chain.
- QGraphicsWidget *parent = static_cast<QGraphicsWidget *>(q_ptr);
- do {
- if (parent->d_func()->focusChild != q_ptr)
- break;
- parent->d_func()->focusChild = 0;
- } while (!parent->isWindow() && (parent = parent->parentWidget()));
-}
-
/**
* is called after a reparent has taken place to fix up the focus chain(s)
*/
@@ -662,12 +642,6 @@ void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *new
QGraphicsWidget *firstOld = 0;
bool wasPreviousNew = true;
-
- if (focusChild) {
- // Ensure that the current focus child doesn't leave pointers around
- // before reparenting.
- focusChild->clearFocus();
- }
while (w != q) {
bool isCurrentNew = q->isAncestorOf(w);
diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h
index f688fe8..dd58bbb 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.h
+++ b/src/gui/graphicsview/qgraphicswidget_p.h
@@ -47,8 +47,8 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
//
// We mean it.
//
@@ -68,19 +68,12 @@ class QStyleOptionTitleBar;
#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
-class Q_GUI_EXPORT QGraphicsWidgetPrivate : public QGraphicsItemPrivate
+class QGraphicsWidgetPrivate : public QGraphicsItemPrivate
{
Q_DECLARE_PUBLIC(QGraphicsWidget)
public:
QGraphicsWidgetPrivate()
- : leftMargin(0),
- topMargin(0),
- rightMargin(0),
- bottomMargin(0),
- leftLayoutItemMargin(0),
- topLayoutItemMargin(0),
- rightLayoutItemMargin(0),
- bottomLayoutItemMargin(0),
+ : margins(0),
layout(0),
inheritedPaletteResolveMask(0),
inheritedFontResolveMask(0),
@@ -90,42 +83,24 @@ public:
focusPolicy(Qt::NoFocus),
focusNext(0),
focusPrev(0),
- focusChild(0),
windowFlags(0),
- hoveredSubControl(QStyle::SC_None),
- grabbedSection(Qt::NoSection),
- buttonMouseOver(false),
- buttonSunken(false),
+ windowData(0),
setWindowFrameMargins(false),
- leftWindowFrameMargin(0),
- topWindowFrameMargin(0),
- rightWindowFrameMargin(0),
- bottomWindowFrameMargin(0)
+ windowFrameMargins(0)
{ }
+ virtual ~QGraphicsWidgetPrivate();
void init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags);
qreal titleBarHeight(const QStyleOptionTitleBar &options) const;
// Margins
- qreal leftMargin;
- qreal topMargin;
- qreal rightMargin;
- qreal bottomMargin;
- QRectF contentsRect;
-
- // Layout item margins
- void getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const;
- void setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom);
- void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0);
+ enum {Left, Top, Right, Bottom};
+ mutable qreal *margins;
+ void ensureMargins() const;
void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *newScene = 0);
void setLayout_helper(QGraphicsLayout *l);
- qreal leftLayoutItemMargin;
- qreal topLayoutItemMargin;
- qreal rightLayoutItemMargin;
- qreal bottomLayoutItemMargin;
-
// Layouts
QGraphicsLayout *layout;
void setLayoutDirection_helper(Qt::LayoutDirection direction);
@@ -202,26 +177,29 @@ public:
Qt::FocusPolicy focusPolicy;
QGraphicsWidget *focusNext;
QGraphicsWidget *focusPrev;
- QGraphicsWidget *focusChild;
- void setFocusWidget();
- void clearFocusWidget();
// Windows
Qt::WindowFlags windowFlags;
- QString windowTitle;
- QStyle::SubControl hoveredSubControl;
- Qt::WindowFrameSection grabbedSection;
- uint buttonMouseOver : 1;
- uint buttonSunken : 1;
- QPointF mouseDelta; // to compensate for small error when interactively resizing
- QRectF startGeometry;
- QRect buttonRect;
+ struct WindowData {
+ QString windowTitle;
+ QStyle::SubControl hoveredSubControl;
+ Qt::WindowFrameSection grabbedSection;
+ uint buttonMouseOver : 1;
+ uint buttonSunken : 1;
+ QRectF startGeometry;
+ QRect buttonRect;
+ WindowData()
+ : hoveredSubControl(QStyle::SC_None)
+ , grabbedSection(Qt::NoSection)
+ , buttonMouseOver(false)
+ , buttonSunken(false)
+ {}
+ } *windowData;
+ void ensureWindowData();
bool setWindowFrameMargins;
- qreal leftWindowFrameMargin;
- qreal topWindowFrameMargin;
- qreal rightWindowFrameMargin;
- qreal bottomWindowFrameMargin;
+ mutable qreal *windowFrameMargins;
+ void ensureWindowFrameMargins() const;
#ifndef QT_NO_ACTION
QList<QAction *> actions;
diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp
index ee09da5..b2b4551 100644
--- a/src/gui/graphicsview/qgridlayoutengine.cpp
+++ b/src/gui/graphicsview/qgridlayoutengine.cpp
@@ -275,7 +275,7 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz
if (hasIgnoreFlag) {
factors[i] = (stretch < 0) ? 1.0 : 0.0;
} else {
- factors[i] = (stretch < 0) ? sizes[i] : 0.0;
+ factors[i] = (stretch < 0) ? sizes[i] : 0.0;
}
} else if (stretch == sumStretches) {
factors[i] = 1.0;
@@ -461,7 +461,7 @@ void QGridLayoutRowData::dump(int indent) const
QGridLayoutItem::QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem,
int row, int column, int rowSpan, int columnSpan,
- Qt::Alignment alignment)
+ Qt::Alignment alignment, int itemAtIndex)
: q_engine(engine), q_layoutItem(layoutItem), q_alignment(alignment)
{
q_firstRows[Hor] = column;
@@ -471,7 +471,7 @@ QGridLayoutItem::QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem
q_stretches[Hor] = -1;
q_stretches[Ver] = -1;
- q_engine->addItem(this);
+ q_engine->insertItem(this, itemAtIndex);
}
int QGridLayoutItem::firstRow(Qt::Orientation orientation) const
@@ -615,7 +615,7 @@ QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal heig
QSizeF size = effectiveMaxSize().boundedTo(QSizeF(cellWidth, cellHeight));
width = size.width();
height = size.height();
-
+
Qt::Alignment align = q_engine->effectiveAlignment(this);
switch (align & Qt::AlignHorizontal_Mask) {
case Qt::AlignHCenter:
@@ -717,7 +717,7 @@ void QGridLayoutItem::dump(int indent) const
void QGridLayoutRowInfo::insertOrRemoveRows(int row, int delta)
{
count += delta;
-
+
insertOrRemoveItems(stretches, row, delta);
insertOrRemoveItems(spacings, row, delta);
insertOrRemoveItems(alignments, row, delta);
@@ -937,11 +937,20 @@ Qt::Alignment QGridLayoutEngine::effectiveAlignment(const QGridLayoutItem *layou
return align;
}
-void QGridLayoutEngine::addItem(QGridLayoutItem *item)
+/*!
+ \internal
+ The \a index is only used by QGraphicsLinearLayout to ensure that itemAt() reflects the order
+ of visual arrangement. Strictly speaking it does not have to, but most people expect it to.
+ (And if it didn't we would have to add itemArrangedAt(int index) or something..)
+ */
+void QGridLayoutEngine::insertItem(QGridLayoutItem *item, int index)
{
maybeExpandGrid(item->lastRow(), item->lastColumn());
- q_items.append(item);
+ if (index == -1)
+ q_items.append(item);
+ else
+ q_items.insert(index, item);
for (int i = item->firstRow(); i <= item->lastRow(); ++i) {
for (int j = item->firstColumn(); j <= item->lastColumn(); ++j) {
@@ -952,6 +961,11 @@ void QGridLayoutEngine::addItem(QGridLayoutItem *item)
}
}
+void QGridLayoutEngine::addItem(QGridLayoutItem *item)
+{
+ insertItem(item, -1);
+}
+
void QGridLayoutEngine::removeItem(QGridLayoutItem *item)
{
Q_ASSERT(q_items.contains(item));
@@ -1076,7 +1090,7 @@ QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHi
break;
}
return QSizeF();
-}
+}
QSizePolicy::ControlTypes QGridLayoutEngine::controlTypes(LayoutSide side) const
{
@@ -1131,9 +1145,9 @@ void QGridLayoutEngine::dump(int indent) const
QString message = QLatin1String("[ ");
for (int column = 0; column < internalGridColumnCount(); ++column) {
message += QString::number(q_items.indexOf(itemAt(row, column))).rightJustified(3);
- message += QLatin1String(" ");
+ message += QLatin1Char(' ');
}
- message += QLatin1String("]");
+ message += QLatin1Char(']');
qDebug("%*s %s", indent, "", qPrintable(message));
}
@@ -1150,16 +1164,16 @@ void QGridLayoutEngine::dump(int indent) const
q_rowData.dump(indent + 2);
qDebug("%*s Geometries output", indent, "");
+ QVector<qreal> *cellPos = &q_yy;
for (int pass = 0; pass < 2; ++pass) {
- QVector<qreal> &cellPos = q_yy;
QString message;
- for (i = 0; i < cellPos.count(); ++i) {
+ for (i = 0; i < cellPos->count(); ++i) {
message += QLatin1String((message.isEmpty() ? "[" : ", "));
- message += QString::number(cellPos.at(i));
+ message += QString::number(cellPos->at(i));
}
- message += QLatin1String("]");
+ message += QLatin1Char(']');
qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message));
- cellPos = q_xx;
+ cellPos = &q_xx;
}
}
#endif
@@ -1538,5 +1552,5 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo,
}
QT_END_NAMESPACE
-
+
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h
index e88fc5e..66cc225 100644
--- a/src/gui/graphicsview/qgridlayoutengine_p.h
+++ b/src/gui/graphicsview/qgridlayoutengine_p.h
@@ -267,7 +267,8 @@ class QGridLayoutItem
{
public:
QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem, int row, int column,
- int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0);
+ int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0,
+ int itemAtIndex = -1);
inline int firstRow() const { return q_firstRows[Ver]; }
inline int firstColumn() const { return q_firstRows[Hor]; }
@@ -378,6 +379,7 @@ public:
Qt::Alignment effectiveAlignment(const QGridLayoutItem *layoutItem) const;
+ void insertItem(QGridLayoutItem *item, int index);
void addItem(QGridLayoutItem *item);
void removeItem(QGridLayoutItem *item);
QGridLayoutItem *findLayoutItem(QGraphicsLayoutItem *layoutItem) const;
diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp
new file mode 100644
index 0000000..30a7d5d
--- /dev/null
+++ b/src/gui/graphicsview/qsimplex_p.cpp
@@ -0,0 +1,412 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplex_p.h"
+
+#include <QtCore/qset.h>
+#include <QtCore/qdebug.h>
+
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+QSimplex::QSimplex() : objective(0), rows(0), columns(0), firstArtificial(0), matrix(0)
+{
+}
+
+QSimplex::~QSimplex()
+{
+ clearDataStructures();
+}
+
+void QSimplex::clearDataStructures()
+{
+ if (matrix == 0)
+ return;
+
+ // Matrix
+ rows = 0;
+ columns = 0;
+ firstArtificial = 0;
+ free(matrix);
+ matrix = 0;
+
+ // Constraints
+ for (int i = 0; i < constraints.size(); ++i) {
+ delete constraints[i]->helper.first;
+ constraints[i]->helper.first = 0;
+ constraints[i]->helper.second = 0.0;
+ delete constraints[i]->artificial;
+ constraints[i]->artificial = 0;
+ }
+ constraints.clear();
+
+ // Other
+ variables.clear();
+ objective = 0;
+}
+
+void QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints)
+{
+ clearDataStructures();
+
+ if (newConstraints.isEmpty())
+ return;
+ constraints = newConstraints;
+
+ // Set Variables direct mapping
+ QSet<QSimplexVariable *> variablesSet;
+ for (int i = 0; i < constraints.size(); ++i)
+ variablesSet += \
+ QSet<QSimplexVariable *>::fromList(constraints[i]->variables.keys());
+ variables = variablesSet.toList();
+
+ // Set Variables reverse mapping
+ for (int i = 0; i < variables.size(); ++i) {
+ // The variable "0" goes at the column "1", etc...
+ variables[i]->index = i + 1;
+ }
+
+ // Normalize Constraints
+ int variableIndex = variables.size();
+ QList <QSimplexVariable *> artificialList;
+
+ for (int i = 0; i < constraints.size(); ++i) {
+ QSimplexVariable *slack;
+ QSimplexVariable *surplus;
+ QSimplexVariable *artificial;
+
+ Q_ASSERT(constraints[i]->helper.first == 0);
+ Q_ASSERT(constraints[i]->artificial == 0);
+
+ switch(constraints[i]->ratio) {
+ case QSimplexConstraint::LessOrEqual:
+ slack = new QSimplexVariable;
+ slack->index = ++variableIndex;
+ constraints[i]->helper.first = slack;
+ constraints[i]->helper.second = 1.0;
+ break;
+ case QSimplexConstraint::MoreOrEqual:
+ surplus = new QSimplexVariable;
+ surplus->index = ++variableIndex;
+ constraints[i]->helper.first = surplus;
+ constraints[i]->helper.second = -1.0;
+ // fall through
+ case QSimplexConstraint::Equal:
+ artificial = new QSimplexVariable;
+ constraints[i]->artificial = artificial;
+ artificialList += constraints[i]->artificial;
+ break;
+ }
+ }
+
+ firstArtificial = variableIndex + 1;
+ for (int i = 0; i < artificialList.size(); ++i)
+ artificialList[i]->index = ++variableIndex;
+ artificialList.clear();
+
+ // Matrix
+
+ // One for each variable plus the Basic and BFS columns (first and last)
+ columns = variableIndex + 2;
+ // One for each constraint plus the objective function
+ rows = constraints.size() + 1;
+
+ matrix = (qreal *)malloc(sizeof(qreal) * columns * rows);
+ if (!matrix) {
+ qWarning() << "QSimplex: Unable to allocate memory!";
+ return;
+ }
+ for (int i = columns * rows - 1; i >= 0; --i)
+ matrix[i] = 0.0;
+
+ // Fill Matrix
+ for (int i = 1; i <= constraints.size(); ++i) {
+ QSimplexConstraint *c = constraints[i - 1];
+
+ if (c->artificial) {
+ // Will use artificial basic variable
+ setValueAt(i, 0, c->artificial->index);
+ setValueAt(i, c->artificial->index, 1.0);
+
+ if (c->helper.second != 0.0) {
+ // Surplus variable
+ setValueAt(i, c->helper.first->index, c->helper.second);
+ }
+ } else {
+ // Slack is used as the basic variable
+ Q_ASSERT(c->helper.second == 1.0);
+ setValueAt(i, 0, c->helper.first->index);
+ setValueAt(i, c->helper.first->index, 1.0);
+ }
+
+ QHash<QSimplexVariable *, qreal>::const_iterator iter;
+ for (iter = c->variables.constBegin();
+ iter != c->variables.constEnd();
+ ++iter) {
+ setValueAt(i, iter.key()->index, iter.value());
+ }
+
+ setValueAt(i, columns - 1, c->constant);
+ }
+
+ // Set temporary objective: -1 * sum_of_artificial_vars
+ for (int j = firstArtificial; j < columns - 1; ++j)
+ setValueAt(0, j, 1.0);
+
+ // Maximize our objective (artificial vars go to zero)
+ solveMaxHelper();
+
+ if (valueAt(0, columns - 1) != 0.0) {
+ qWarning() << "QSimplex: No feasible solution!";
+ clearDataStructures();
+ return;
+ }
+
+ // Remove artificial variables
+ clearColumns(firstArtificial, columns - 2);
+}
+
+void QSimplex::solveMaxHelper()
+{
+ reducedRowEchelon();
+ while (iterate()) ;
+}
+
+void QSimplex::setObjective(QSimplexConstraint *newObjective)
+{
+ objective = newObjective;
+}
+
+void QSimplex::clearRow(int rowIndex)
+{
+ qreal *item = matrix + rowIndex * columns;
+ for (int i = 0; i < columns; ++i)
+ item[i] = 0.0;
+}
+
+void QSimplex::clearColumns(int first, int last)
+{
+ for (int i = 0; i < rows; ++i) {
+ qreal *row = matrix + i * columns;
+ for (int j = first; j <= last; ++j)
+ row[j] = 0.0;
+ }
+}
+
+void QSimplex::dumpMatrix()
+{
+ printf("---- Simplex Matrix ----\n");
+
+ printf(" ");
+ for (int j = 0; j < columns; ++j)
+ printf(" <% 2d >", j);
+ printf("\n");
+
+ for (int i = 0; i < rows; ++i) {
+ printf("Row %2d:", i);
+
+ qreal *row = matrix + i * columns;
+ for (int j = 0; j < columns; ++j) {
+ printf(" % 2.2f", row[j]);
+ }
+ printf("\n");
+ }
+ printf("------------------------\n\n");
+}
+
+void QSimplex::combineRows(int toIndex, int fromIndex, qreal factor)
+{
+ if (!factor)
+ return;
+
+ qreal *from = matrix + fromIndex * columns;
+ qreal *to = matrix + toIndex * columns;
+
+ for (int j = 1; j < columns; ++j) {
+ qreal value = from[j];
+
+ // skip to[j] = to[j] + factor*0.0
+ if (value == 0.0)
+ continue;
+
+ to[j] += factor * value;
+
+ // ### Avoid Numerical errors
+ if (qAbs(to[j]) < 0.0000000001)
+ to[j] = 0.0;
+ }
+}
+
+int QSimplex::findPivotColumn()
+{
+ qreal min = 0;
+ int minIndex = -1;
+
+ for (int j = 0; j < columns-1; ++j) {
+ if (valueAt(0, j) < min) {
+ min = valueAt(0, j);
+ minIndex = j;
+ }
+ }
+
+ return minIndex;
+}
+
+int QSimplex::pivotRowForColumn(int column)
+{
+ qreal min = qreal(999999999999.0); // ###
+ int minIndex = -1;
+
+ for (int i = 1; i < rows; ++i) {
+ qreal divisor = valueAt(i, column);
+ if (divisor <= 0)
+ continue;
+
+ qreal quotient = valueAt(i, columns - 1) / divisor;
+ if (quotient < min) {
+ min = quotient;
+ minIndex = i;
+ }
+ }
+
+ return minIndex;
+}
+
+void QSimplex::reducedRowEchelon()
+{
+ for (int i = 1; i < rows; ++i) {
+ int factorInObjectiveRow = valueAt(i, 0);
+ combineRows(0, i, -1 * valueAt(0, factorInObjectiveRow));
+ }
+}
+
+bool QSimplex::iterate()
+{
+ // Find Pivot column
+ int pivotColumn = findPivotColumn();
+ if (pivotColumn == -1)
+ return false;
+
+ // Find Pivot row for column
+ int pivotRow = pivotRowForColumn(pivotColumn);
+ if (pivotRow == -1) {
+ qWarning() << "QSimplex: Unbounded problem!";
+ return false;
+ }
+
+ // Normalize Pivot Row
+ qreal pivot = valueAt(pivotRow, pivotColumn);
+ if (pivot != 1.0)
+ combineRows(pivotRow, pivotRow, (1.0 - pivot) / pivot);
+
+ // Update other rows
+ for (int row=0; row < rows; ++row) {
+ if (row == pivotRow)
+ continue;
+
+ combineRows(row, pivotRow, -1 * valueAt(row, pivotColumn));
+ }
+
+ // Update first column
+ setValueAt(pivotRow, 0, pivotColumn);
+
+ // dumpMatrix();
+ // printf("------------ end of iteration --------------\n");
+ return true;
+}
+
+/*!
+ \internal
+
+ Both solveMin and solveMax are interfaces to this method.
+
+ The enum solverFactor admits 2 values: Minimum (-1) and Maximum (+1).
+ */
+qreal QSimplex::solver(solverFactor factor)
+{
+ // Remove old objective
+ clearRow(0);
+
+ // Set new objective
+ QHash<QSimplexVariable *, qreal>::const_iterator iter;
+ for (iter = objective->variables.constBegin();
+ iter != objective->variables.constEnd();
+ ++iter) {
+ setValueAt(0, iter.key()->index, -1 * factor * iter.value());
+ }
+
+ solveMaxHelper();
+ collectResults();
+
+ return factor * valueAt(0, columns - 1);
+}
+
+qreal QSimplex::solveMin()
+{
+ return solver(Minimum);
+}
+
+qreal QSimplex::solveMax()
+{
+ return solver(Maximum);
+}
+
+void QSimplex::collectResults()
+{
+ // All variables are zero unless overridden below.
+
+ // ### Is this really needed? Is there any chance that an
+ // important variable remains as non-basic at the end of simplex?
+ for (int i = 0; i < variables.size(); ++i)
+ variables[i]->result = 0;
+
+ // Basic variables
+ // Update the variable indicated in the first column with the value
+ // in the last column.
+ for (int i = 1; i < rows; ++i) {
+ int index = valueAt(i, 0) - 1;
+ if (index < variables.size())
+ variables[index]->result = valueAt(i, columns - 1);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qsimplex_p.h b/src/gui/graphicsview/qsimplex_p.h
new file mode 100644
index 0000000..5d32dd3
--- /dev/null
+++ b/src/gui/graphicsview/qsimplex_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLEX_P_H
+#define QSIMPLEX_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/qhash.h>
+#include <QtCore/qpair.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QSimplexVariable
+{
+ QSimplexVariable() : result(0), index(0) {};
+
+ qreal result;
+ uint index;
+};
+
+
+/*!
+ \internal
+
+ Representation of a LP constraint like:
+
+ (c1 * X1) + (c2 * X2) + ... = K
+ or <= K
+ or >= K
+
+ Where (ci, Xi) are the pairs in "variables" and K the real "constant".
+*/
+struct QSimplexConstraint
+{
+ QSimplexConstraint() : constant(0), ratio(Equal), artificial(0) {};
+
+ enum Ratio {
+ LessOrEqual = 0,
+ Equal,
+ MoreOrEqual
+ };
+
+ QHash<QSimplexVariable *, qreal> variables;
+ qreal constant;
+ Ratio ratio;
+
+ QPair<QSimplexVariable *, qreal> helper;
+ QSimplexVariable * artificial;
+};
+
+
+class QSimplex
+{
+public:
+ QSimplex();
+ virtual ~QSimplex();
+
+ qreal solveMin();
+ qreal solveMax();
+ QList<QSimplexVariable *> constraintsVariables();
+
+ void setConstraints(const QList<QSimplexConstraint *> constraints);
+ void setObjective(QSimplexConstraint *objective);
+
+ void dumpMatrix();
+
+private:
+ // Matrix handling
+ qreal valueAt(int row, int column);
+ void setValueAt(int row, int column, qreal value);
+ void clearRow(int rowIndex);
+ void clearColumns(int first, int last);
+ void combineRows(int toIndex, int fromIndex, qreal factor);
+
+ // Simplex
+ int findPivotColumn();
+ int pivotRowForColumn(int column);
+ void reducedRowEchelon();
+ bool iterate();
+
+ // Helpers
+ void clearDataStructures();
+ void solveMaxHelper();
+ enum solverFactor { Minimum = -1, Maximum = 1 };
+ qreal solver(solverFactor factor);
+ void collectResults();
+
+ QList<QSimplexConstraint *> constraints;
+ QList<QSimplexVariable *> variables;
+ QSimplexConstraint *objective;
+
+ int rows;
+ int columns;
+ int firstArtificial;
+
+ qreal *matrix;
+};
+
+inline QList<QSimplexVariable *> QSimplex::constraintsVariables()
+{
+ return variables;
+}
+
+inline qreal QSimplex::valueAt(int rowIndex, int columnIndex)
+{
+ return matrix[rowIndex * columns + columnIndex];
+}
+
+inline void QSimplex::setValueAt(int rowIndex, int columnIndex, qreal value)
+{
+ matrix[rowIndex * columns + columnIndex] = value;
+}
+
+QT_END_NAMESPACE
+
+#endif // QSIMPLEX_P_H
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index f224e67..eb3a33f 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -4,7 +4,7 @@ QT = core
DEFINES += QT_BUILD_GUI_LIB QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000
-!win32:!embedded:!mac:CONFIG += x11
+!win32:!embedded:!mac:!symbian:CONFIG += x11
unix:QMAKE_PKGCONFIG_REQUIRES = QtCore
@@ -17,8 +17,10 @@ x11:include(kernel/x11.pri)
mac:include(kernel/mac.pri)
win32:include(kernel/win.pri)
embedded:include(embedded/embedded.pri)
+symbian:include(kernel/symbian.pri)
#modules
+include(animation/animation.pri)
include(kernel/kernel.pri)
include(image/image.pri)
include(painting/painting.pri)
@@ -31,6 +33,11 @@ include(itemviews/itemviews.pri)
include(inputmethod/inputmethod.pri)
include(graphicsview/graphicsview.pri)
include(util/util.pri)
+include(statemachine/statemachine.pri)
+include(math3d/math3d.pri)
+include(effects/effects.pri)
+
+contains(QT_CONFIG, egl): include(egl/egl.pri)
embedded: QT += network
@@ -41,4 +48,7 @@ contains(DEFINES,QT_EVAL):include($$QT_SOURCE_TREE/src/corelib/eval.pri)
QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtGui.dynlist
DEFINES += Q_INTERNAL_QAPP_SRC
+symbian:TARGET.UID3=0x2001B2DD
+# ro-section in gui can exceed default allocated space, so more rw-section little further
+symbian-sbsv2: MMP_RULES += "LINKEROPTION armcc --rw-base 0x800000"
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index ca52974..0970385 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -6,6 +6,8 @@
HEADERS += \
image/qbitmap.h \
image/qicon.h \
+ image/qicon_p.h \
+ image/qiconloader_p.h \
image/qiconengine.h \
image/qiconengineplugin.h \
image/qimage.h \
@@ -22,13 +24,17 @@ HEADERS += \
image/qpixmap.h \
image/qpixmap_raster_p.h \
image/qpixmapcache.h \
+ image/qpixmapcache_p.h \
image/qpixmapdata_p.h \
image/qpixmapdatafactory_p.h \
- image/qpixmapfilter_p.h
+ image/qpixmapfilter_p.h \
+ image/qimagepixmapcleanuphooks_p.h \
+
SOURCES += \
image/qbitmap.cpp \
image/qicon.cpp \
+ image/qiconloader.cpp \
image/qimage.cpp \
image/qimageiohandler.cpp \
image/qimagereader.cpp \
@@ -46,6 +52,8 @@ SOURCES += \
image/qmovie.cpp \
image/qpixmap_raster.cpp \
image/qnativeimage.cpp \
+ image/qimagepixmapcleanuphooks.cpp \
+
win32 {
SOURCES += image/qpixmap_win.cpp
@@ -61,6 +69,9 @@ mac {
HEADERS += image/qpixmap_mac_p.h
SOURCES += image/qpixmap_mac.cpp
}
+symbian {
+ SOURCES += image/qpixmap_s60.cpp
+}
# Built-in image format support
HEADERS += \
@@ -81,7 +92,7 @@ SOURCES += \
SOURCES += image/qpnghandler.cpp
contains(QT_CONFIG, system-png) {
- unix:LIBS += -lpng
+ unix:LIBS_PRIVATE += -lpng
win32:LIBS += libpng.lib
} else {
!isEqual(QT_ARCH, i386):!isEqual(QT_ARCH, x86_64):DEFINES += PNG_NO_ASSEMBLER_CODE
diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp
index 820b25e..8c3b9be 100644
--- a/src/gui/image/qbitmap.cpp
+++ b/src/gui/image/qbitmap.cpp
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
\class QBitmap
\brief The QBitmap class provides monochrome (1-bit depth) pixmaps.
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
The QBitmap class is a monochrome off-screen paint device used
@@ -78,7 +78,7 @@ QT_BEGIN_NAMESPACE
0 for black and 1 for white.
The QBitmap class provides the transformed() function returning a
- transformed copy of the bitmap; use the QMatrix argument to
+ transformed copy of the bitmap; use the QTransform argument to
translate, scale, shear, and rotate the bitmap. In addition,
QBitmap provides the static fromData() function which returns a
bitmap constructed from the given \c uchar data, and the static
@@ -265,15 +265,12 @@ QBitmap QBitmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
img.setColor(1, c0);
}
- QPixmapData *d;
QGraphicsSystem* gs = QApplicationPrivate::graphicsSystem();
- if (gs)
- d = gs->createPixmapData(QPixmapData::BitmapType);
- else
- d = QGraphicsSystem::createDefaultPixmapData(QPixmapData::BitmapType);
+ QScopedPointer<QPixmapData> data(gs ? gs->createPixmapData(QPixmapData::BitmapType)
+ : QGraphicsSystem::createDefaultPixmapData(QPixmapData::BitmapType));
- d->fromImage(img, flags | Qt::MonoOnly);
- return QPixmap(d);
+ data->fromImage(img, flags | Qt::MonoOnly);
+ return QPixmap(data.take());
}
/*!
@@ -318,6 +315,7 @@ QBitmap QBitmap::transformed(const QTransform &matrix) const
/*!
\overload
+ \obsolete
This convenience function converts the \a matrix to a QTransform
and calls the overloaded function.
diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h
index d095b62..c531061 100644
--- a/src/gui/image/qbitmap.h
+++ b/src/gui/image/qbitmap.h
@@ -82,6 +82,8 @@ public:
QT3_SUPPORT_CONSTRUCTOR QBitmap(const QImage &image) { *this = fromImage(image); }
QT3_SUPPORT QBitmap &operator=(const QImage &image) { *this = fromImage(image); return *this; }
#endif
+
+ typedef QExplicitlySharedDataPointer<QPixmapData> DataPtr;
};
Q_DECLARE_SHARED(QBitmap)
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index e24fdcc..0380026 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -81,14 +81,14 @@ static void swapPixel01(QImage *image) // 1-bpp: swap 0 and 1 pixels
const int BMP_FILEHDR_SIZE = 14; // size of BMP_FILEHDR data
-QDataStream &operator>>(QDataStream &s, BMP_FILEHDR &bf)
+static QDataStream &operator>>(QDataStream &s, BMP_FILEHDR &bf)
{ // read file header
s.readRawData(bf.bfType, 2);
s >> bf.bfSize >> bf.bfReserved1 >> bf.bfReserved2 >> bf.bfOffBits;
return s;
}
-QDataStream &operator<<(QDataStream &s, const BMP_FILEHDR &bf)
+static QDataStream &operator<<(QDataStream &s, const BMP_FILEHDR &bf)
{ // write file header
s.writeRawData(bf.bfType, 2);
s << bf.bfSize << bf.bfReserved1 << bf.bfReserved2 << bf.bfOffBits;
@@ -106,7 +106,7 @@ const int BMP_RLE4 = 2; // run-length encoded, 4
const int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fields
-QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
+static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
{
s >> bi.biSize;
if (bi.biSize == BMP_WIN || bi.biSize == BMP_OS2) {
@@ -128,7 +128,7 @@ QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
return s;
}
-QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi)
+static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi)
{
s << bi.biSize;
s << bi.biWidth << bi.biHeight;
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 28796e3..a4ea6af 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -40,9 +40,11 @@
****************************************************************************/
#include "qicon.h"
+#include "qicon_p.h"
#include "qiconengine.h"
#include "qiconengineplugin.h"
#include "private/qfactoryloader_p.h"
+#include "private/qiconloader_p.h"
#include "qapplication.h"
#include "qstyleoption.h"
#include "qpainter.h"
@@ -50,11 +52,17 @@
#include "qstyle.h"
#include "qpixmapcache.h"
#include "qvariant.h"
+#include "qcache.h"
#include "qdebug.h"
#ifdef Q_WS_MAC
#include <private/qt_mac_p.h>
-#include <Carbon/Carbon.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
+#ifdef Q_WS_X11
+#include "private/qt_x11_p.h"
+#include "private/qkde_p.h"
#endif
QT_BEGIN_NAMESPACE
@@ -94,73 +102,14 @@ QT_BEGIN_NAMESPACE
static QBasicAtomicInt serialNumCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
-class QIconPrivate
-{
-public:
- QIconPrivate(): engine(0), ref(1), serialNum(serialNumCounter.fetchAndAddRelaxed(1)), detach_no(0), engine_version(2), v1RefCount(0) {}
-
- ~QIconPrivate() {
- if (engine_version == 1) {
- if (!v1RefCount->deref()) {
- delete engine;
- delete v1RefCount;
- }
- } else if (engine_version == 2) {
- delete engine;
- }
- }
-
- QIconEngine *engine;
-
- QAtomicInt ref;
- int serialNum;
- int detach_no;
- int engine_version;
-
- QAtomicInt *v1RefCount;
-};
-
-
-struct QPixmapIconEngineEntry
+QIconPrivate::QIconPrivate()
+ : engine(0), ref(1),
+ serialNum(serialNumCounter.fetchAndAddRelaxed(1)),
+ detach_no(0),
+ engine_version(2),
+ v1RefCount(0)
{
- QPixmapIconEngineEntry():mode(QIcon::Normal), state(QIcon::Off){}
- QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
- :pixmap(pm), size(pm.size()), mode(m), state(s){}
- QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
- :fileName(file), size(sz), mode(m), state(s){}
- QPixmap pixmap;
- QString fileName;
- QSize size;
- QIcon::Mode mode;
- QIcon::State state;
- bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }
-};
-
-class QPixmapIconEngine : public QIconEngineV2 {
-public:
- QPixmapIconEngine();
- QPixmapIconEngine(const QPixmapIconEngine &);
- ~QPixmapIconEngine();
- void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state);
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
- QPixmapIconEngineEntry *bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly);
- QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
- void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state);
- void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state);
-
- // v2 functions
- QString key() const;
- QIconEngineV2 *clone() const;
- bool read(QDataStream &in);
- bool write(QDataStream &out) const;
- void virtual_hook(int id, void *data);
-
-private:
- QPixmapIconEngineEntry *tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state);
- QVector<QPixmapIconEngineEntry> pixmaps;
-
- friend QDataStream &operator<<(QDataStream &s, const QIcon &icon);
-};
+}
QPixmapIconEngine::QPixmapIconEngine()
{
@@ -178,8 +127,8 @@ QPixmapIconEngine::~QPixmapIconEngine()
void QPixmapIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
{
QSize pixmapSize = rect.size();
-#if defined(Q_WS_MAC) && !defined(Q_WS_MAC64)
- pixmapSize *= (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) ? HIGetScaleFactor() : 1;
+#if defined(Q_WS_MAC)
+ pixmapSize *= qt_mac_get_scalefactor();
#endif
painter->drawPixmap(rect, pixmap(pixmapSize, mode, state));
}
@@ -304,6 +253,8 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
QString key = QLatin1String("$qt_icon_")
+ QString::number(pm.cacheKey())
+ QString::number(pe->mode)
+ + QString::number(QApplication::palette().cacheKey())
+ + QLatin1Char('_')
+ QString::number(actualSize.width())
+ QLatin1Char('_')
+ QString::number(actualSize.height())
@@ -494,9 +445,9 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loaderV2,
\brief The QIcon class provides scalable icons in different modes
and states.
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
- \mainclass
+
A QIcon can generate smaller, larger, active, and disabled pixmaps
from the set of pixmaps it is given. Such pixmaps are used by Qt
@@ -916,6 +867,148 @@ QList<QSize> QIcon::availableSizes(Mode mode, State state) const
return engine->availableSizes(mode, state);
}
+/*!
+ \since 4.6
+
+ Sets the search paths for icon themes to \a paths.
+ \sa themeSearchPaths(), fromTheme(), setThemeName()
+*/
+void QIcon::setThemeSearchPaths(const QStringList &paths)
+{
+ QIconLoader::instance()->setThemeSearchPath(paths);
+}
+
+/*!
+ \since 4.6
+
+ Returns the search paths for icon themes.
+
+ The default value will depend on the platform:
+
+ On X11, the search path will use the XDG_DATA_DIRS environment
+ variable if available.
+
+ On Windows the search path defaults to [Application Directory]/icons
+
+ On Mac the default search path will search in the
+ [Contents/Resources/icons] part of the application bundle.
+
+ \sa setThemeSearchPaths(), fromTheme(), setThemeName()
+*/
+QStringList QIcon::themeSearchPaths()
+{
+ return QIconLoader::instance()->themeSearchPaths();
+}
+
+/*!
+ \since 4.6
+
+ Sets the current icon theme to \a name.
+
+ The \a name should correspond to a directory name in the
+ current themeSearchPath() containing an index.theme
+ file describing it's contents.
+
+ \sa themeSearchPaths(), themeName()
+*/
+void QIcon::setThemeName(const QString &name)
+{
+ QIconLoader::instance()->setThemeName(name);
+}
+
+/*!
+ \since 4.6
+
+ Returns the name of the current icon theme.
+
+ On X11, the current icon theme depends on your desktop
+ settings. On other platforms it is not set by default.
+
+ \sa setThemeName(), themeSearchPaths(), fromTheme(),
+ hasThemeIcon()
+*/
+QString QIcon::themeName()
+{
+ return QIconLoader::instance()->themeName();
+}
+
+/*!
+ \since 4.6
+
+ Returns the QIcon corresponding to \a name in the current
+ icon theme. If no such icon is found in the current theme
+ \a fallback is return instead.
+
+ To use an icon theme on Windows or Mac, you will need to
+ bundle a compliant theme with your application and make sure
+ it is located in your themeSarchPaths.
+
+ The lastest version of the freedesktop icon specification and naming
+ spesification can be obtained here:
+ http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
+ http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
+
+ To fetch an icon from the current icon theme:
+
+ \snippet doc/src/snippets/code/src_gui_image_qicon.cpp 3
+
+ Or if you want to provide a guaranteed fallback for platforms that
+ do not support theme icons, you can use the second argument:
+
+ \snippet doc/src/snippets/code/src_gui_image_qicon.cpp 4
+
+ \note By default, only X11 will support themed icons. In order to
+ use themed icons on Mac and Windows, you will have to bundle a
+ compliant theme in one of your themeSearchPaths() and set the
+ appropriate themeName().
+
+ \sa themeName(), setThemeName(), themeSearchPaths()
+*/
+QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
+{
+
+ static QCache <QString, QIcon> iconCache;
+
+ QIcon icon;
+
+#ifdef Q_WS_X11
+ if (X11->desktopEnvironment == DE_KDE) {
+ icon = QKde::kdeIcon(name);
+ if (!icon.isNull())
+ return icon;
+ }
+#endif
+
+ if (iconCache.contains(name)) {
+ icon = *iconCache.object(name);
+ } else {
+ QIcon *cachedIcon = new QIcon(new QIconLoaderEngine(name));
+ iconCache.insert(name, cachedIcon);
+ icon = *cachedIcon;
+ }
+
+ if (icon.availableSizes().isEmpty())
+ return fallback;
+
+ return icon;
+}
+
+/*!
+ \since 4.6
+
+ Returns true if there is an icon available for \a name in the
+ current icon theme, otherwise returns false.
+
+ \sa themeSearchPaths(), fromTheme(), setThemeName()
+*/
+bool QIcon::hasThemeIcon(const QString &name)
+{
+ QIcon icon = fromTheme(name);
+
+ return !icon.isNull();
+}
+
+
/*****************************************************************************
QIcon stream functions
*****************************************************************************/
@@ -987,6 +1080,11 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon)
QIconEngineV2 *engine = new QPixmapIconEngine;
icon.d->engine = engine;
engine->read(s);
+ } else if (key == QLatin1String("QIconLoaderEngine")) {
+ icon.d = new QIconPrivate;
+ QIconEngineV2 *engine = new QIconLoaderEngine();
+ icon.d->engine = engine;
+ engine->read(s);
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
} else if (QIconEngineFactoryInterfaceV2 *factory = qobject_cast<QIconEngineFactoryInterfaceV2*>(loaderV2()->instance(key))) {
if (QIconEngineV2 *engine= factory->create()) {
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index 7c412f1..676a055 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -97,6 +97,16 @@ public:
QList<QSize> availableSizes(Mode mode = Normal, State state = Off) const;
+ static QIcon fromTheme(const QString &name, const QIcon &fallback = QIcon());
+ static bool hasThemeIcon(const QString &name);
+
+ static QStringList themeSearchPaths();
+ static void setThemeSearchPaths(const QStringList &searchpath);
+
+ static QString themeName();
+ static void setThemeName(const QString &path);
+
+
#ifdef QT3_SUPPORT
enum Size { Small, Large, Automatic = Small };
static QT3_SUPPORT void setPixmapSize(Size which, const QSize &size);
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
new file mode 100644
index 0000000..5525ac5
--- /dev/null
+++ b/src/gui/image/qicon_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QICON_P_H
+#define QICON_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/qglobal.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qicon.h>
+#include <QtGui/qiconengine.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIconPrivate
+{
+public:
+ QIconPrivate();
+
+ ~QIconPrivate() {
+ if (engine_version == 1) {
+ if (!v1RefCount->deref()) {
+ delete engine;
+ delete v1RefCount;
+ }
+ } else if (engine_version == 2) {
+ delete engine;
+ }
+ }
+
+ QIconEngine *engine;
+
+ QAtomicInt ref;
+ int serialNum;
+ int detach_no;
+ int engine_version;
+
+ QAtomicInt *v1RefCount;
+};
+
+
+struct QPixmapIconEngineEntry
+{
+ QPixmapIconEngineEntry():mode(QIcon::Normal), state(QIcon::Off){}
+ QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
+ :pixmap(pm), size(pm.size()), mode(m), state(s){}
+ QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
+ :fileName(file), size(sz), mode(m), state(s){}
+ QPixmap pixmap;
+ QString fileName;
+ QSize size;
+ QIcon::Mode mode;
+ QIcon::State state;
+ bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }
+};
+
+
+
+class QPixmapIconEngine : public QIconEngineV2 {
+public:
+ QPixmapIconEngine();
+ QPixmapIconEngine(const QPixmapIconEngine &);
+ ~QPixmapIconEngine();
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state);
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QPixmapIconEngineEntry *bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly);
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state);
+ void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state);
+
+ // v2 functions
+ QString key() const;
+ QIconEngineV2 *clone() const;
+ bool read(QDataStream &in);
+ bool write(QDataStream &out) const;
+ void virtual_hook(int id, void *data);
+
+private:
+ QPixmapIconEngineEntry *tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QVector<QPixmapIconEngineEntry> pixmaps;
+
+ friend QDataStream &operator<<(QDataStream &s, const QIcon &icon);
+ friend class QIconThemeEngine;
+};
+
+QT_END_NAMESPACE
+
+#endif // QICON_P_H
diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp
index 7807f63..67bf401 100644
--- a/src/gui/image/qiconengine.cpp
+++ b/src/gui/image/qiconengine.cpp
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
\brief The QIconEngine class provides an abstract base class for QIcon renderers.
- \ingroup multimedia
+ \ingroup painting
\bold {Use QIconEngineV2 instead.}
@@ -144,7 +144,7 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI
\brief The QIconEngineV2 class provides an abstract base class for QIcon renderers.
- \ingroup multimedia
+ \ingroup painting
\since 4.3
An icon engine renders \l{QIcon}s. With icon engines, you can
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
new file mode 100644
index 0000000..e5f0043
--- /dev/null
+++ b/src/gui/image/qiconloader.cpp
@@ -0,0 +1,604 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qiconloader_p.h>
+
+#include <private/qapplication_p.h>
+#include <private/qicon_p.h>
+#include <private/qkde_p.h>
+
+#include <QtGui/QIconEnginePlugin>
+#include <QtGui/QPixmapCache>
+#include <QtGui/QIconEngine>
+#include <QtGui/QStyleOption>
+#include <QtCore/QList>
+#include <QtCore/QHash>
+#include <QtCore/QDir>
+#include <QtCore/QSettings>
+#include <QtGui/QPainter>
+
+#ifdef Q_WS_MAC
+#include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
+#ifdef Q_WS_X11
+#include <private/qt_x11_p.h>
+#include <private/gtksymbols_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
+
+static QString systemThemeName()
+{
+ QString result;
+#ifdef Q_WS_X11
+ if (X11->desktopEnvironment == DE_GNOME) {
+#if defined(QT_NO_STYLE_GTK)
+ result = QLatin1String("gnome");
+#else
+ result = QGtk::getGConfString(QLatin1String("/desktop/gnome/interface/icon_theme"),
+ QLatin1String("gnome"));
+#endif
+ } else if (X11->desktopEnvironment == DE_KDE) {
+ QString kdeDefault = X11->desktopVersion >= 4 ?
+ QString::fromLatin1("oxygen") :
+ QString::fromLatin1("crystalsvg");
+
+ QSettings settings(QKde::kdeHome() +
+ QLatin1String("/share/config/kdeglobals"),
+ QSettings::IniFormat);
+
+ settings.beginGroup(QLatin1String("Icons"));
+
+ result = settings.value(QLatin1String("Theme"), kdeDefault).toString();
+ }
+#endif
+ return result;
+}
+
+static QString fallbackTheme()
+{
+ QString defaultTheme = systemThemeName();
+ if (defaultTheme.isEmpty())
+ defaultTheme = QLatin1String("hicolor");
+ return defaultTheme;
+}
+
+QIconLoader::QIconLoader() :
+ m_themeKey(1), m_supportsSvg(false)
+{
+ m_systemTheme = systemThemeName();
+
+ QFactoryLoader iconFactoryLoader(QIconEngineFactoryInterfaceV2_iid,
+ QLatin1String("/iconengines"),
+ Qt::CaseInsensitive);
+ if (iconFactoryLoader.keys().contains(QLatin1String("svg")))
+ m_supportsSvg = true;
+}
+
+QIconLoader *QIconLoader::instance()
+{
+ return iconLoaderInstance();
+}
+
+// Queries the system theme and invalidates existing
+// icons if the theme has changed.
+void QIconLoader::updateSystemTheme()
+{
+ // Only change if this is not explicitly set by the user
+ if (m_userTheme.isEmpty()) {
+ QString theme = systemThemeName();
+ if (theme != m_systemTheme) {
+ m_systemTheme = theme;
+ invalidateKey();
+ }
+ }
+}
+
+void QIconLoader::setThemeName(const QString &themeName)
+{
+ m_userTheme = themeName;
+ invalidateKey();
+}
+
+void QIconLoader::setThemeSearchPath(const QStringList &searchPaths)
+{
+ m_iconDirs = searchPaths;
+ themeList.clear();
+ invalidateKey();
+}
+
+QStringList QIconLoader::themeSearchPaths() const
+{
+ if (m_iconDirs.isEmpty()) {
+
+#if defined(Q_WS_X11)
+
+ QString xdgDirString = QFile::decodeName(getenv("XDG_DATA_DIRS"));
+ if (xdgDirString.isEmpty())
+ xdgDirString = QLatin1String("/usr/local/share/:/usr/share/");
+
+ QStringList xdgDirs = xdgDirString.split(QLatin1Char(':'));
+
+ for (int i = 0 ; i < xdgDirs.size() ; ++i) {
+ QDir dir(xdgDirs[i]);
+ if (dir.exists())
+ m_iconDirs.append(dir.path() +
+ QLatin1String("/icons"));
+ }
+
+ if (X11->desktopEnvironment == DE_KDE) {
+
+ m_iconDirs << QLatin1Char(':') +
+ QKde::kdeHome() +
+ QLatin1String("/share/icons");
+ QStringList kdeDirs =
+ QFile::decodeName(getenv("KDEDIRS")).split(QLatin1Char(':'));
+
+ for (int i = 0 ; i< kdeDirs.count() ; ++i) {
+ QDir dir(QLatin1Char(':') + kdeDirs.at(i) +
+ QLatin1String("/share/icons"));
+ if (dir.exists())
+ m_iconDirs.append(dir.path());
+ }
+ }
+
+ // Add home directory first in search path
+ QDir homeDir(QDir::homePath() + QLatin1String("/.icons"));
+ if (homeDir.exists())
+ m_iconDirs.prepend(homeDir.path());
+
+#elif defined(Q_WS_WIN)
+ m_iconDirs.append(qApp->applicationDirPath() +
+ QLatin1String("/icons"));
+#elif defined(Q_WS_MAC)
+ m_iconDirs.append(qApp->applicationDirPath() +
+ QLatin1String("/../Resources/icons"));
+#endif
+ }
+ return m_iconDirs;
+}
+
+QIconTheme::QIconTheme(const QString &themeName)
+ : m_valid(false)
+{
+ QFile themeIndex;
+
+ QList <QIconDirInfo> keyList;
+ QStringList iconDirs = QIcon::themeSearchPaths();
+ for ( int i = 0 ; i < iconDirs.size() ; ++i) {
+ QDir iconDir(iconDirs[i]);
+ QString themeDir = iconDir.path() + QLatin1Char('/') + themeName;
+ themeIndex.setFileName(themeDir + QLatin1String("/index.theme"));
+ if (themeIndex.exists()) {
+ m_contentDir = themeDir;
+ m_valid = true;
+ break;
+ }
+ }
+
+ if (themeIndex.exists()) {
+ const QSettings indexReader(themeIndex.fileName(), QSettings::IniFormat);
+ QStringListIterator keyIterator(indexReader.allKeys());
+ while (keyIterator.hasNext()) {
+
+ const QString key = keyIterator.next();
+ if (key.endsWith(QLatin1String("/Size"))) {
+ // Note the QSettings ini-format does not accept
+ // slashes in key names, hence we have to cheat
+ if (int size = indexReader.value(key).toInt()) {
+ QString directoryKey = key.left(key.size() - 5);
+ QIconDirInfo dirInfo(directoryKey);
+ dirInfo.size = size;
+ QString type = indexReader.value(directoryKey +
+ QLatin1String("/Type")
+ ).toString();
+
+ if (type == QLatin1String("Fixed"))
+ dirInfo.type = QIconDirInfo::Fixed;
+ else if (type == QLatin1String("Scalable"))
+ dirInfo.type = QIconDirInfo::Scalable;
+ else
+ dirInfo.type = QIconDirInfo::Threshold;
+
+ dirInfo.threshold = indexReader.value(directoryKey +
+ QLatin1String("/Threshold"),
+ 2).toInt();
+
+ dirInfo.minSize = indexReader.value(directoryKey +
+ QLatin1String("/MinSize"),
+ size).toInt();
+
+ dirInfo.maxSize = indexReader.value(directoryKey +
+ QLatin1String("/MaxSize"),
+ size).toInt();
+ m_keyList.append(dirInfo);
+ }
+ }
+ }
+
+ // Parent themes provide fallbacks for missing icons
+ m_parents = indexReader.value(
+ QLatin1String("Icon Theme/Inherits")).toStringList();
+
+ // Ensure a default platform fallback for all themes
+ if (m_parents.isEmpty())
+ m_parents.append(fallbackTheme());
+
+ // Ensure that all themes fall back to hicolor
+ if (!m_parents.isEmpty())
+ m_parents.append(QLatin1String("hicolor"));
+ }
+}
+
+QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName,
+ const QString &iconName,
+ QStringList &visited) const
+{
+ QThemeIconEntries entries;
+ Q_ASSERT(!themeName.isEmpty());
+
+ QPixmap pixmap;
+
+ // Used to protect against potential recursions
+ visited << themeName;
+
+ QIconTheme theme = themeList.value(themeName);
+ if (!theme.isValid()) {
+ theme = QIconTheme(themeName);
+ if (!theme.isValid())
+ theme = fallbackTheme();
+
+ themeList.insert(themeName, theme);
+ }
+
+ QString contentDir = theme.contentDir() + QLatin1Char('/');
+ QList<QIconDirInfo> subDirs = theme.keyList();
+
+ const QString svgext(QLatin1String(".svg"));
+ const QString pngext(QLatin1String(".png"));
+
+ // Add all relevant files
+ for (int i = 0; i < subDirs.size() ; ++i) {
+ const QIconDirInfo &dirInfo = subDirs.at(i);
+ QString subdir = dirInfo.path;
+ QDir currentDir(contentDir + subdir);
+
+ if (dirInfo.type == QIconDirInfo::Scalable && m_supportsSvg &&
+ currentDir.exists(iconName + svgext)) {
+ ScalableEntry *iconEntry = new ScalableEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + svgext);
+ entries.append(iconEntry);
+
+ } else if (currentDir.exists(iconName + pngext)) {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(iconName + pngext);
+ // Notice we ensure that pixmap entries allways come before
+ // scalable to preserve search order afterwards
+ entries.prepend(iconEntry);
+ }
+ }
+
+ if (entries.isEmpty()) {
+ const QStringList parents = theme.parents();
+ // Search recursively through inherited themes
+ for (int i = 0 ; i < parents.size() ; ++i) {
+
+ const QString parentTheme = parents.at(i).trimmed();
+
+ if (!visited.contains(parentTheme)) // guard against recursion
+ entries = findIconHelper(parentTheme, iconName, visited);
+
+ if (!entries.isEmpty()) // success
+ break;
+ }
+ }
+ return entries;
+}
+
+QThemeIconEntries QIconLoader::loadIcon(const QString &name) const
+{
+ if (!themeName().isEmpty()) {
+ QStringList visited;
+ return findIconHelper(themeName(), name, visited);
+ }
+
+ return QThemeIconEntries();
+}
+
+
+// -------- Icon Loader Engine -------- //
+
+
+QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)
+ : m_iconName(iconName), m_key(0)
+{
+}
+
+QIconLoaderEngine::~QIconLoaderEngine()
+{
+ while (!m_entries.isEmpty())
+ delete m_entries.takeLast();
+ Q_ASSERT(m_entries.size() == 0);
+}
+
+QIconLoaderEngine::QIconLoaderEngine(const QIconLoaderEngine &other)
+ : QIconEngineV2(other),
+ m_iconName(other.m_iconName),
+ m_key(0)
+{
+}
+
+QIconEngineV2 *QIconLoaderEngine::clone() const
+{
+ return new QIconLoaderEngine(*this);
+}
+
+bool QIconLoaderEngine::read(QDataStream &in) {
+ in >> m_iconName;
+ return true;
+}
+
+bool QIconLoaderEngine::write(QDataStream &out) const
+{
+ out << m_iconName;
+ return true;
+}
+
+bool QIconLoaderEngine::hasIcon() const
+{
+ return !(m_entries.isEmpty());
+}
+
+// Lazily load the icon
+void QIconLoaderEngine::ensureLoaded()
+{
+ if (!(iconLoaderInstance()->themeKey() == m_key)) {
+
+ while (!m_entries.isEmpty())
+ delete m_entries.takeLast();
+
+ Q_ASSERT(m_entries.size() == 0);
+ m_entries = iconLoaderInstance()->loadIcon(m_iconName);
+ m_key = iconLoaderInstance()->themeKey();
+ }
+}
+
+void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect,
+ QIcon::Mode mode, QIcon::State state)
+{
+ QSize pixmapSize = rect.size();
+#if defined(Q_WS_MAC)
+ pixmapSize *= qt_mac_get_scalefactor();
+#endif
+ painter->drawPixmap(rect, pixmap(pixmapSize, mode, state));
+}
+
+/*
+ * This algorithm is defined by the freedesktop spec:
+ * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
+ */
+static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize)
+{
+ if (dir.type == QIconDirInfo::Fixed) {
+ return dir.size == iconsize;
+
+ } else if (dir.type == QIconDirInfo::Scalable) {
+ return dir.size <= dir.maxSize &&
+ iconsize >= dir.minSize;
+
+ } else if (dir.type == QIconDirInfo::Threshold) {
+ return iconsize >= dir.size - dir.threshold &&
+ iconsize <= dir.size + dir.threshold;
+ }
+
+ Q_ASSERT(1); // Not a valid value
+ return false;
+}
+
+/*
+ * This algorithm is defined by the freedesktop spec:
+ * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
+ */
+static int directorySizeDistance(const QIconDirInfo &dir, int iconsize)
+{
+ if (dir.type == QIconDirInfo::Fixed) {
+ return qAbs(dir.size - iconsize);
+
+ } else if (dir.type == QIconDirInfo::Scalable) {
+ if (iconsize < dir.minSize)
+ return dir.minSize - iconsize;
+ else if (iconsize > dir.maxSize)
+ return iconsize - dir.maxSize;
+ else
+ return 0;
+
+ } else if (dir.type == QIconDirInfo::Threshold) {
+ if (iconsize < dir.size - dir.threshold)
+ return dir.minSize - iconsize;
+ else if (iconsize > dir.size + dir.threshold)
+ return iconsize - dir.maxSize;
+ else return 0;
+ }
+
+ Q_ASSERT(1); // Not a valid value
+ return INT_MAX;
+}
+
+QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size)
+{
+ int iconsize = qMin(size.width(), size.height());
+
+ // Note that m_entries are sorted so that png-files
+ // come first
+
+ // Search for exact matches first
+ for (int i = 0; i < m_entries.count(); ++i) {
+ QIconLoaderEngineEntry *entry = m_entries.at(i);
+ if (directoryMatchesSize(entry->dir, iconsize)) {
+ return entry;
+ }
+ }
+
+ // Find the minimum distance icon
+ int minimalSize = INT_MAX;
+ QIconLoaderEngineEntry *closestMatch = 0;
+ for (int i = 0; i < m_entries.count(); ++i) {
+ QIconLoaderEngineEntry *entry = m_entries.at(i);
+ int distance = directorySizeDistance(entry->dir, iconsize);
+ if (distance < minimalSize) {
+ minimalSize = distance;
+ closestMatch = entry;
+ }
+ }
+ return closestMatch;
+}
+
+/*
+ * Returns the actual icon size. For scalable svg's this is equivalent
+ * to the requested size. Otherwise the closest match is returned.
+ *
+ * todo: the spec is a bit fuzzy in this area, but we should probably
+ * allow scaling down pixmap icons as well.
+ *
+ */
+QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
+ QIcon::State state)
+{
+ ensureLoaded();
+
+ QIconLoaderEngineEntry *entry = entryForSize(size);
+ if (entry) {
+ const QIconDirInfo &dir = entry->dir;
+ if (dir.type == QIconDirInfo::Scalable)
+ return size;
+ else
+ return QSize(dir.size, dir.size);
+ }
+ return QIconEngineV2::actualSize(size, mode, state);
+}
+
+QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ Q_UNUSED(state);
+
+ // Ensure that basePixmap is lazily initialized before generating the
+ // key, otherwise the cache key is not unique
+ if (basePixmap.isNull())
+ basePixmap.load(filename);
+
+ int actualSize = qMin(size.width(), size.height());
+ QString key = QLatin1String("$qt_theme_")
+ + QString::number(basePixmap.cacheKey(), 16)
+ + QLatin1Char('_')
+ + QString::number(mode)
+ + QLatin1Char('_')
+ + QString::number(qApp->palette().cacheKey(), 16)
+ + QLatin1Char('_')
+ + QString::number(actualSize);
+
+ QPixmap cachedPixmap;
+ if (QPixmapCache::find(key, &cachedPixmap)) {
+ return cachedPixmap;
+ } else {
+ QStyleOption opt(0);
+ opt.palette = qApp->palette();
+ cachedPixmap = qApp->style()->generatedIconPixmap(mode, basePixmap, &opt);
+ QPixmapCache::insert(key, cachedPixmap);
+ }
+ return cachedPixmap;
+}
+
+QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ if (svgIcon.isNull())
+ svgIcon = QIcon(filename);
+
+ // Simply reuse svg icon engine
+ return svgIcon.pixmap(size, mode, state);
+}
+
+QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,
+ QIcon::State state)
+{
+ ensureLoaded();
+
+ QIconLoaderEngineEntry *entry = entryForSize(size);
+ if (entry)
+ return entry->pixmap(size, mode, state);
+
+ return QPixmap();
+}
+
+QString QIconLoaderEngine::key() const
+{
+ return QLatin1String("QIconLoaderEngine");
+}
+
+void QIconLoaderEngine::virtual_hook(int id, void *data)
+{
+ ensureLoaded();
+
+ switch (id) {
+ case QIconEngineV2::AvailableSizesHook:
+ {
+ QIconEngineV2::AvailableSizesArgument &arg
+ = *reinterpret_cast<QIconEngineV2::AvailableSizesArgument*>(data);
+ const QList<QIconDirInfo> directoryKey = iconLoaderInstance()->theme().keyList();
+ arg.sizes.clear();
+
+ // Gets all sizes from the DirectoryInfo entries
+ for (int i = 0 ; i < m_entries.size() ; ++i) {
+ int size = m_entries.at(i)->dir.size;
+ arg.sizes.append(QSize(size, size));
+ }
+ }
+ break;
+ default:
+ QIconEngineV2::virtual_hook(id, data);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
new file mode 100644
index 0000000..5d5c211
--- /dev/null
+++ b/src/gui/image/qiconloader_p.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESKTOPICON_P_H
+#define QDESKTOPICON_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 <QtGui/QIcon>
+#include <QtGui/QIconEngine>
+#include <QtGui/QPixmapCache>
+#include <private/qicon_p.h>
+#include <private/qfactoryloader_p.h>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QIconLoader;
+
+struct QIconDirInfo
+{
+ enum Type { Fixed, Scalable, Threshold };
+ QIconDirInfo(const QString &_path = QString()) :
+ path(_path),
+ size(0),
+ maxSize(0),
+ minSize(0),
+ threshold(0),
+ type(Threshold) {}
+ QString path;
+ short size;
+ short maxSize;
+ short minSize;
+ short threshold;
+ Type type : 4;
+};
+
+class QIconLoaderEngineEntry
+ {
+public:
+ virtual ~QIconLoaderEngineEntry() {}
+ virtual QPixmap pixmap(const QSize &size,
+ QIcon::Mode mode,
+ QIcon::State state) = 0;
+ QString filename;
+ QIconDirInfo dir;
+ static int count;
+};
+
+struct ScalableEntry : public QIconLoaderEngineEntry
+{
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QIcon svgIcon;
+};
+
+struct PixmapEntry : public QIconLoaderEngineEntry
+{
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QPixmap basePixmap;
+};
+
+typedef QList<QIconLoaderEngineEntry*> QThemeIconEntries;
+
+class QIconLoaderEngine : public QIconEngineV2
+{
+public:
+ QIconLoaderEngine(const QString& iconName = QString());
+ ~QIconLoaderEngine();
+
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state);
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ QIconEngineV2 *clone() const;
+ bool read(QDataStream &in);
+ bool write(QDataStream &out) const;
+
+private:
+ QString key() const;
+ bool hasIcon() const;
+ void ensureLoaded();
+ void virtual_hook(int id, void *data);
+ QIconLoaderEngineEntry *entryForSize(const QSize &size);
+ QIconLoaderEngine(const QIconLoaderEngine &other);
+ QThemeIconEntries m_entries;
+ QString m_iconName;
+ uint m_key;
+
+ friend class QIconLoader;
+};
+
+class QIconTheme
+{
+public:
+ QIconTheme(const QString &name);
+ QIconTheme() : m_valid(false) {};
+ QStringList parents() { return m_parents; }
+ QList <QIconDirInfo> keyList() { return m_keyList; }
+ QString contentDir() { return m_contentDir; }
+ bool isValid() { return m_valid; }
+
+private:
+ QString m_contentDir;
+ QList <QIconDirInfo> m_keyList;
+ QStringList m_parents;
+ bool m_valid;
+};
+
+class QIconLoader : public QObject
+{
+public:
+ QIconLoader();
+ QThemeIconEntries loadIcon(const QString &iconName) const;
+ uint themeKey() const { return m_themeKey; }
+
+ QString themeName() const { return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme; }
+ void setThemeName(const QString &themeName);
+ QIconTheme theme() { return themeList.value(themeName()); }
+ void setThemeSearchPath(const QStringList &searchPaths);
+ QStringList themeSearchPaths() const;
+ QIconDirInfo dirInfo(int dirindex);
+ static QIconLoader *instance();
+ void updateSystemTheme();
+ void invalidateKey() { m_themeKey++; }
+
+private:
+ QThemeIconEntries findIconHelper(const QString &themeName,
+ const QString &iconName,
+ QStringList &visited) const;
+ uint m_themeKey;
+ bool m_supportsSvg;
+
+ mutable QString m_userTheme;
+ mutable QString m_systemTheme;
+ mutable QStringList m_iconDirs;
+ mutable QHash <QString, QIconTheme> themeList;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESKTOPICON_P_H
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index d48d427..2b82f49 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -49,6 +49,7 @@
#include "qimagewriter.h"
#include "qstringlist.h"
#include "qvariant.h"
+#include "qimagepixmapcleanuphooks_p.h"
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>
@@ -60,11 +61,7 @@
#include <qhash.h>
-#ifdef QT_RASTER_IMAGEENGINE
#include <private/qpaintengine_raster_p.h>
-#else
-#include <qpaintengine.h>
-#endif
#include <private/qimage_p.h>
@@ -106,14 +103,6 @@ static inline bool checkPixelSize(const QImage::Format format)
}
-// ### Qt 5: remove
-typedef void (*_qt_image_cleanup_hook)(int);
-Q_GUI_EXPORT _qt_image_cleanup_hook qt_image_cleanup_hook = 0;
-
-// ### Qt 5: rename
-typedef void (*_qt_image_cleanup_hook_64)(qint64);
-Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64 = 0;
-
static QImage rotated90(const QImage &src);
static QImage rotated180(const QImage &src);
static QImage rotated270(const QImage &src);
@@ -185,6 +174,13 @@ static int depthForFormat(QImage::Format format)
return depth;
}
+/*! \fn QImageData * QImageData::create(const QSize &size, QImage::Format format, int numColors)
+
+ \internal
+
+ Creates a new image data.
+ Returns 0 if invalid parameters are give or anything else failed.
+*/
QImageData * QImageData::create(const QSize &size, QImage::Format format, int numColors)
{
if (!size.isValid() || numColors < 0 || format == QImage::Format_Invalid)
@@ -223,7 +219,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu
|| INT_MAX/sizeof(uchar *) < uint(height))
return 0;
- QImageData *d = new QImageData;
+ QScopedPointer<QImageData> d(new QImageData);
d->colortable.resize(numColors);
if (depth == 1) {
d->colortable[0] = QColor(Qt::black).rgba();
@@ -246,19 +242,18 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu
d->data = (uchar *)malloc(d->nbytes);
if (!d->data) {
- delete d;
return 0;
}
d->ref.ref();
- return d;
+ return d.take();
}
QImageData::~QImageData()
{
- if (is_cached && qt_image_cleanup_hook_64)
- qt_image_cleanup_hook_64((((qint64) ser_no) << 32) | ((qint64) detach_no));
+ if (is_cached)
+ QImagePixmapCleanupHooks::executeImageHooks((((qint64) ser_no) << 32) | ((qint64) detach_no));
delete paintEngine;
if (data && own_data)
free(data);
@@ -344,9 +339,9 @@ bool QImageData::checkForAlphaPixels() const
/*!
\class QImage
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
- \mainclass
+
\reentrant
\brief The QImage class provides a hardware-independent image
@@ -590,9 +585,8 @@ bool QImageData::checkForAlphaPixels() const
The mirrored() function returns a mirror of the image in the
desired direction, the scaled() returns a copy of the image scaled
- to a rectangle of the desired measures, the rgbSwapped() function
- constructs a BGR image from a RGB image, and the alphaChannel()
- function constructs an image from this image's alpha channel.
+ to a rectangle of the desired measures, and the rgbSwapped() function
+ constructs a BGR image from a RGB image.
The scaledToWidth() and scaledToHeight() functions return scaled
copies of the image.
@@ -612,9 +606,6 @@ bool QImageData::checkForAlphaPixels() const
\table
\header \o Function \o Description
\row
- \o setAlphaChannel()
- \o Sets the alpha channel of the image.
- \row
\o setDotsPerMeterX()
\o Defines the aspect ratio by setting the number of pixels that fit
horizontally in a physical meter.
@@ -1346,8 +1337,8 @@ QImage::operator QVariant() const
void QImage::detach()
{
if (d) {
- if (d->is_cached && qt_image_cleanup_hook_64 && d->ref == 1)
- qt_image_cleanup_hook_64(cacheKey());
+ if (d->is_cached && d->ref == 1)
+ QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
if (d->ref != 1 || d->ro_data)
*this = copy();
@@ -1621,6 +1612,7 @@ int QImage::numColors() const
/*!
Returns a pointer to the scanline pointer table. This is the
beginning of the data block for the image.
+ Returns 0 in case of an error.
Use the bits() or scanLine() function instead.
*/
@@ -1636,6 +1628,8 @@ uchar **QImage::jumpTable()
if (!d->jumptable) {
d->jumptable = (uchar **)malloc(d->height*sizeof(uchar *));
+ if (!d->jumptable)
+ return 0;
uchar *data = d->data;
int height = d->height;
uchar **p = d->jumptable;
@@ -1656,6 +1650,8 @@ const uchar * const *QImage::jumpTable() const
return 0;
if (!d->jumptable) {
d->jumptable = (uchar **)malloc(d->height*sizeof(uchar *));
+ if (!d->jumptable)
+ return 0;
uchar *data = d->data;
int height = d->height;
uchar **p = d->jumptable;
@@ -1691,8 +1687,12 @@ void QImage::setColorTable(const QVector<QRgb> colors)
d->colortable = colors;
d->has_alpha_clut = false;
- for (int i = 0; i < d->colortable.size(); ++i)
- d->has_alpha_clut |= (qAlpha(d->colortable.at(i)) != 255);
+ for (int i = 0; i < d->colortable.size(); ++i) {
+ if (qAlpha(d->colortable.at(i)) != 255) {
+ d->has_alpha_clut = true;
+ break;
+ }
+ }
}
/*!
@@ -2370,8 +2370,9 @@ static void dither_to_Mono(QImageData *dst, const QImageData *src,
switch (dithermode) {
case Diffuse: {
- int *line1 = new int[w];
- int *line2 = new int[w];
+ QScopedArrayPointer<int> lineBuffer(new int[w * 2]);
+ int *line1 = lineBuffer.data();
+ int *line2 = lineBuffer.data() + w;
int bmwidth = (w+7)/8;
int *b1, *b2;
@@ -2451,8 +2452,6 @@ static void dither_to_Mono(QImageData *dst, const QImageData *src,
b2++;
}
}
- delete [] line1;
- delete [] line2;
} break;
case Ordered: {
@@ -2593,10 +2592,9 @@ static void convert_X_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageC
static void convert_ARGB_PM_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
{
- QImageData *tmp = QImageData::create(QSize(src->width, src->height), QImage::Format_ARGB32);
- convert_ARGB_PM_to_ARGB(tmp, src, flags);
- dither_to_Mono(dst, tmp, flags, false);
- delete tmp;
+ QScopedPointer<QImageData> tmp(QImageData::create(QSize(src->width, src->height), QImage::Format_ARGB32));
+ convert_ARGB_PM_to_ARGB(tmp.data(), src, flags);
+ dither_to_Mono(dst, tmp.data(), flags, false);
}
//
@@ -2745,15 +2743,16 @@ static void convert_RGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::
int* line1[3];
int* line2[3];
int* pv[3];
- line1[0] = new int[src->width];
- line2[0] = new int[src->width];
- line1[1] = new int[src->width];
- line2[1] = new int[src->width];
- line1[2] = new int[src->width];
- line2[2] = new int[src->width];
- pv[0] = new int[src->width];
- pv[1] = new int[src->width];
- pv[2] = new int[src->width];
+ QScopedArrayPointer<int> lineBuffer(new int[src->width * 9]);
+ line1[0] = lineBuffer.data();
+ line2[0] = lineBuffer.data() + src->width;
+ line1[1] = lineBuffer.data() + src->width * 2;
+ line2[1] = lineBuffer.data() + src->width * 3;
+ line1[2] = lineBuffer.data() + src->width * 4;
+ line2[2] = lineBuffer.data() + src->width * 5;
+ pv[0] = lineBuffer.data() + src->width * 6;
+ pv[1] = lineBuffer.data() + src->width * 7;
+ pv[2] = lineBuffer.data() + src->width * 8;
int endian = (QSysInfo::ByteOrder == QSysInfo::BigEndian);
for (int y = 0; y < src->height; y++) {
@@ -2816,15 +2815,6 @@ static void convert_RGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::
src_data += src->bytes_per_line;
dest_data += dst->bytes_per_line;
}
- delete [] line1[0];
- delete [] line2[0];
- delete [] line1[1];
- delete [] line2[1];
- delete [] line1[2];
- delete [] line2[2];
- delete [] pv[0];
- delete [] pv[1];
- delete [] pv[2];
} else { // OrderedDither
for (int y = 0; y < src->height; y++) {
const QRgb *p = (const QRgb *)src_data;
@@ -2857,8 +2847,8 @@ static void convert_RGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::
const int trans = 216;
Q_ASSERT(dst->colortable.size() > trans);
dst->colortable[trans] = 0;
- QImageData *mask = QImageData::create(QSize(src->width, src->height), QImage::Format_Mono);
- dither_to_Mono(mask, src, flags, true);
+ QScopedPointer<QImageData> mask(QImageData::create(QSize(src->width, src->height), QImage::Format_Mono));
+ dither_to_Mono(mask.data(), src, flags, true);
uchar *dst_data = dst->data;
const uchar *mask_data = mask->data;
for (int y = 0; y < src->height; y++) {
@@ -2870,7 +2860,6 @@ static void convert_RGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::
dst_data += dst->bytes_per_line;
}
dst->has_alpha_clut = true;
- delete mask;
}
#undef MAX_R
@@ -2883,10 +2872,9 @@ static void convert_RGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::
static void convert_ARGB_PM_to_Indexed8(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
{
- QImageData *tmp = QImageData::create(QSize(src->width, src->height), QImage::Format_ARGB32);
- convert_ARGB_PM_to_ARGB(tmp, src, flags);
- convert_RGB_to_Indexed8(dst, tmp, flags);
- delete tmp;
+ QScopedPointer<QImageData> tmp(QImageData::create(QSize(src->width, src->height), QImage::Format_ARGB32));
+ convert_ARGB_PM_to_ARGB(tmp.data(), src, flags);
+ convert_RGB_to_Indexed8(dst, tmp.data(), flags);
}
static void convert_ARGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
@@ -3947,10 +3935,8 @@ QImage QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Transf
if (newSize == size())
return copy();
- QImage img;
- QTransform wm;
- wm.scale((qreal)newSize.width() / width(), (qreal)newSize.height() / height());
- img = transformed(wm, mode);
+ QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(), (qreal)newSize.height() / height());
+ QImage img = transformed(wm, mode);
return img;
}
@@ -3977,9 +3963,8 @@ QImage QImage::scaledToWidth(int w, Qt::TransformationMode mode) const
if (w <= 0)
return QImage();
- QTransform wm;
qreal factor = (qreal) w / width();
- wm.scale(factor, factor);
+ QTransform wm = QTransform::fromScale(factor, factor);
return transformed(wm, mode);
}
@@ -4006,9 +3991,8 @@ QImage QImage::scaledToHeight(int h, Qt::TransformationMode mode) const
if (h <= 0)
return QImage();
- QTransform wm;
qreal factor = (qreal) h / height();
- wm.scale(factor, factor);
+ QTransform wm = QTransform::fromScale(factor, factor);
return transformed(wm, mode);
}
@@ -4632,12 +4616,19 @@ bool QImage::loadFromData(const uchar *data, int len, const char *format)
binary \a data. The loader attempts to read the image using the
specified \a format. If \a format is not specified (which is the default),
the loader probes the file for a header to guess the file format.
+ binary \a data. The loader attempts to read the image, either using the
+ optional image \a format specified or by determining the image format from
+ the data.
- If the loading of the image failed, this object is a null image.
+ If \a format is not specified (which is the default), the loader probes the
+ file for a header to determine the file format. If \a format is specified,
+ it must be one of the values returned by QImageReader::supportedImageFormats().
+
+ If the loading of the image fails, the image returned will be a null image.
+
+ \sa load(), save(), {QImage#Reading and Writing Image Files}{Reading and Writing Image Files}
+ */
- \sa load(), save(), {QImage#Reading and Writing Image
- Files}{Reading and Writing Image Files}
-*/
QImage QImage::fromData(const uchar *data, int size, const char *format)
{
QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(data), size);
@@ -4764,7 +4755,7 @@ QDataStream &operator>>(QDataStream &s, QImage &image)
image = QImageReader(s.device(), 0).read();
return s;
}
-#endif
+#endif // QT_NO_DATASTREAM
#ifdef QT3_SUPPORT
@@ -4854,8 +4845,6 @@ bool QImage::operator==(const QImage & i) const
return false;
if (d->format != Format_RGB32) {
- if (d->colortable != i.d->colortable)
- return false;
if (d->format >= Format_ARGB32) { // all bits defined
const int n = d->width * d->depth / 8;
if (n == d->bytes_per_line && n == i.d->bytes_per_line) {
@@ -4868,11 +4857,13 @@ bool QImage::operator==(const QImage & i) const
}
}
} else {
- int w = width();
- int h = height();
+ const int w = width();
+ const int h = height();
+ const QVector<QRgb> &colortable = d->colortable;
+ const QVector<QRgb> &icolortable = i.d->colortable;
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
- if (pixelIndex(x, y) != i.pixelIndex(x, y))
+ if (colortable[pixelIndex(x, y)] != icolortable[i.pixelIndex(x, y)])
return false;
}
}
@@ -5259,17 +5250,16 @@ QPaintEngine *QImage::paintEngine() const
if (!d)
return 0;
-#ifdef QT_RASTER_IMAGEENGINE
if (!d->paintEngine) {
d->paintEngine = new QRasterPaintEngine(const_cast<QImage *>(this));
}
-#endif
+
return d->paintEngine;
}
/*!
- \reimp
+ \internal
Returns the size for the specified \a metric on the device.
*/
@@ -5587,7 +5577,7 @@ bool QImage::isDetached() const
Note that the image will be converted to the Format_ARGB32_Premultiplied
format if the function succeeds.
- Use one of the composition mods in QPainter::CompositionMode instead.
+ Use one of the composition modes in QPainter::CompositionMode instead.
\warning This function is expensive.
@@ -5665,6 +5655,8 @@ void QImage::setAlphaChannel(const QImage &alphaChannel)
/*!
+ \obsolete
+
Returns the alpha channel of the image as a new grayscale QImage in which
each pixel's red, green, and blue values are given the alpha value of the
original image. The color depth of the returned image is 8-bit.
@@ -5744,7 +5736,7 @@ QImage QImage::alphaChannel() const
Returns true if the image has a format that respects the alpha
channel, otherwise returns false.
- \sa alphaChannel(), {QImage#Image Information}{Image Information}
+ \sa {QImage#Image Information}{Image Information}
*/
bool QImage::hasAlphaChannel() const
{
diff --git a/src/gui/image/qimageiohandler.cpp b/src/gui/image/qimageiohandler.cpp
index d04fa39..8b6c1d9 100644
--- a/src/gui/image/qimageiohandler.cpp
+++ b/src/gui/image/qimageiohandler.cpp
@@ -272,7 +272,6 @@ QImageIOHandler::QImageIOHandler(QImageIOHandlerPrivate &dd)
*/
QImageIOHandler::~QImageIOHandler()
{
- delete d_ptr;
}
/*!
diff --git a/src/gui/image/qimageiohandler.h b/src/gui/image/qimageiohandler.h
index 84f20dc..5f94778 100644
--- a/src/gui/image/qimageiohandler.h
+++ b/src/gui/image/qimageiohandler.h
@@ -44,6 +44,7 @@
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -109,7 +110,7 @@ public:
protected:
QImageIOHandler(QImageIOHandlerPrivate &dd);
- QImageIOHandlerPrivate *d_ptr;
+ QScopedPointer<QImageIOHandlerPrivate> d_ptr;
private:
Q_DISABLE_COPY(QImageIOHandler)
};
diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp
new file mode 100644
index 0000000..10573fd
--- /dev/null
+++ b/src/gui/image/qimagepixmapcleanuphooks.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qimagepixmapcleanuphooks_p.h"
+#include "qpixmapdata_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+// Legacy, single instance hooks: ### Qt 5: remove
+typedef void (*_qt_pixmap_cleanup_hook)(int);
+typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
+typedef void (*_qt_image_cleanup_hook)(int);
+Q_GUI_EXPORT _qt_pixmap_cleanup_hook qt_pixmap_cleanup_hook = 0;
+Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64 = 0;
+Q_GUI_EXPORT _qt_image_cleanup_hook qt_image_cleanup_hook = 0;
+Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64 = 0;
+
+
+QImagePixmapCleanupHooks* qt_image_and_pixmap_cleanup_hooks = 0;
+
+
+QImagePixmapCleanupHooks::QImagePixmapCleanupHooks()
+{
+ qt_image_and_pixmap_cleanup_hooks = this;
+}
+
+QImagePixmapCleanupHooks *QImagePixmapCleanupHooks::instance()
+{
+ if (!qt_image_and_pixmap_cleanup_hooks)
+ qt_image_and_pixmap_cleanup_hooks = new QImagePixmapCleanupHooks;
+ return qt_image_and_pixmap_cleanup_hooks;
+}
+
+void QImagePixmapCleanupHooks::addPixmapHook(_qt_pixmap_cleanup_hook_pm hook)
+{
+ pixmapHooks.append(hook);
+}
+
+void QImagePixmapCleanupHooks::addImageHook(_qt_image_cleanup_hook_64 hook)
+{
+ imageHooks.append(hook);
+}
+
+void QImagePixmapCleanupHooks::removePixmapHook(_qt_pixmap_cleanup_hook_pm hook)
+{
+ pixmapHooks.removeAll(hook);
+}
+
+void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook)
+{
+ imageHooks.removeAll(hook);
+}
+
+
+void QImagePixmapCleanupHooks::executePixmapHooks(QPixmap* pm)
+{
+ for (int i = 0; i < qt_image_and_pixmap_cleanup_hooks->pixmapHooks.count(); ++i)
+ qt_image_and_pixmap_cleanup_hooks->pixmapHooks[i](pm);
+
+ if (qt_pixmap_cleanup_hook_64)
+ qt_pixmap_cleanup_hook_64(pm->cacheKey());
+}
+
+
+void QImagePixmapCleanupHooks::executeImageHooks(qint64 key)
+{
+ for (int i = 0; i < qt_image_and_pixmap_cleanup_hooks->imageHooks.count(); ++i)
+ qt_image_and_pixmap_cleanup_hooks->imageHooks[i](key);
+
+ if (qt_image_cleanup_hook_64)
+ qt_image_cleanup_hook_64(key);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qkbdsl5000_qws.h b/src/gui/image/qimagepixmapcleanuphooks_p.h
index fba8fe3..f1ac1cb 100644
--- a/src/gui/embedded/qkbdsl5000_qws.h
+++ b/src/gui/image/qimagepixmapcleanuphooks_p.h
@@ -39,41 +39,51 @@
**
****************************************************************************/
-#ifndef QKBDSL5000_QWS_H
-#define QKBDSL5000_QWS_H
+#ifndef QIMAGEPIXMAP_CLEANUPHOOKS_P_H
+#define QIMAGEPIXMAP_CLEANUPHOOKS_P_H
-#include <QtGui/qkbdtty_qws.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.
+//
-QT_BEGIN_HEADER
+#include <QtGui/qpixmap.h>
QT_BEGIN_NAMESPACE
-QT_MODULE(Gui)
+typedef void (*_qt_image_cleanup_hook_64)(qint64);
+typedef void (*_qt_pixmap_cleanup_hook_pm)(QPixmap*);
-#ifndef QT_NO_QWS_KBD_SL5000
+class QImagePixmapCleanupHooks;
+extern QImagePixmapCleanupHooks* qt_image_and_pixmap_cleanup_hooks;
-class QWSSL5000KbPrivate;
-
-class QWSSL5000KeyboardHandler : public QWSTtyKeyboardHandler
+class Q_GUI_EXPORT QImagePixmapCleanupHooks
{
public:
- explicit QWSSL5000KeyboardHandler(const QString&);
- virtual ~QWSSL5000KeyboardHandler();
+ QImagePixmapCleanupHooks();
+
+ static QImagePixmapCleanupHooks *instance();
+
+ void addPixmapHook(_qt_pixmap_cleanup_hook_pm);
+ void addImageHook(_qt_image_cleanup_hook_64);
- virtual void doKey(uchar scancode);
- virtual const QWSKeyMap *keyMap() const;
+ void removePixmapHook(_qt_pixmap_cleanup_hook_pm);
+ void removeImageHook(_qt_image_cleanup_hook_64);
+
+ static void executePixmapHooks(QPixmap*);
+ static void executeImageHooks(qint64 key);
private:
- bool meta;
- bool fn;
- bool numLock;
- QWSSL5000KbPrivate *d;
+ QList<_qt_image_cleanup_hook_64> imageHooks;
+ QList<_qt_pixmap_cleanup_hook_pm> pixmapHooks;
};
-#endif // QT_NO_QWS_KBD_SL5000
-
QT_END_NAMESPACE
-QT_END_HEADER
-
-#endif // QKBDSL5000_QWS_H
+#endif // QIMAGEPIXMAP_CLEANUPHOOKS_P_H
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index a064937..fb5bed4 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -47,7 +47,7 @@
for reading images from files or other devices.
\reentrant
- \ingroup multimedia
+ \ingroup painting
\ingroup io
The most common way to read images is through QImage and QPixmap's
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index 1dcf4c4..4c121b0 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -45,7 +45,7 @@
for writing images to files or other devices.
\reentrant
- \ingroup multimedia
+ \ingroup painting
\ingroup io
QImageWriter supports setting format specific options, such as the
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index 0c1c2e1..5c910a8 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -45,7 +45,7 @@
\brief The QMovie class is a convenience class for playing movies
with QImageReader.
- \ingroup multimedia
+ \ingroup painting
First, create a QMovie object by passing either the name of a file or a
pointer to a QIODevice containing an animated image format to QMovie's
@@ -356,7 +356,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
reader = new QImageReader(device, format);
else
reader = new QImageReader(absoluteFilePath, format);
- reader->canRead(); // Provoke a device->open() call
+ (void)reader->canRead(); // Provoke a device->open() call
reader->device()->seek(initialDevicePos);
reader->setBackgroundColor(bgColor);
reader->setScaledSize(scaledSize);
diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp
index c0cff24..7de9fe9 100644
--- a/src/gui/image/qnativeimage.cpp
+++ b/src/gui/image/qnativeimage.cpp
@@ -52,6 +52,10 @@
#include <qwidget.h>
#endif
+#ifdef Q_WS_MAC
+#include <private/qpaintengine_mac_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
#ifdef Q_WS_WIN
@@ -65,7 +69,7 @@ typedef struct {
QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool isTextBuffer, QWidget *)
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
Q_UNUSED(isTextBuffer);
#endif
BITMAPINFO_MASK bmi;
@@ -78,7 +82,7 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool is
if (format == QImage::Format_RGB16) {
bmi.bmiHeader.biBitCount = 16;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (isTextBuffer) {
bmi.bmiHeader.biCompression = BI_RGB;
bmi.redMask = 0;
@@ -116,7 +120,7 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool is
Q_ASSERT(image.paintEngine()->type() == QPaintEngine::Raster);
static_cast<QRasterPaintEngine *>(image.paintEngine())->setDC(hdc);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
GdiFlush();
#endif
}
@@ -229,18 +233,19 @@ QImage::Format QNativeImage::systemFormat()
#elif defined(Q_WS_MAC)
-QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /* isTextBuffer */, QWidget *)
+QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /* isTextBuffer */, QWidget *widget)
: image(width, height, format)
{
- cgColorSpace = CGColorSpaceCreateDeviceRGB();
+
+
uint cgflags = kCGImageAlphaNoneSkipFirst;
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
- if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- cgflags |= kCGBitmapByteOrder32Host;
+ cgflags |= kCGBitmapByteOrder32Host;
#endif
- cg = CGBitmapContextCreate(image.bits(), width, height, 8, image.bytesPerLine(), cgColorSpace, cgflags);
+ cg = CGBitmapContextCreate(image.bits(), width, height, 8, image.bytesPerLine(),
+ QCoreGraphicsPaintEngine::macDisplayColorSpace(widget), cgflags);
CGContextTranslateCTM(cg, 0, height);
CGContextScaleCTM(cg, 1, -1);
@@ -252,7 +257,6 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /*
QNativeImage::~QNativeImage()
{
CGContextRelease(cg);
- CGColorSpaceRelease(cgColorSpace);
}
QImage::Format QNativeImage::systemFormat()
diff --git a/src/gui/image/qnativeimage_p.h b/src/gui/image/qnativeimage_p.h
index cfbeb6e..46fa13d 100644
--- a/src/gui/image/qnativeimage_p.h
+++ b/src/gui/image/qnativeimage_p.h
@@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE
class QWidget;
-class Q_GUI_EXPORT QNativeImage
+class QNativeImage
{
public:
QNativeImage(int width, int height, QImage::Format format, bool isTextBuffer = false, QWidget *widget = 0);
@@ -95,7 +95,6 @@ public:
#elif defined(Q_WS_MAC)
CGContextRef cg;
- CGColorSpaceRef cgColorSpace;
#endif
private:
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index 110a38f..b32861c 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -69,9 +69,9 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
\brief The QPicture class is a paint device that records and
replays QPainter commands.
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
- \mainclass
+
A picture serializes painter commands to an IO device in a
platform-independent format. They are sometimes referred to as meta-files.
@@ -131,8 +131,6 @@ QPicture::QPicture(int formatVersion)
d_ptr(new QPicturePrivate)
{
Q_D(QPicture);
- d_ptr->q_ptr = this;
- d->paintEngine = 0;
if (formatVersion == 0)
qWarning("QPicture: invalid format version 0");
@@ -142,8 +140,7 @@ QPicture::QPicture(int formatVersion)
d->formatMajor = formatVersion;
d->formatMinor = 0;
d->formatOk = false;
- }
- else {
+ } else {
d->resetFormat();
}
}
@@ -157,7 +154,6 @@ QPicture::QPicture(int formatVersion)
QPicture::QPicture(const QPicture &pic)
: QPaintDevice(), d_ptr(pic.d_ptr)
{
- d_func()->ref.ref();
}
/*! \internal */
@@ -165,7 +161,6 @@ QPicture::QPicture(QPicturePrivate &dptr)
: QPaintDevice(),
d_ptr(&dptr)
{
- d_ptr->q_ptr = this;
}
/*!
@@ -173,10 +168,6 @@ QPicture::QPicture(QPicturePrivate &dptr)
*/
QPicture::~QPicture()
{
- if (!d_func()->ref.deref()) {
- delete d_func()->paintEngine;
- delete d_func();
- }
}
/*!
@@ -230,8 +221,7 @@ const char* QPicture::data() const
void QPicture::detach()
{
- if (d_func()->ref != 1)
- detach_helper();
+ d_ptr.detach();
}
bool QPicture::isDetached() const
@@ -954,6 +944,8 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
}
/*!
+ \internal
+
Internal implementation of the virtual QPaintDevice::metric()
function.
@@ -1015,24 +1007,16 @@ int QPicture::metric(PaintDeviceMetric m) const
/*! \fn bool QPicture::isDetached() const
\internal
*/
+
+/*! \internal
+### Qt 5 - remove me
+ */
void QPicture::detach_helper()
{
- Q_D(QPicture);
- QPicturePrivate *x = new QPicturePrivate;
- int pictsize = size();
- x->pictb.setData(data(), pictsize);
- if (d->pictb.isOpen()) {
- x->pictb.open(d->pictb.openMode());
- x->pictb.seek(d->pictb.pos());
- }
- x->trecs = d->trecs;
- x->formatOk = d->formatOk;
- x->formatMinor = d->formatMinor;
- x->brect = d->brect;
- x->override_rect = d->override_rect;
- if (!d->ref.deref())
- delete d;
- d_ptr = x;
+ // QExplicitelySharedDataPointer takes care of cloning using
+ // QPicturePrivate's copy constructor. Do not call detach_helper() anymore
+ // and remove in Qt 5, please.
+ Q_ASSERT_X(false, "QPicture::detach_helper()", "Do not call this function");
}
/*!
@@ -1041,13 +1025,43 @@ void QPicture::detach_helper()
*/
QPicture& QPicture::operator=(const QPicture &p)
{
- qAtomicAssign<QPicturePrivate>(d_ptr, p.d_ptr);
+ d_ptr = p.d_ptr;
return *this;
}
/*!
\internal
+ Constructs a QPicturePrivate
+*/
+QPicturePrivate::QPicturePrivate()
+ : in_memory_only(false)
+{
+}
+
+/*!
+ \internal
+
+ Copy-Constructs a QPicturePrivate. Needed when detaching.
+*/
+QPicturePrivate::QPicturePrivate(const QPicturePrivate &other)
+ : trecs(other.trecs),
+ formatOk(other.formatOk),
+ formatMinor(other.formatMinor),
+ brect(other.brect),
+ override_rect(other.override_rect),
+ in_memory_only(false)
+{
+ pictb.setData(other.pictb.data(), other.pictb.size());
+ if (other.pictb.isOpen()) {
+ pictb.open(other.pictb.openMode());
+ pictb.seek(other.pictb.pos());
+ }
+}
+
+/*!
+ \internal
+
Sets formatOk to false and resets the format version numbers to default
*/
@@ -1135,14 +1149,15 @@ bool QPicturePrivate::checkFormat()
QPaintEngine *QPicture::paintEngine() const
{
if (!d_func()->paintEngine)
- const_cast<QPicture*>(this)->d_func()->paintEngine = new QPicturePaintEngine;
- return d_func()->paintEngine;
+ const_cast<QPicture*>(this)->d_func()->paintEngine.reset(new QPicturePaintEngine);
+ return d_func()->paintEngine.data();
}
/*****************************************************************************
QPicture stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
/*!
\relates QPicture
@@ -1188,6 +1203,7 @@ QDataStream &operator>>(QDataStream &s, QPicture &r)
r.d_func()->resetFormat();
return s;
}
+#endif // QT_NO_DATASTREAM
#ifndef QT_NO_PICTUREIO
@@ -1294,7 +1310,7 @@ QList<QByteArray> QPicture::outputFormats()
\brief The QPictureIO class contains parameters for loading and
saving pictures.
- \ingroup multimedia
+ \ingroup painting
\ingroup io
QPictureIO contains a QIODevice object that is used for picture data
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index add9f61..30281b7 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -42,8 +42,9 @@
#ifndef QPICTURE_H
#define QPICTURE_H
-#include <QtGui/qpaintdevice.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtGui/qpaintdevice.h>
QT_BEGIN_HEADER
@@ -106,14 +107,14 @@ private:
bool exec(QPainter *p, QDataStream &ds, int i);
void detach_helper();
- QPicturePrivate *d_ptr;
+ QExplicitlySharedDataPointer<QPicturePrivate> d_ptr;
friend class QPicturePaintEngine;
friend class Q3Picture;
friend class QAlphaPaintEngine;
friend class QPreviewPaintEngine;
public:
- typedef QPicturePrivate* DataPtr;
+ typedef QExplicitlySharedDataPointer<QPicturePrivate> DataPtr;
inline DataPtr &data_ptr() { return d_ptr; }
};
@@ -184,8 +185,10 @@ private:
QPicture stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPicture &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPicture &);
+#endif
#endif // QT_NO_PICTURE
diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h
index 360cf48..27c443c 100644
--- a/src/gui/image/qpicture_p.h
+++ b/src/gui/image/qpicture_p.h
@@ -69,9 +69,8 @@ class QPaintEngine;
extern const char *qt_mfhdr_tag;
-class Q_GUI_EXPORT QPicturePrivate
+class QPicturePrivate
{
- Q_DECLARE_PUBLIC(QPicture)
friend class QPicturePaintEngine;
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &s, const QPicture &r);
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &s, QPicture &r);
@@ -143,7 +142,8 @@ public:
PdcReservedStop = 199 // for Qt
};
- inline QPicturePrivate() : in_memory_only(false), q_ptr(0) { ref = 1; }
+ QPicturePrivate();
+ QPicturePrivate(const QPicturePrivate &other);
QAtomicInt ref;
bool checkFormat();
@@ -156,14 +156,12 @@ public:
int formatMinor;
QRect brect;
QRect override_rect;
- QPaintEngine *paintEngine;
+ QScopedPointer<QPaintEngine> paintEngine;
bool in_memory_only;
QList<QImage> image_list;
QList<QPixmap> pixmap_list;
QList<QBrush> brush_list;
QList<QPen> pen_list;
-
- QPicture *q_ptr;
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index e7fc000..7f5b943 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -43,6 +43,7 @@
#include "qpixmap.h"
#include "qpixmapdata_p.h"
+#include "qimagepixmapcleanuphooks_p.h"
#include "qbitmap.h"
#include "qcolormap.h"
@@ -76,19 +77,15 @@
# include <private/qpixmap_x11_p.h>
#endif
+#if defined(Q_OS_SYMBIAN)
+# include <private/qt_s60_p.h>
+#endif
+
#include "qpixmap_raster_p.h"
QT_BEGIN_NAMESPACE
// ### Qt 5: remove
-typedef void (*_qt_pixmap_cleanup_hook)(int);
-Q_GUI_EXPORT _qt_pixmap_cleanup_hook qt_pixmap_cleanup_hook = 0;
-
-// ### Qt 5: rename
-typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
-Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64 = 0;
-
-// ### Qt 5: remove
Q_GUI_EXPORT qint64 qt_pixmap_id(const QPixmap &pixmap)
{
return pixmap.cacheKey();
@@ -123,7 +120,6 @@ void QPixmap::init(int w, int h, int type)
data = QGraphicsSystem::createDefaultPixmapData(static_cast<QPixmapData::PixelType>(type));
data->resize(w, h);
- data->ref.ref();
}
/*!
@@ -225,7 +221,6 @@ QPixmap::QPixmap(const QSize &s, int type)
QPixmap::QPixmap(QPixmapData *d)
: QPaintDevice(), data(d)
{
- data->ref.ref();
}
/*!
@@ -281,11 +276,9 @@ QPixmap::QPixmap(const QPixmap &pixmap)
return;
}
if (pixmap.paintingActive()) { // make a deep copy
- data = 0;
operator=(pixmap.copy());
} else {
data = pixmap.data;
- data->ref.ref();
}
}
@@ -329,7 +322,8 @@ QPixmap::QPixmap(const char * const xpm[])
QPixmap::~QPixmap()
{
- deref();
+ if (data->is_cached && data->ref == 1)
+ QImagePixmapCleanupHooks::executePixmapHooks(this);
}
/*!
@@ -374,11 +368,64 @@ QPixmap QPixmap::copy(const QRect &rect) const
else
d = QGraphicsSystem::createDefaultPixmapData(data->pixelType());
- d->copy(data, r);
+ d->copy(data.data(), r);
return QPixmap(d);
}
/*!
+ \fn QPixmap::scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed)
+ \since 4.6
+
+ This convenience function is equivalent to calling QPixmap::scroll(\a dx,
+ \a dy, QRect(\a x, \a y, \a width, \a height), \a exposed).
+
+ \sa QWidget::scroll(), QGraphicsItem::scroll()
+*/
+
+/*!
+ \since 4.6
+
+ Scrolls the area \a rect of this pixmap by (\a dx, \a dy). The exposed
+ region is left unchanged. You can optionally pass a pointer to an empty
+ QRegion to get the region that is \a exposed by the scroll operation.
+
+ \snippet doc/src/snippets/code/src_gui_image_qpixmap.cpp 2
+
+ You cannot scroll while there is an active painter on the pixmap.
+
+ \sa QWidget::scroll(), QGraphicsItem::scroll()
+*/
+void QPixmap::scroll(int dx, int dy, const QRect &rect, QRegion *exposed)
+{
+ if (isNull() || (dx == 0 && dy == 0))
+ return;
+ QRect dest = rect & this->rect();
+ QRect src = dest.translated(-dx, -dy) & dest;
+ if (src.isEmpty()) {
+ if (exposed)
+ *exposed += dest;
+ return;
+ }
+
+ detach();
+
+ if (!data->scroll(dx, dy, src)) {
+ // Fallback
+ QPixmap pix = *this;
+ QPainter painter(&pix);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.drawPixmap(src.translated(dx, dy), *this, src);
+ painter.end();
+ *this = pix;
+ }
+
+ if (exposed) {
+ *exposed += dest;
+ *exposed -= src.translated(dx, dy);
+ }
+}
+
+/*!
Assigns the given \a pixmap to this pixmap and returns a reference
to this pixmap.
@@ -394,8 +441,6 @@ QPixmap &QPixmap::operator=(const QPixmap &pixmap)
if (pixmap.paintingActive()) { // make a deep copy
*this = pixmap.copy();
} else {
- pixmap.data->ref.ref(); // avoid 'x = x'
- deref();
data = pixmap.data;
}
return *this;
@@ -502,7 +547,7 @@ bool QPixmap::isQBitmap() const
*/
bool QPixmap::isNull() const
{
- return data->width() == 0;
+ return data->isNull();
}
/*!
@@ -600,13 +645,13 @@ void QPixmap::resize_helper(const QSize &s)
QPixmap pm(QSize(w, h), data->type);
bool uninit = false;
#if defined(Q_WS_X11)
- QX11PixmapData *x11Data = data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data) : 0;
+ QX11PixmapData *x11Data = data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data.data()) : 0;
if (x11Data) {
pm.x11SetScreen(x11Data->xinfo.screen());
- uninit = x11Data->uninit;
+ uninit = x11Data->flags & QX11PixmapData::Uninitialized;
}
#elif defined(Q_WS_MAC)
- QMacPixmapData *macData = data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data) : 0;
+ QMacPixmapData *macData = data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
if (macData)
uninit = macData->uninit;
#endif
@@ -618,14 +663,9 @@ void QPixmap::resize_helper(const QSize &s)
p.drawPixmap(0, 0, *this, 0, 0, qMin(width(), w), qMin(height(), h));
}
-#if defined(Q_WS_MAC)
-#ifndef QT_MAC_NO_QUICKDRAW
- if(macData && macData->qd_alpha)
- macData->macQDUpdateAlpha();
-#endif
-#elif defined(Q_WS_X11)
+#if defined(Q_WS_X11)
if (x11Data && x11Data->x11_mask) {
- QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pm.data);
+ QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pm.data.data());
pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display,
RootWindow(x11Data->xinfo.display(),
x11Data->xinfo.screen()),
@@ -794,19 +834,11 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
if (QPixmapCache::find(key, *this))
return true;
- QImage image = QImageReader(fileName, format).read();
- if (image.isNull())
- return false;
- QPixmap pm;
- if (data->pixelType() == QPixmapData::BitmapType)
- pm = QBitmap::fromImage(image, flags);
- else
- pm = fromImage(image, flags);
- if (!pm.isNull()) {
- *this = pm;
+ if (data->fromFile(fileName, format, flags)) {
QPixmapCache::insert(key, *this);
return true;
}
+
return false;
}
@@ -831,21 +863,7 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
bool QPixmap::loadFromData(const uchar *buf, uint len, const char *format, Qt::ImageConversionFlags flags)
{
- QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buf), len);
- QBuffer b(&a);
- b.open(QIODevice::ReadOnly);
-
- QImage image = QImageReader(&b, format).read();
- QPixmap pm;
- if (data->pixelType() == QPixmapData::BitmapType)
- pm = QBitmap::fromImage(image, flags);
- else
- pm = fromImage(image, flags);
- if (!pm.isNull()) {
- *this = pm;
- return true;
- }
- return false;
+ return data->fromData(buf, len, format, flags);
}
/*!
@@ -1119,7 +1137,7 @@ Qt::HANDLE QPixmap::handle() const
{
#if defined(Q_WS_X11)
if (data->classId() == QPixmapData::X11Class)
- return static_cast<QX11PixmapData*>(data)->handle();
+ return static_cast<const QX11PixmapData*>(data.constData())->handle();
#endif
return 0;
}
@@ -1267,7 +1285,7 @@ QDataStream &operator>>(QDataStream &stream, QPixmap &pixmap)
return stream;
}
-#endif //QT_NO_DATASTREAM
+#endif // QT_NO_DATASTREAM
#ifdef QT3_SUPPORT
Q_GUI_EXPORT void copyBlt(QPixmap *dst, int dx, int dy,
@@ -1306,22 +1324,12 @@ bool QPixmap::isDetached() const
return data->ref == 1;
}
+/*! \internal
+ ### Qt5 - remove me.
+*/
void QPixmap::deref()
{
- if (data && !data->ref.deref()) { // Destroy image if last ref
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
- if (data->classId() == QPixmapData::RasterClass) {
- QRasterPixmapData *rData = static_cast<QRasterPixmapData*>(data);
- if (rData->texture)
- rData->texture->Release();
- rData->texture = 0;
- }
-#endif
- if (data->is_cached && qt_pixmap_cleanup_hook_64)
- qt_pixmap_cleanup_hook_64(cacheKey());
- delete data;
- data = 0;
- }
+ Q_ASSERT_X(false, "QPixmap::deref()", "Do not call this function anymore!");
}
/*!
@@ -1404,10 +1412,9 @@ QPixmap QPixmap::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Tran
if (newSize == size())
return *this;
- QPixmap pix;
- QTransform wm;
- wm.scale((qreal)newSize.width() / width(), (qreal)newSize.height() / height());
- pix = transformed(wm, mode);
+ QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(),
+ (qreal)newSize.height() / height());
+ QPixmap pix = transformed(wm, mode);
return pix;
}
@@ -1434,9 +1441,8 @@ QPixmap QPixmap::scaledToWidth(int w, Qt::TransformationMode mode) const
if (w <= 0)
return QPixmap();
- QTransform wm;
qreal factor = (qreal) w / width();
- wm.scale(factor, factor);
+ QTransform wm = QTransform::fromScale(factor, factor);
return transformed(wm, mode);
}
@@ -1463,9 +1469,8 @@ QPixmap QPixmap::scaledToHeight(int h, Qt::TransformationMode mode) const
if (h <= 0)
return QPixmap();
- QTransform wm;
qreal factor = (qreal) h / height();
- wm.scale(factor, factor);
+ QTransform wm = QTransform::fromScale(factor, factor);
return transformed(wm, mode);
}
@@ -1520,9 +1525,9 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
\brief The QPixmap class is an off-screen image representation
that can be used as a paint device.
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
- \mainclass
+
Qt provides four classes for handling image data: QImage, QPixmap,
QBitmap and QPicture. QImage is designed and optimized for I/O,
@@ -1530,24 +1535,24 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
designed and optimized for showing images on screen. QBitmap is
only a convenience class that inherits QPixmap, ensuring a depth
of 1. The isQBitmap() function returns true if a QPixmap object is
- really a bitmap, otherwise returns false. Finally, the QPicture class is a
- paint device that records and replays QPainter commands.
+ really a bitmap, otherwise returns false. Finally, the QPicture class
+ is a paint device that records and replays QPainter commands.
A QPixmap can easily be displayed on the screen using QLabel or
one of QAbstractButton's subclasses (such as QPushButton and
QToolButton). QLabel has a pixmap property, whereas
- QAbstractButton has an icon property. And because QPixmap is a
- QPaintDevice subclass, QPainter can be used to draw directly onto
- pixmaps.
+ QAbstractButton has an icon property.
In addition to the ordinary constructors, a QPixmap can be
constructed using the static grabWidget() and grabWindow()
functions which creates a QPixmap and paints the given widget, or
- window, in it.
+ window, into it.
+
+ QPixmap objects can be passed around by value since the QPixmap
+ class uses implicit data sharing. For more information, see the \l
+ {Implicit Data Sharing} documentation. QPixmap objects can also be
+ streamed.
- Note that the pixel data in a pixmap is internal and is managed by
- the underlying window system. Pixels can only be accessed through
- QPainter functions or by converting the QPixmap to a QImage.
Depending on the system, QPixmap is stored using a RGB32 or a
premultiplied alpha format. If the image has an alpha channel, and
if the system allows, the preferred format is premultiplied alpha.
@@ -1558,6 +1563,13 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
QPixmap are stored on the client side and don't use any GDI
resources).
+ Note that the pixel data in a pixmap is internal and is managed by
+ the underlying window system. Because QPixmap is a QPaintDevice
+ subclass, QPainter can be used to draw directly onto pixmaps.
+ Pixels can only be accessed through QPainter functions or by
+ converting the QPixmap to a QImage. However, the fill() function
+ is available for initializing the entire pixmap with a given color.
+
There are functions to convert between QImage and
QPixmap. Typically, the QImage class is used to load an image
file, optionally manipulating the image data, before the QImage
@@ -1572,11 +1584,6 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
there are several functions that enables transformation of the
pixmap.
- QPixmap objects can be passed around by value since the QPixmap
- class uses implicit data sharing. For more information, see the \l
- {Implicit Data Sharing} documentation. QPixmap objects can also be
- streamed.
-
\tableofcontents
\section1 Reading and Writing Image Files
@@ -1633,12 +1640,15 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
The hasAlphaChannel() returns true if the pixmap has a format that
respects the alpha channel, otherwise returns false, while the
hasAlpha() function returns true if the pixmap has an alpha
- channel \e or a mask (otherwise false).
+ channel \e or a mask (otherwise false). The mask() function returns
+ the mask as a QBitmap object, which can be set using setMask().
- The alphaChannel() function returns the alpha channel as a new
- QPixmap object, while the mask() function returns the mask as a
- QBitmap object. The alpha channel and mask can be set using the
- setAlphaChannel() and setMask() functions, respectively.
+ The createHeuristicMask() function creates and returns a 1-bpp
+ heuristic mask (i.e. a QBitmap) for this pixmap. It works by
+ selecting a color from one of the corners and then chipping away
+ pixels of that color, starting at all the edges. The
+ createMaskFromColor() function creates and returns a mask (i.e. a
+ QBitmap) for the pixmap based on a given color.
\row
\o Low-level information
@@ -1676,14 +1686,7 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
\section1 Pixmap Transformations
QPixmap supports a number of functions for creating a new pixmap
- that is a transformed version of the original: The
- createHeuristicMask() function creates and returns a 1-bpp
- heuristic mask (i.e. a QBitmap) for this pixmap. It works by
- selecting a color from one of the corners and then chipping away
- pixels of that color, starting at all the edges. The
- createMaskFromColor() function creates and returns a mask (i.e. a
- QBitmap) for the pixmap based on a given color.
-
+ that is a transformed version of the original:
The scaled(), scaledToWidth() and scaledToHeight() functions
return scaled copies of the pixmap, while the copy() function
@@ -1698,11 +1701,6 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
function returns the actual matrix used for transforming the
pixmap.
- There are also functions for changing attributes of a pixmap.
- in-place: The fill() function fills the entire image with the
- given color, the setMask() function sets a mask bitmap, and the
- setAlphaChannel() function sets the pixmap's alpha channel.
-
\sa QBitmap, QImage, QImageReader, QImageWriter
*/
@@ -1721,7 +1719,7 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
Returns true if this pixmap has an alpha channel, \e or has a
mask, otherwise returns false.
- \sa hasAlphaChannel(), alphaChannel(), mask()
+ \sa hasAlphaChannel(), mask()
*/
bool QPixmap::hasAlpha() const
{
@@ -1732,7 +1730,7 @@ bool QPixmap::hasAlpha() const
Returns true if the pixmap has a format that respects the alpha
channel, otherwise returns false.
- \sa alphaChannel(), hasAlpha()
+ \sa hasAlpha()
*/
bool QPixmap::hasAlphaChannel() const
{
@@ -1740,7 +1738,7 @@ bool QPixmap::hasAlphaChannel() const
}
/*!
- \reimp
+ \internal
*/
int QPixmap::metric(PaintDeviceMetric metric) const
{
@@ -1749,6 +1747,7 @@ int QPixmap::metric(PaintDeviceMetric metric) const
/*!
\fn void QPixmap::setAlphaChannel(const QPixmap &alphaChannel)
+ \obsolete
Sets the alpha channel of this pixmap to the given \a alphaChannel
by converting the \a alphaChannel into 32 bit and using the
@@ -1786,6 +1785,8 @@ void QPixmap::setAlphaChannel(const QPixmap &alphaChannel)
}
/*!
+ \obsolete
+
Returns the alpha channel of the pixmap as a new grayscale QPixmap in which
each pixel's red, green, and blue values are given the alpha value of the
original pixmap. The color depth of the returned pixmap is the system depth
@@ -1804,7 +1805,9 @@ void QPixmap::setAlphaChannel(const QPixmap &alphaChannel)
\image alphachannelimage.png The pixmap and channelImage QPixmaps
\warning This is an expensive operation. The alpha channel of the
- pixmap is extracted dynamically from the pixeldata.
+ pixmap is extracted dynamically from the pixeldata. Most usecases of this
+ function are covered by QPainter and compositionModes which will normally
+ execute faster.
\sa setAlphaChannel(), {QPixmap#Pixmap Information}{Pixmap
Information}
@@ -1815,7 +1818,7 @@ QPixmap QPixmap::alphaChannel() const
}
/*!
- \reimp
+ \internal
*/
QPaintEngine *QPixmap::paintEngine() const
{
@@ -1825,7 +1828,7 @@ QPaintEngine *QPixmap::paintEngine() const
/*!
\fn QBitmap QPixmap::mask() const
- Extracts a bitmap mask from the pixmap's alphachannel.
+ Extracts a bitmap mask from the pixmap's alpha channel.
\warning This is potentially an expensive operation. The mask of
the pixmap is extracted dynamically from the pixeldata.
@@ -1853,18 +1856,17 @@ int QPixmap::defaultDepth()
return QScreen::instance()->depth();
#elif defined(Q_WS_X11)
return QX11Info::appDepth();
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WINCE)
return QColormap::instance().depth();
#elif defined(Q_WS_WIN)
return 32; // XXX
#elif defined(Q_WS_MAC)
return 32;
+#elif defined(Q_OS_SYMBIAN)
+ return S60->screenDepth;
#endif
}
-typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
-extern _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64;
-
/*!
Detaches the pixmap from shared pixmap data.
@@ -1886,21 +1888,15 @@ void QPixmap::detach()
{
QPixmapData::ClassId id = data->classId();
if (id == QPixmapData::RasterClass) {
- QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data);
+ QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data.data());
rasterData->image.detach();
-#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D)
- if (rasterData->texture) {
- rasterData->texture->Release();
- rasterData->texture = 0;
- }
-#endif
}
- if (data->is_cached && qt_pixmap_cleanup_hook_64 && data->ref == 1)
- qt_pixmap_cleanup_hook_64(cacheKey());
+ if (data->is_cached && data->ref == 1)
+ QImagePixmapCleanupHooks::executePixmapHooks(this);
#if defined(Q_WS_MAC)
- QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data) : 0;
+ QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
if (macData) {
if (macData->cg_mask) {
CGImageRelease(macData->cg_mask);
@@ -1911,18 +1907,13 @@ void QPixmap::detach()
if (data->ref != 1) {
*this = copy();
-#if defined(Q_WS_MAC) && !defined(QT_MAC_NO_QUICKDRAW)
- if (id == QPixmapData::MacClass) {
- macData->qd_alpha = 0;
- }
-#endif
}
++data->detach_no;
#if defined(Q_WS_X11)
if (data->classId() == QPixmapData::X11Class) {
- QX11PixmapData *d = static_cast<QX11PixmapData*>(data);
- d->uninit = false;
+ QX11PixmapData *d = static_cast<QX11PixmapData*>(data.data());
+ d->flags &= ~QX11PixmapData::Uninitialized;
// reset the cache data
if (d->hd2) {
@@ -1958,15 +1949,11 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
if (image.isNull())
return QPixmap();
- QPixmapData *data;
QGraphicsSystem* gs = QApplicationPrivate::graphicsSystem();
- if (gs)
- data = gs->createPixmapData(QPixmapData::PixmapType);
- else
- data = QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixmapType);
-
+ QScopedPointer<QPixmapData> data(gs ? gs->createPixmapData(QPixmapData::PixmapType)
+ : QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixmapType));
data->fromImage(image, flags);
- return QPixmap(data);
+ return QPixmap(data.take());
}
/*!
@@ -2011,7 +1998,7 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
*/
QPixmapData* QPixmap::pixmapData() const
{
- return data;
+ return data.data();
}
/*!
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 08b2643..c2d6d56 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -46,11 +46,16 @@
#include <QtGui/qcolor.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qstring.h> // char*->QString conversion
+#include <QtCore/qsharedpointer.h>
#include <QtGui/qimage.h>
#include <QtGui/qtransform.h>
QT_BEGIN_HEADER
+#if defined(Q_OS_SYMBIAN)
+class CFbsBitmap;
+#endif
+
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
@@ -59,7 +64,6 @@ class QImageWriter;
class QColor;
class QVariant;
class QX11Info;
-
class QPixmapData;
class Q_GUI_EXPORT QPixmap : public QPaintDevice
@@ -79,11 +83,11 @@ public:
QPixmap &operator=(const QPixmap &);
operator QVariant() const;
- bool isNull() const;
+ bool isNull() const; // ### Qt 5: make inline
int devType() const;
- int width() const;
- int height() const;
+ int width() const; // ### Qt 5: make inline
+ int height() const; // ### Qt 5: make inline
QSize size() const;
QRect rect() const;
int depth() const;
@@ -152,9 +156,17 @@ public:
static QPixmap fromMacCGImageRef(CGImageRef image);
#endif
+#if defined(Q_OS_SYMBIAN)
+ CFbsBitmap *toSymbianCFbsBitmap() const;
+ static QPixmap fromSymbianCFbsBitmap(CFbsBitmap *bitmap);
+#endif
+
inline QPixmap copy(int x, int y, int width, int height) const;
QPixmap copy(const QRect &rect = QRect()) const;
+ inline void scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed = 0);
+ void scroll(int dx, int dy, const QRect &rect, QRegion *exposed = 0);
+
int serialNumber() const;
qint64 cacheKey() const;
@@ -216,7 +228,7 @@ public:
#endif
private:
- QPixmapData *data;
+ QExplicitlySharedDataPointer<QPixmapData> data;
bool doImageIO(QImageWriter *io, int quality) const;
@@ -251,8 +263,6 @@ private:
friend class QWidgetPrivate;
friend class QRasterPaintEngine;
friend class QRasterBuffer;
- friend class QDirect3DPaintEngine;
- friend class QDirect3DPaintEnginePrivate;
friend class QDetachedPixmap;
#if !defined(QT_NO_DATASTREAM)
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPixmap &);
@@ -263,7 +273,7 @@ public:
QPixmapData* pixmapData() const;
public:
- typedef QPixmapData * DataPtr;
+ typedef QExplicitlySharedDataPointer<QPixmapData> DataPtr;
inline DataPtr &data_ptr() { return data; }
};
@@ -274,6 +284,11 @@ inline QPixmap QPixmap::copy(int ax, int ay, int awidth, int aheight) const
return copy(QRect(ax, ay, awidth, aheight));
}
+inline void QPixmap::scroll(int dx, int dy, int ax, int ay, int awidth, int aheight, QRegion *exposed)
+{
+ scroll(dx, dy, QRect(ax, ay, awidth, aheight), exposed);
+}
+
inline bool QPixmap::loadFromData(const QByteArray &buf, const char *format,
Qt::ImageConversionFlags flags)
{
diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp
index 3a9676d..5cfdba9 100644
--- a/src/gui/image/qpixmap_mac.cpp
+++ b/src/gui/image/qpixmap_mac.cpp
@@ -38,7 +38,6 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-//#define QT_RASTER_PAINTENGINE
#include "qpixmap.h"
#include "qimage.h"
@@ -52,9 +51,6 @@
#include <private/qdrawhelper_p.h>
#include <private/qpixmap_mac_p.h>
#include <private/qpixmap_raster_p.h>
-#ifdef QT_RASTER_PAINTENGINE
-# include <private/qpaintengine_raster_p.h>
-#endif
#include <private/qpaintengine_mac_p.h>
#include <private/qt_mac_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
@@ -77,12 +73,12 @@ static int qt_pixmap_serial = 0;
Q_GUI_EXPORT quint32 *qt_mac_pixmap_get_base(const QPixmap *pix)
{
- return static_cast<QMacPixmapData*>(pix->data)->pixels;
+ return static_cast<QMacPixmapData*>(pix->data.data())->pixels;
}
Q_GUI_EXPORT int qt_mac_pixmap_get_bytes_per_line(const QPixmap *pix)
{
- return static_cast<QMacPixmapData*>(pix->data)->bytesPerRow;
+ return static_cast<QMacPixmapData*>(pix->data.data())->bytesPerRow;
}
void qt_mac_cgimage_data_free(void *info, const void *memoryToFree, size_t)
@@ -119,14 +115,9 @@ CGImageRef qt_mac_image_to_cgimage(const QImage &image)
CGDataProviderCreateWithData(0, image.bits(), image.bytesPerLine() * image.height(),
0);
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
uint cgflags = kCGImageAlphaPremultipliedFirst;
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
- if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- cgflags |= kCGBitmapByteOrder32Host;
-#endif
-#else
- CGImageAlphaInfo cgflags = kCGImageAlphaPremultipliedFirst;
+ cgflags |= kCGBitmapByteOrder32Host;
#endif
CGImageRef cgImage = CGImageCreate(image.width(), image.height(), bitsPerColor, bitsPerPixel,
@@ -168,12 +159,9 @@ static inline QRgb qt_conv16ToRgb(ushort c) {
QSet<QMacPixmapData*> QMacPixmapData::validDataPointers;
QMacPixmapData::QMacPixmapData(PixelType type)
- : QPixmapData(type, MacClass), w(0), h(0), d(0), has_alpha(0), has_mask(0),
+ : QPixmapData(type, MacClass), has_alpha(0), has_mask(0),
uninit(true), pixels(0), pixelsToFree(0), bytesPerRow(0),
cg_data(0), cg_dataBeingReleased(0), cg_mask(0),
-#ifndef QT_MAC_NO_QUICKDRAW
- qd_data(0), qd_alpha(0),
-#endif
pengine(0)
{
}
@@ -188,11 +176,13 @@ void QMacPixmapData::resize(int width, int height)
w = width;
h = height;
+ is_null = (w <= 0 || h <= 0);
d = (pixelType() == BitmapType ? 1 : 32);
bool make_null = w <= 0 || h <= 0; // create null pixmap
if (make_null || d == 0) {
w = 0;
h = 0;
+ is_null = true;
d = 0;
if (!make_null)
qWarning("Qt: QPixmap: Invalid pixmap parameters");
@@ -231,6 +221,7 @@ void QMacPixmapData::fromImage(const QImage &img,
w = img.width();
h = img.height();
+ is_null = (w <= 0 || h <= 0);
d = (pixelType() == BitmapType ? 1 : img.depth());
QImage image = img;
@@ -430,7 +421,7 @@ QPixmap QMacPixmapData::alphaChannel() const
void QMacPixmapData::setAlphaChannel(const QPixmap &alpha)
{
has_mask = true;
- QMacPixmapData *alphaData = static_cast<QMacPixmapData*>(alpha.data);
+ QMacPixmapData *alphaData = static_cast<QMacPixmapData*>(alpha.data.data());
macSetAlphaChannel(alphaData, false);
}
@@ -458,7 +449,7 @@ void QMacPixmapData::setMask(const QBitmap &mask)
has_alpha = false;
has_mask = true;
- QMacPixmapData *maskData = static_cast<QMacPixmapData*>(mask.data);
+ QMacPixmapData *maskData = static_cast<QMacPixmapData*>(mask.data.data());
macSetAlphaChannel(maskData, true);
}
@@ -496,13 +487,6 @@ int QMacPixmapData::metric(QPaintDevice::PaintDeviceMetric theMetric) const
QMacPixmapData::~QMacPixmapData()
{
validDataPointers.remove(this);
-#ifndef QT_MAC_NO_QUICKDRAW
- macQDDisposeAlpha();
- if (qd_data) {
- DisposeGWorld(qd_data);
- qd_data = 0;
- }
-#endif
if (cg_mask) {
CGImageRelease(cg_mask);
cg_mask = 0;
@@ -591,48 +575,9 @@ void QMacPixmapData::macGetAlphaChannel(QMacPixmapData *pix, bool asMask) const
void QMacPixmapData::macSetHasAlpha(bool b)
{
has_alpha = b;
-#ifndef QT_MAC_NO_QUICKDRAW
- macQDDisposeAlpha(); //let it get created lazily
-#endif
macReleaseCGImageRef();
}
-#ifndef QT_MAC_NO_QUICKDRAW
-void QMacPixmapData::macQDDisposeAlpha()
-{
- if (qd_alpha) {
- DisposeGWorld(qd_alpha);
- qd_alpha = 0;
- }
-}
-
-void QMacPixmapData::macQDUpdateAlpha()
-{
- macQDDisposeAlpha(); // get rid of alpha pixmap
- if (!has_alpha && !has_mask)
- return;
-
- //setup
- Rect rect;
- SetRect(&rect, 0, 0, w, h);
- const int params = alignPix | stretchPix | newDepth;
- NewGWorld(&qd_alpha, 32, &rect, 0, 0, params);
- int *dptr = (int *)GetPixBaseAddr(GetGWorldPixMap(qd_alpha)), *drow;
- unsigned short dbpr = GetPixRowBytes(GetGWorldPixMap(qd_alpha));
- const int *sptr = (int*)pixels, *srow;
- const uint sbpr = bytesPerRow;
- uchar clr;
- for (int y = 0; y < h; ++y) {
- drow = (int*)((char *)dptr + (y * dbpr));
- srow = (int*)((char *)sptr + (y * sbpr));
- for (int x=0; x < w; x++) {
- clr = qAlpha(*(srow + x));
- *(drow + x) = qRgba(~clr, ~clr, ~clr, 0);
- }
- }
-}
-#endif
-
void QMacPixmapData::macCreateCGImageRef()
{
Q_ASSERT(cg_data == 0);
@@ -642,14 +587,9 @@ void QMacPixmapData::macCreateCGImageRef()
pixels, bytesPerRow * h,
qt_mac_cgimage_data_free);
validDataPointers.insert(this);
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
uint cgflags = kCGImageAlphaPremultipliedFirst;
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
- if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- cgflags |= kCGBitmapByteOrder32Host;
-#endif
-#else
- CGImageAlphaInfo cgflags = kCGImageAlphaPremultipliedFirst;
+ cgflags |= kCGBitmapByteOrder32Host;
#endif
cg_data = CGImageCreate(w, h, 8, 32, bytesPerRow, colorspace,
cgflags, provider, 0, 0, kCGRenderingIntentDefault);
@@ -890,38 +830,6 @@ static void qt_mac_grabDisplayRect(CGDirectDisplayID display, const QRect &displ
ptrCGLDestroyContext(glContextObj); // and destroy the context
}
-static CGImageRef qt_mac_createImageFromBitmapContext(CGContextRef c)
-{
- void *rasterData = CGBitmapContextGetData(c);
- const int width = CGBitmapContextGetBytesPerRow(c),
- height = CGBitmapContextGetHeight(c);
- size_t imageDataSize = width*height;
-
- if(!rasterData)
- return 0;
-
- // Create the data provider from the image data, using
- // the image releaser function releaseBitmapContextImageData.
- CGDataProviderRef dataProvider = CGDataProviderCreateWithData(0, rasterData,
- imageDataSize,
- qt_mac_cgimage_data_free);
-
- if(!dataProvider)
- return 0;
-
- uint bitmapInfo = 0;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- if(CGBitmapContextGetBitmapInfo)
- bitmapInfo = CGBitmapContextGetBitmapInfo(c);
- else
-#endif
- bitmapInfo = CGBitmapContextGetAlphaInfo(c);
- return CGImageCreate(width, height, CGBitmapContextGetBitsPerComponent(c),
- CGBitmapContextGetBitsPerPixel(c), CGBitmapContextGetBytesPerRow(c),
- CGBitmapContextGetColorSpace(c), bitmapInfo, dataProvider,
- 0, true, kCGRenderingIntentDefault);
-}
-
// Returns a pixmap containing the screen contents at rect.
static QPixmap qt_mac_grabScreenRect(const QRect &rect)
{
@@ -955,19 +863,8 @@ static QPixmap qt_mac_grabScreenRect(const QRect &rect)
rect.height(), 8, bytewidth,
QCoreGraphicsPaintEngine::macGenericColorSpace(),
kCGImageAlphaNoneSkipFirst);
-
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- QCFType<CGImageRef> image = CGBitmapContextCreateImage(bitmap);
- return QPixmap::fromMacCGImageRef(image);
- } else
-#endif
- {
- QCFType<CGImageRef> image = qt_mac_createImageFromBitmapContext(bitmap);
- if (!image)
- return QPixmap();
- return QPixmap::fromMacCGImageRef(image);
- }
+ QCFType<CGImageRef> image = CGBitmapContextCreateImage(bitmap);
+ return QPixmap::fromMacCGImageRef(image);
}
#ifndef QT_MAC_USE_COCOA // no QuickDraw in 64-bit mode
@@ -1029,37 +926,12 @@ QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
relocated.
\warning This function is only available on Mac OS X.
+ \warning As of Qt 4.6, this function \e{always} returns zero.
*/
Qt::HANDLE QPixmap::macQDHandle() const
{
-#ifndef QT_MAC_NO_QUICKDRAW
- QMacPixmapData *d = static_cast<QMacPixmapData*>(data);
- if (!d->qd_data) { //create the qd data
- Rect rect;
- SetRect(&rect, 0, 0, d->w, d->h);
- unsigned long qdformat = k32ARGBPixelFormat;
- GWorldFlags qdflags = 0;
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- //we play such games so we can use the same buffer in CG as QD this
- //makes our merge much simpler, at some point the hacks will go away
- //because QD will be removed, but until that day this keeps them coexisting
- if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
- qdformat = k32BGRAPixelFormat;
-#if 0
- qdflags |= kNativeEndianPixMap;
-#endif
- }
-#endif
- if(NewGWorldFromPtr(&d->qd_data, qdformat, &rect, 0, 0, qdflags,
- (char*)d->pixels, d->bytesPerRow) != noErr)
- qWarning("Qt: internal: QPixmap::init error (%d %d %d %d)", rect.left, rect.top, rect.right, rect.bottom);
- }
- return d->qd_data;
-#else
return 0;
-#endif
}
/*! \internal
@@ -1069,18 +941,11 @@ Qt::HANDLE QPixmap::macQDHandle() const
long as it can be relocated.
\warning This function is only available on Mac OS X.
+ \warning As of Qt 4.6, this function \e{always} returns zero.
*/
Qt::HANDLE QPixmap::macQDAlphaHandle() const
{
-#ifndef QT_MAC_NO_QUICKDRAW
- QMacPixmapData *d = static_cast<QMacPixmapData*>(data);
- if (d->has_alpha || d->has_mask) {
- if (!d->qd_alpha) //lazily created
- d->macQDUpdateAlpha();
- return d->qd_alpha;
- }
-#endif
return 0;
}
@@ -1096,14 +961,14 @@ Qt::HANDLE QPixmap::macQDAlphaHandle() const
Qt::HANDLE QPixmap::macCGHandle() const
{
if (data->classId() == QPixmapData::MacClass) {
- QMacPixmapData *d = static_cast<QMacPixmapData *>(data);
+ QMacPixmapData *d = static_cast<QMacPixmapData *>(data.data());
if (!d->cg_data)
d->macCreateCGImageRef();
CGImageRef ret = d->cg_data;
CGImageRetain(ret);
return ret;
} else if (data->classId() == QPixmapData::RasterClass) {
- return qt_mac_image_to_cgimage(static_cast<QRasterPixmapData *>(data)->image);
+ return qt_mac_image_to_cgimage(static_cast<QRasterPixmapData *>(data.data())->image);
}
return 0;
}
@@ -1115,7 +980,7 @@ bool QMacPixmapData::hasAlphaChannel() const
CGImageRef qt_mac_create_imagemask(const QPixmap &pixmap, const QRectF &sr)
{
- QMacPixmapData *px = static_cast<QMacPixmapData*>(pixmap.data);
+ QMacPixmapData *px = static_cast<QMacPixmapData*>(pixmap.data.data());
if (px->cg_mask) {
if (px->cg_mask_rect == sr) {
CGImageRetain(px->cg_mask); //reference for the caller
@@ -1150,7 +1015,6 @@ IconRef qt_mac_create_iconref(const QPixmap &px)
if (px.isNull())
return 0;
- QMacSavedPortInfo pi; //save the current state
//create icon
IconFamilyHandle iconFamily = reinterpret_cast<IconFamilyHandle>(NewHandle(0));
//create data
@@ -1225,38 +1089,12 @@ IconRef qt_mac_create_iconref(const QPixmap &px)
}
#endif
-QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height)
-{
- QPixmap ret(width, height);
- ret.fill(QColor(0, 0, 0, 0));
-
- CGRect rect = CGRectMake(0, 0, width, height);
-
- CGContextRef ctx = qt_mac_cg_context(&ret);
- CGAffineTransform old_xform = CGContextGetCTM(ctx);
- CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform));
- CGContextConcatCTM(ctx, CGAffineTransformIdentity);
-
- ::RGBColor b;
- b.blue = b.green = b.red = 255*255;
- PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon);
- CGContextRelease(ctx);
- return ret;
-}
-
/*! \internal */
QPaintEngine* QMacPixmapData::paintEngine() const
{
if (!pengine) {
QMacPixmapData *that = const_cast<QMacPixmapData*>(this);
-#ifdef QT_RASTER_PAINTENGINE
- if (qgetenv("QT_MAC_USE_COREGRAPHICS").isNull())
- that->pengine = new QRasterPaintEngine();
- else
- that->pengine = new QCoreGraphicsPaintEngine();
-#else
that->pengine = new QCoreGraphicsPaintEngine();
-#endif
}
return pengine;
}
@@ -1290,6 +1128,14 @@ void QMacPixmapData::copy(const QPixmapData *data, const QRect &rect)
has_mask = macData->has_mask;
}
+bool QMacPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+ Q_UNUSED(rect);
+ return false;
+}
+
/*!
\since 4.2
@@ -1321,6 +1167,7 @@ QPixmap QPixmap::fromMacCGImageRef(CGImageRef image)
const size_t w = CGImageGetWidth(image),
h = CGImageGetHeight(image);
QPixmap ret(w, h);
+ ret.fill(Qt::transparent);
CGRect rect = CGRectMake(0, 0, w, h);
CGContextRef ctx = qt_mac_cg_context(&ret);
qt_mac_drawCGImage(ctx, &rect, image);
diff --git a/src/gui/image/qpixmap_mac_p.h b/src/gui/image/qpixmap_mac_p.h
index d0d828f..d32e933 100644
--- a/src/gui/image/qpixmap_mac_p.h
+++ b/src/gui/image/qpixmap_mac_p.h
@@ -68,6 +68,7 @@ public:
void resize(int width, int height);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
void copy(const QPixmapData *data, const QRect &rect);
+ bool scroll(int dx, int dy, const QRect &rect);
int metric(QPaintDevice::PaintDeviceMetric metric) const;
void fill(const QColor &color);
@@ -82,7 +83,6 @@ public:
QPaintEngine* paintEngine() const;
private:
- int w, h, d;
uint has_alpha : 1, has_mask : 1, uninit : 1;
@@ -109,11 +109,6 @@ private:
uint bytesPerRow;
QRectF cg_mask_rect;
CGImageRef cg_data, cg_dataBeingReleased, cg_mask;
-#ifndef QT_MAC_NO_QUICKDRAW
- GWorldPtr qd_data, qd_alpha;
- void macQDDisposeAlpha();
- void macQDUpdateAlpha();
-#endif
static QSet<QMacPixmapData*> validDataPointers;
QPaintEngine *pengine;
diff --git a/src/gui/image/qpixmap_qws.cpp b/src/gui/image/qpixmap_qws.cpp
index 55968f1..8966c43 100644
--- a/src/gui/image/qpixmap_qws.cpp
+++ b/src/gui/image/qpixmap_qws.cpp
@@ -48,6 +48,9 @@
#include <private/qdrawhelper_p.h>
#include <private/qpixmap_raster_p.h>
+
+QT_BEGIN_NAMESPACE
+
QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
{
QWidget *widget = QWidget::find(window);
@@ -112,7 +115,7 @@ QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
QRgb* QPixmap::clut() const
{
if (data->classId() == QPixmapData::RasterClass) {
- const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data);
+ const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data.data());
return d->image.colorTable().data();
}
@@ -122,7 +125,7 @@ QRgb* QPixmap::clut() const
int QPixmap::numCols() const
{
if (data->classId() == QPixmapData::RasterClass) {
- const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data);
+ const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data.data());
return d->image.numColors();
}
@@ -132,7 +135,7 @@ int QPixmap::numCols() const
const uchar* QPixmap::qwsBits() const
{
if (data->classId() == QPixmapData::RasterClass) {
- const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data);
+ const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data.data());
return d->image.bits();
}
@@ -142,9 +145,11 @@ const uchar* QPixmap::qwsBits() const
int QPixmap::qwsBytesPerLine() const
{
if (data->classId() == QPixmapData::RasterClass) {
- const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data);
+ const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data.data());
return d->image.bytesPerLine();
}
return 0;
}
+
+QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 47996ce..da8a33c 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -50,12 +50,6 @@
#include <private/qwidget_p.h>
#include <private/qdrawhelper_p.h>
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
-#include <private/qpaintengine_d3d_p.h>
-#include <d3d9.h>
-extern QDirect3DPaintEngine *qt_d3dEngine();
-#endif
-
QT_BEGIN_NAMESPACE
const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
@@ -63,9 +57,6 @@ const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
QRasterPixmapData::QRasterPixmapData(PixelType type)
: QPixmapData(type, RasterClass)
-#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D)
- , texture(0)
-#endif
{
}
@@ -94,6 +85,10 @@ void QRasterPixmapData::resize(int width, int height)
#endif
image = QImage(width, height, format);
+ w = width;
+ h = height;
+ d = image.depth();
+ is_null = (w <= 0 || h <= 0);
if (pixelType() == BitmapType && !image.isNull()) {
image.setNumColors(2);
@@ -177,10 +172,28 @@ void QRasterPixmapData::fromImage(const QImage &sourceImage,
}
}
#endif
+ if (image.d) {
+ w = image.d->width;
+ h = image.d->height;
+ d = image.d->depth;
+ } else {
+ w = h = d = 0;
+ }
+ is_null = (w <= 0 || h <= 0);
setSerialNumber(image.serialNumber());
}
+// from qwindowsurface.cpp
+extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
+
+bool QRasterPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ if (!image.isNull())
+ qt_scrollRectInImage(image, rect, QPoint(dx, dy));
+ return true;
+}
+
void QRasterPixmapData::fill(const QColor &color)
{
uint pixel;
@@ -321,25 +334,36 @@ extern int qt_defaultDpiY();
int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
{
+ QImageData *d = image.d;
+ if (!d)
+ return 0;
+
// override the image dpi with the screen dpi when rendering to a pixmap
- const int dpmX = qRound(qt_defaultDpiX() * 100 / qreal(2.54));
- const int dpmY = qRound(qt_defaultDpiY() * 100 / qreal(2.54));
switch (metric) {
+ case QPaintDevice::PdmWidth:
+ return w;
+ case QPaintDevice::PdmHeight:
+ return h;
case QPaintDevice::PdmWidthMM:
- return qRound(image.width() * 1000 / dpmX);
+ return qRound(d->width * 25.4 / qt_defaultDpiX());
case QPaintDevice::PdmHeightMM:
- return qRound(image.height() * 1000 / dpmY);
- case QPaintDevice::PdmDpiX:
- return qRound(dpmX * qreal(0.0254));
- case QPaintDevice::PdmDpiY:
- return qRound(dpmY * qreal(0.0254));
+ return qRound(d->width * 25.4 / qt_defaultDpiY());
+ case QPaintDevice::PdmNumColors:
+ return d->colortable.size();
+ case QPaintDevice::PdmDepth:
+ return this->d;
+ case QPaintDevice::PdmDpiX: // fall-through
case QPaintDevice::PdmPhysicalDpiX:
- return qRound(dpmX * qreal(0.0254));
+ return qt_defaultDpiX();
+ case QPaintDevice::PdmDpiY: // fall-through
case QPaintDevice::PdmPhysicalDpiY:
- return qRound(dpmY * qreal(0.0254));
+ return qt_defaultDpiY();
default:
- return image.metric(metric);
+ qWarning("QRasterPixmapData::metric(): Unhandled metric type %d", metric);
+ break;
}
+
+ return 0;
}
QImage* QRasterPixmapData::buffer()
diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h
index 682c84f..8eed2a1 100644
--- a/src/gui/image/qpixmap_raster_p.h
+++ b/src/gui/image/qpixmap_raster_p.h
@@ -58,9 +58,6 @@
#ifdef Q_WS_WIN
# include "qt_windows.h"
-# ifndef QT_NO_DIRECT3D
-# include <d3d9.h>
-# endif
#endif
QT_BEGIN_NAMESPACE
@@ -75,6 +72,7 @@ public:
void fromFile(const QString &filename, Qt::ImageConversionFlags flags);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
+ bool scroll(int dx, int dy, const QRect &rect);
void fill(const QColor &color);
void setMask(const QBitmap &mask);
bool hasAlphaChannel() const;
@@ -87,10 +85,6 @@ protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;
private:
-#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D)
- friend class QDirect3DPaintEnginePrivate;
- IDirect3DTexture9 *texture;
-#endif
friend class QPixmap;
friend class QBitmap;
friend class QDetachedPixmap;
diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp
new file mode 100644
index 0000000..e00bf26
--- /dev/null
+++ b/src/gui/image/qpixmap_s60.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <exception>
+#include <w32std.h>
+#include <fbs.h>
+
+#include <private/qt_s60_p.h>
+#include "qpixmap.h"
+#include "qpixmap_raster_p.h"
+#include <qwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
+{
+ CWsScreenDevice* screenDevice = S60->screenDevice();
+ TSize screenSize = screenDevice->SizeInPixels();
+
+ TSize srcSize;
+ // Find out if this is one of our windows.
+ QSymbianControl *sControl;
+ sControl = winId->MopGetObject(sControl);
+ if (sControl && sControl->widget()->windowType() == Qt::Desktop) {
+ // Grabbing desktop widget
+ srcSize = screenSize;
+ } else {
+ TPoint relativePos = winId->PositionRelativeToScreen();
+ x += relativePos.iX;
+ y += relativePos.iY;
+ srcSize = winId->Size();
+ }
+
+ TRect srcRect(TPoint(x, y), srcSize);
+ // Clip to the screen
+ srcRect.Intersection(TRect(screenSize));
+
+ if (w > 0 && h > 0) {
+ TRect subRect(TPoint(x, y), TSize(w, h));
+ // Clip to the subRect
+ srcRect.Intersection(subRect);
+ }
+
+ if (srcRect.IsEmpty())
+ return QPixmap();
+
+ TDisplayMode displayMode = screenDevice->DisplayMode();
+ CFbsBitmap* temporary = q_check_ptr(new CFbsBitmap()); // CBase derived object needs check on new
+ TInt error = temporary->Create(srcRect.Size(), displayMode);
+ if (error == KErrNone)
+ error = screenDevice->CopyScreenToBitmap(temporary, srcRect);
+
+ if (error != KErrNone) {
+ CBase::Delete(temporary);
+ return QPixmap();
+ }
+
+ QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(temporary);
+ CBase::Delete(temporary);
+ return pixmap;
+}
+
+/*!
+\since 4.6
+
+Returns a \c CFbsBitmap that is equivalent to the QPixmap by copying the data.
+
+It is the caller's responsibility to delete the \c CFbsBitmap after use.
+
+\warning This function is only available on Symbian OS.
+
+\sa fromSymbianCFbsBitmap()
+*/
+
+CFbsBitmap *QPixmap::toSymbianCFbsBitmap() const
+{
+ if (isNull())
+ return 0;
+
+ TDisplayMode mode;
+ const QImage img = toImage();
+ QImage::Format destFormat = img.format();
+ switch (img.format()) {
+ case QImage::Format_Mono:
+ destFormat = QImage::Format_MonoLSB;
+ // Fall through intended
+ case QImage::Format_MonoLSB:
+ mode = EGray2;
+ break;
+ case QImage::Format_Indexed8:
+ if (img.isGrayscale())
+ mode = EGray256;
+ else
+ mode = EColor256;
+ break;
+ case QImage::Format_RGB32:
+ mode = EColor16MU;
+ break;
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ destFormat = QImage::Format_ARGB32_Premultiplied;
+ // Fall through intended
+ case QImage::Format_ARGB32_Premultiplied:
+#if !defined(__SERIES60_31__) && !defined(__S60_32__)
+ // ### TODO: Add runtime detection as well?
+ mode = EColor16MAP;
+ break;
+#endif
+ destFormat = QImage::Format_ARGB32;
+ // Fall through intended
+ case QImage::Format_ARGB32:
+ mode = EColor16MA;
+ break;
+ case QImage::Format_RGB555:
+ destFormat = QImage::Format_RGB16;
+ // Fall through intended
+ case QImage::Format_RGB16:
+ mode = EColor64K;
+ break;
+ case QImage::Format_RGB666:
+ destFormat = QImage::Format_RGB888;
+ // Fall through intended
+ case QImage::Format_RGB888:
+ mode = EColor16M;
+ break;
+ case QImage::Format_RGB444:
+ mode = EColor4K;
+ break;
+ case QImage::Format_Invalid:
+ return 0;
+ default:
+ qWarning("Image format not supported: %d", img.format());
+ return 0;
+ }
+
+ CFbsBitmap* bitmap = q_check_ptr(new CFbsBitmap()); // CBase derived object needs check on new
+ TSize size(width(), height());
+ if (bitmap->Create(size, mode) != KErrNone) {
+ CBase::Delete(bitmap);
+ return 0;
+ }
+
+ const QImage converted = img.convertToFormat(destFormat);
+
+ bitmap->LockHeap();
+ const uchar *sptr = converted.bits();
+ uchar *dptr = (uchar*)bitmap->DataAddress();
+ Mem::Copy(dptr, sptr, converted.numBytes());
+ bitmap->UnlockHeap();
+ return bitmap;
+}
+
+/*!
+ \since 4.6
+
+ Returns a QPixmap that is equivalent to the \c CFbsBitmap \a bitmap
+ by copying the data. If the CFbsBitmap is not valid or is compressed
+ in memory, this function will return a null QPixmap.
+
+ \warning This function is only available on Symbian OS.
+
+ \sa toSymbianCFbsBitmap(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
+*/
+
+QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap)
+{
+ if (!bitmap)
+ return QPixmap();
+
+ int width = bitmap->SizeInPixels().iWidth;
+ int height = bitmap->SizeInPixels().iHeight;
+
+ if (width <= 0 || height <= 0 || bitmap->IsCompressedInRAM())
+ return QPixmap();
+
+ TDisplayMode displayMode = bitmap->DisplayMode();
+ QImage::Format format = qt_TDisplayMode2Format(displayMode);
+ int bytesPerLine = CFbsBitmap::ScanLineLength(width, displayMode);
+ bitmap->LockHeap();
+ QImage image = QImage((const uchar*)bitmap->DataAddress(), width, height, bytesPerLine, format);
+ if (displayMode == EGray2) {
+ image.setNumColors(2);
+ image.setColor(0, QColor(Qt::color0).rgba());
+ image.setColor(1, QColor(Qt::color1).rgba());
+ } else if (displayMode == EGray256) {
+ for (int i=0; i < 256; ++i)
+ image.setColor(i, qRgb(i, i, i));
+ }else if (displayMode == EColor256) {
+ const TColor256Util *palette = TColor256Util::Default();
+ for (int i=0; i < 256; ++i)
+ image.setColor(i, (QRgb)(palette->Color256(i).Value()));
+ }
+ QPixmap pixmap = QPixmap::fromImage(image.copy());
+ bitmap->UnlockHeap();
+ return pixmap;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index 9bab0cf..c748adc 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -59,7 +59,7 @@
#include "qdebug.h"
#include "qt_windows.h"
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include <winbase.h>
#include "qguifunctions_wince.h"
extern bool qt_wince_is_high_dpi();
@@ -80,7 +80,7 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
if (w < 0) w = r.right - r.left;
if (h < 0) h = r.bottom - r.top;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
if (qt_wince_is_pocket_pc()) {
QWidget *widget = QWidget::find(winId);
if (qobject_cast<QDesktopWidget *>(widget)) {
@@ -101,7 +101,7 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
// copy data
HDC window_dc = GetDC(winId);
BitBlt(bitmap_dc, 0, 0, w, h, window_dc, x, y, SRCCOPY
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
| CAPTUREBLT
#endif
);
@@ -123,7 +123,7 @@ HBITMAP QPixmap::toWinHBITMAP(HBitmapFormat format) const
{
HBITMAP bitmap = 0;
if (data->classId() == QPixmapData::RasterClass) {
- QRasterPixmapData* d = static_cast<QRasterPixmapData*>(data);
+ QRasterPixmapData* d = static_cast<QRasterPixmapData*>(data.data());
int w = d->image.width();
int h = d->image.height();
@@ -179,13 +179,7 @@ QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format)
BITMAP bitmap_info;
memset(&bitmap_info, 0, sizeof(BITMAP));
- int res;
- QT_WA({
- res = GetObjectW(bitmap, sizeof(BITMAP), &bitmap_info);
- } , {
- res = GetObjectA(bitmap, sizeof(BITMAP), &bitmap_info);
- });
-
+ int res = GetObject(bitmap, sizeof(BITMAP), &bitmap_info);
if (!res) {
qErrnoWarning("QPixmap::fromWinHBITMAP(), failed to get bitmap info");
return QPixmap();
@@ -243,7 +237,7 @@ QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format)
}
#ifdef Q_WS_WIN
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
static QImage qt_fromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
{
@@ -347,7 +341,7 @@ QPixmap convertHIconToPixmap( const HICON icon)
DeleteDC(hdc);
return QPixmap::fromImage(image);
}
-#else //ifndef Q_OS_WINCE
+#else //ifndef Q_WS_WINCE
QPixmap convertHIconToPixmap( const HICON icon, bool large)
{
HDC screenDevice = GetDC(0);
@@ -412,14 +406,14 @@ QPixmap convertHIconToPixmap( const HICON icon, bool large)
DeleteDC(hdc);
return QPixmap::fromImage(image);
}
-#endif //ifndef Q_OS_WINCE
+#endif //ifndef Q_WS_WINCE
QPixmap loadIconFromShell32( int resourceId, int size )
{
#ifdef Q_OS_WINCE
- HMODULE hmod = LoadLibrary((const wchar_t *) QString::fromLatin1("ceshell.dll").utf16());
+ HMODULE hmod = LoadLibrary(L"ceshell.dll");
#else
- HMODULE hmod = LoadLibraryA("shell32.dll");
+ HMODULE hmod = LoadLibrary(L"shell32.dll");
#endif
if( hmod ) {
HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size, size, 0);
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 796d88c..aea995a 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -312,8 +312,8 @@ static int qt_pixmap_serial = 0;
int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0;
QX11PixmapData::QX11PixmapData(PixelType type)
- : QPixmapData(type, X11Class), hd(0), w(0), h(0), d(0),
- uninit(true), read_only(false), x11_mask(0), picture(0), mask_picture(0), hd2(0),
+ : QPixmapData(type, X11Class), hd(0),
+ flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0), gl_surface(0),
share_mode(QPixmap::ImplicitlyShared), pengine(0)
{
}
@@ -324,6 +324,7 @@ void QX11PixmapData::resize(int width, int height)
w = width;
h = height;
+ is_null = (w <= 0 || h <= 0);
if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
QX11InfoData* xd = xinfo.getX11Data(true);
@@ -347,6 +348,7 @@ void QX11PixmapData::resize(int width, int height)
if (make_null || d == 0) {
w = 0;
h = 0;
+ is_null = true;
hd = 0;
picture = 0;
d = 0;
@@ -375,6 +377,7 @@ void QX11PixmapData::fromImage(const QImage &img,
w = img.width();
h = img.height();
d = img.depth();
+ is_null = (w <= 0 || h <= 0);
if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
QX11InfoData* xd = xinfo.getX11Data(true);
@@ -395,6 +398,7 @@ void QX11PixmapData::fromImage(const QImage &img,
if (uint(w) >= 32768 || uint(h) >= 32768) {
w = h = 0;
+ is_null = true;
return;
}
@@ -1109,6 +1113,7 @@ void QX11PixmapData::bitmapFromImage(const QImage &image)
w = img.width();
h = img.height();
d = 1;
+ is_null = (w <= 0 || h <= 0);
int bpl = (w + 7) / 8;
int ibpl = img.bytesPerLine();
if (bpl != ibpl) {
@@ -1212,7 +1217,7 @@ void QX11PixmapData::release()
XFreePixmap(xinfo.display(), hd2);
hd2 = 0;
}
- if (!read_only)
+ if (!(flags & Readonly))
XFreePixmap(xinfo.display(), hd);
hd = 0;
}
@@ -1870,12 +1875,13 @@ QPixmap QX11PixmapData::transformed(const QTransform &transform,
return bm;
} else { // color pixmap
QPixmap pm;
- QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(pm.data);
- x11Data->uninit = false;
+ QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(pm.data.data());
+ x11Data->flags &= ~QX11PixmapData::Uninitialized;
x11Data->xinfo = xinfo;
x11Data->d = d;
x11Data->w = w;
x11Data->h = h;
+ x11Data->is_null = (w <= 0 || h <= 0);
x11Data->hd = (Qt::HANDLE)XCreatePixmap(X11->display,
RootWindow(X11->display, xinfo.screen()),
w, h, d);
@@ -1934,7 +1940,7 @@ void QPixmap::x11SetScreen(int screen)
if (screen < 0)
screen = QX11Info::appScreen();
- QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(data);
+ QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(data.data());
if (screen == x11Data->xinfo.screen())
return; // nothing to do
@@ -2012,7 +2018,7 @@ QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
QPixmap pm(data);
- data->uninit = false;
+ data->flags &= ~QX11PixmapData::Uninitialized;
pm.x11SetScreen(scr);
GC gc = XCreateGC(dpy, pm.handle(), 0, 0);
@@ -2031,7 +2037,7 @@ bool QX11PixmapData::hasAlphaChannel() const
const QX11Info &QPixmap::x11Info() const
{
if (data->classId() == QPixmapData::X11Class)
- return static_cast<QX11PixmapData*>(data)->xinfo;
+ return static_cast<QX11PixmapData*>(data.data())->xinfo;
else {
static QX11Info nullX11Info;
return nullX11Info;
@@ -2054,7 +2060,7 @@ QPaintEngine* QX11PixmapData::paintEngine() const
{
QX11PixmapData *that = const_cast<QX11PixmapData*>(this);
- if (read_only && share_mode == QPixmap::ImplicitlyShared) {
+ if ((flags & Readonly) && share_mode == QPixmap::ImplicitlyShared) {
// if someone wants to draw onto us, copy the shared contents
// and turn it into a fully fledged QPixmap
::Pixmap hd_copy = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()),
@@ -2076,7 +2082,7 @@ QPaintEngine* QX11PixmapData::paintEngine() const
XFreeGC(X11->display, gc);
}
that->hd = hd_copy;
- that->read_only = false;
+ that->flags &= ~QX11PixmapData::Readonly;
}
if (!that->pengine)
@@ -2088,7 +2094,7 @@ Qt::HANDLE QPixmap::x11PictureHandle() const
{
#ifndef QT_NO_XRENDER
if (data->classId() == QPixmapData::X11Class)
- return static_cast<QX11PixmapData*>(data)->picture;
+ return static_cast<const QX11PixmapData*>(data.data())->picture;
else
return 0;
#else
@@ -2127,11 +2133,12 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect)
setSerialNumber(++qt_pixmap_serial);
- uninit = false;
+ flags &= ~Uninitialized;
xinfo = x11Data->xinfo;
d = x11Data->d;
w = rect.width();
h = rect.height();
+ is_null = (w <= 0 || h <= 0);
hd = (Qt::HANDLE)XCreatePixmap(X11->display,
RootWindow(X11->display, x11Data->xinfo.screen()),
w, h, d);
@@ -2177,6 +2184,16 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect)
}
}
+bool QX11PixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ GC gc = XCreateGC(X11->display, hd, 0, 0);
+ XCopyArea(X11->display, hd, hd, gc,
+ rect.left(), rect.top(), rect.width(), rect.height(),
+ rect.left() + dx, rect.top() + dy);
+ XFreeGC(X11->display, gc);
+ return true;
+}
+
#if !defined(QT_NO_XRENDER)
void QX11PixmapData::convertToARGB32(bool preserveContents)
{
@@ -2184,7 +2201,7 @@ void QX11PixmapData::convertToARGB32(bool preserveContents)
return;
// Q_ASSERT(count == 1);
- if (read_only && share_mode == QPixmap::ExplicitlyShared)
+ if ((flags & Readonly) && share_mode == QPixmap::ExplicitlyShared)
return;
Pixmap pm = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()),
@@ -2194,10 +2211,10 @@ void QX11PixmapData::convertToARGB32(bool preserveContents)
if (picture) {
if (preserveContents)
XRenderComposite(X11->display, PictOpSrc, picture, 0, p, 0, 0, 0, 0, 0, 0, w, h);
- if (!read_only)
+ if (!(flags & Readonly))
XRenderFreePicture(X11->display, picture);
}
- if (hd && !read_only)
+ if (hd && !(flags & Readonly))
XFreePixmap(X11->display, hd);
if (x11_mask) {
XFreePixmap(X11->display, x11_mask);
@@ -2235,11 +2252,11 @@ QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode)
QX11PixmapData *data = new QX11PixmapData(depth == 1 ? QPixmapData::BitmapType : QPixmapData::PixmapType);
data->setSerialNumber(++qt_pixmap_serial);
- data->read_only = true;
+ data->flags = QX11PixmapData::Readonly;
data->share_mode = mode;
- data->uninit = false;
data->w = width;
data->h = height;
+ data->is_null = (width <= 0 || height <= 0);
data->d = depth;
data->hd = pixmap;
diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h
index ee492f6..fc80186 100644
--- a/src/gui/image/qpixmap_x11_p.h
+++ b/src/gui/image/qpixmap_x11_p.h
@@ -74,6 +74,7 @@ public:
void resize(int width, int height);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
void copy(const QPixmapData *data, const QRect &rect);
+ bool scroll(int dx, int dy, const QRect &rect);
void fill(const QColor &color);
QBitmap mask() const;
@@ -98,6 +99,7 @@ private:
friend class QX11PaintEngine;
friend class QX11WindowSurface;
friend class QRasterWindowSurface;
+ friend class QGLContextPrivate; // Needs to access xinfo, gl_surface & flags
void release();
@@ -107,16 +109,21 @@ private:
Qt::HANDLE hd;
- int w, h;
- short d;
- uint uninit : 1;
- uint read_only : 1;
+ enum Flag {
+ NoFlags = 0x0,
+ Uninitialized = 0x1,
+ Readonly = 0x2,
+ InvertedWhenBoundToTexture = 0x4,
+ GlSurfaceCreatedWithAlpha = 0x8
+ };
+ uint flags;
QX11Info xinfo;
Qt::HANDLE x11_mask;
Qt::HANDLE picture;
Qt::HANDLE mask_picture;
Qt::HANDLE hd2; // sorted in the default display depth
+ Qt::HANDLE gl_surface;
#ifndef QT_NO_XRENDER
void convertToARGB32(bool preserveContents = true);
#endif
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index af300a8..6b34898 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -40,13 +40,9 @@
****************************************************************************/
#include "qpixmapcache.h"
-#include "qcache.h"
#include "qobject.h"
#include "qdebug.h"
-
-#include "qpaintengine.h"
-#include <private/qimage_p.h>
-#include <private/qpixmap_raster_p.h>
+#include "qpixmapcache_p.h"
QT_BEGIN_NAMESPACE
@@ -55,8 +51,7 @@ QT_BEGIN_NAMESPACE
\brief The QPixmapCache class provides an application-wide cache for pixmaps.
- \ingroup environment
- \ingroup multimedia
+ \ingroup painting
This class is a tool for optimized drawing with QPixmap. You can
use it to store temporary pixmaps that are expensive to generate
@@ -68,15 +63,24 @@ QT_BEGIN_NAMESPACE
access the global pixmap cache. It creates an internal QCache
object for caching the pixmaps.
- The cache associates a pixmap with a string (key). If two pixmaps
- are inserted into the cache using equal keys, then the last pixmap
- will hide the first pixmap. The QHash and QCache classes do
- exactly the same.
+ The cache associates a pixmap with a user-provided string as a key,
+ or with a QPixmapCache::Key that the cache generates.
+ Using QPixmapCache::Key for keys is faster than using strings. The string API is
+ very convenient for complex keys but the QPixmapCache::Key API will be very
+ efficient and convenient for a one-to-one object-to-pixmap mapping \mdash in
+ this case, you can store the keys as members of an object.
+
+ If two pixmaps are inserted into the cache using equal keys then the
+ last pixmap will replace the first pixmap in the cache. This follows the
+ behavior of the QHash and QCache classes.
The cache becomes full when the total size of all pixmaps in the
- cache exceeds cacheLimit(). The initial cache limit is 1024 KB (1
- MB); it is changed with setCacheLimit(). A pixmap takes roughly
- (\e{width} * \e{height} * \e{depth})/8 bytes of memory.
+ cache exceeds cacheLimit(). The initial cache limit is
+ 2048 KB (2 MB) on embedded platforms, 10240 KB (10 MB) on desktop
+ platforms; you can change this by calling setCacheLimit() with the
+ required value.
+ A pixmap takes roughly (\e{width} * \e{height} * \e{depth})/8 bytes of
+ memory.
The \e{Qt Quarterly} article
\l{http://qt.nokia.com/doc/qq/qq12-qpixmapcache.html}{Optimizing
@@ -86,58 +90,142 @@ QT_BEGIN_NAMESPACE
\sa QCache, QPixmap
*/
-#if defined(Q_WS_QWS) || defined(Q_OS_WINCE)
+#if defined(Q_OS_SYMBIAN)
+static int cache_limit = 1024; // 1048 KB cache limit for symbian
+#elif defined(Q_WS_QWS) || defined(Q_WS_WINCE)
static int cache_limit = 2048; // 2048 KB cache limit for embedded
#else
static int cache_limit = 10240; // 10 MB cache limit for desktop
#endif
-// XXX: hw: is this a general concept we need to abstract?
-class QDetachedPixmap : public QPixmap
+/*!
+ \class QPixmapCache::Key
+ \brief The QPixmapCache::Key class can be used for efficient access
+ to the QPixmapCache.
+ \since 4.6
+
+ Use QPixmapCache::insert() to receive an instance of Key generated
+ by the pixmap cache. You can store the key in your own objects for
+ a very efficient one-to-one object-to-pixmap mapping.
+*/
+
+/*!
+ Constructs an empty Key object.
+*/
+QPixmapCache::Key::Key() : d(0)
{
-public:
- QDetachedPixmap(const QPixmap &pix) : QPixmap(pix)
- {
- if (data && data->classId() == QPixmapData::RasterClass) {
- QRasterPixmapData *d = static_cast<QRasterPixmapData*>(data);
- if (!d->image.isNull() && d->image.d->paintEngine
- && !d->image.d->paintEngine->isActive())
- {
- delete d->image.d->paintEngine;
- d->image.d->paintEngine = 0;
- }
- }
+}
+
+/*!
+ \internal
+ Constructs a copy of \a other.
+*/
+QPixmapCache::Key::Key(const Key &other)
+{
+ if (other.d)
+ ++(other.d->ref);
+ d = other.d;
+}
+
+/*!
+ Destroys the key.
+*/
+QPixmapCache::Key::~Key()
+{
+ if (d && --(d->ref) == 0)
+ delete d;
+}
+
+/*!
+ \internal
+
+ Returns true if this key is the same as the given \a key; otherwise returns
+ false.
+*/
+bool QPixmapCache::Key::operator ==(const Key &key) const
+{
+ return (d == key.d);
+}
+
+/*!
+ \fn bool QPixmapCache::Key::operator !=(const Key &key) const
+ \internal
+*/
+
+/*!
+ \internal
+*/
+QPixmapCache::Key &QPixmapCache::Key::operator =(const Key &other)
+{
+ if (d != other.d) {
+ if (other.d)
+ ++(other.d->ref);
+ if (d && --(d->ref) == 0)
+ delete d;
+ d = other.d;
}
-};
+ return *this;
+}
-class QPMCache : public QObject, public QCache<qint64, QDetachedPixmap>
+class QPMCache : public QObject, public QCache<QPixmapCache::Key, QDetachedPixmap>
{
Q_OBJECT
public:
- QPMCache()
- : QObject(0),
- QCache<qint64, QDetachedPixmap>(cache_limit * 1024),
- theid(0), ps(0), t(false) { }
- ~QPMCache() { }
+ QPMCache();
+ ~QPMCache();
void timerEvent(QTimerEvent *);
bool insert(const QString& key, const QPixmap &pixmap, int cost);
+ QPixmapCache::Key insert(const QPixmap &pixmap, int cost);
+ bool replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost);
bool remove(const QString &key);
+ bool remove(const QPixmapCache::Key &key);
+
+ void resizeKeyArray(int size);
+ QPixmapCache::Key createKey();
+ void releaseKey(const QPixmapCache::Key &key);
+ void clear();
QPixmap *object(const QString &key) const;
+ QPixmap *object(const QPixmapCache::Key &key) const;
+
+ static inline QPixmapCache::KeyData *get(const QPixmapCache::Key &key)
+ {return key.d;}
+
+ static QPixmapCache::KeyData* getKeyData(QPixmapCache::Key *key);
private:
- QHash<QString, qint64> cacheKeys;
+ int *keyArray;
int theid;
int ps;
+ int keyArraySize;
+ int freeKey;
+ QHash<QString, QPixmapCache::Key> cacheKeys;
bool t;
};
+
QT_BEGIN_INCLUDE_NAMESPACE
#include "qpixmapcache.moc"
QT_END_INCLUDE_NAMESPACE
+uint qHash(const QPixmapCache::Key &k)
+{
+ return qHash(QPMCache::get(k)->key);
+}
+
+QPMCache::QPMCache()
+ : QObject(0),
+ QCache<QPixmapCache::Key, QDetachedPixmap>(cache_limit * 1024),
+ keyArray(0), theid(0), ps(0), keyArraySize(0), freeKey(0), t(false)
+{
+}
+QPMCache::~QPMCache()
+{
+ free(keyArray);
+}
+
/*
- This is supposed to cut the cache size down by about 80-90% in a
+ This is supposed to cut the cache size down by about 25% in a
minute once the application becomes idle, to let any inserted pixmap
remain in the cache for some time before it becomes a candidate for
cleaning-up, and to not cut down the size of the cache while the
@@ -146,23 +234,28 @@ QT_END_INCLUDE_NAMESPACE
When the last pixmap has been deleted from the cache, kill the
timer so Qt won't keep the CPU from going into sleep mode.
*/
-
void QPMCache::timerEvent(QTimerEvent *)
{
int mc = maxCost();
bool nt = totalCost() == ps;
+ QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QDetachedPixmap>::keys();
setMaxCost(nt ? totalCost() * 3 / 4 : totalCost() -1);
setMaxCost(mc);
ps = totalCost();
- QHash<QString, qint64>::iterator it = cacheKeys.begin();
+ QHash<QString, QPixmapCache::Key>::iterator it = cacheKeys.begin();
while (it != cacheKeys.end()) {
if (!contains(it.value())) {
+ releaseKey(it.value());
it = cacheKeys.erase(it);
} else {
++it;
}
}
+ for (int i = 0; i < keys.size(); ++i) {
+ if (!contains(keys.at(i)))
+ releaseKey(keys.at(i));
+ }
if (!size()) {
killTimer(theid);
@@ -176,44 +269,163 @@ void QPMCache::timerEvent(QTimerEvent *)
QPixmap *QPMCache::object(const QString &key) const
{
- return QCache<qint64, QDetachedPixmap>::object(cacheKeys.value(key, -1));
+ QPixmapCache::Key cacheKey = cacheKeys.value(key);
+ if (!cacheKey.d || !cacheKey.d->isValid) {
+ const_cast<QPMCache *>(this)->cacheKeys.remove(key);
+ return 0;
+ }
+ QPixmap *ptr = QCache<QPixmapCache::Key, QDetachedPixmap>::object(cacheKey);
+ //We didn't find the pixmap in the cache, the key is not valid anymore
+ if (!ptr) {
+ const_cast<QPMCache *>(this)->cacheKeys.remove(key);
+ const_cast<QPMCache *>(this)->releaseKey(cacheKey);
+ }
+ return ptr;
}
+QPixmap *QPMCache::object(const QPixmapCache::Key &key) const
+{
+ Q_ASSERT(key.d->isValid);
+ QPixmap *ptr = QCache<QPixmapCache::Key, QDetachedPixmap>::object(key);
+ //We didn't find the pixmap in the cache, the key is not valid anymore
+ if (!ptr)
+ const_cast<QPMCache *>(this)->releaseKey(key);
+ return ptr;
+}
bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost)
{
- qint64 cacheKey = pixmap.cacheKey();
- if (QCache<qint64, QDetachedPixmap>::object(cacheKey)) {
+ QPixmapCache::Key cacheKey;
+ QPixmapCache::Key oldCacheKey = cacheKeys.value(key);
+ //If for the same key we add already a pixmap we should delete it
+ if (oldCacheKey.d) {
+ QCache<QPixmapCache::Key, QDetachedPixmap>::remove(oldCacheKey);
+ cacheKey = oldCacheKey;
+ } else {
+ cacheKey = createKey();
+ }
+
+ bool success = QCache<QPixmapCache::Key, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost);
+ if (success) {
cacheKeys.insert(key, cacheKey);
- return true;
+ if (!theid) {
+ theid = startTimer(30000);
+ t = false;
+ }
+ } else {
+ //Insertion failed we released the new allocated key
+ releaseKey(cacheKey);
}
- qint64 oldCacheKey = cacheKeys.value(key, -1);
- //If for the same key we add already a pixmap we should delete it
- if (oldCacheKey != -1)
- QCache<qint64, QDetachedPixmap>::remove(oldCacheKey);
+ return success;
+}
- bool success = QCache<qint64, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost);
+QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost)
+{
+ QPixmapCache::Key cacheKey = createKey();
+ bool success = QCache<QPixmapCache::Key, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost);
if (success) {
- cacheKeys.insert(key, cacheKey);
if (!theid) {
theid = startTimer(30000);
t = false;
}
+ } else {
+ //Insertion failed we released the key and return an invalid one
+ releaseKey(cacheKey);
+ }
+ return cacheKey;
+}
+
+bool QPMCache::replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost)
+{
+ Q_ASSERT(key.d->isValid);
+ //If for the same key we add already a pixmap we should delete it
+ QCache<QPixmapCache::Key, QDetachedPixmap>::remove(key);
+
+ bool success = QCache<QPixmapCache::Key, QDetachedPixmap>::insert(key, new QDetachedPixmap(pixmap), cost);
+ if (success && !theid) {
+ theid = startTimer(30000);
+ t = false;
}
return success;
}
bool QPMCache::remove(const QString &key)
{
- qint64 cacheKey = cacheKeys.value(key, -1);
+ QPixmapCache::Key cacheKey = cacheKeys.value(key);
+ //The key was not in the cache
+ if (!cacheKey.d)
+ return false;
cacheKeys.remove(key);
- return QCache<qint64, QDetachedPixmap>::remove(cacheKey);
+ releaseKey(cacheKey);
+ return QCache<QPixmapCache::Key, QDetachedPixmap>::remove(cacheKey);
+}
+
+bool QPMCache::remove(const QPixmapCache::Key &key)
+{
+ bool result = QCache<QPixmapCache::Key, QDetachedPixmap>::remove(key);
+ //We release the key after we removed it from the cache
+ releaseKey(key);
+ return result;
+}
+
+void QPMCache::resizeKeyArray(int size)
+{
+ if (size <= keyArraySize || size == 0)
+ return;
+ keyArray = q_check_ptr(reinterpret_cast<int *>(realloc(keyArray,
+ size * sizeof(int))));
+ for (int i = keyArraySize; i != size; ++i)
+ keyArray[i] = i + 1;
+ keyArraySize = size;
+}
+
+QPixmapCache::Key QPMCache::createKey()
+{
+ if (freeKey == keyArraySize)
+ resizeKeyArray(keyArraySize ? keyArraySize << 1 : 2);
+ int id = freeKey;
+ freeKey = keyArray[id];
+ QPixmapCache::Key key;
+ QPixmapCache::KeyData *d = QPMCache::getKeyData(&key);
+ d->key = ++id;
+ return key;
+}
+
+void QPMCache::releaseKey(const QPixmapCache::Key &key)
+{
+ if (key.d->key > keyArraySize || key.d->key <= 0)
+ return;
+ key.d->key--;
+ keyArray[key.d->key] = freeKey;
+ freeKey = key.d->key;
+ key.d->isValid = false;
+ key.d->key = 0;
+}
+
+void QPMCache::clear()
+{
+ free(keyArray);
+ keyArray = 0;
+ freeKey = 0;
+ keyArraySize = 0;
+ //Mark all keys as invalid
+ QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QDetachedPixmap>::keys();
+ for (int i = 0; i < keys.size(); ++i)
+ keys.at(i).d->isValid = false;
+ QCache<QPixmapCache::Key, QDetachedPixmap>::clear();
+}
+
+QPixmapCache::KeyData* QPMCache::getKeyData(QPixmapCache::Key *key)
+{
+ if (!key->d)
+ key->d = new QPixmapCache::KeyData;
+ return key->d;
}
Q_GLOBAL_STATIC(QPMCache, pm_cache)
/*!
- \obsolete
+ \obsolete
\overload
Returns the pixmap associated with the \a key in the cache, or
@@ -222,7 +434,7 @@ Q_GLOBAL_STATIC(QPMCache, pm_cache)
\warning If valid, you should copy the pixmap immediately (this is
fast). Subsequent insertions into the cache could cause the
pointer to become invalid. For this reason, we recommend you use
- find(const QString&, QPixmap&) instead.
+ bool find(const QString&, QPixmap*) instead.
Example:
\snippet doc/src/snippets/code/src_gui_image_qpixmapcache.cpp 0
@@ -235,25 +447,57 @@ QPixmap *QPixmapCache::find(const QString &key)
/*!
- Looks for a cached pixmap associated with the \a key in the cache.
- If the pixmap is found, the function sets \a pm to that pixmap and
- returns true; otherwise it leaves \a pm alone and returns false.
+ \obsolete
+
+ Use bool find(const QString&, QPixmap*) instead.
+*/
+
+bool QPixmapCache::find(const QString &key, QPixmap& pixmap)
+{
+ return find(key, &pixmap);
+}
+
+/*!
+ Looks for a cached pixmap associated with the given \a key in the cache.
+ If the pixmap is found, the function sets \a pixmap to that pixmap and
+ returns true; otherwise it leaves \a pixmap alone and returns false.
+
+ \since 4.6
Example:
\snippet doc/src/snippets/code/src_gui_image_qpixmapcache.cpp 1
*/
-bool QPixmapCache::find(const QString &key, QPixmap& pm)
+bool QPixmapCache::find(const QString &key, QPixmap* pixmap)
{
QPixmap *ptr = pm_cache()->object(key);
- if (ptr)
- pm = *ptr;
+ if (ptr && pixmap)
+ *pixmap = *ptr;
return ptr != 0;
}
+/*!
+ Looks for a cached pixmap associated with the given \a key in the cache.
+ If the pixmap is found, the function sets \a pixmap to that pixmap and
+ returns true; otherwise it leaves \a pixmap alone and returns false. If
+ the pixmap is not found, it means that the \a key is no longer valid,
+ so it will be released for the next insertion.
+
+ \since 4.6
+*/
+bool QPixmapCache::find(const Key &key, QPixmap* pixmap)
+{
+ //The key is not valid anymore, a flush happened before probably
+ if (!key.d || !key.d->isValid)
+ return false;
+ QPixmap *ptr = pm_cache()->object(key);
+ if (ptr && pixmap)
+ *pixmap = *ptr;
+ return ptr != 0;
+}
/*!
- Inserts a copy of the pixmap \a pm associated with the \a key into
+ Inserts a copy of the pixmap \a pixmap associated with the \a key into
the cache.
All pixmaps inserted by the Qt library have a key starting with
@@ -272,16 +516,53 @@ bool QPixmapCache::find(const QString &key, QPixmap& pm)
\sa setCacheLimit()
*/
-bool QPixmapCache::insert(const QString &key, const QPixmap &pm)
+bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
+{
+ return pm_cache()->insert(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
+}
+
+/*!
+ Inserts a copy of the given \a pixmap into the cache and returns a key
+ that can be used to retrieve it.
+
+ When a pixmap is inserted and the cache is about to exceed its
+ limit, it removes pixmaps until there is enough room for the
+ pixmap to be inserted.
+
+ The oldest pixmaps (least recently accessed in the cache) are
+ deleted when more space is needed.
+
+ \sa setCacheLimit(), replace()
+
+ \since 4.6
+*/
+QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
+{
+ return pm_cache()->insert(pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
+}
+
+/*!
+ Replaces the pixmap associated with the given \a key with the \a pixmap
+ specified. Returns true if the \a pixmap has been correctly inserted into
+ the cache; otherwise returns false.
+
+ \sa setCacheLimit(), insert()
+
+ \since 4.6
+*/
+bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
{
- return pm_cache()->insert(key, pm, pm.width() * pm.height() * pm.depth() / 8);
+ //The key is not valid anymore, a flush happened before probably
+ if (!key.d || !key.d->isValid)
+ return false;
+ return pm_cache()->replace(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
}
/*!
Returns the cache limit (in kilobytes).
- The default cache limit is 2048 KB for Embedded, 10240 KB for
- Desktops.
+ The default cache limit is 2048 KB on embedded platforms, 10240 KB on
+ desktop platforms.
\sa setCacheLimit()
*/
@@ -294,8 +575,8 @@ int QPixmapCache::cacheLimit()
/*!
Sets the cache limit to \a n kilobytes.
- The default setting is 2048 KB for Embedded, 10240 KB for
- Desktops.
+ The default setting is 2048 KB on embedded platforms, 10240 KB on
+ desktop platforms.
\sa cacheLimit()
*/
@@ -314,6 +595,19 @@ void QPixmapCache::remove(const QString &key)
pm_cache()->remove(key);
}
+/*!
+ Removes the pixmap associated with \a key from the cache and releases
+ the key for a future insertion.
+
+ \since 4.6
+*/
+void QPixmapCache::remove(const Key &key)
+{
+ //The key is not valid anymore, a flush happened before probably
+ if (!key.d || !key.d->isValid)
+ return;
+ pm_cache()->remove(key);
+}
/*!
Removes all pixmaps from the cache.
@@ -321,7 +615,12 @@ void QPixmapCache::remove(const QString &key)
void QPixmapCache::clear()
{
- pm_cache()->clear();
+ QT_TRY {
+ pm_cache()->clear();
+ } QT_CATCH(const std::bad_alloc &) {
+ // if we ran out of memory during pm_cache(), it's no leak,
+ // so just ignore it.
+ }
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h
index 0a8524f..a0b3964 100644
--- a/src/gui/image/qpixmapcache.h
+++ b/src/gui/image/qpixmapcache.h
@@ -53,12 +53,35 @@ QT_MODULE(Gui)
class Q_GUI_EXPORT QPixmapCache
{
public:
+ class KeyData;
+ class Q_GUI_EXPORT Key
+ {
+ public:
+ Key();
+ Key(const Key &other);
+ ~Key();
+ bool operator ==(const Key &key) const;
+ inline bool operator !=(const Key &key) const
+ { return !operator==(key); }
+ Key &operator =(const Key &other);
+
+ private:
+ KeyData *d;
+ friend class QPMCache;
+ friend class QPixmapCache;
+ };
+
static int cacheLimit();
static void setCacheLimit(int);
static QPixmap *find(const QString &key);
- static bool find(const QString &key, QPixmap&);
- static bool insert(const QString &key, const QPixmap&);
+ static bool find(const QString &key, QPixmap &pixmap);
+ static bool find(const QString &key, QPixmap *pixmap);
+ static bool find(const Key &key, QPixmap *pixmap);
+ static bool insert(const QString &key, const QPixmap &pixmap);
+ static Key insert(const QPixmap &pixmap);
+ static bool replace(const Key &key, const QPixmap &pixmap);
static void remove(const QString &key);
+ static void remove(const Key &key);
static void clear();
};
diff --git a/src/gui/image/qpixmapcache_p.h b/src/gui/image/qpixmapcache_p.h
new file mode 100644
index 0000000..511c852
--- /dev/null
+++ b/src/gui/image/qpixmapcache_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIXMAPCACHE_P_H
+#define QPIXMAPCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpixmapcache.h"
+#include "qpaintengine.h"
+#include <private/qimage_p.h>
+#include <private/qpixmap_raster_p.h>
+#include "qcache.h"
+
+QT_BEGIN_NAMESPACE
+
+uint qHash(const QPixmapCache::Key &k);
+
+class QPixmapCache::KeyData
+{
+public:
+ KeyData() : isValid(true), key(0), ref(1) {}
+ KeyData(const KeyData &other)
+ : isValid(other.isValid), key(other.key), ref(1) {}
+ ~KeyData() {}
+
+ bool isValid;
+ int key;
+ int ref;
+};
+
+// XXX: hw: is this a general concept we need to abstract?
+class QDetachedPixmap : public QPixmap
+{
+public:
+ QDetachedPixmap(const QPixmap &pix) : QPixmap(pix)
+ {
+ if (data && data->classId() == QPixmapData::RasterClass) {
+ QRasterPixmapData *d = static_cast<QRasterPixmapData*>(data.data());
+ if (!d->image.isNull() && d->image.d->paintEngine
+ && !d->image.d->paintEngine->isActive())
+ {
+ delete d->image.d->paintEngine;
+ d->image.d->paintEngine = 0;
+ }
+ }
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QPIXMAPCACHE_P_H
diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp
index 6a9a3d0..a52790c 100644
--- a/src/gui/image/qpixmapdata.cpp
+++ b/src/gui/image/qpixmapdata.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qpixmapdata_p.h"
+#include <QtCore/qbuffer.h>
#include <QtGui/qbitmap.h>
#include <QtGui/qimagereader.h>
@@ -49,23 +50,61 @@ const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
0x10, 0x20, 0x40, 0x80 };
QPixmapData::QPixmapData(PixelType pixelType, int objectId)
- : ref(0), detach_no(0), type(pixelType), id(objectId), ser_no(0), is_cached(false)
+ : w(0),
+ h(0),
+ d(0),
+ is_null(true),
+ ref(0),
+ detach_no(0),
+ type(pixelType),
+ id(objectId),
+ ser_no(0),
+ is_cached(false)
{
-
}
QPixmapData::~QPixmapData()
{
}
-void QPixmapData::fromFile(const QString &fileName, const char *format,
+static QImage makeBitmapCompliantIfNeeded(QPixmapData *d, const QImage &image, Qt::ImageConversionFlags flags)
+{
+ if (d->pixelType() == QPixmapData::BitmapType) {
+ QImage img = image.convertToFormat(QImage::Format_MonoLSB, flags);
+
+ // make sure image.color(0) == Qt::color0 (white)
+ // and image.color(1) == Qt::color1 (black)
+ const QRgb c0 = QColor(Qt::black).rgb();
+ const QRgb c1 = QColor(Qt::white).rgb();
+ if (img.color(0) == c0 && img.color(1) == c1) {
+ img.invertPixels();
+ img.setColor(0, c1);
+ img.setColor(1, c0);
+ }
+ return img;
+ }
+
+ return image;
+}
+
+bool QPixmapData::fromFile(const QString &fileName, const char *format,
Qt::ImageConversionFlags flags)
{
- const QImage image = QImageReader(fileName, format).read();
+ QImage image = QImageReader(fileName, format).read();
if (image.isNull())
- return;
+ return false;
+ fromImage(makeBitmapCompliantIfNeeded(this, image, flags), flags);
+ return !isNull();
+}
- fromImage(image, flags);
+bool QPixmapData::fromData(const uchar *buf, uint len, const char *format, Qt::ImageConversionFlags flags)
+{
+ QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buf), len);
+ QBuffer b(&a);
+ b.open(QIODevice::ReadOnly);
+ QImage image = QImageReader(&b, format).read();
+ fromImage(makeBitmapCompliantIfNeeded(this, image, flags), flags);
+ return !isNull();
}
void QPixmapData::copy(const QPixmapData *data, const QRect &rect)
@@ -73,6 +112,14 @@ void QPixmapData::copy(const QPixmapData *data, const QRect &rect)
fromImage(data->toImage().copy(rect), Qt::AutoColor);
}
+bool QPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+ Q_UNUSED(rect);
+ return false;
+}
+
void QPixmapData::setMask(const QBitmap &mask)
{
if (mask.size().isEmpty()) {
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 3b5cf16..7d462a4 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -75,9 +75,14 @@ public:
virtual void resize(int width, int height) = 0;
virtual void fromImage(const QImage &image,
Qt::ImageConversionFlags flags) = 0;
- virtual void fromFile(const QString &filename, const char *format,
+
+ virtual bool fromFile(const QString &filename, const char *format,
+ Qt::ImageConversionFlags flags);
+ virtual bool fromData(const uchar *buffer, uint len, const char *format,
Qt::ImageConversionFlags flags);
+
virtual void copy(const QPixmapData *data, const QRect &rect);
+ virtual bool scroll(int dx, int dy, const QRect &rect);
virtual int metric(QPaintDevice::PaintDeviceMetric metric) const = 0;
virtual void fill(const QColor &color) = 0;
@@ -98,18 +103,25 @@ public:
virtual QImage* buffer();
- int width() const { return metric(QPaintDevice::PdmWidth); }
- int height() const { return metric(QPaintDevice::PdmHeight); }
- int numColors() const { return metric(QPaintDevice::PdmNumColors); }
- int depth() const { return metric(QPaintDevice::PdmDepth); }
+ inline int width() const { return w; }
+ inline int height() const { return h; }
+ inline int numColors() const { return metric(QPaintDevice::PdmNumColors); }
+ inline int depth() const { return d; }
+ inline bool isNull() const { return is_null; }
protected:
void setSerialNumber(int serNo);
+ int w;
+ int h;
+ int d;
+ bool is_null;
private:
friend class QPixmap;
friend class QGLContextPrivate;
friend class QX11PixmapData;
+ friend class QGLTextureCache; //Needs to check the reference count
+ friend class QExplicitlySharedDataPointer<QPixmapData>;
QAtomicInt ref;
int detach_no;
@@ -121,7 +133,7 @@ private:
};
#ifdef Q_WS_WIN
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
QPixmap convertHIconToPixmap( const HICON icon);
#else
QPixmap convertHIconToPixmap( const HICON icon, bool large = false);
diff --git a/src/gui/image/qpixmapdatafactory.cpp b/src/gui/image/qpixmapdatafactory.cpp
index 9cad585..53c93ad 100644
--- a/src/gui/image/qpixmapdatafactory.cpp
+++ b/src/gui/image/qpixmapdatafactory.cpp
@@ -47,7 +47,7 @@
#ifdef Q_WS_X11
# include <private/qpixmap_x11_p.h>
#endif
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
# include <private/qpixmap_raster_p.h>
#endif
#ifdef Q_WS_MAC
@@ -75,7 +75,7 @@ QPixmapData* QSimplePixmapDataFactory::create(QPixmapData::PixelType type)
#if defined(Q_WS_X11)
return new QX11PixmapData(type);
-#elif defined(Q_WS_WIN)
+#elif defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
return new QRasterPixmapData(type);
#elif defined(Q_WS_MAC)
return new QMacPixmapData(type);
@@ -84,7 +84,7 @@ QPixmapData* QSimplePixmapDataFactory::create(QPixmapData::PixelType type)
#endif
}
-Q_GLOBAL_STATIC(QSimplePixmapDataFactory, factory);
+Q_GLOBAL_STATIC(QSimplePixmapDataFactory, factory)
#endif // !defined(Q_WS_QWS)
diff --git a/src/gui/image/qpixmapdatafactory_p.h b/src/gui/image/qpixmapdatafactory_p.h
index 134ef2e..2a99e0a 100644
--- a/src/gui/image/qpixmapdatafactory_p.h
+++ b/src/gui/image/qpixmapdatafactory_p.h
@@ -65,7 +65,7 @@ QT_MODULE(Gui)
class QPixmapData;
-class Q_GUI_EXPORT QPixmapDataFactory
+class QPixmapDataFactory
{
public:
static QPixmapDataFactory* instance(int screen = 0);
diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp
index 3358091..b2d7f0c 100644
--- a/src/gui/image/qpixmapfilter.cpp
+++ b/src/gui/image/qpixmapfilter.cpp
@@ -65,7 +65,7 @@ public:
/*!
\class QPixmapFilter
\since 4.5
- \ingroup multimedia
+ \ingroup painting
\brief The QPixmapFilter class provides the basic functionality for
pixmap filter classes. Pixmap filter can be for example colorize or blur.
@@ -93,6 +93,9 @@ public:
\value DropShadowFilter A filter that is used to add a drop shadow to an
image. See QPixmapDropShadowFilter for more
information.
+ \value BlurFilter A filter that is used to blur an image using
+ a simple blur radius. See QPixmapBlurFilter
+ for more information.
\value UserFilter The first filter type that can be used for
application-specific purposes.
@@ -172,7 +175,7 @@ QRectF QPixmapFilter::boundingRectFor(const QRectF &rect) const
/*!
\class QPixmapConvolutionFilter
\since 4.5
- \ingroup multimedia
+ \ingroup painting
\brief The QPixmapConvolutionFilter class provides convolution
filtering for pixmaps.
@@ -293,8 +296,6 @@ int QPixmapConvolutionFilter::columns() const
/*!
- \reimp
-
\internal
*/
QRectF QPixmapConvolutionFilter::boundingRectFor(const QRectF &rect) const
@@ -401,11 +402,10 @@ static void convolute(
}
yk++;
}
+ delete[] fixedKernel;
}
/*!
- \reimp
-
\internal
*/
void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const QPixmap &src, const QRectF& srcRect) const
@@ -478,6 +478,223 @@ void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const Q
}
}
+/*!
+ \class QPixmapBlurFilter
+ \since 4.6
+ \ingroup multimedia
+
+ \brief The QPixmapBlurFilter class provides blur filtering
+ for pixmaps.
+
+ QPixmapBlurFilter implements a blur pixmap filter,
+ which is applied when \l{QPixmapFilter::}{draw()} is called.
+
+ The filter lets you specialize the radius of the blur as well
+ as the quality.
+
+ By default, the blur effect is produced by applying an exponential
+ filter generated from the specified blurRadius(). Paint engines
+ may override this with a custom blur that is faster on the
+ underlying hardware.
+
+ \sa {Pixmap Filters Example}, QPixmapConvolutionFilter, QPixmapDropShadowFilter
+
+ \internal
+*/
+
+class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate
+{
+public:
+ QPixmapBlurFilterPrivate() : radius(5), quality(Qt::FastTransformation) {}
+
+ int radius;
+ Qt::TransformationMode quality;
+};
+
+
+/*!
+ Constructs a pixmap blur filter.
+
+ \internal
+*/
+QPixmapBlurFilter::QPixmapBlurFilter(QObject *parent)
+ : QPixmapFilter(*new QPixmapBlurFilterPrivate, BlurFilter, parent)
+{
+}
+
+/*!
+ Destructor of pixmap blur filter.
+
+ \internal
+*/
+QPixmapBlurFilter::~QPixmapBlurFilter()
+{
+}
+
+/*!
+ Sets the radius of the blur filter. Higher radius produces increased blurriness.
+
+ \internal
+*/
+void QPixmapBlurFilter::setRadius(int radius)
+{
+ Q_D(QPixmapBlurFilter);
+ d->radius = radius;
+}
+
+/*!
+ Gets the radius of the blur filter.
+
+ \internal
+*/
+int QPixmapBlurFilter::radius() const
+{
+ Q_D(const QPixmapBlurFilter);
+ return d->radius;
+}
+
+/*!
+ Setting the quality to FastTransformation causes the implementation
+ to trade off visual quality to blur the image faster. Setting the
+ quality to SmoothTransformation causes the implementation to improve
+ visual quality at the expense of speed. The implementation is free
+ to ignore this value if it only has a single blur algorithm.
+
+ \internal
+*/
+void QPixmapBlurFilter::setQuality(Qt::TransformationMode quality)
+{
+ Q_D(QPixmapBlurFilter);
+ d->quality = quality;
+}
+
+/*!
+ Gets the quality of the blur filter.
+
+ \internal
+*/
+Qt::TransformationMode QPixmapBlurFilter::quality() const
+{
+ Q_D(const QPixmapBlurFilter);
+ return d->quality;
+}
+
+/*!
+ \internal
+*/
+QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const
+{
+ Q_D(const QPixmapBlurFilter);
+ const qreal delta = d->radius * 2;
+ return rect.adjusted(-delta, -delta, delta, delta);
+}
+
+// Blur the image according to the blur radius
+// Based on exponential blur algorithm by Jani Huhtanen
+// (maximum radius is set to 16)
+static QImage blurred(const QImage& image, const QRect& rect, int radius)
+{
+ int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
+ int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1];
+
+ QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ int r1 = rect.top();
+ int r2 = rect.bottom();
+ int c1 = rect.left();
+ int c2 = rect.right();
+
+ int bpl = result.bytesPerLine();
+ int rgba[4];
+ unsigned char* p;
+
+ for (int col = c1; col <= c2; col++) {
+ p = result.scanLine(r1) + col * 4;
+ for (int i = 0; i < 4; i++)
+ rgba[i] = p[i] << 4;
+
+ p += bpl;
+ for (int j = r1; j < r2; j++, p += bpl)
+ for (int i = 0; i < 4; i++)
+ p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
+ }
+
+ for (int row = r1; row <= r2; row++) {
+ p = result.scanLine(row) + c1 * 4;
+ for (int i = 0; i < 4; i++)
+ rgba[i] = p[i] << 4;
+
+ p += 4;
+ for (int j = c1; j < c2; j++, p += 4)
+ for (int i = 0; i < 4; i++)
+ p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
+ }
+
+ for (int col = c1; col <= c2; col++) {
+ p = result.scanLine(r2) + col * 4;
+ for (int i = 0; i < 4; i++)
+ rgba[i] = p[i] << 4;
+
+ p -= bpl;
+ for (int j = r1; j < r2; j++, p -= bpl)
+ for (int i = 0; i < 4; i++)
+ p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
+ }
+
+ for (int row = r1; row <= r2; row++) {
+ p = result.scanLine(row) + c2 * 4;
+ for (int i = 0; i < 4; i++)
+ rgba[i] = p[i] << 4;
+
+ p -= 4;
+ for (int j = c1; j < c2; j++, p -= 4)
+ for (int i = 0; i < 4; i++)
+ p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
+ }
+
+ return result;
+}
+
+/*!
+ \internal
+*/
+void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap &src, const QRectF &srcRect) const
+{
+ Q_D(const QPixmapBlurFilter);
+ if (!painter->isActive())
+ return;
+
+ if (d->radius == 0) {
+ painter->drawPixmap(srcRect.translated(p), src, srcRect);
+ return;
+ }
+
+ QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ?
+ static_cast<QPaintEngineEx *>(painter->paintEngine())->createPixmapFilter(type()) : 0;
+ QPixmapBlurFilter *blurFilter = static_cast<QPixmapBlurFilter*>(filter);
+ if (blurFilter) {
+ blurFilter->setRadius(d->radius);
+ blurFilter->setQuality(d->quality);
+ blurFilter->draw(painter, p, src, srcRect);
+ delete blurFilter;
+ return;
+ }
+
+ QImage srcImage;
+ QImage destImage;
+
+ if (srcRect.isNull()) {
+ srcImage = src.toImage();
+ destImage = blurred(srcImage, srcImage.rect(), d->radius);
+ } else {
+ QRect rect = srcRect.toAlignedRect().intersected(src.rect());
+
+ srcImage = src.copy(rect).toImage();
+ destImage = blurred(srcImage, srcImage.rect(), d->radius);
+ }
+
+ painter->drawImage(p, destImage);
+}
+
// grayscales the image to dest (could be same). If rect isn't defined
// destination image size is used to determine the dimension of grayscaling
// process.
@@ -520,7 +737,7 @@ static void grayscale(const QImage &image, QImage &dest, const QRect& rect = QRe
/*!
\class QPixmapColorizeFilter
\since 4.5
- \ingroup multimedia
+ \ingroup painting
\brief The QPixmapColorizeFilter class provides colorizing
filtering for pixmaps.
@@ -580,8 +797,6 @@ void QPixmapColorizeFilter::setColor(const QColor &color)
}
/*!
- \reimp
-
\internal
*/
void QPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
@@ -631,22 +846,17 @@ class QPixmapDropShadowFilterPrivate : public QPixmapFilterPrivate
{
public:
QPixmapDropShadowFilterPrivate()
- : offset(8, 8),
- radius(1),
- color(63, 63, 63, 255) {
- }
+ : offset(8, 8), color(63, 63, 63, 180), blurFilter(new QPixmapBlurFilter) {}
QPointF offset;
- qreal radius;
QColor color;
-
- QPixmapConvolutionFilter *convolution;
+ QPixmapBlurFilter *blurFilter;
};
/*!
\class QPixmapDropShadowFilter
\since 4.5
- \ingroup multimedia
+ \ingroup painting
\brief The QPixmapDropShadowFilter class is a convenience class
for drawing pixmaps with drop shadows.
@@ -685,9 +895,7 @@ QPixmapDropShadowFilter::QPixmapDropShadowFilter(QObject *parent)
: QPixmapFilter(*new QPixmapDropShadowFilterPrivate, DropShadowFilter, parent)
{
Q_D(QPixmapDropShadowFilter);
- d->convolution = new QPixmapConvolutionFilter;
-
- setBlurRadius(1);
+ d->blurFilter->setRadius(1);
}
/*!
@@ -698,7 +906,7 @@ QPixmapDropShadowFilter::QPixmapDropShadowFilter(QObject *parent)
QPixmapDropShadowFilter::~QPixmapDropShadowFilter()
{
Q_D(QPixmapDropShadowFilter);
- delete d->convolution;
+ delete d->blurFilter;
}
/*!
@@ -710,10 +918,10 @@ QPixmapDropShadowFilter::~QPixmapDropShadowFilter()
\internal
*/
-qreal QPixmapDropShadowFilter::blurRadius() const
+int QPixmapDropShadowFilter::blurRadius() const
{
Q_D(const QPixmapDropShadowFilter);
- return d->radius;
+ return d->blurFilter->radius();
}
/*!
@@ -725,18 +933,10 @@ qreal QPixmapDropShadowFilter::blurRadius() const
\internal
*/
-void QPixmapDropShadowFilter::setBlurRadius(qreal radius)
+void QPixmapDropShadowFilter::setBlurRadius(int radius)
{
Q_D(QPixmapDropShadowFilter);
-
- d->radius = radius;
-
- int dim = 2 * qRound(radius) + 1;
- QVarLengthArray<qreal> arr(dim * dim);
- qreal f = 1 / qreal(dim * dim);
- for (int i = 0; i < dim * dim; ++i)
- arr[i] = f;
- d->convolution->setConvolutionKernel(arr.data(), dim, dim);
+ d->blurFilter->setRadius(radius);
}
/*!
@@ -804,25 +1004,22 @@ void QPixmapDropShadowFilter::setOffset(const QPointF &offset)
*/
/*!
- \reimp
-
\internal
*/
QRectF QPixmapDropShadowFilter::boundingRectFor(const QRectF &rect) const
{
Q_D(const QPixmapDropShadowFilter);
- qreal x1 = qMin(rect.left(), rect.left() + d->offset.x() - d->radius);
- qreal y1 = qMin(rect.top(), rect.top() + d->offset.y() - d->radius);
- qreal x2 = qMax(rect.right(), rect.right() + d->offset.x() + d->radius);
- qreal y2 = qMax(rect.bottom(), rect.bottom() + d->offset.y() + d->radius);
+ const qreal delta = qreal(d->blurFilter->radius() * 2);
+ qreal x1 = qMin(rect.left(), rect.left() + d->offset.x() - delta);
+ qreal y1 = qMin(rect.top(), rect.top() + d->offset.y() - delta);
+ qreal x2 = qMax(rect.right(), rect.right() + d->offset.x() + delta);
+ qreal y2 = qMax(rect.bottom(), rect.bottom() + d->offset.y() + delta);
return QRectF(x1, y1, x2 - x1, y2 - y1);
}
/*!
- \reimp
-
\internal
*/
void QPixmapDropShadowFilter::draw(QPainter *p,
@@ -832,7 +1029,7 @@ void QPixmapDropShadowFilter::draw(QPainter *p,
{
Q_D(const QPixmapDropShadowFilter);
- QPixmap tmp = src.isNull() ? px : px.copy(src.toRect());
+ QImage tmp = src.isNull() ? px.toImage() : px.copy(src.toRect()).toImage();
QPainter tmpPainter(&tmp);
// blacken the image...
@@ -840,10 +1037,13 @@ void QPixmapDropShadowFilter::draw(QPainter *p,
tmpPainter.fillRect(0, 0, tmp.width(), tmp.height(), d->color);
tmpPainter.end();
+ const QPixmap pixTmp = QPixmap::fromImage(tmp);
+
// draw the blurred drop shadow...
- d->convolution->draw(p, pos + d->offset, tmp);
+ d->blurFilter->draw(p, pos + d->offset, pixTmp);
// Draw the actual pixmap...
p->drawPixmap(pos, px, src);
}
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h
index 351aaf6..4489344 100644
--- a/src/gui/image/qpixmapfilter_p.h
+++ b/src/gui/image/qpixmapfilter_p.h
@@ -78,6 +78,7 @@ public:
ConvolutionFilter,
ColorizeFilter,
DropShadowFilter,
+ BlurFilter,
UserFilter = 1024
};
@@ -117,6 +118,30 @@ private:
int columns() const;
};
+class QPixmapBlurFilterPrivate;
+
+class Q_GUI_EXPORT QPixmapBlurFilter : public QPixmapFilter
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPixmapBlurFilter)
+
+public:
+ QPixmapBlurFilter(QObject *parent = 0);
+ ~QPixmapBlurFilter();
+
+ void setRadius(int radius);
+ void setQuality(Qt::TransformationMode mode);
+
+ int radius() const;
+ Qt::TransformationMode quality() const;
+
+ QRectF boundingRectFor(const QRectF &rect) const;
+ void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const;
+
+private:
+ friend class QGLPixmapBlurFilter;
+};
+
class QPixmapColorizeFilterPrivate;
class Q_GUI_EXPORT QPixmapColorizeFilter : public QPixmapFilter
@@ -147,8 +172,8 @@ public:
QRectF boundingRectFor(const QRectF &rect) const;
void draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src = QRectF()) const;
- qreal blurRadius() const;
- void setBlurRadius(qreal radius);
+ int blurRadius() const;
+ void setBlurRadius(int radius);
QColor color() const;
void setColor(const QColor &color);
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 449e179..3f3a55c 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -956,7 +956,7 @@ QVariant QPngHandler::option(ImageOption option) const
void QPngHandler::setOption(ImageOption option, const QVariant &value)
{
if (option == Gamma)
- d->gamma = value.toDouble();
+ d->gamma = value.toFloat();
else if (option == Quality)
d->quality = value.toInt();
else if (option == Description)
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 4e037ae..a97aef4 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -80,7 +80,7 @@ static int read_pbm_int(QIODevice *d)
else if (isspace((uchar) c))
continue;
else if (c == '#')
- d->readLine(buf, buflen);
+ (void)d->readLine(buf, buflen);
else
break;
}
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index 433bd90..9a96762 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -1146,7 +1146,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
QTextStream s(device);
s << "/* XPM */" << endl
<< "static char *" << fbname(fileName) << "[]={" << endl
- << "\"" << w << " " << h << " " << ncolors << " " << cpp << "\"";
+ << '\"' << w << ' ' << h << ' ' << ncolors << ' ' << cpp << '\"';
// write palette
QMap<QRgb, int>::Iterator c = colorMap.begin();
@@ -1162,7 +1162,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
qGreen(color),
qBlue(color));
++c;
- s << "," << endl << line;
+ s << ',' << endl << line;
}
// write pixels, limit to 4 characters per pixel
@@ -1184,7 +1184,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
}
}
}
- s << "," << endl << "\"" << line << "\"";
+ s << ',' << endl << '\"' << line << '\"';
}
s << "};" << endl;
return (s.status() == QTextStream::Ok);
diff --git a/src/gui/inputmethod/inputmethod.pri b/src/gui/inputmethod/inputmethod.pri
index d321cd4..6d9f748 100644
--- a/src/gui/inputmethod/inputmethod.pri
+++ b/src/gui/inputmethod/inputmethod.pri
@@ -23,4 +23,9 @@ mac:!embedded {
HEADERS += inputmethod/qmacinputcontext_p.h
SOURCES += inputmethod/qmacinputcontext_mac.cpp
}
+symbian:contains(QT_CONFIG, s60) {
+ HEADERS += inputmethod/qcoefepinputcontext_p.h
+ SOURCES += inputmethod/qcoefepinputcontext_s60.cpp
+ LIBS += -lfepbase
+}
diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h
new file mode 100644
index 0000000..c9a9423
--- /dev/null
+++ b/src/gui/inputmethod/qcoefepinputcontext_p.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOEFEPINPUTCONTEXT_P_H
+#define QCOEFEPINPUTCONTEXT_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.
+//
+
+#ifndef QT_NO_IM
+
+#include "qinputcontext.h"
+#include <qhash.h>
+#include <private/qcore_symbian_p.h>
+#include <private/qt_s60_p.h>
+
+#include <fepbase.h>
+#include <aknedsts.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QCoeFepInputContext : public QInputContext,
+ public MCoeFepAwareTextEditor,
+ public MCoeFepAwareTextEditor_Extension1,
+ public MObjectProvider
+{
+ Q_OBJECT
+
+public:
+ QCoeFepInputContext(QObject *parent = 0);
+ ~QCoeFepInputContext();
+
+ QString identifierName() { return QLatin1String("coefep"); }
+ QString language();
+
+ void reset();
+ void update();
+
+ bool filterEvent(const QEvent *event);
+ void mouseHandler( int x, QMouseEvent *event);
+ bool isComposing() const { return m_isEditing; }
+
+ void setFocusWidget(QWidget * w);
+ void widgetDestroyed(QWidget *w);
+
+ TCoeInputCapabilities inputCapabilities();
+
+private:
+ void commitCurrentString(bool triggeredBySymbian);
+ void updateHints(bool mustUpdateInputCapabilities);
+ void applyHints(Qt::InputMethodHints hints);
+ void applyFormat(QList<QInputMethodEvent::Attribute> *attributes);
+ void queueInputCapabilitiesChanged();
+
+private Q_SLOTS:
+ void ensureInputCapabilitiesChanged();
+
+ // From MCoeFepAwareTextEditor
+public:
+ void StartFepInlineEditL(const TDesC& aInitialInlineText, TInt aPositionOfInsertionPointInInlineText,
+ TBool aCursorVisibility, const MFormCustomDraw* aCustomDraw,
+ MFepInlineTextFormatRetriever& aInlineTextFormatRetriever,
+ MFepPointerEventHandlerDuringInlineEdit& aPointerEventHandlerDuringInlineEdit);
+ void UpdateFepInlineTextL(const TDesC& aNewInlineText, TInt aPositionOfInsertionPointInInlineText);
+ void SetInlineEditingCursorVisibilityL(TBool aCursorVisibility);
+ void CancelFepInlineEdit();
+ TInt DocumentLengthForFep() const;
+ TInt DocumentMaximumLengthForFep() const;
+ void SetCursorSelectionForFepL(const TCursorSelection& aCursorSelection);
+ void GetCursorSelectionForFep(TCursorSelection& aCursorSelection) const;
+ void GetEditorContentForFep(TDes& aEditorContent, TInt aDocumentPosition, TInt aLengthToRetrieve) const;
+ void GetFormatForFep(TCharFormat& aFormat, TInt aDocumentPosition) const;
+ void GetScreenCoordinatesForFepL(TPoint& aLeftSideOfBaseLine, TInt& aHeight, TInt& aAscent,
+ TInt aDocumentPosition) const;
+private:
+ void DoCommitFepInlineEditL();
+ MCoeFepAwareTextEditor_Extension1* Extension1(TBool& aSetToTrue);
+ void ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType);
+
+ // From MCoeFepAwareTextEditor_Extension1
+public:
+ void SetStateTransferingOwnershipL(MCoeFepAwareTextEditor_Extension1::CState* aState, TUid aTypeSafetyUid);
+ MCoeFepAwareTextEditor_Extension1::CState* State(TUid aTypeSafetyUid);
+
+ // From MObjectProvider
+public:
+ TTypeUid::Ptr MopSupplyObject(TTypeUid id);
+
+private:
+ QSymbianControl *m_parent;
+ CAknEdwinState *m_fepState;
+ QString m_preeditString;
+ Qt::InputMethodHints m_lastImHints;
+ TUint m_textCapabilities;
+ bool m_isEditing;
+ bool m_inDestruction;
+ bool m_pendingInputCapabilitiesChanged;
+ int m_cursorVisibility;
+ int m_inlinePosition;
+ MFepInlineTextFormatRetriever *m_formatRetriever;
+ MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_IM
+
+#endif // QCOEFEPINPUTCONTEXT_P_H
diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
new file mode 100644
index 0000000..09eda67
--- /dev/null
+++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
@@ -0,0 +1,667 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_IM
+
+#include "qcoefepinputcontext_p.h"
+#include <qapplication.h>
+#include <qtextformat.h>
+#include <private/qcore_symbian_p.h>
+
+#include <fepitfr.h>
+
+#include <limits.h>
+// You only find these enumerations on SDK 5 onwards, so we need to provide our own
+// to remain compatible with older releases. They won't be called by pre-5.0 SDKs.
+
+// MAknEdStateObserver::EAknCursorPositionChanged
+#define QT_EAknCursorPositionChanged MAknEdStateObserver::EAknEdwinStateEvent(6)
+// MAknEdStateObserver::EAknActivatePenInputRequest
+#define QT_EAknActivatePenInputRequest MAknEdStateObserver::EAknEdwinStateEvent(7)
+
+QT_BEGIN_NAMESPACE
+
+QCoeFepInputContext::QCoeFepInputContext(QObject *parent)
+ : QInputContext(parent),
+ m_fepState(q_check_ptr(new CAknEdwinState)), // CBase derived object needs check on new
+ m_lastImHints(Qt::ImhNone),
+ m_textCapabilities(TCoeInputCapabilities::EAllText),
+ m_isEditing(false),
+ m_inDestruction(false),
+ m_pendingInputCapabilitiesChanged(false),
+ m_cursorVisibility(1),
+ m_inlinePosition(0),
+ m_formatRetriever(0),
+ m_pointerHandler(0)
+{
+ m_fepState->SetObjectProvider(this);
+ m_fepState->SetFlags(EAknEditorFlagDefault);
+ m_fepState->SetDefaultInputMode( EAknEditorTextInputMode );
+ m_fepState->SetPermittedInputModes( EAknEditorAllInputModes );
+ m_fepState->SetDefaultCase( EAknEditorLowerCase );
+ m_fepState->SetPermittedCases( EAknEditorLowerCase|EAknEditorUpperCase );
+ m_fepState->SetSpecialCharacterTableResourceId( 0 );
+ m_fepState->SetNumericKeymap( EAknEditorStandardNumberModeKeymap );
+}
+
+QCoeFepInputContext::~QCoeFepInputContext()
+{
+ m_inDestruction = true;
+
+ // This is to make sure that the FEP manager "forgets" about us,
+ // otherwise we may get callbacks even after we're destroyed.
+ // The call below is essentially equivalent to InputCapabilitiesChanged(),
+ // but is synchronous, rather than asynchronous.
+ CCoeEnv::Static()->SyncNotifyFocusObserversOfChangeInFocus();
+
+ if (m_fepState)
+ delete m_fepState;
+}
+
+void QCoeFepInputContext::reset()
+{
+ CCoeEnv::Static()->Fep()->CancelTransaction();
+}
+
+void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType)
+{
+ QT_TRAP_THROWING(m_fepState->ReportAknEdStateEventL(aEventType));
+}
+
+void QCoeFepInputContext::update()
+{
+ updateHints(false);
+
+ // For pre-5.0 SDKs, we don't do text updates on S60 side.
+ if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) {
+ return;
+ }
+
+ // Don't be fooled (as I was) by the name of this enumeration.
+ // What it really does is tell the virtual keyboard UI that the text has been
+ // updated and it should be reflected in the internal display of the VK.
+ ReportAknEdStateEvent(QT_EAknCursorPositionChanged);
+}
+
+void QCoeFepInputContext::setFocusWidget(QWidget *w)
+{
+ commitCurrentString(false);
+
+ QInputContext::setFocusWidget(w);
+
+ updateHints(true);
+}
+
+void QCoeFepInputContext::widgetDestroyed(QWidget *w)
+{
+ // Make sure that the input capabilities of whatever new widget got focused are queried.
+ CCoeControl *ctrl = w->effectiveWinId();
+ if (ctrl->IsFocused()) {
+ ctrl->SetFocus(false);
+ ctrl->SetFocus(true);
+ }
+}
+
+QString QCoeFepInputContext::language()
+{
+ TLanguage lang = m_fepState->LocalLanguage();
+ const QByteArray localeName = qt_symbianLocaleName(lang);
+ if (!localeName.isEmpty()) {
+ return QString::fromLatin1(localeName);
+ } else {
+ return QString::fromLatin1("C");
+ }
+}
+
+bool QCoeFepInputContext::filterEvent(const QEvent *event)
+{
+ // The CloseSoftwareInputPanel event is not handled here, because the VK will automatically
+ // close when it discovers that the underlying widget does not have input capabilities.
+
+ if (!focusWidget())
+ return false;
+
+ if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
+ const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
+ Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints());
+ if (keyEvent->key() == Qt::Key_F20 && m_lastImHints & Qt::ImhHiddenText) {
+ // Special case in Symbian. On editors with secret text, F20 is for some reason
+ // considered to be a backspace.
+ QKeyEvent modifiedEvent(keyEvent->type(), Qt::Key_Backspace, keyEvent->modifiers(),
+ keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count());
+ QApplication::sendEvent(focusWidget(), &modifiedEvent);
+ return true;
+ }
+ }
+
+ // For pre-5.0 SDKs, we don't launch the keyboard.
+ if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) {
+ return false;
+ }
+
+ if (event->type() == QEvent::RequestSoftwareInputPanel) {
+ // Notify S60 that we want the virtual keyboard to show up.
+ QSymbianControl *sControl;
+ sControl = focusWidget()->effectiveWinId()->MopGetObject(sControl);
+ Q_ASSERT(sControl);
+
+ // The FEP UI temporarily steals focus when it shows up the first time, causing
+ // all sorts of weird effects on the focused widgets. Since it will immediately give
+ // back focus to us, we temporarily disable focus handling until the job's done.
+ if (sControl) {
+ sControl->setIgnoreFocusChanged(true);
+ }
+
+ ensureInputCapabilitiesChanged();
+ m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::QT_EAknActivatePenInputRequest);
+
+ if (sControl) {
+ sControl->setIgnoreFocusChanged(false);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event)
+{
+ Q_ASSERT(m_isEditing);
+ Q_ASSERT(focusWidget());
+
+ if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) {
+ commitCurrentString(false);
+ int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos + x, 0, QVariant());
+ QInputMethodEvent event("", attributes);
+ sendEvent(event);
+ }
+}
+
+TCoeInputCapabilities QCoeFepInputContext::inputCapabilities()
+{
+ if (m_inDestruction) {
+ return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0);
+ }
+
+ return TCoeInputCapabilities(m_textCapabilities, this, 0);
+}
+
+static QTextCharFormat qt_TCharFormat2QTextCharFormat(const TCharFormat &cFormat)
+{
+ QTextCharFormat qFormat;
+
+ QBrush foreground(QColor(cFormat.iFontPresentation.iTextColor.Internal()));
+ qFormat.setForeground(foreground);
+
+ qFormat.setFontStrikeOut(cFormat.iFontPresentation.iStrikethrough == EStrikethroughOn);
+ qFormat.setFontUnderline(cFormat.iFontPresentation.iUnderline == EUnderlineOn);
+
+ return qFormat;
+}
+
+void QCoeFepInputContext::updateHints(bool mustUpdateInputCapabilities)
+{
+ QWidget *w = focusWidget();
+ if (w) {
+ Qt::InputMethodHints hints = w->inputMethodHints();
+ if (hints != m_lastImHints) {
+ m_lastImHints = hints;
+ applyHints(hints);
+ } else if (!mustUpdateInputCapabilities) {
+ // Optimization. Return immediately if there was no change.
+ return;
+ }
+ }
+ queueInputCapabilitiesChanged();
+}
+
+void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints)
+{
+ using namespace Qt;
+
+ bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
+ || hints & ImhDialableCharactersOnly;
+ bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly
+ || hints & ImhLowercaseOnly);
+ TInt flags;
+ Qt::InputMethodHints oldHints = hints;
+
+ // Some sanity checking. Make sure that only one preference is set.
+ InputMethodHints prefs = ImhPreferNumbers | ImhPreferUppercase | ImhPreferLowercase;
+ prefs &= hints;
+ if (prefs != ImhPreferNumbers && prefs != ImhPreferUppercase && prefs != ImhPreferLowercase) {
+ hints &= ~prefs;
+ }
+ if (!noOnlys) {
+ // Make sure that the preference is within the permitted set.
+ if (hints & ImhPreferNumbers && !(hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
+ || hints & ImhDialableCharactersOnly)) {
+ hints &= ~ImhPreferNumbers;
+ } else if (hints & ImhPreferUppercase && !(hints & ImhUppercaseOnly)) {
+ hints &= ~ImhPreferUppercase;
+ } else if (hints & ImhPreferLowercase && !(hints & ImhLowercaseOnly)) {
+ hints &= ~ImhPreferLowercase;
+ }
+ // If there is no preference, set it to something within the permitted set.
+ if (!(hints & ImhPreferNumbers || hints & ImhPreferUppercase || hints & ImhPreferLowercase)) {
+ if (hints & ImhLowercaseOnly) {
+ hints |= ImhPreferLowercase;
+ } else if (hints & ImhUppercaseOnly) {
+ hints |= ImhPreferUppercase;
+ } else if (hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
+ || hints & ImhDialableCharactersOnly) {
+ hints |= ImhPreferNumbers;
+ }
+ }
+ }
+
+ if (hints & ImhPreferNumbers) {
+ m_fepState->SetDefaultInputMode(EAknEditorNumericInputMode);
+ m_fepState->SetCurrentInputMode(EAknEditorNumericInputMode);
+ } else {
+ m_fepState->SetDefaultInputMode(EAknEditorTextInputMode);
+ m_fepState->SetCurrentInputMode(EAknEditorTextInputMode);
+ }
+ flags = 0;
+ if (numbersOnly) {
+ flags |= EAknEditorNumericInputMode;
+ }
+ if (hints & ImhUppercaseOnly || hints & ImhLowercaseOnly) {
+ flags |= EAknEditorTextInputMode;
+ }
+ if (flags == 0) {
+ flags = EAknEditorAllInputModes;
+ }
+ m_fepState->SetPermittedInputModes(flags);
+ ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateInputModeUpdate);
+
+ if (hints & ImhPreferLowercase) {
+ m_fepState->SetDefaultCase(EAknEditorLowerCase);
+ m_fepState->SetCurrentCase(EAknEditorLowerCase);
+ } else if (hints & ImhPreferUppercase) {
+ m_fepState->SetDefaultCase(EAknEditorUpperCase);
+ m_fepState->SetCurrentCase(EAknEditorUpperCase);
+ } else if (hints & ImhNoAutoUppercase) {
+ m_fepState->SetDefaultCase(EAknEditorLowerCase);
+ m_fepState->SetCurrentCase(EAknEditorLowerCase);
+ } else {
+ m_fepState->SetDefaultCase(EAknEditorTextCase);
+ m_fepState->SetCurrentCase(EAknEditorTextCase);
+ }
+ flags = 0;
+ if (hints & ImhUppercaseOnly) {
+ flags |= EAknEditorUpperCase;
+ }
+ if (hints & ImhLowercaseOnly) {
+ flags |= EAknEditorLowerCase;
+ }
+ if (flags == 0) {
+ flags = EAknEditorAllCaseModes;
+ if (hints & ImhNoAutoUppercase) {
+ flags &= ~EAknEditorTextCase;
+ }
+ }
+ m_fepState->SetPermittedCases(flags);
+ ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateCaseModeUpdate);
+
+ flags = 0;
+ if (hints & ImhUppercaseOnly && !(hints & ImhLowercaseOnly)
+ || hints & ImhLowercaseOnly && !(hints & ImhUppercaseOnly)) {
+ flags |= EAknEditorFlagFixedCase;
+ }
+ // Using T9 and hidden text together may actually crash the FEP, so check for hidden text too.
+ if (hints & ImhNoPredictiveText || hints & ImhHiddenText) {
+ flags |= EAknEditorFlagNoT9;
+ }
+ m_fepState->SetFlags(flags);
+ ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateFlagsUpdate);
+
+ if (hints & ImhFormattedNumbersOnly) {
+ flags = EAknEditorCalculatorNumberModeKeymap;
+ } else if (hints & ImhDigitsOnly) {
+ flags = EAknEditorPlainNumberModeKeymap;
+ } else {
+ // ImhDialableCharactersOnly is the fallback as well, so we don't need to check for
+ // that flag.
+ flags = EAknEditorStandardNumberModeKeymap;
+ }
+ m_fepState->SetNumericKeymap(static_cast<TAknEditorNumericKeymap>(flags));
+
+ if (hints & ImhHiddenText) {
+ m_textCapabilities = TCoeInputCapabilities::EAllText | TCoeInputCapabilities::ESecretText;
+ } else {
+ m_textCapabilities = TCoeInputCapabilities::EAllText;
+ }
+}
+
+void QCoeFepInputContext::applyFormat(QList<QInputMethodEvent::Attribute> *attributes)
+{
+ TCharFormat cFormat;
+ TInt numChars = 0;
+ TInt charPos = 0;
+ int oldSize = attributes->size();
+ while (m_formatRetriever) {
+ m_formatRetriever->GetFormatOfFepInlineText(cFormat, numChars, charPos);
+ if (numChars <= 0) {
+ // This shouldn't happen according to S60 docs, but apparently does sometimes.
+ break;
+ }
+ attributes->append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ charPos,
+ numChars,
+ QVariant(qt_TCharFormat2QTextCharFormat(cFormat))));
+ charPos += numChars;
+ if (charPos >= m_preeditString.size()) {
+ break;
+ }
+ }
+
+ if (attributes->size() == oldSize) {
+ // S60 didn't provide any format, so let's give our own instead.
+ attributes->append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ 0,
+ m_preeditString.size(),
+ standardFormat(PreeditFormat)));
+ }
+}
+
+void QCoeFepInputContext::queueInputCapabilitiesChanged()
+{
+ if (m_pendingInputCapabilitiesChanged)
+ return;
+
+ // Call ensureInputCapabilitiesChanged asynchronously. This is done to improve performance
+ // by not updating input capabilities too often. The reason we don't call the Symbian
+ // asynchronous version of InputCapabilitiesChanged is because we need to ensure that it
+ // is synchronous in some specific cases. Those will call ensureInputCapabilitesChanged.
+ QMetaObject::invokeMethod(this, "ensureInputCapabilitiesChanged", Qt::QueuedConnection);
+ m_pendingInputCapabilitiesChanged = true;
+}
+
+void QCoeFepInputContext::ensureInputCapabilitiesChanged()
+{
+ if (!m_pendingInputCapabilitiesChanged)
+ return;
+
+ // The call below is essentially equivalent to InputCapabilitiesChanged(),
+ // but is synchronous, rather than asynchronous.
+ CCoeEnv::Static()->SyncNotifyFocusObserversOfChangeInFocus();
+ m_pendingInputCapabilitiesChanged = false;
+}
+
+void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText,
+ TInt aPositionOfInsertionPointInInlineText, TBool aCursorVisibility, const MFormCustomDraw* /*aCustomDraw*/,
+ MFepInlineTextFormatRetriever& aInlineTextFormatRetriever,
+ MFepPointerEventHandlerDuringInlineEdit& aPointerEventHandlerDuringInlineEdit)
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ m_isEditing = true;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+
+ m_cursorVisibility = aCursorVisibility ? 1 : 0;
+ m_inlinePosition = aPositionOfInsertionPointInInlineText;
+ m_preeditString = qt_TDesC2QString(aInitialInlineText);
+
+ m_formatRetriever = &aInlineTextFormatRetriever;
+ m_pointerHandler = &aPointerEventHandlerDuringInlineEdit;
+
+ applyFormat(&attributes);
+
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ m_inlinePosition,
+ m_cursorVisibility,
+ QVariant()));
+ QInputMethodEvent event(m_preeditString, attributes);
+ sendEvent(event);
+}
+
+void QCoeFepInputContext::UpdateFepInlineTextL(const TDesC& aNewInlineText,
+ TInt aPositionOfInsertionPointInInlineText)
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ m_inlinePosition = aPositionOfInsertionPointInInlineText;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ applyFormat(&attributes);
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ m_inlinePosition,
+ m_cursorVisibility,
+ QVariant()));
+ m_preeditString = qt_TDesC2QString(aNewInlineText);
+ QInputMethodEvent event(m_preeditString, attributes);
+ sendEvent(event);
+}
+
+void QCoeFepInputContext::SetInlineEditingCursorVisibilityL(TBool aCursorVisibility)
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ m_cursorVisibility = aCursorVisibility ? 1 : 0;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ m_inlinePosition,
+ m_cursorVisibility,
+ QVariant()));
+ QInputMethodEvent event(m_preeditString, attributes);
+ sendEvent(event);
+}
+
+void QCoeFepInputContext::CancelFepInlineEdit()
+{
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString("", 0, 0);
+ m_preeditString.clear();
+ sendEvent(event);
+
+ m_isEditing = false;
+}
+
+TInt QCoeFepInputContext::DocumentLengthForFep() const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return 0;
+
+ QVariant variant = w->inputMethodQuery(Qt::ImSurroundingText);
+ return variant.value<QString>().size() + m_preeditString.size();
+}
+
+TInt QCoeFepInputContext::DocumentMaximumLengthForFep() const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return 0;
+
+ QVariant variant = w->inputMethodQuery(Qt::ImMaximumTextLength);
+ int size;
+ if (variant.isValid()) {
+ size = variant.toInt();
+ } else {
+ size = INT_MAX; // Sensible default for S60.
+ }
+ return size;
+}
+
+void QCoeFepInputContext::SetCursorSelectionForFepL(const TCursorSelection& aCursorSelection)
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ int pos = aCursorSelection.iAnchorPos;
+ int length = aCursorSelection.iCursorPos - pos;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos, length, QVariant());
+ QInputMethodEvent event(m_preeditString, attributes);
+ sendEvent(event);
+}
+
+void QCoeFepInputContext::GetCursorSelectionForFep(TCursorSelection& aCursorSelection) const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt() + m_preeditString.size();
+ int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt() + m_preeditString.size();
+ aCursorSelection.iAnchorPos = anchor;
+ aCursorSelection.iCursorPos = cursor;
+}
+
+void QCoeFepInputContext::GetEditorContentForFep(TDes& aEditorContent, TInt aDocumentPosition,
+ TInt aLengthToRetrieve) const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ QString text = w->inputMethodQuery(Qt::ImSurroundingText).value<QString>();
+ // FEP expects the preedit string to be part of the editor content, so let's mix it in.
+ int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt();
+ text.insert(cursor, m_preeditString);
+ aEditorContent.Copy(qt_QString2TPtrC(text.mid(aDocumentPosition, aLengthToRetrieve)));
+}
+
+void QCoeFepInputContext::GetFormatForFep(TCharFormat& aFormat, TInt /* aDocumentPosition */) const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ QFont font = w->inputMethodQuery(Qt::ImFont).value<QFont>();
+ QFontMetrics metrics(font);
+ //QString name = font.rawName();
+ QString name = font.defaultFamily(); // TODO! FIXME! Should be the above.
+ QHBufC hBufC(name);
+ aFormat = TCharFormat(hBufC->Des(), metrics.height());
+}
+
+void QCoeFepInputContext::GetScreenCoordinatesForFepL(TPoint& aLeftSideOfBaseLine, TInt& aHeight,
+ TInt& aAscent, TInt /* aDocumentPosition */) const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ QRect rect = w->inputMethodQuery(Qt::ImMicroFocus).value<QRect>();
+ aLeftSideOfBaseLine.iX = rect.left();
+ aLeftSideOfBaseLine.iY = rect.bottom();
+
+ QFont font = w->inputMethodQuery(Qt::ImFont).value<QFont>();
+ QFontMetrics metrics(font);
+ aHeight = metrics.height();
+ aAscent = metrics.ascent();
+}
+
+void QCoeFepInputContext::DoCommitFepInlineEditL()
+{
+ commitCurrentString(true);
+}
+
+void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian)
+{
+ if (m_preeditString.size() == 0) {
+ return;
+ }
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString(m_preeditString, 0, 0);//m_preeditString.size());
+ m_preeditString.clear();
+ sendEvent(event);
+
+ m_isEditing = false;
+
+ if (!triggeredBySymbian) {
+ CCoeEnv::Static()->Fep()->CancelTransaction();
+ }
+}
+
+MCoeFepAwareTextEditor_Extension1* QCoeFepInputContext::Extension1(TBool& aSetToTrue)
+{
+ aSetToTrue = ETrue;
+ return this;
+}
+
+void QCoeFepInputContext::SetStateTransferingOwnershipL(MCoeFepAwareTextEditor_Extension1::CState* aState,
+ TUid /*aTypeSafetyUid*/)
+{
+ // Note: The S60 docs are wrong! See the State() function.
+ if (m_fepState)
+ delete m_fepState;
+ m_fepState = static_cast<CAknEdwinState *>(aState);
+}
+
+MCoeFepAwareTextEditor_Extension1::CState* QCoeFepInputContext::State(TUid /*aTypeSafetyUid*/)
+{
+ // Note: The S60 docs are horribly wrong when describing the
+ // SetStateTransferingOwnershipL function and this function. They say that the former
+ // sets a CState object identified by the TUid, and the latter retrieves it.
+ // In reality, the CState is expected to always be a CAknEdwinState (even if it was not
+ // previously set), and the TUid is ignored. All in all, there is a single CAknEdwinState
+ // per QCoeFepInputContext, which should be deleted if the SetStateTransferingOwnershipL
+ // function is used to set a new one.
+ return m_fepState;
+}
+
+TTypeUid::Ptr QCoeFepInputContext::MopSupplyObject(TTypeUid /*id*/)
+{
+ return TTypeUid::Null();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_IM
diff --git a/src/gui/inputmethod/qinputcontext.cpp b/src/gui/inputmethod/qinputcontext.cpp
index 9acdc81..2422355 100644
--- a/src/gui/inputmethod/qinputcontext.cpp
+++ b/src/gui/inputmethod/qinputcontext.cpp
@@ -78,7 +78,7 @@ QT_BEGIN_NAMESPACE
\ingroup i18n
- An input method is responsible to input complex text that cannot
+ An input method is responsible for inputting complex text that cannot
be inputted via simple keymap. It converts a sequence of input
events (typically key events) into a text string through the input
method specific converting process. The class of the processes are
@@ -89,11 +89,11 @@ QT_BEGIN_NAMESPACE
To abstract such different input method specific intermediate
information, Qt offers the QInputContext as base class. The
concept is well known as 'input context' in the input method
- domain. an input context is created for a text widget in response
+ domain. An input context is created for a text widget in response
to a demand. It is ensured that an input context is prepared for
an input method before input to a text widget.
- Multiple input contexts that is belonging to a single input method
+ Multiple input contexts that belong to a single input method
may concurrently coexist. Suppose multi-window text editor. Each
text widget of window A and B holds different QInputContext
instance which contains different state information such as
@@ -105,25 +105,27 @@ QT_BEGIN_NAMESPACE
\header \o Context \o Functions
\row \o Receiving information \o
- x11FilterEvent(),
- filterEvent(),
- mouseHandler()
+ x11FilterEvent(),
+ filterEvent(),
+ mouseHandler()
\row \o Sending back composed text \o
- sendEvent()
+ sendEvent()
\row \o State change notification \o
- setFocusWidget(),
- reset()
+ setFocusWidget(),
+ reset()
\row \o Context information \o
- identifierName(),
- language(),
- font(),
- isComposing()
+ identifierName(),
+ language(),
+ font(),
+ isComposing()
\endtable
+ \section1 Licensing Information
+
\legalese
Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
@@ -154,16 +156,17 @@ QInputContext::~QInputContext()
}
/*!
- \internal
Returns the widget that has an input focus for this input
- context. Ordinary input methods should not call this function
- directly to keep platform independence and flexible configuration
- possibility.
+ context.
The return value may differ from holderWidget() if the input
context is shared between several text widgets.
- \sa setFocusWidget(), holderWidget()
+ \warning To ensure platform independence and support flexible
+ configuration of widgets, ordinary input methods should not call
+ this function directly.
+
+ \sa setFocusWidget()
*/
QWidget *QInputContext::focusWidget() const
{
@@ -173,9 +176,9 @@ QWidget *QInputContext::focusWidget() const
/*!
- \internal
- Sets the widget that has an input focus for this input
- context. Ordinary input methods must not call this function
+ Sets the widget that has an input focus for this input context.
+
+ \warning Ordinary input methods must not call this function
directly.
\sa focusWidget()
@@ -209,9 +212,21 @@ void QInputContext::setFocusWidget(QWidget *widget)
way. Although the input events have accept() and ignore()
methods, leave it untouched.
- \a event is currently restricted to QKeyEvent. But some input
- method related events such as QWheelEvent or QTabletEvent may be
- added in future.
+ \a event is currently restricted to events of these types:
+
+ \list
+ \i CloseSoftwareInputPanel
+ \i KeyPress
+ \i KeyRelease
+ \i MouseButtonDblClick
+ \i MouseButtonPress
+ \i MouseButtonRelease
+ \i MouseMove
+ \i RequestSoftwareInputPanel
+ \endlist
+
+ But some input method related events such as QWheelEvent or
+ QTabletEvent may be added in future.
The filtering opportunity is always given to the input context as
soon as possible. It has to be taken place before any other key
@@ -262,7 +277,7 @@ void QInputContext::sendEvent(const QInputMethodEvent &event)
return;
QInputMethodEvent e(event);
- qApp->sendEvent(focus, &e);
+ QApplication::sendEvent(focus, &e);
}
@@ -408,20 +423,13 @@ QList<QAction *> QInputContext::actions()
QTextFormat QInputContext::standardFormat(StandardFormat s) const
{
QWidget *focus = focusWidget();
- const QPalette &pal = focus ? focus->palette() : qApp->palette();
+ const QPalette &pal = focus ? focus->palette() : QApplication::palette();
QTextCharFormat fmt;
QColor bg;
switch (s) {
case QInputContext::PreeditFormat: {
fmt.setUnderlineStyle(QTextCharFormat::DashUnderline);
-#ifndef Q_WS_WIN
- int h1, s1, v1, h2, s2, v2;
- pal.color(QPalette::Base).getHsv(&h1, &s1, &v1);
- pal.color(QPalette::Background).getHsv(&h2, &s2, &v2);
- bg.setHsv(h1, s1, (v1 + v2) / 2);
- fmt.setBackground(QBrush(bg));
-#endif
break;
}
case QInputContext::SelectionFormat: {
@@ -459,6 +467,31 @@ bool QInputContext::x11FilterEvent(QWidget * /*keywidget*/, XEvent * /*event*/)
}
#endif // Q_WS_X11
+#ifdef Q_WS_S60
+/*!
+ This function may be overridden only if input method is depending
+ on Symbian and you need raw TWsEvent. Otherwise, this function must not.
+
+ This function is designed to filter raw key events on S60, but
+ other input methods may use this to implement some special
+ features.
+
+ Return true if the \a event has been consumed. Otherwise, the
+ unfiltered \a event will be translated into QEvent and forwarded
+ to filterEvent(). Filtering at both s60FilterEvent() and
+ filterEvent() in single input method is allowed.
+
+ \a keywidget is a client widget into which a text is inputted. \a
+ event is inputted TWsEvent.
+
+ \sa filterEvent()
+*/
+bool QInputContext::s60FilterEvent(QWidget * /*keywidget*/, TWsEvent * /*event*/)
+{
+ return false;
+}
+#endif // Q_WS_S60
+
QT_END_NAMESPACE
#endif //Q_NO_IM
diff --git a/src/gui/inputmethod/qinputcontext.h b/src/gui/inputmethod/qinputcontext.h
index 30aa5b6..cf659ea 100644
--- a/src/gui/inputmethod/qinputcontext.h
+++ b/src/gui/inputmethod/qinputcontext.h
@@ -67,6 +67,10 @@
QT_BEGIN_HEADER
+#ifdef Q_WS_S60
+class TWsEvent;
+#endif
+
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
@@ -76,7 +80,6 @@ class QFont;
class QPopupMenu;
class QInputContextPrivate;
-
class Q_GUI_EXPORT QInputContext : public QObject
{
Q_OBJECT
@@ -105,6 +108,9 @@ public:
#if defined(Q_WS_X11)
virtual bool x11FilterEvent( QWidget *keywidget, XEvent *event );
#endif // Q_WS_X11
+#if defined(Q_WS_S60)
+ virtual bool s60FilterEvent( QWidget *keywidget, TWsEvent *event );
+#endif // Q_WS_S60
virtual bool filterEvent( const QEvent *event );
void sendEvent(const QInputMethodEvent &event);
diff --git a/src/gui/inputmethod/qinputcontext_p.h b/src/gui/inputmethod/qinputcontext_p.h
index e9cafed..aa6c3bc 100644
--- a/src/gui/inputmethod/qinputcontext_p.h
+++ b/src/gui/inputmethod/qinputcontext_p.h
@@ -84,10 +84,6 @@ public:
{}
QWidget *focusWidget;
-
-#if defined(Q_WS_WIN) || defined(Q_WS_QWS)
- static void updateImeStatus(QWidget *w, bool hasFocus);
-#endif
};
QT_END_NAMESPACE
diff --git a/src/gui/inputmethod/qinputcontextfactory.cpp b/src/gui/inputmethod/qinputcontextfactory.cpp
index 87fe138..7389bf2 100644
--- a/src/gui/inputmethod/qinputcontextfactory.cpp
+++ b/src/gui/inputmethod/qinputcontextfactory.cpp
@@ -71,6 +71,9 @@
#ifdef Q_WS_MAC
#include "qmacinputcontext_p.h"
#endif
+#ifdef Q_WS_S60
+#include "qcoefepinputcontext_p.h"
+#endif
#include "private/qfactoryloader_p.h"
#include "qmutex.h"
@@ -86,7 +89,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
\class QInputContextFactory
\brief The QInputContextFactory class creates QInputContext objects.
- \ingroup appearance
The input context factory creates a QInputContext object for a
given key with QInputContextFactory::create().
@@ -145,6 +147,11 @@ QInputContext *QInputContextFactory::create( const QString& key, QObject *parent
result = new QMacInputContext;
}
#endif
+#if defined(Q_WS_S60)
+ if (key == QLatin1String("coefep")) {
+ result = new QCoeFepInputContext;
+ }
+#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
#else
@@ -182,6 +189,9 @@ QStringList QInputContextFactory::keys()
#if defined(Q_WS_MAC)
result << QLatin1String("mac");
#endif
+#if defined(Q_WS_S60)
+ result << QLatin1String("coefep");
+#endif
#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
result += loader()->keys();
#endif // QT_NO_LIBRARY
@@ -217,6 +227,10 @@ QStringList QInputContextFactory::languages( const QString &key )
if (key == QLatin1String("mac"))
return QStringList(QString());
#endif
+#if defined(Q_WS_S60)
+ if (key == QLatin1String("coefep"))
+ return QStringList(QString());
+#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
#else
@@ -241,6 +255,10 @@ QString QInputContextFactory::displayName( const QString &key )
if (key == QLatin1String("xim"))
return QInputContext::tr( "XIM" );
#endif
+#ifdef Q_WS_S60
+ if (key == QLatin1String("coefep"))
+ return QInputContext::tr( "FEP" );
+#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
#else
@@ -272,6 +290,10 @@ QString QInputContextFactory::description( const QString &key )
if (key == QLatin1String("mac"))
return QInputContext::tr( "Mac OS X input method" );
#endif
+#if defined(Q_WS_S60)
+ if (key == QLatin1String("coefep"))
+ return QInputContext::tr( "S60 FEP input method" );
+#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
#else
diff --git a/src/gui/inputmethod/qinputcontextplugin.h b/src/gui/inputmethod/qinputcontextplugin.h
index fb3f3f6..fde48f1 100644
--- a/src/gui/inputmethod/qinputcontextplugin.h
+++ b/src/gui/inputmethod/qinputcontextplugin.h
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-#if !defined(QT_NO_IM) && !defined(QT_NO_LIBRARY)
+#if !defined(QT_NO_IM)
class QInputContext;
class QInputContextPluginPrivate;
diff --git a/src/gui/inputmethod/qmacinputcontext_mac.cpp b/src/gui/inputmethod/qmacinputcontext_mac.cpp
index 8e80161..e47c734 100644
--- a/src/gui/inputmethod/qmacinputcontext_mac.cpp
+++ b/src/gui/inputmethod/qmacinputcontext_mac.cpp
@@ -45,6 +45,7 @@
#include "qtextformat.h"
#include <qdebug.h>
#include <private/qapplication_p.h>
+#include <private/qkeymapper_p.h>
QT_BEGIN_NAMESPACE
@@ -56,7 +57,8 @@ extern bool qt_sendSpontaneousEvent(QObject*, QEvent*);
#endif
QMacInputContext::QMacInputContext(QObject *parent)
- : QInputContext(parent), composing(false), recursionGuard(false), textDocument(0)
+ : QInputContext(parent), composing(false), recursionGuard(false), textDocument(0),
+ keydownEvent(0)
{
// createTextDocument();
}
@@ -188,6 +190,16 @@ QMacInputContext::cleanup()
#endif
}
+void QMacInputContext::setLastKeydownEvent(EventRef event)
+{
+ EventRef tmpEvent = keydownEvent;
+ keydownEvent = event;
+ if (keydownEvent)
+ RetainEvent(keydownEvent);
+ if (tmpEvent)
+ ReleaseEvent(tmpEvent);
+}
+
OSStatus
QMacInputContext::globalEventProcessor(EventHandlerCallRef, EventRef event, void *)
{
@@ -340,6 +352,12 @@ QMacInputContext::globalEventProcessor(EventHandlerCallRef, EventRef event, void
GetEventParameter(key_ev, kEventParamKeyMacCharCodes, typeChar, 0, sizeof(chr), 0, &chr);
if(!chr || chr >= 128 || (text.length() > 0 && (text.length() > 1 || text.at(0) != QLatin1Char(chr))))
handled_event = !widget->testAttribute(Qt::WA_InputMethodEnabled);
+ QMacInputContext *context = qobject_cast<QMacInputContext*>(qApp->inputContext());
+ if (context && context->lastKeydownEvent()) {
+ qt_keymapper_private()->translateKeyEvent(widget, 0, context->lastKeydownEvent(),
+ 0, false);
+ context->setLastKeydownEvent(0);
+ }
}
break; }
default:
diff --git a/src/gui/inputmethod/qmacinputcontext_p.h b/src/gui/inputmethod/qmacinputcontext_p.h
index e42b36c..472b37b 100644
--- a/src/gui/inputmethod/qmacinputcontext_p.h
+++ b/src/gui/inputmethod/qmacinputcontext_p.h
@@ -78,6 +78,10 @@ public:
static OSStatus globalEventProcessor(EventHandlerCallRef, EventRef, void *);
static void initialize();
static void cleanup();
+
+ EventRef lastKeydownEvent() { return keydownEvent; }
+ void setLastKeydownEvent(EventRef);
+
protected:
void mouseHandler(int pos, QMouseEvent *);
private:
@@ -85,6 +89,7 @@ private:
bool recursionGuard;
TSMDocumentID textDocument;
QString currentText;
+ EventRef keydownEvent;
};
QT_END_NAMESPACE
diff --git a/src/gui/inputmethod/qwininputcontext_p.h b/src/gui/inputmethod/qwininputcontext_p.h
index 3cb2d13..bd553d4 100644
--- a/src/gui/inputmethod/qwininputcontext_p.h
+++ b/src/gui/inputmethod/qwininputcontext_p.h
@@ -79,10 +79,12 @@ public:
bool startComposition();
bool endComposition();
bool composition(LPARAM lparam);
+ int reconvertString(RECONVERTSTRING *reconv);
static void TranslateMessage(const MSG *msg);
static LRESULT DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static void updateImeStatus(QWidget *w, bool hasFocus);
static void enablePopupChild(QWidget *w, bool e);
static void enable(QWidget *w, bool e);
diff --git a/src/gui/inputmethod/qwininputcontext_win.cpp b/src/gui/inputmethod/qwininputcontext_win.cpp
index ec7e7c1..aba97e0 100644
--- a/src/gui/inputmethod/qwininputcontext_win.cpp
+++ b/src/gui/inputmethod/qwininputcontext_win.cpp
@@ -45,21 +45,17 @@
#include "qfont.h"
#include "qwidget.h"
#include "qapplication.h"
-#include "qlibrary.h"
#include "qevent.h"
#include "qtextformat.h"
+#include "qtextboundaryfinder.h"
//#define Q_IME_DEBUG
-/* Active Input method support on Win95/98/NT */
-#include <objbase.h>
-#include <initguid.h>
-
#ifdef Q_IME_DEBUG
#include "qdebug.h"
#endif
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
extern void qt_wince_show_SIP(bool show); // defined in qguifunctions_wince.cpp
#endif
@@ -218,26 +214,7 @@ static DWORD WM_MSIME_MOUSE = 0;
QWinInputContext::QWinInputContext(QObject *parent)
: QInputContext(parent), recursionGuard(false)
{
- if (QSysInfo::WindowsVersion < QSysInfo::WV_2000) {
- // try to get the Active IMM COM object on Win95/98/NT, where english versions don't
- // support the regular Windows input methods.
- if (CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_INPROC_SERVER,
- IID_IActiveIMMApp, (LPVOID *)&aimm) != S_OK) {
- aimm = 0;
- }
- if (aimm && (aimm->QueryInterface(IID_IActiveIMMMessagePumpOwner, (LPVOID *)&aimmpump) != S_OK ||
- aimm->Activate(true) != S_OK)) {
- aimm->Release();
- aimm = 0;
- if (aimmpump)
- aimmpump->Release();
- aimmpump = 0;
- }
- if (aimmpump)
- aimmpump->Start();
- }
-
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
QSysInfo::WinVersion ver = QSysInfo::windowsVersion();
if (ver & QSysInfo::WV_NT_based && ver >= QSysInfo::WV_VISTA) {
// Since the IsValidLanguageGroup/IsValidLocale functions always return true on
@@ -262,25 +239,21 @@ QWinInputContext::QWinInputContext(QObject *parent)
delete []lpList;
}
} else {
- // figure out whether a RTL language is installed
- typedef BOOL(WINAPI *PtrIsValidLanguageGroup)(DWORD,DWORD);
- PtrIsValidLanguageGroup isValidLanguageGroup = (PtrIsValidLanguageGroup)QLibrary::resolve(QLatin1String("kernel32"), "IsValidLanguageGroup");
- if (isValidLanguageGroup) {
- qt_use_rtl_extensions = isValidLanguageGroup(LGRPID_ARABIC, LGRPID_INSTALLED)
- || isValidLanguageGroup(LGRPID_HEBREW, LGRPID_INSTALLED);
- }
- qt_use_rtl_extensions |= IsValidLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
- || IsValidLocale(MAKELCID(MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
+ // figure out whether a RTL language is installed
+ qt_use_rtl_extensions = IsValidLanguageGroup(LGRPID_ARABIC, LGRPID_INSTALLED)
+ || IsValidLanguageGroup(LGRPID_HEBREW, LGRPID_INSTALLED)
+ || IsValidLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
+ || IsValidLocale(MAKELCID(MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
#ifdef LANG_SYRIAC
- || IsValidLocale(MAKELCID(MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
+ || IsValidLocale(MAKELCID(MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
#endif
- || IsValidLocale(MAKELCID(MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED);
+ || IsValidLocale(MAKELCID(MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED);
}
#else
qt_use_rtl_extensions = false;
#endif
- WM_MSIME_MOUSE = QT_WA_INLINE(RegisterWindowMessage(L"MSIMEMouseOperation"), RegisterWindowMessageA("MSIMEMouseOperation"));
+ WM_MSIME_MOUSE = RegisterWindowMessage(L"MSIMEMouseOperation");
}
QWinInputContext::~QWinInputContext()
@@ -337,26 +310,13 @@ static void notifyIME(HIMC imc, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
ImmNotifyIME(imc, dwAction, dwIndex, dwValue);
}
-static LONG getCompositionString(HIMC himc, DWORD dwIndex, LPVOID lpbuf, DWORD dBufLen, bool *unicode = 0)
+static LONG getCompositionString(HIMC himc, DWORD dwIndex, LPVOID lpbuf, DWORD dBufLen)
{
LONG len = 0;
- if (unicode)
- *unicode = true;
if (aimm)
aimm->GetCompositionStringW(himc, dwIndex, dBufLen, &len, lpbuf);
else
- {
- if(QSysInfo::WindowsVersion != QSysInfo::WV_95) {
- len = ImmGetCompositionStringW(himc, dwIndex, lpbuf, dBufLen);
- }
-#if !defined(Q_OS_WINCE)
- else {
- len = ImmGetCompositionStringA(himc, dwIndex, lpbuf, dBufLen);
- if (unicode)
- *unicode = false;
- }
-#endif
- }
+ len = ImmGetCompositionString(himc, dwIndex, lpbuf, dBufLen);
return len;
}
@@ -367,29 +327,28 @@ static int getCursorPosition(HIMC himc)
static QString getString(HIMC himc, DWORD dwindex, int *selStart = 0, int *selLength = 0)
{
- static char *buffer = 0;
+ static wchar_t *buffer = 0;
static int buflen = 0;
int len = getCompositionString(himc, dwindex, 0, 0) + 1;
if (!buffer || len > buflen) {
delete [] buffer;
buflen = qMin(len, 256);
- buffer = new char[buflen];
+ buffer = new wchar_t[buflen];
}
- bool unicode = true;
- len = getCompositionString(himc, dwindex, buffer, buflen, &unicode);
+ len = getCompositionString(himc, dwindex, buffer, buflen * sizeof(wchar_t));
if (selStart) {
- static char *attrbuffer = 0;
+ static wchar_t *attrbuffer = 0;
static int attrbuflen = 0;
int attrlen = getCompositionString(himc, dwindex, 0, 0) + 1;
if (!attrbuffer || attrlen> attrbuflen) {
delete [] attrbuffer;
attrbuflen = qMin(attrlen, 256);
- attrbuffer = new char[attrbuflen];
+ attrbuffer = new wchar_t[attrbuflen];
}
- attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, attrbuflen);
+ attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, attrbuflen * sizeof(wchar_t));
*selStart = attrlen+1;
*selLength = -1;
for (int i = 0; i < attrlen; i++) {
@@ -403,18 +362,8 @@ static QString getString(HIMC himc, DWORD dwindex, int *selStart = 0, int *selLe
if (len <= 0)
return QString();
- if (unicode) {
- return QString((QChar *)buffer, len/sizeof(QChar));
- }
- else {
- buffer[len] = 0;
- WCHAR *wc = new WCHAR[len+1];
- int l = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
- buffer, len, wc, len+1);
- QString res = QString((QChar *)wc, l);
- delete [] wc;
- return res;
- }
+
+ return QString((QChar*)buffer, len / sizeof(QChar));
}
void QWinInputContext::TranslateMessage(const MSG *msg)
@@ -428,11 +377,7 @@ LRESULT QWinInputContext::DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
LRESULT retval;
if (!aimm || aimm->OnDefWindowProc(hwnd, msg, wParam, lParam, &retval) != S_OK)
{
- QT_WA({
- retval = ::DefWindowProc(hwnd, msg, wParam, lParam);
- } , {
- retval = ::DefWindowProcA(hwnd,msg, wParam, lParam);
- });
+ retval = ::DefWindowProc(hwnd, msg, wParam, lParam);
}
return retval;
}
@@ -454,21 +399,13 @@ void QWinInputContext::update()
HFONT hf;
hf = f.handle();
- QT_WA({
- LOGFONT lf;
- if (GetObject(hf, sizeof(lf), &lf))
- if (aimm)
- aimm->SetCompositionFontW(imc, &lf);
- else
- ImmSetCompositionFont(imc, &lf);
- } , {
- LOGFONTA lf;
- if (GetObjectA(hf, sizeof(lf), &lf))
- if (aimm)
- aimm->SetCompositionFontA(imc, &lf);
- else
- ImmSetCompositionFontA(imc, &lf);
- });
+ LOGFONT lf;
+ if (GetObject(hf, sizeof(lf), &lf)) {
+ if (aimm)
+ aimm->SetCompositionFontW(imc, &lf);
+ else
+ ImmSetCompositionFont(imc, &lf);
+ }
QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect();
@@ -539,7 +476,7 @@ bool QWinInputContext::endComposition()
}
if (!fw)
- fw = qApp->focusWidget();
+ fw = QApplication::focusWidget();
if (fw) {
QInputMethodEvent e;
@@ -637,7 +574,7 @@ bool QWinInputContext::composition(LPARAM lParam)
// bogus event
return true;
- QWidget *fw = qApp->focusWidget();
+ QWidget *fw = QApplication::focusWidget();
if (fw) {
Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
HIMC imc = getContext(fw->effectiveWinId());
@@ -738,7 +675,7 @@ inline void enableIme(QWidget *w, bool value)
// enable ime
if (defaultContext)
ImmAssociateContext(w->effectiveWinId(), defaultContext);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qApp->autoSipEnabled())
qt_wince_show_SIP(true);
#endif
@@ -747,7 +684,7 @@ inline void enableIme(QWidget *w, bool value)
HIMC oldimc = ImmAssociateContext(w->effectiveWinId(), 0);
if (!defaultContext)
defaultContext = oldimc;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qApp->autoSipEnabled())
qt_wince_show_SIP(false);
#endif
@@ -755,11 +692,16 @@ inline void enableIme(QWidget *w, bool value)
}
-void QInputContextPrivate::updateImeStatus(QWidget *w, bool hasFocus)
+void QWinInputContext::updateImeStatus(QWidget *w, bool hasFocus)
{
if (!w)
return;
- bool e = w->testAttribute(Qt::WA_InputMethodEnabled) && w->isEnabled();
+ // It's always the proxy that carries the hints.
+ QWidget *focusProxyWidget = w->focusProxy();
+ if (!focusProxyWidget)
+ focusProxyWidget = w;
+ bool e = w->testAttribute(Qt::WA_InputMethodEnabled) && w->isEnabled()
+ && !(focusProxyWidget->inputMethodHints() & Qt::ImhExclusiveInputMask);
bool hasIme = e && hasFocus;
#ifdef Q_IME_DEBUG
qDebug("%s HasFocus = %d hasIme = %d e = %d ", w->className(), hasFocus, hasIme, e);
@@ -824,6 +766,15 @@ void QWinInputContext::enable(QWidget *w, bool e)
void QWinInputContext::setFocusWidget(QWidget *w)
{
+ QWidget *oldFocus = focusWidget();
+ if (oldFocus == w)
+ return;
+ if (w) {
+ QWinInputContext::updateImeStatus(w, true);
+ } else {
+ if (oldFocus)
+ QWinInputContext::updateImeStatus(oldFocus , false);
+ }
QInputContext::setFocusWidget(w);
update();
}
@@ -860,4 +811,52 @@ QString QWinInputContext::language()
return QString();
}
+int QWinInputContext::reconvertString(RECONVERTSTRING *reconv)
+{
+ QWidget *w = focusWidget();
+ if(!w)
+ return -1;
+
+ Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
+ QString surroundingText = qvariant_cast<QString>(w->inputMethodQuery(Qt::ImSurroundingText));
+ int memSize = sizeof(RECONVERTSTRING)+(surroundingText.length()+1)*sizeof(ushort);
+ // If memory is not allocated, return the required size.
+ if (!reconv) {
+ if (surroundingText.isEmpty())
+ return -1;
+ else
+ return memSize;
+ }
+ int pos = qvariant_cast<int>(w->inputMethodQuery(Qt::ImCursorPosition));
+ // find the word in the surrounding text.
+ QTextBoundaryFinder bounds(QTextBoundaryFinder::Word, surroundingText);
+ bounds.setPosition(pos);
+ if (bounds.isAtBoundary()) {
+ if (QTextBoundaryFinder::EndWord == bounds.boundaryReasons())
+ bounds.toPreviousBoundary();
+ } else {
+ bounds.toPreviousBoundary();
+ }
+ int startPos = bounds.position();
+ bounds.toNextBoundary();
+ int endPos = bounds.position();
+ // select the text, this will be overwritten by following ime events.
+ QList<QInputMethodEvent::Attribute> attrs;
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, startPos, endPos-startPos, QVariant());
+ QInputMethodEvent e(QString(), attrs);
+ qt_sendSpontaneousEvent(w, &e);
+
+ reconv->dwSize = memSize;
+ reconv->dwVersion = 0;
+
+ reconv->dwStrLen = surroundingText.length();
+ reconv->dwStrOffset = sizeof(RECONVERTSTRING);
+ reconv->dwCompStrLen = endPos-startPos;
+ reconv->dwCompStrOffset = startPos*sizeof(ushort);
+ reconv->dwTargetStrLen = reconv->dwCompStrLen;
+ reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
+ memcpy((char*)(reconv+1), surroundingText.utf16(), surroundingText.length()*sizeof(ushort));
+ return memSize;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/inputmethod/qwsinputcontext_p.h b/src/gui/inputmethod/qwsinputcontext_p.h
index 2903c0f..0b5c7b2 100644
--- a/src/gui/inputmethod/qwsinputcontext_p.h
+++ b/src/gui/inputmethod/qwsinputcontext_p.h
@@ -87,6 +87,7 @@ public:
static bool translateIMEvent(QWidget *w, const QWSIMEvent *e);
static bool translateIMQueryEvent(QWidget *w, const QWSIMQueryEvent *e);
static bool translateIMInitEvent(const QWSIMInitEvent *e);
+ static void updateImeStatus(QWidget *w, bool hasFocus);
};
QT_END_NAMESPACE
diff --git a/src/gui/inputmethod/qwsinputcontext_qws.cpp b/src/gui/inputmethod/qwsinputcontext_qws.cpp
index 0d0f797..064fbfc 100644
--- a/src/gui/inputmethod/qwsinputcontext_qws.cpp
+++ b/src/gui/inputmethod/qwsinputcontext_qws.cpp
@@ -73,10 +73,17 @@ void QWSInputContext::reset()
void QWSInputContext::setFocusWidget( QWidget *w )
{
- QWidget *oldFocus = focusWidget();
+ QWidget *oldFocus = focusWidget();
if (oldFocus == w)
return;
+ if (w) {
+ QWSInputContext::updateImeStatus(w, true);
+ } else {
+ if (oldFocus)
+ QWSInputContext::updateImeStatus(oldFocus, false);
+ }
+
if (oldFocus) {
QWidget *tlw = oldFocus->window();
int winid = tlw->internalWinId();
@@ -104,8 +111,8 @@ void QWSInputContext::setFocusWidget( QWidget *w )
void QWSInputContext::widgetDestroyed(QWidget *w)
{
- if (w == ::activeWidget)
- ::activeWidget = 0;
+ if (w == QT_PREPEND_NAMESPACE(activeWidget))
+ QT_PREPEND_NAMESPACE(activeWidget) = 0;
QInputContext::widgetDestroyed(w);
}
@@ -131,13 +138,13 @@ void QWSInputContext::mouseHandler( int x, QMouseEvent *event)
QWidget *QWSInputContext::activeWidget()
{
- return ::activeWidget;
+ return QT_PREPEND_NAMESPACE(activeWidget);
}
bool QWSInputContext::isComposing() const
{
- return ::activeWidget != 0;
+ return QT_PREPEND_NAMESPACE(activeWidget) != 0;
}
bool QWSInputContext::translateIMQueryEvent(QWidget *w, const QWSIMQueryEvent *e)
@@ -175,8 +182,8 @@ bool QWSInputContext::translateIMEvent(QWidget *w, const QWSIMEvent *e)
stream >> preedit;
stream >> commit;
- if (preedit.isEmpty() && ::activeWidget)
- w = ::activeWidget;
+ if (preedit.isEmpty() && QT_PREPEND_NAMESPACE(activeWidget))
+ w = QT_PREPEND_NAMESPACE(activeWidget);
QInputContext *qic = w->inputContext();
if (!qic)
@@ -206,9 +213,9 @@ bool QWSInputContext::translateIMEvent(QWidget *w, const QWSIMEvent *e)
#endif
if (preedit.isEmpty())
- ::activeWidget = 0;
+ QT_PREPEND_NAMESPACE(activeWidget) = 0;
else
- ::activeWidget = w;
+ QT_PREPEND_NAMESPACE(activeWidget) = w;
QInputMethodEvent ime(preedit, attrs);
@@ -224,7 +231,7 @@ bool QWSInputContext::translateIMEvent(QWidget *w, const QWSIMEvent *e)
Q_GUI_EXPORT void (*qt_qws_inputMethodStatusChanged)(QWidget*) = 0;
-void QInputContextPrivate::updateImeStatus(QWidget *w, bool hasFocus)
+void QWSInputContext::updateImeStatus(QWidget *w, bool hasFocus)
{
Q_UNUSED(hasFocus);
diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp
index ae91c04..f60c961 100644
--- a/src/gui/inputmethod/qximinputcontext_x11.cpp
+++ b/src/gui/inputmethod/qximinputcontext_x11.cpp
@@ -53,6 +53,7 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
#include "qdebug.h"
#include "qximinputcontext_p.h"
@@ -438,7 +439,8 @@ void QXIMInputContext::create_xim()
// server (like SCIM) has been launched without
// requiring the user to manually switch focus.
if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled)
- && focusWidget->testAttribute(Qt::WA_WState_Created))
+ && focusWidget->testAttribute(Qt::WA_WState_Created)
+ && focusWidget->isEnabled())
setFocusWidget(focusWidget);
}
// following code fragment is not required for immodule
@@ -610,7 +612,7 @@ void QXIMInputContext::setFocusWidget(QWidget *w)
QInputContext::setFocusWidget(w);
- if (!w)
+ if (!w || w->inputMethodHints() & Qt::ImhExclusiveInputMask)
return;
ICData *data = ximData.value(w->effectiveWinId());
diff --git a/src/gui/itemviews/qabstractitemdelegate.cpp b/src/gui/itemviews/qabstractitemdelegate.cpp
index 101047a..f7396f0 100644
--- a/src/gui/itemviews/qabstractitemdelegate.cpp
+++ b/src/gui/itemviews/qabstractitemdelegate.cpp
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
data items from a model.
\ingroup model-view
- \mainclass
+
A QAbstractItemDelegate provides the interface and common functionality
for delegates in the model/view architecture. Delegates display
diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp
index 3d7ab5c..07c5454 100644
--- a/src/gui/itemviews/qabstractitemview.cpp
+++ b/src/gui/itemviews/qabstractitemview.cpp
@@ -61,6 +61,7 @@
#ifndef QT_NO_ACCESSIBILITY
#include <qaccessible.h>
#endif
+#include <private/qactiontokeyeventmapper_p.h>
QT_BEGIN_NAMESPACE
@@ -73,6 +74,7 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate()
currentlyCommittingEditor(0),
pressedModifiers(Qt::NoModifier),
pressedPosition(QPoint(-1, -1)),
+ pressedAlreadySelected(false),
viewportEnteredNeeded(false),
state(QAbstractItemView::NoState),
editTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed),
@@ -108,16 +110,16 @@ void QAbstractItemViewPrivate::init()
Q_Q(QAbstractItemView);
q->setItemDelegate(new QStyledItemDelegate(q));
- q->verticalScrollBar()->setRange(0, 0);
- q->horizontalScrollBar()->setRange(0, 0);
+ vbar->setRange(0, 0);
+ hbar->setRange(0, 0);
- QObject::connect(q->verticalScrollBar(), SIGNAL(actionTriggered(int)),
+ QObject::connect(vbar, SIGNAL(actionTriggered(int)),
q, SLOT(verticalScrollbarAction(int)));
- QObject::connect(q->horizontalScrollBar(), SIGNAL(actionTriggered(int)),
+ QObject::connect(hbar, SIGNAL(actionTriggered(int)),
q, SLOT(horizontalScrollbarAction(int)));
- QObject::connect(q->verticalScrollBar(), SIGNAL(valueChanged(int)),
+ QObject::connect(vbar, SIGNAL(valueChanged(int)),
q, SLOT(verticalScrollbarValueChanged(int)));
- QObject::connect(q->horizontalScrollBar(), SIGNAL(valueChanged(int)),
+ QObject::connect(hbar, SIGNAL(valueChanged(int)),
q, SLOT(horizontalScrollbarValueChanged(int)));
viewport->setBackgroundRole(QPalette::Base);
@@ -127,6 +129,37 @@ void QAbstractItemViewPrivate::init()
q->setAttribute(Qt::WA_InputMethodEnabled);
}
+void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index)
+{
+ //we take a persistent model index because the model might change by emitting signals
+ Q_Q(QAbstractItemView);
+ if (viewportEnteredNeeded || enteredIndex != index) {
+ viewportEnteredNeeded = false;
+
+ if (index.isValid()) {
+ emit q->entered(index);
+#ifndef QT_NO_STATUSTIP
+ QString statustip = model->data(index, Qt::StatusTipRole).toString();
+ if (parent && !statustip.isEmpty()) {
+ QStatusTipEvent tip(statustip);
+ QApplication::sendEvent(parent, &tip);
+ }
+#endif
+ } else {
+#ifndef QT_NO_STATUSTIP
+ if (parent) {
+ QString emptyString;
+ QStatusTipEvent tip( emptyString );
+ QApplication::sendEvent(parent, &tip);
+ }
+#endif
+ emit q->viewportEntered();
+ }
+ enteredIndex = index;
+ }
+}
+
+
/*!
\class QAbstractItemView
@@ -134,7 +167,7 @@ void QAbstractItemViewPrivate::init()
item view classes.
\ingroup model-view
- \mainclass
+
QAbstractItemView class is the base class for every standard view
that uses a QAbstractItemModel. QAbstractItemView is an abstract
@@ -552,7 +585,7 @@ void QAbstractItemView::setModel(QAbstractItemModel *model)
"QAbstractItemView::setModel",
"The parent of a top level index should be invalid");
- if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
+ if (d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
connect(d->model, SIGNAL(destroyed()),
this, SLOT(_q_modelDestroyed()));
connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
@@ -820,8 +853,8 @@ QAbstractItemDelegate *QAbstractItemView::itemDelegateForColumn(int column) cons
}
/*!
- Returns the item delegate used by this view and model for
- the given \a index.
+ Returns the item delegate used by this view and model for
+ the given \a index.
*/
QAbstractItemDelegate *QAbstractItemView::itemDelegate(const QModelIndex &index) const
{
@@ -830,14 +863,14 @@ QAbstractItemDelegate *QAbstractItemView::itemDelegate(const QModelIndex &index)
}
/*!
- \property QAbstractItemView::selectionMode
- \brief which selection mode the view operates in
+ \property QAbstractItemView::selectionMode
+ \brief which selection mode the view operates in
- This property controls whether the user can select one or many items
- and, in many-item selections, whether the selection must be a
- continuous range of items.
+ This property controls whether the user can select one or many items
+ and, in many-item selections, whether the selection must be a
+ continuous range of items.
- \sa SelectionMode SelectionBehavior
+ \sa SelectionMode SelectionBehavior
*/
void QAbstractItemView::setSelectionMode(SelectionMode mode)
{
@@ -852,13 +885,13 @@ QAbstractItemView::SelectionMode QAbstractItemView::selectionMode() const
}
/*!
- \property QAbstractItemView::selectionBehavior
- \brief which selection behavior the view uses
+ \property QAbstractItemView::selectionBehavior
+ \brief which selection behavior the view uses
- This property holds whether selections are done
- in terms of single items, rows or columns.
+ This property holds whether selections are done
+ in terms of single items, rows or columns.
- \sa SelectionMode SelectionBehavior
+ \sa SelectionMode SelectionBehavior
*/
void QAbstractItemView::setSelectionBehavior(QAbstractItemView::SelectionBehavior behavior)
@@ -875,7 +908,9 @@ QAbstractItemView::SelectionBehavior QAbstractItemView::selectionBehavior() cons
/*!
Sets the current item to be the item at \a index.
- Depending on the current selection mode, the item may also be selected.
+
+ Unless the current selection mode is
+ \l{QAbstractItemView::}{NoSelection}, the item is also be selected.
Note that this function also updates the starting position for any
new selections the user performs.
@@ -929,6 +964,8 @@ void QAbstractItemView::reset()
d->currentIndexSet = false;
setState(NoState);
setRootIndex(QModelIndex());
+ if (d->selectionModel)
+ d->selectionModel->reset();
}
/*!
@@ -959,11 +996,11 @@ QModelIndex QAbstractItemView::rootIndex() const
}
/*!
- Selects all item in the view.
- This function wil use the selection selection behavior
- set on the view when selecting.
+ Selects all items in the view.
+ This function will use the selection behavior
+ set on the view when selecting.
- \sa setSelection(), selectedIndexes(), clearSelection()
+ \sa setSelection(), selectedIndexes(), clearSelection()
*/
void QAbstractItemView::selectAll()
{
@@ -1192,10 +1229,10 @@ bool QAbstractItemView::tabKeyNavigation() const
#ifndef QT_NO_DRAGANDDROP
/*!
- \property QAbstractItemView::showDropIndicator
- \brief whether the drop indicator is shown when dragging items and dropping.
+ \property QAbstractItemView::showDropIndicator
+ \brief whether the drop indicator is shown when dragging items and dropping.
- \sa dragEnabled DragDropMode dragDropOverwriteMode acceptDrops
+ \sa dragEnabled DragDropMode dragDropOverwriteMode acceptDrops
*/
void QAbstractItemView::setDropIndicatorShown(bool enable)
@@ -1211,10 +1248,10 @@ bool QAbstractItemView::showDropIndicator() const
}
/*!
- \property QAbstractItemView::dragEnabled
- \brief whether the view supports dragging of its own items
+ \property QAbstractItemView::dragEnabled
+ \brief whether the view supports dragging of its own items
- \sa showDropIndicator DragDropMode dragDropOverwriteMode acceptDrops
+ \sa showDropIndicator DragDropMode dragDropOverwriteMode acceptDrops
*/
void QAbstractItemView::setDragEnabled(bool enable)
@@ -1250,11 +1287,11 @@ bool QAbstractItemView::dragEnabled() const
*/
/*!
- \property QAbstractItemView::dragDropMode
- \brief the drag and drop event the view will act upon
+ \property QAbstractItemView::dragDropMode
+ \brief the drag and drop event the view will act upon
- \since 4.2
- \sa showDropIndicator dragDropOverwriteMode
+ \since 4.2
+ \sa showDropIndicator dragDropOverwriteMode
*/
void QAbstractItemView::setDragDropMode(DragDropMode behavior)
{
@@ -1290,14 +1327,14 @@ QAbstractItemView::DragDropMode QAbstractItemView::dragDropMode() const
#endif // QT_NO_DRAGANDDROP
/*!
- \property QAbstractItemView::alternatingRowColors
- \brief whether to draw the background using alternating colors
+ \property QAbstractItemView::alternatingRowColors
+ \brief whether to draw the background using alternating colors
- If this property is true, the item background will be drawn using
- QPalette::Base and QPalette::AlternateBase; otherwise the background
- will be drawn using the QPalette::Base color.
+ If this property is true, the item background will be drawn using
+ QPalette::Base and QPalette::AlternateBase; otherwise the background
+ will be drawn using the QPalette::Base color.
- By default, this property is false.
+ By default, this property is false.
*/
void QAbstractItemView::setAlternatingRowColors(bool enable)
{
@@ -1426,10 +1463,10 @@ bool QAbstractItemView::viewportEvent(QEvent *event)
case QEvent::HoverEnter: {
QHoverEvent *he = static_cast<QHoverEvent*>(event);
d->hover = indexAt(he->pos());
- d->viewport->update(visualRect(d->hover));
+ update(d->hover);
break; }
case QEvent::HoverLeave: {
- d->viewport->update(visualRect(d->hover)); // update old
+ update(d->hover); // update old
d->hover = QModelIndex();
break; }
case QEvent::HoverMove: {
@@ -1557,7 +1594,7 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event)
}
#endif // QT_NO_DRAGANDDROP
- QModelIndex index = indexAt(bottomRight);
+ QPersistentModelIndex index = indexAt(bottomRight);
QModelIndex buddy = d->model->buddy(d->pressedIndex);
if ((state() == EditingState && d->hasEditor(buddy))
|| edit(index, NoEditTriggers, event))
@@ -1568,36 +1605,10 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event)
else
topLeft = bottomRight;
- if (d->viewportEnteredNeeded || d->enteredIndex != index) {
- d->viewportEnteredNeeded = false;
-
- // signal handlers may change the model
- QPersistentModelIndex persistent = index;
- if (persistent.isValid()) {
- emit entered(persistent);
-#ifndef QT_NO_STATUSTIP
- QString statustip = d->model->data(persistent, Qt::StatusTipRole).toString();
- if (parent() && !statustip.isEmpty()) {
- QStatusTipEvent tip(statustip);
- QApplication::sendEvent(parent(), &tip);
- }
-#endif
- } else {
-#ifndef QT_NO_STATUSTIP
- if (parent()) {
- QString emptyString;
- QStatusTipEvent tip(emptyString);
- QApplication::sendEvent(parent(), &tip);
- }
-#endif
- emit viewportEntered();
- }
- d->enteredIndex = persistent;
- index = persistent;
- }
+ d->checkMouseMove(index);
#ifndef QT_NO_DRAGANDDROP
- if (index.isValid()
+ if (d->pressedIndex.isValid()
&& d->dragEnabled
&& (state() != DragSelectingState)
&& (event->buttons() != Qt::NoButton)
@@ -1613,14 +1624,13 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event)
// Do the normalize ourselves, since QRect::normalized() is flawed
QRect selectionRect = QRect(topLeft, bottomRight);
- QPersistentModelIndex persistent = index;
setSelection(selectionRect, command);
// set at the end because it might scroll the view
- if (persistent.isValid()
- && (persistent != d->selectionModel->currentIndex())
- && d->isIndexEnabled(persistent))
- d->selectionModel->setCurrentIndex(persistent, QItemSelectionModel::NoUpdate);
+ if (index.isValid()
+ && (index != d->selectionModel->currentIndex())
+ && d->isIndexEnabled(index))
+ d->selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
}
}
@@ -1642,7 +1652,7 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event)
if (d->isIndexValid(index)
&& d->isIndexEnabled(index)
&& d->sendDelegateEvent(index, event))
- d->viewport->update(visualRect(index));
+ update(index);
return;
}
@@ -1651,9 +1661,6 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event)
EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers);
bool edited = edit(index, trigger, event);
- if (d->selectionModel)
- d->selectionModel->select(index, selectionCommand(index, event));
-
setState(NoState);
if (click) {
@@ -2003,15 +2010,18 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
if (QApplication::keypadNavigationEnabled()) {
if (!hasEditFocus()) {
setEditFocus(true);
+ QActionToKeyEventMapper::addSoftKey(QAction::BackSoftKey, Qt::Key_Back, this);
return;
}
}
break;
case Qt::Key_Back:
- if (QApplication::keypadNavigationEnabled() && hasEditFocus())
+ if (QApplication::keypadNavigationEnabled() && hasEditFocus()) {
+ QActionToKeyEventMapper::removeSoftkey(this);
setEditFocus(false);
- else
+ } else {
event->ignore();
+ }
return;
default:
if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
@@ -2165,11 +2175,12 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
}
#endif
bool modified = (event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier));
- if (!event->text().isEmpty() && !modified) {
- if (!edit(currentIndex(), AnyKeyPressed, event))
- keyboardSearch(event->text());
+ if (!event->text().isEmpty() && !modified && !edit(currentIndex(), AnyKeyPressed, event)) {
+ keyboardSearch(event->text());
+ event->accept();
+ } else {
+ event->ignore();
}
- event->ignore();
break; }
}
}
@@ -2195,6 +2206,8 @@ void QAbstractItemView::resizeEvent(QResizeEvent *event)
void QAbstractItemView::timerEvent(QTimerEvent *event)
{
Q_D(QAbstractItemView);
+ if (event->timerId() == d->fetchMoreTimer.timerId())
+ d->fetchMore();
if (event->timerId() == d->autoScrollTimer.timerId())
doAutoScroll();
else if (event->timerId() == d->updateTimer.timerId())
@@ -2250,8 +2263,8 @@ void QAbstractItemView::inputMethodEvent(QInputMethodEvent *event)
\value BelowItem The item will be dropped below the index.
\value OnViewport The item will be dropped onto a region of the viewport with
-no items. The way each view handles items dropped onto the viewport depends on
-the behavior of the underlying model in use.
+ no items. The way each view handles items dropped onto the viewport depends on
+ the behavior of the underlying model in use.
*/
@@ -2268,11 +2281,11 @@ QAbstractItemView::DropIndicatorPosition QAbstractItemView::dropIndicatorPositio
#endif
/*!
- This convenience function returns a list of all selected and
- non-hidden item indexes in the view. The list contains no
- duplicates, and is not sorted.
+ This convenience function returns a list of all selected and
+ non-hidden item indexes in the view. The list contains no
+ duplicates, and is not sorted.
- \sa QItemSelectionModel::selectedIndexes()
+ \sa QItemSelectionModel::selectedIndexes()
*/
QModelIndexList QAbstractItemView::selectedIndexes() const
{
@@ -2325,7 +2338,7 @@ bool QAbstractItemView::edit(const QModelIndex &index, EditTrigger trigger, QEve
}
if (d->sendDelegateEvent(index, event)) {
- d->viewport->update(visualRect(index));
+ update(index);
return true;
}
@@ -2354,8 +2367,8 @@ bool QAbstractItemView::edit(const QModelIndex &index, EditTrigger trigger, QEve
}
/*!
- \internal
- Updates the data shown in the open editor widgets in the view.
+ \internal
+ Updates the data shown in the open editor widgets in the view.
*/
void QAbstractItemView::updateEditorData()
{
@@ -2364,8 +2377,8 @@ void QAbstractItemView::updateEditorData()
}
/*!
- \internal
- Updates the geometry of the open editor widgets in the view.
+ \internal
+ Updates the geometry of the open editor widgets in the view.
*/
void QAbstractItemView::updateEditorGeometries()
{
@@ -2397,8 +2410,8 @@ void QAbstractItemView::updateEditorGeometries()
//we release the editor outside of the loop because it might change the focus and try
//to change the d->editors list.
- foreach(QWidget *editor, editorsToRelease) {
- d->releaseEditor(editor);
+ for (int i = 0; i < editorsToRelease.count(); ++i) {
+ d->releaseEditor(editorsToRelease.at(i));
}
}
@@ -2410,27 +2423,29 @@ void QAbstractItemView::updateEditorGeometries()
void QAbstractItemView::updateGeometries()
{
updateEditorGeometries();
- QMetaObject::invokeMethod(this, "_q_fetchMore", Qt::QueuedConnection);
+ d_func()->fetchMoreTimer.start(0, this); //fetch more later
}
/*!
- \internal
+ \internal
*/
void QAbstractItemView::verticalScrollbarValueChanged(int value)
{
Q_D(QAbstractItemView);
if (verticalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
d->model->fetchMore(d->root);
+ d->checkMouseMove(viewport()->mapFromGlobal(QCursor::pos()));
}
/*!
- \internal
+ \internal
*/
void QAbstractItemView::horizontalScrollbarValueChanged(int value)
{
Q_D(QAbstractItemView);
if (horizontalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
d->model->fetchMore(d->root);
+ d->checkMouseMove(viewport()->mapFromGlobal(QCursor::pos()));
}
/*!
@@ -2525,9 +2540,9 @@ void QAbstractItemView::closeEditor(QWidget *editor, QAbstractItemDelegate::EndE
}
/*!
- Commit the data in the \a editor to the model.
+ Commit the data in the \a editor to the model.
- \sa closeEditor()
+ \sa closeEditor()
*/
void QAbstractItemView::commitData(QWidget *editor)
{
@@ -2546,9 +2561,9 @@ void QAbstractItemView::commitData(QWidget *editor)
}
/*!
- This function is called when the given \a editor has been destroyed.
+ This function is called when the given \a editor has been destroyed.
- \sa closeEditor()
+ \sa closeEditor()
*/
void QAbstractItemView::editorDestroyed(QObject *editor)
{
@@ -2619,12 +2634,12 @@ int QAbstractItemView::verticalStepsPerItem() const
}
/*!
- Moves to and selects the item best matching the string \a search.
- If no item is found nothing happens.
+ Moves to and selects the item best matching the string \a search.
+ If no item is found nothing happens.
- In the default implementation, the search is reset if \a search is empty, or
- the time interval since the last search has exceeded
- QApplication::keyboardInputInterval().
+ In the default implementation, the search is reset if \a search is empty, or
+ the time interval since the last search has exceeded
+ QApplication::keyboardInputInterval().
*/
void QAbstractItemView::keyboardSearch(const QString &search)
{
@@ -2639,7 +2654,7 @@ void QAbstractItemView::keyboardSearch(const QString &search)
if (search.isEmpty()
|| (d->keyboardInputTime.msecsTo(now) > QApplication::keyboardInputInterval())) {
d->keyboardInput = search;
- skipRow = true;
+ skipRow = currentIndex().isValid(); //if it is not valid we should really start at QModelIndex(0,0)
} else {
d->keyboardInput += search;
}
@@ -2679,9 +2694,9 @@ void QAbstractItemView::keyboardSearch(const QString &search)
setCurrentIndex(firstMatch);
break;
}
- int row = firstMatch.row() + 1;
- if (row >= d->model->rowCount(firstMatch.parent()))
- row = 0;
+ int row = firstMatch.row() + 1;
+ if (row >= d->model->rowCount(firstMatch.parent()))
+ row = 0;
current = firstMatch.sibling(row, firstMatch.column());
//avoid infinite loop if all the matching items are disabled.
@@ -2794,9 +2809,9 @@ void QAbstractItemView::openPersistentEditor(const QModelIndex &index)
}
/*!
- Closes the persistent editor for the item at the given \a index.
+ Closes the persistent editor for the item at the given \a index.
- \sa openPersistentEditor()
+ \sa openPersistentEditor()
*/
void QAbstractItemView::closePersistentEditor(const QModelIndex &index)
{
@@ -2851,9 +2866,9 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget
d->persistent.insert(widget);
d->addEditor(index, widget, true);
widget->show();
+ dataChanged(index, index); // update the geometry
if (!d->delayedPendingLayout)
widget->setGeometry(visualRect(index));
- dataChanged(index, index); // update the geometry
}
}
@@ -2960,7 +2975,7 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde
void QAbstractItemView::rowsInserted(const QModelIndex &, int, int)
{
if (!isVisible())
- QMetaObject::invokeMethod(this, "_q_fetchMore", Qt::QueuedConnection);
+ d_func()->fetchMoreTimer.start(0, this); //fetch more later
else
updateEditorGeometries();
}
@@ -3144,9 +3159,7 @@ void QAbstractItemView::selectionChanged(const QItemSelection &selected,
{
Q_D(QAbstractItemView);
if (isVisible() && updatesEnabled()) {
- d->setDirtyRegion(visualRegionForSelection(deselected));
- d->setDirtyRegion(visualRegionForSelection(selected));
- d->updateDirtyRegion();
+ d->viewport->update(visualRegionForSelection(deselected) | visualRegionForSelection(selected));
}
}
@@ -3174,19 +3187,18 @@ void QAbstractItemView::currentChanged(const QModelIndex &current, const QModelI
closeEditor(editor, QAbstractItemDelegate::NoHint);
}
if (isVisible()) {
- d->setDirtyRegion(visualRect(previous));
- d->updateDirtyRegion();
+ update(previous);
}
}
+
if (current.isValid() && !d->autoScrollTimer.isActive()) {
if (isVisible()) {
if (d->autoScroll)
scrollTo(current);
- d->setDirtyRegion(visualRect(current));
- d->updateDirtyRegion();
+ update(current);
edit(current, CurrentChanged, 0);
if (current.row() == (d->model->rowCount(d->root) - 1))
- d->_q_fetchMore();
+ d->fetchMore();
} else {
d->shouldScrollToCurrentOnShow = d->autoScroll;
}
@@ -3334,14 +3346,14 @@ void QAbstractItemView::setDirtyRegion(const QRegion &region)
}
/*!
- Prepares the view for scrolling by (\a{dx},\a{dy}) pixels by moving the dirty regions in the
- opposite direction. You only need to call this function if you are implementing a scrolling
- viewport in your view subclass.
+ Prepares the view for scrolling by (\a{dx},\a{dy}) pixels by moving the dirty regions in the
+ opposite direction. You only need to call this function if you are implementing a scrolling
+ viewport in your view subclass.
- If you implement scrollContentsBy() in a subclass of QAbstractItemView, call this function
- before you call QWidget::scroll() on the viewport. Alternatively, just call update().
+ If you implement scrollContentsBy() in a subclass of QAbstractItemView, call this function
+ before you call QWidget::scroll() on the viewport. Alternatively, just call update().
- \sa scrollContentsBy(), dirtyRegionOffset(), setDirtyRegion()
+ \sa scrollContentsBy(), dirtyRegionOffset(), setDirtyRegion()
*/
void QAbstractItemView::scrollDirtyRegion(int dx, int dy)
{
@@ -3350,13 +3362,13 @@ void QAbstractItemView::scrollDirtyRegion(int dx, int dy)
}
/*!
- Returns the offset of the dirty regions in the view.
+ Returns the offset of the dirty regions in the view.
- If you use scrollDirtyRegion() and implement a paintEvent() in a subclass of
- QAbstractItemView, you should translate the area given by the paint event with
- the offset returned from this function.
+ If you use scrollDirtyRegion() and implement a paintEvent() in a subclass of
+ QAbstractItemView, you should translate the area given by the paint event with
+ the offset returned from this function.
- \sa scrollDirtyRegion(), setDirtyRegion()
+ \sa scrollDirtyRegion(), setDirtyRegion()
*/
QPoint QAbstractItemView::dirtyRegionOffset() const
{
@@ -3369,11 +3381,7 @@ QPoint QAbstractItemView::dirtyRegionOffset() const
*/
void QAbstractItemView::startAutoScroll()
{
- Q_D(QAbstractItemView);
- // ### it would be nice to make this into a style hint one day
- int scrollInterval = (verticalScrollMode() == QAbstractItemView::ScrollPerItem) ? 150 : 50;
- d->autoScrollTimer.start(scrollInterval, this);
- d->autoScrollCount = 0;
+ d_func()->startAutoScroll();
}
/*!
@@ -3381,9 +3389,7 @@ void QAbstractItemView::startAutoScroll()
*/
void QAbstractItemView::stopAutoScroll()
{
- Q_D(QAbstractItemView);
- d->autoScrollTimer.stop();
- d->autoScrollCount = 0;
+ d_func()->stopAutoScroll();
}
/*!
@@ -3528,7 +3534,7 @@ QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::extendedSelectionC
const bool shiftKeyPressed = modifiers & Qt::ShiftModifier;
const bool controlKeyPressed = modifiers & Qt::ControlModifier;
if (((index == pressedIndex && selectionModel->isSelected(index))
- || !index.isValid()) && state != QAbstractItemView::DragSelectingState
+ || !index.isValid()) && state != QAbstractItemView::DragSelectingState
&& !shiftKeyPressed && !controlKeyPressed && !rightButtonPressed)
return QItemSelectionModel::ClearAndSelect|selectionBehaviorFlags();
return QItemSelectionModel::NoUpdate;
@@ -3607,8 +3613,9 @@ QAbstractItemViewPrivate::contiguousSelectionCommand(const QModelIndex &index,
}
}
-void QAbstractItemViewPrivate::_q_fetchMore()
+void QAbstractItemViewPrivate::fetchMore()
{
+ fetchMoreTimer.stop();
if (!model->canFetchMore(root))
return;
int last = model->rowCount(root) - 1;
@@ -3759,7 +3766,7 @@ void QAbstractItemViewPrivate::updateEditorData(const QModelIndex &tl, const QMo
but the behavior is view dependant (table just clears the selected indexes for example).
Either remove the selected rows or clear them
- */
+*/
void QAbstractItemViewPrivate::clearOrRemove()
{
#ifndef QT_NO_DRAGANDDROP
@@ -3795,11 +3802,11 @@ void QAbstractItemViewPrivate::clearOrRemove()
When persistent aeditor gets/loses focus, we need to check
and setcorrectly the current index.
- */
+*/
void QAbstractItemViewPrivate::checkPersistentEditorFocus()
{
Q_Q(QAbstractItemView);
- if (QWidget *widget = qApp->focusWidget()) {
+ if (QWidget *widget = QApplication::focusWidget()) {
if (persistent.contains(widget)) {
//a persistent editor has gained the focus
QModelIndex index = indexForEditor(widget);
@@ -3881,30 +3888,48 @@ bool QAbstractItemViewPrivate::openEditor(const QModelIndex &index, QEvent *even
return true;
}
-QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes, QRect *r) const
+/*
+ \internal
+
+ returns the pair QRect/QModelIndex that should be painted on the viewports's rect
+*/
+
+QItemViewPaintPairs QAbstractItemViewPrivate::draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const
{
+ Q_ASSERT(r);
Q_Q(const QAbstractItemView);
- QRect rect = q->visualRect(indexes.at(0));
- QList<QRect> rects;
+ QRect &rect = *r;
+ const QRect viewportRect = viewport->rect();
+ QItemViewPaintPairs ret;
for (int i = 0; i < indexes.count(); ++i) {
- rects.append(q->visualRect(indexes.at(i)));
- rect |= rects.at(i);
+ const QModelIndex &index = indexes.at(i);
+ const QRect current = q->visualRect(index);
+ if (current.intersects(viewportRect)) {
+ ret += qMakePair(current, index);
+ rect |= current;
+ }
}
- rect = rect.intersected(viewport->rect());
- if (rect.width() <= 0 || rect.height() <= 0)
+ rect &= viewportRect;
+ return ret;
+}
+
+QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes, QRect *r) const
+{
+ Q_ASSERT(r);
+ QItemViewPaintPairs paintPairs = draggablePaintPairs(indexes, r);
+ if (paintPairs.isEmpty())
return QPixmap();
- QImage image(rect.size(), QImage::Format_ARGB32_Premultiplied);
- image.fill(0);
- QPainter painter(&image);
+ QPixmap pixmap(r->size());
+ pixmap.fill(Qt::transparent);
+ QPainter painter(&pixmap);
QStyleOptionViewItemV4 option = viewOptionsV4();
option.state |= QStyle::State_Selected;
- for (int j = 0; j < indexes.count(); ++j) {
- option.rect = QRect(rects.at(j).topLeft() - rect.topLeft(), rects.at(j).size());
- delegateForIndex(indexes.at(j))->paint(&painter, option, indexes.at(j));
+ for (int j = 0; j < paintPairs.count(); ++j) {
+ option.rect = paintPairs.at(j).first.translated(-r->topLeft());
+ const QModelIndex &current = paintPairs.at(j).second;
+ delegateForIndex(current)->paint(&painter, option, current);
}
- painter.end();
- if (r) *r = rect;
- return QPixmap::fromImage(image);
+ return pixmap;
}
void QAbstractItemViewPrivate::selectAll(QItemSelectionModel::SelectionFlags command)
diff --git a/src/gui/itemviews/qabstractitemview.h b/src/gui/itemviews/qabstractitemview.h
index 0495d54..36c19e5 100644
--- a/src/gui/itemviews/qabstractitemview.h
+++ b/src/gui/itemviews/qabstractitemview.h
@@ -353,7 +353,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex&, int, int))
Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed())
Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged())
- Q_PRIVATE_SLOT(d_func(), void _q_fetchMore())
friend class QTreeViewPrivate; // needed to compile with MSVC
friend class QAccessibleItemRow;
diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h
index 7b28556..4517941 100644
--- a/src/gui/itemviews/qabstractitemview_p.h
+++ b/src/gui/itemviews/qabstractitemview_p.h
@@ -61,11 +61,10 @@
#include "QtGui/qmime.h"
#include "QtGui/qpainter.h"
#include "QtCore/qpair.h"
-#include "QtCore/qtimer.h"
-#include "QtCore/qtimeline.h"
#include "QtGui/qregion.h"
#include "QtCore/qdebug.h"
#include "QtGui/qpainter.h"
+#include "QtCore/qbasictimer.h"
#ifndef QT_NO_ITEMVIEWS
@@ -87,6 +86,9 @@ struct QEditorInfo
};
+typedef QPair<QRect, QModelIndex> QItemViewPaintPair;
+typedef QList<QItemViewPaintPair> QItemViewPaintPairs;
+
class QEmptyModel : public QAbstractItemModel
{
public:
@@ -99,7 +101,7 @@ public:
QVariant data(const QModelIndex &, int) const { return QVariant(); }
};
-class Q_GUI_EXPORT QAbstractItemViewPrivate : public QAbstractScrollAreaPrivate
+class Q_AUTOTEST_EXPORT QAbstractItemViewPrivate : public QAbstractScrollAreaPrivate
{
Q_DECLARE_PUBLIC(QAbstractItemView)
@@ -109,13 +111,14 @@ public:
void init();
- void _q_rowsRemoved(const QModelIndex &parent, int start, int end);
- void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
- void _q_columnsRemoved(const QModelIndex &parent, int start, int end);
- void _q_columnsInserted(const QModelIndex &parent, int start, int end);
- void _q_modelDestroyed();
- void _q_layoutChanged();
- void _q_fetchMore();
+ virtual void _q_rowsRemoved(const QModelIndex &parent, int start, int end);
+ virtual void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ virtual void _q_columnsRemoved(const QModelIndex &parent, int start, int end);
+ virtual void _q_columnsInserted(const QModelIndex &parent, int start, int end);
+ virtual void _q_modelDestroyed();
+ virtual void _q_layoutChanged();
+
+ void fetchMore();
bool shouldEdit(QAbstractItemView::EditTrigger trigger, const QModelIndex &index) const;
bool shouldForwardEvent(QAbstractItemView::EditTrigger trigger, const QEvent *event) const;
@@ -123,6 +126,15 @@ public:
void doDelayedItemsLayout(int delay = 0);
void interruptDelayedItemsLayout() const;
+ void startAutoScroll()
+ { // ### it would be nice to make this into a style hint one day
+ int scrollInterval = (verticalScrollMode == QAbstractItemView::ScrollPerItem) ? 150 : 50;
+ autoScrollTimer.start(scrollInterval, q_func());
+ autoScrollCount = 0;
+ }
+ void stopAutoScroll() { autoScrollTimer.stop(); autoScrollCount = 0;}
+
+
bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index);
bool droppingOnItself(QDropEvent *event, const QModelIndex &index);
@@ -139,6 +151,9 @@ public:
const QEvent *event) const;
virtual void selectAll(QItemSelectionModel::SelectionFlags command);
+ void checkMouseMove(const QPersistentModelIndex &index);
+ inline void checkMouseMove(const QPoint &pos) { checkMouseMove(q_func()->indexAt(pos)); }
+
inline QItemSelectionModel::SelectionFlags selectionBehaviorFlags() const
{
switch (selectionBehavior) {
@@ -173,7 +188,9 @@ public:
q_func()->style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &opt, painter, q_func());
}
}
+
#endif
+ virtual QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const;
inline void releaseEditor(QWidget *editor) const {
if (editor) {
@@ -218,7 +235,7 @@ public:
void clearOrRemove();
void checkPersistentEditorFocus();
- QPixmap renderToPixmap(const QModelIndexList &indexes, QRect *r = 0) const;
+ QPixmap renderToPixmap(const QModelIndexList &indexes, QRect *r) const;
inline QPoint offset() const {
const Q_Q(QAbstractItemView);
@@ -304,7 +321,7 @@ public:
*/
inline bool isPersistent(const QModelIndex &index) const
{
- return static_cast<QAbstractItemModelPrivate *>(model->d_ptr)->persistent.indexes.contains(index);
+ return static_cast<QAbstractItemModelPrivate *>(model->d_ptr.data())->persistent.indexes.contains(index);
}
QModelIndexList selectedDraggableIndexes() const;
@@ -372,7 +389,6 @@ public:
QBasicTimer updateTimer;
QBasicTimer delayedEditing;
QBasicTimer delayedAutoScroll; //used when an item is clicked
- QTimeLine timeline;
QAbstractItemView::ScrollMode verticalScrollMode;
QAbstractItemView::ScrollMode horizontalScrollMode;
@@ -384,6 +400,7 @@ public:
private:
mutable QBasicTimer delayedLayout;
+ mutable QBasicTimer fetchMoreTimer;
};
QT_BEGIN_INCLUDE_NAMESPACE
diff --git a/src/gui/itemviews/qcolumnview.cpp b/src/gui/itemviews/qcolumnview.cpp
index ac31ecc..efd4879 100644
--- a/src/gui/itemviews/qcolumnview.cpp
+++ b/src/gui/itemviews/qcolumnview.cpp
@@ -52,7 +52,6 @@
#include <qscrollbar.h>
#include <qpainter.h>
#include <qdebug.h>
-#include <qpainterpath.h>
QT_BEGIN_NAMESPACE
@@ -64,7 +63,7 @@ QT_BEGIN_NAMESPACE
\brief The QColumnView class provides a model/view implementation of a column view.
\ingroup model-view
\ingroup advanced
- \mainclass
+
QColumnView displays a model in a number of QListViews, one for each
hierarchy in the tree. This is sometimes referred to as a cascading list.
@@ -108,9 +107,13 @@ void QColumnViewPrivate::initialize()
{
Q_Q(QColumnView);
q->setTextElideMode(Qt::ElideMiddle);
- q->connect(&currentAnimation, SIGNAL(frameChanged(int)),
- q->horizontalScrollBar(), SLOT(setValue(int)));
- q->connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
+#ifndef QT_NO_ANIMATION
+ QObject::connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
+ currentAnimation.setDuration(ANIMATION_DURATION_MSEC);
+ currentAnimation.setTargetObject(hbar);
+ currentAnimation.setPropertyName("value");
+ currentAnimation.setEasingCurve(QEasingCurve::InOutQuad);
+#endif //QT_NO_ANIMATION
delete itemDelegate;
q->setItemDelegate(new QColumnViewDelegate(q));
}
@@ -260,10 +263,12 @@ void QColumnView::scrollTo(const QModelIndex &index, ScrollHint hint)
if (!index.isValid() || d->columns.isEmpty())
return;
- if (d->currentAnimation.state() == QTimeLine::Running)
+#ifndef QT_NO_ANIMATION
+ if (d->currentAnimation.state() == QPropertyAnimation::Running)
return;
d->currentAnimation.stop();
+#endif //QT_NO_ANIMATION
// Fill up what is needed to get to index
d->closeColumns(index, true);
@@ -326,22 +331,12 @@ void QColumnView::scrollTo(const QModelIndex &index, ScrollHint hint)
}
}
- //horizontalScrollBar()->setValue(newScrollbarValue);
- //d->_q_changeCurrentColumn();
- //return;
- // or do the following currentAnimation
-
- int oldValue = horizontalScrollBar()->value();
-
- if (oldValue < newScrollbarValue) {
- d->currentAnimation.setFrameRange(oldValue, newScrollbarValue);
- d->currentAnimation.setDirection(QTimeLine::Forward);
- d->currentAnimation.setCurrentTime(0);
- } else {
- d->currentAnimation.setFrameRange(newScrollbarValue, oldValue);
- d->currentAnimation.setDirection(QTimeLine::Backward);
- }
+#ifndef QT_NO_ANIMATION
+ d->currentAnimation.setEndValue(newScrollbarValue);
d->currentAnimation.start();
+#else
+ horizontalScrollBar()->setValue(newScrollbarValue);
+#endif //QT_NO_ANIMATION
}
/*!
@@ -410,8 +405,10 @@ void QColumnView::resizeEvent(QResizeEvent *event)
void QColumnViewPrivate::updateScrollbars()
{
Q_Q(QColumnView);
- if (currentAnimation.state() == QTimeLine::Running)
+#ifndef QT_NO_ANIMATION
+ if (currentAnimation.state() == QPropertyAnimation::Running)
return;
+#endif //QT_NO_ANIMATION
// find the total horizontal length of the laid out columns
int horizontalLength = 0;
@@ -421,23 +418,23 @@ void QColumnViewPrivate::updateScrollbars()
horizontalLength = (columns.first()->x() + columns.first()->width()) - columns.last()->x();
}
- QSize viewportSize = q->viewport()->size();
- if (horizontalLength < viewportSize.width() && q->horizontalScrollBar()->value() == 0) {
- q->horizontalScrollBar()->setRange(0, 0);
+ QSize viewportSize = viewport->size();
+ if (horizontalLength < viewportSize.width() && hbar->value() == 0) {
+ hbar->setRange(0, 0);
} else {
int visibleLength = qMin(horizontalLength + q->horizontalOffset(), viewportSize.width());
int hiddenLength = horizontalLength - visibleLength;
- if (hiddenLength != q->horizontalScrollBar()->maximum())
- q->horizontalScrollBar()->setRange(0, hiddenLength);
+ if (hiddenLength != hbar->maximum())
+ hbar->setRange(0, hiddenLength);
}
if (!columns.isEmpty()) {
int pageStepSize = columns.at(0)->width();
- if (pageStepSize != q->horizontalScrollBar()->pageStep())
- q->horizontalScrollBar()->setPageStep(pageStepSize);
+ if (pageStepSize != hbar->pageStep())
+ hbar->setPageStep(pageStepSize);
}
- bool visible = (q->horizontalScrollBar()->maximum() > 0);
- if (visible != q->horizontalScrollBar()->isVisible())
- q->horizontalScrollBar()->setVisible(visible);
+ bool visible = (hbar->maximum() > 0);
+ if (visible != hbar->isVisible())
+ hbar->setVisible(visible);
}
/*!
@@ -696,7 +693,7 @@ QAbstractItemView *QColumnViewPrivate::createColumn(const QModelIndex &index, bo
q, SIGNAL(pressed(const QModelIndex &)));
view->setFocusPolicy(Qt::NoFocus);
- view->setParent(q->viewport());
+ view->setParent(viewport);
Q_ASSERT(view);
// Setup corner grip
@@ -707,13 +704,13 @@ QAbstractItemView *QColumnViewPrivate::createColumn(const QModelIndex &index, bo
}
if (columnSizes.count() > columns.count()) {
- view->setGeometry(0, 0, columnSizes.at(columns.count()), q->viewport()->height());
+ view->setGeometry(0, 0, columnSizes.at(columns.count()), viewport->height());
} else {
int initialWidth = view->sizeHint().width();
if (q->isRightToLeft())
- view->setGeometry(q->viewport()->width() - initialWidth, 0, initialWidth, q->viewport()->height());
+ view->setGeometry(viewport->width() - initialWidth, 0, initialWidth, viewport->height());
else
- view->setGeometry(0, 0, initialWidth, q->viewport()->height());
+ view->setGeometry(0, 0, initialWidth, viewport->height());
columnSizes.resize(qMax(columnSizes.count(), columns.count() + 1));
columnSizes[columns.count()] = initialWidth;
}
@@ -896,6 +893,15 @@ QList<int> QColumnView::columnWidths() const
/*!
\reimp
*/
+void QColumnView::rowsInserted(const QModelIndex &parent, int start, int end)
+{
+ QAbstractItemView::rowsInserted(parent, start, end);
+ d_func()->checkColumnCreation(parent);
+}
+
+/*!
+ \reimp
+*/
void QColumnView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
{
Q_D(QColumnView);
@@ -1036,7 +1042,6 @@ QColumnViewPrivate::QColumnViewPrivate()
: QAbstractItemViewPrivate()
,showResizeGrips(true)
,offset(0)
-,currentAnimation(ANIMATION_DURATION_MSEC)
,previewWidget(0)
,previewColumn(0)
{
@@ -1048,6 +1053,41 @@ QColumnViewPrivate::~QColumnViewPrivate()
/*!
\internal
+
+ */
+void QColumnViewPrivate::_q_columnsInserted(const QModelIndex &parent, int start, int end)
+{
+ QAbstractItemViewPrivate::_q_columnsInserted(parent, start, end);
+ checkColumnCreation(parent);
+}
+
+/*!
+ \internal
+
+ Makes sure we create a corresponding column as a result of changing the model.
+
+ */
+void QColumnViewPrivate::checkColumnCreation(const QModelIndex &parent)
+{
+ if (parent == q_func()->currentIndex() && model->hasChildren(parent)) {
+ //the parent has children and is the current
+ //let's try to find out if there is already a mapping that is good
+ for (int i = 0; i < columns.count(); ++i) {
+ QAbstractItemView *view = columns.at(i);
+ if (view->rootIndex() == parent) {
+ if (view == previewColumn) {
+ //let's recreate the parent
+ closeColumns(parent, false);
+ createColumn(parent, true /*show*/);
+ }
+ break;
+ }
+ }
+ }
+}
+
+/*!
+ \internal
Place all of the columns where they belong inside of the viewport, resize as necessary.
*/
void QColumnViewPrivate::doLayout()
@@ -1056,11 +1096,11 @@ void QColumnViewPrivate::doLayout()
if (!model || columns.isEmpty())
return;
- int viewportHeight = q->viewport()->height();
+ int viewportHeight = viewport->height();
int x = columns.at(0)->x();
if (q->isRightToLeft()) {
- x = q->viewport()->width() + q->horizontalOffset();
+ x = viewport->width() + q->horizontalOffset();
for (int i = 0; i < columns.size(); ++i) {
QAbstractItemView *view = columns.at(i);
x -= view->width();
@@ -1116,7 +1156,7 @@ void QColumnViewDelegate::paint(QPainter *painter,
// Draw >
if (index.model()->hasChildren(index)) {
const QWidget *view = opt.widget;
- QStyle *style = view ? view->style() : qApp->style();
+ QStyle *style = view ? view->style() : QApplication::style();
style->drawPrimitive(QStyle::PE_IndicatorColumnViewArrow, &opt, painter, view);
}
}
diff --git a/src/gui/itemviews/qcolumnview.h b/src/gui/itemviews/qcolumnview.h
index c5cfb3f..0d7880f 100644
--- a/src/gui/itemviews/qcolumnview.h
+++ b/src/gui/itemviews/qcolumnview.h
@@ -97,16 +97,14 @@ protected:
QRegion visualRegionForSelection(const QItemSelection &selection) const;
int horizontalOffset() const;
int verticalOffset() const;
- void scrollContentsBy(int dx, int dy);
+ void rowsInserted(const QModelIndex &parent, int start, int end);
+ void currentChanged(const QModelIndex &current, const QModelIndex &previous);
// QColumnView functions
+ void scrollContentsBy(int dx, int dy);
virtual QAbstractItemView* createColumn(const QModelIndex &rootIndex);
void initializeColumn(QAbstractItemView *column) const;
-protected Q_SLOTS:
- // QAbstractItemView overloads
- void currentChanged(const QModelIndex &current, const QModelIndex &previous);
-
private:
Q_DECLARE_PRIVATE(QColumnView)
Q_DISABLE_COPY(QColumnView)
diff --git a/src/gui/itemviews/qcolumnview_p.h b/src/gui/itemviews/qcolumnview_p.h
index 2d7c4f9..97def07 100644
--- a/src/gui/itemviews/qcolumnview_p.h
+++ b/src/gui/itemviews/qcolumnview_p.h
@@ -55,12 +55,12 @@
#include "qcolumnview.h"
-#ifndef QT_NO_QCOlUMNVIEW
+#ifndef QT_NO_QCOLUMNVIEW
#include <private/qabstractitemview_p.h>
#include <QtCore/qabstractitemmodel.h>
-#include <QtCore/qtimeline.h>
+#include <QtCore/qpropertyanimation.h>
#include <QtGui/qabstractitemdelegate.h>
#include <QtGui/qabstractitemview.h>
#include <QtGui/qitemdelegate.h>
@@ -148,16 +148,21 @@ public:
void closeColumns(const QModelIndex &parent = QModelIndex(), bool build = false);
void doLayout();
void setPreviewWidget(QWidget *widget);
+ void checkColumnCreation(const QModelIndex &parent);
+
void _q_gripMoved(int offset);
void _q_changeCurrentColumn();
void _q_clicked(const QModelIndex &index);
+ void _q_columnsInserted(const QModelIndex &parent, int start, int end);
QList<QAbstractItemView*> columns;
QVector<int> columnSizes; // used during init and corner moving
bool showResizeGrips;
int offset;
- QTimeLine currentAnimation;
+#ifndef QT_NO_ANIMATION
+ QPropertyAnimation currentAnimation;
+#endif
QWidget *previewWidget;
QAbstractItemView *previewColumn;
};
diff --git a/src/gui/itemviews/qdirmodel.cpp b/src/gui/itemviews/qdirmodel.cpp
index 01526af..a4dbf52 100644
--- a/src/gui/itemviews/qdirmodel.cpp
+++ b/src/gui/itemviews/qdirmodel.cpp
@@ -44,6 +44,7 @@
#ifndef QT_NO_DIRMODEL
#include <qstack.h>
#include <qfile.h>
+#include <qfilesystemmodel.h>
#include <qurl.h>
#include <qmime.h>
#include <qpair.h>
@@ -871,8 +872,10 @@ QModelIndex QDirModel::index(const QString &path, int column) const
return QModelIndex();
QString absolutePath = QDir(path).absolutePath();
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
absolutePath = absolutePath.toLower();
+#endif
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
// On Windows, "filename......." and "filename" are equivalent
if (absolutePath.endsWith(QLatin1Char('.'))) {
int i;
@@ -912,7 +915,10 @@ QModelIndex QDirModel::index(const QString &path, int column) const
pathElements.pop_front();
if (childAppended)
emit const_cast<QDirModel*>(this)->layoutChanged();
- } else if (pathElements.at(0).endsWith(QLatin1Char(':'))) {
+ } else
+#endif
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
+ if (pathElements.at(0).endsWith(QLatin1Char(':'))) {
pathElements[0] += QLatin1Char('/');
}
#else
@@ -934,11 +940,9 @@ QModelIndex QDirModel::index(const QString &path, int column) const
for (int j = parent->children.count() - 1; j >= 0; --j) {
const QFileInfo& fi = parent->children.at(j).info;
QString childFileName;
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
childFileName = idx.isValid() ? fi.fileName() : fi.absoluteFilePath();
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
childFileName = childFileName.toLower();
-#else
- childFileName = idx.isValid() ? fi.fileName() : fi.absoluteFilePath();
#endif
if (childFileName == element) {
if (i == pathElements.count() - 1)
@@ -955,7 +959,7 @@ QModelIndex QDirModel::index(const QString &path, int column) const
if (parent->info.isRoot())
newPath = parent->info.absoluteFilePath() + element;
else
- newPath= parent->info.absoluteFilePath() + QLatin1Char('/') + element;
+ newPath = parent->info.absoluteFilePath() + QLatin1Char('/') + element;
#else
QString newPath = parent->info.absoluteFilePath() + QLatin1Char('/') + element;
#endif
@@ -1307,6 +1311,8 @@ QString QDirModelPrivate::name(const QModelIndex &index) const
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
if (name.startsWith(QLatin1Char('/'))) // UNC host
return info.fileName();
+#endif
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
if (name.endsWith(QLatin1Char('/')))
name.chop(1);
#endif
@@ -1338,14 +1344,14 @@ QString QDirModelPrivate::size(const QModelIndex &index) const
const quint64 tb = 1024 * gb;
quint64 bytes = n->info.size();
if (bytes >= tb)
- return QLocale().toString(bytes / tb) + QString::fromLatin1(" TB");
+ return QFileSystemModel::tr("%1 TB").arg(QLocale().toString(qreal(bytes) / tb, 'f', 3));
if (bytes >= gb)
- return QLocale().toString(bytes / gb) + QString::fromLatin1(" GB");
+ return QFileSystemModel::tr("%1 GB").arg(QLocale().toString(qreal(bytes) / gb, 'f', 2));
if (bytes >= mb)
- return QLocale().toString(bytes / mb) + QString::fromLatin1(" MB");
+ return QFileSystemModel::tr("%1 MB").arg(QLocale().toString(qreal(bytes) / mb, 'f', 1));
if (bytes >= kb)
- return QLocale().toString(bytes / kb) + QString::fromLatin1(" KB");
- return QLocale().toString(bytes) + QString::fromLatin1(" bytes");
+ return QFileSystemModel::tr("%1 KB").arg(QLocale().toString(bytes / kb));
+ return QFileSystemModel::tr("%1 bytes").arg(QLocale().toString(bytes));
}
QString QDirModelPrivate::type(const QModelIndex &index) const
diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp
index 035055c..b1177db 100644
--- a/src/gui/itemviews/qfileiconprovider.cpp
+++ b/src/gui/itemviews/qfileiconprovider.cpp
@@ -48,15 +48,14 @@
#include <qpixmapcache.h>
#if defined(Q_WS_WIN)
#define _WIN32_IE 0x0500
+#include <qt_windows.h>
+#include <commctrl.h>
#include <objbase.h>
#include <private/qpixmapdata_p.h>
#elif defined(Q_WS_MAC)
-#include <private/qt_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
#endif
#include <private/qfunctions_p.h>
-#ifdef Q_OS_WINCE
-#include <Commctrl.h>
-#endif
#ifndef SHGFI_ADDOVERLAYS
#define SHGFI_ADDOVERLAYS 0x000000020
@@ -180,7 +179,6 @@ QFileIconProvider::QFileIconProvider()
QFileIconProvider::~QFileIconProvider()
{
- delete d_ptr;
}
/*!
@@ -215,8 +213,7 @@ QIcon QFileIconProvider::icon(IconType type) const
QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
{
QIcon retIcon;
- QString fileExtension = fileInfo.suffix().toUpper();
- fileExtension.prepend( QLatin1String(".") );
+ const QString fileExtension = QLatin1Char('.') + fileInfo.suffix().toUpper();
QString key;
if (fileInfo.isFile() && !fileInfo.isExecutable() && !fileInfo.isSymLink())
@@ -244,10 +241,10 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
//Get the small icon
#ifndef Q_OS_WINCE
- val = SHGetFileInfo((const WCHAR *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
+ val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS);
#else
- val = SHGetFileInfo((const WCHAR *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
+ val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_SYSICONINDEX);
#endif
if (val) {
@@ -283,10 +280,10 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
//Get the big icon
#ifndef Q_OS_WINCE
- val = SHGetFileInfo((const WCHAR *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
+ val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_LARGEICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS);
#else
- val = SHGetFileInfo((const WCHAR *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
+ val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
sizeof(SHFILEINFO), SHGFI_LARGEICON|SHGFI_SYSICONINDEX);
#endif
if (val) {
@@ -353,10 +350,11 @@ QIcon QFileIconProviderPrivate::getMacIcon(const QFileInfo &fi) const
return retIcon;
IconRef iconRef;
SInt16 iconLabel;
- status = GetIconRefFromFileInfo(&macRef, macName.length, macName.unicode, kIconServicesCatalogInfoMask, &info, kIconServicesNormalUsageFlag, &iconRef, &iconLabel);
+ status = GetIconRefFromFileInfo(&macRef, macName.length, macName.unicode,
+ kIconServicesCatalogInfoMask, &info, kIconServicesNormalUsageFlag,
+ &iconRef, &iconLabel);
if (status != noErr)
return retIcon;
- extern void qt_mac_constructQIconFromIconRef(const IconRef, const IconRef, QIcon*, QStyle::StandardPixmap = QStyle::SP_CustomBase); // qmacstyle_mac.cpp
qt_mac_constructQIconFromIconRef(iconRef, 0, &retIcon);
ReleaseIconRef(iconRef);
@@ -391,11 +389,9 @@ QIcon QFileIconProvider::icon(const QFileInfo &info) const
return icon;
#endif
if (info.isRoot())
-#if defined (Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined (Q_WS_WIN) && !defined(Q_WS_WINCE)
{
- uint type = DRIVE_UNKNOWN;
- QT_WA({ type = GetDriveTypeW((wchar_t *)info.absoluteFilePath().utf16()); },
- { type = GetDriveTypeA(info.absoluteFilePath().toLocal8Bit()); });
+ UINT type = GetDriveType((wchar_t *)info.absoluteFilePath().utf16());
switch (type) {
case DRIVE_REMOVABLE:
@@ -451,26 +447,22 @@ QString QFileIconProvider::type(const QFileInfo &info) const
}
if (info.isDir())
- return QApplication::translate("QFileDialog",
#ifdef Q_WS_WIN
- "File Folder", "Match Windows Explorer"
+ return QApplication::translate("QFileDialog", "File Folder", "Match Windows Explorer");
#else
- "Folder", "All other platforms"
+ return QApplication::translate("QFileDialog", "Folder", "All other platforms");
#endif
- );
// Windows - "File Folder"
// OS X - "Folder"
// Konqueror - "Folder"
// Nautilus - "folder"
if (info.isSymLink())
- return QApplication::translate("QFileDialog",
#ifdef Q_OS_MAC
- "Alias", "Mac OS X Finder"
+ return QApplication::translate("QFileDialog", "Alias", "Mac OS X Finder");
#else
- "Shortcut", "All other platforms"
+ return QApplication::translate("QFileDialog", "Shortcut", "All other platforms");
#endif
- );
// OS X - "Alias"
// Windows - "Shortcut"
// Konqueror - "Folder" or "TXT File" i.e. what it is pointing to
diff --git a/src/gui/itemviews/qfileiconprovider.h b/src/gui/itemviews/qfileiconprovider.h
index a5a3891..cf1b34f 100644
--- a/src/gui/itemviews/qfileiconprovider.h
+++ b/src/gui/itemviews/qfileiconprovider.h
@@ -42,8 +42,9 @@
#ifndef QFILEICONPROVIDER_H
#define QFILEICONPROVIDER_H
-#include <QtGui/qicon.h>
#include <QtCore/qfileinfo.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtGui/qicon.h>
QT_BEGIN_HEADER
@@ -67,7 +68,7 @@ public:
private:
Q_DECLARE_PRIVATE(QFileIconProvider)
- QFileIconProviderPrivate *d_ptr;
+ QScopedPointer<QFileIconProviderPrivate> d_ptr;
Q_DISABLE_COPY(QFileIconProvider)
};
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index 3575ccb..a1c3e4e 100644
--- a/src/gui/itemviews/qheaderview.cpp
+++ b/src/gui/itemviews/qheaderview.cpp
@@ -62,9 +62,11 @@
#ifndef QT_NO_DATASTREAM
#include <qdatastream.h>
+#endif
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &out, const QHeaderViewPrivate::SectionSpan &span)
{
span.write(out);
@@ -76,7 +78,7 @@ QDataStream &operator>>(QDataStream &in, QHeaderViewPrivate::SectionSpan &span)
span.read(in);
return in;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
@@ -86,7 +88,7 @@ QDataStream &operator>>(QDataStream &in, QHeaderViewPrivate::SectionSpan &span)
item views.
\ingroup model-view
- \mainclass
+
A QHeaderView displays the headers used in item views such as the
QTableView and QTreeView classes. It takes the place of Qt3's \c QHeader
@@ -520,31 +522,29 @@ int QHeaderView::length() const
QSize QHeaderView::sizeHint() const
{
Q_D(const QHeaderView);
- if (count() < 1)
- return QSize(0, 0);
if (d->cachedSizeHint.isValid())
return d->cachedSizeHint;
- int width = 0;
- int height = 0;
+ d->cachedSizeHint = QSize(0, 0); //reinitialize the cached size hint
+ const int sectionCount = count();
+
// get size hint for the first n sections
- int c = qMin(count(), 100);
- for (int i = 0; i < c; ++i) {
+ int i = 0;
+ for (int checked = 0; checked < 100 && i < sectionCount; ++i) {
if (isSectionHidden(i))
continue;
+ checked++;
QSize hint = sectionSizeFromContents(i);
- width = qMax(hint.width(), width);
- height = qMax(hint.height(), height);
+ d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint);
}
// get size hint for the last n sections
- c = qMax(count() - 100, c);
- for (int j = count() - 1; j >= c; --j) {
+ i = qMax(i, sectionCount - 100 );
+ for (int j = sectionCount - 1, checked = 0; j >= i && checked < 100; --j) {
if (isSectionHidden(j))
continue;
+ checked++;
QSize hint = sectionSizeFromContents(j);
- width = qMax(hint.width(), width);
- height = qMax(hint.height(), height);
+ d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint);
}
- d->cachedSizeHint = QSize(width, height);
return d->cachedSizeHint;
}
@@ -1151,7 +1151,8 @@ void QHeaderView::setResizeMode(ResizeMode mode)
\overload
Sets the constraints on how the section specified by \a logicalIndex in
- the header can be resized to those described by the given \a mode.
+ the header can be resized to those described by the given \a mode. The logical
+ index should exist at the time this function is called.
\note This setting will be ignored for the last section if the stretchLastSection
property is set to true. This is the default for the horizontal headers provided
@@ -1194,8 +1195,9 @@ QHeaderView::ResizeMode QHeaderView::resizeMode(int logicalIndex) const
{
Q_D(const QHeaderView);
int visual = visualIndex(logicalIndex);
- Q_ASSERT(visual != -1);
- return d->visualIndexResizeMode(visual);
+ if (visual == -1)
+ return Fixed; //the default value
+ return d->headerSectionResizeMode(visual);
}
/*!
@@ -1234,7 +1236,7 @@ void QHeaderView::setSortIndicatorShown(bool show)
if (sortIndicatorSection() < 0 || sortIndicatorSection() > count())
return;
- if (d->visualIndexResizeMode(sortIndicatorSection()) == ResizeToContents)
+ if (d->headerSectionResizeMode(sortIndicatorSection()) == ResizeToContents)
resizeSections();
d->viewport->update();
@@ -1535,7 +1537,7 @@ bool QHeaderView::restoreState(const QByteArray &state)
}
return false;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
\reimp
@@ -1969,20 +1971,19 @@ void QHeaderView::currentChanged(const QModelIndex &current, const QModelIndex &
if (d->orientation == Qt::Horizontal && current.column() != old.column()) {
if (old.isValid() && old.parent() == d->root)
- d->setDirtyRegion(QRect(sectionViewportPosition(old.column()), 0,
+ d->viewport->update(QRect(sectionViewportPosition(old.column()), 0,
sectionSize(old.column()), d->viewport->height()));
if (current.isValid() && current.parent() == d->root)
- d->setDirtyRegion(QRect(sectionViewportPosition(current.column()), 0,
+ d->viewport->update(QRect(sectionViewportPosition(current.column()), 0,
sectionSize(current.column()), d->viewport->height()));
} else if (d->orientation == Qt::Vertical && current.row() != old.row()) {
if (old.isValid() && old.parent() == d->root)
- d->setDirtyRegion(QRect(0, sectionViewportPosition(old.row()),
+ d->viewport->update(QRect(0, sectionViewportPosition(old.row()),
d->viewport->width(), sectionSize(old.row())));
if (current.isValid() && current.parent() == d->root)
- d->setDirtyRegion(QRect(0, sectionViewportPosition(current.row()),
+ d->viewport->update(QRect(0, sectionViewportPosition(current.row()),
d->viewport->width(), sectionSize(current.row())));
}
- d->updateDirtyRegion();
}
@@ -2538,7 +2539,7 @@ QSize QHeaderView::sectionSizeFromContents(int logicalIndex) const
if (opt.icon.isNull())
opt.icon = qvariant_cast<QPixmap>(variant);
QSize size = style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), this);
- if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex) {
+ if (isSortIndicatorShown()) {
int margin = style()->pixelMetric(QStyle::PM_HeaderMargin, &opt, this);
if (d->orientation == Qt::Horizontal)
size.rwidth() += size.height() + margin;
@@ -2615,7 +2616,7 @@ void QHeaderView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bot
int first = orientation() == Qt::Horizontal ? topLeft.column() : topLeft.row();
int last = orientation() == Qt::Horizontal ? bottomRight.column() : bottomRight.row();
for (int i = first; i <= last && !resizeRequired; ++i)
- resizeRequired = (resizeRequired && resizeMode(i));
+ resizeRequired = (resizeMode(i) == ResizeToContents);
if (resizeRequired)
d->doDelayedResizeSections();
}
@@ -2821,16 +2822,12 @@ void QHeaderViewPrivate::setupSectionIndicator(int section, int position)
sectionIndicator = new QLabel(viewport);
}
- int x, y, w, h;
+ int w, h;
int p = q->sectionViewportPosition(section);
if (orientation == Qt::Horizontal) {
- x = p;
- y = 0;
w = q->sectionSize(section);
h = viewport->height();
} else {
- x = 0;
- y = p;
w = viewport->width();
h = q->sectionSize(section);
}
@@ -2936,22 +2933,25 @@ int QHeaderViewPrivate::lastVisibleVisualIndex() const
void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool useGlobalMode)
{
Q_Q(QHeaderView);
+ //stop the timer in case it is delayed
+ delayedResize.stop();
executePostedLayout();
if (sectionCount == 0)
return;
+
+ if (resizeRecursionBlock)
+ return;
+ resizeRecursionBlock = true;
+
invalidateCachedSizeHint();
+ const int lastVisibleSection = lastVisibleVisualIndex();
+
// find stretchLastSection if we have it
int stretchSection = -1;
- if (stretchLastSection && !useGlobalMode) {
- for (int i = sectionCount - 1; i >= 0; --i) {
- if (!isVisualIndexHidden(i)) {
- stretchSection = i;
- break;
- }
- }
- }
+ if (stretchLastSection && !useGlobalMode)
+ stretchSection = lastVisibleVisualIndex();
// count up the number of strected sections and how much space left for them
int lengthToStrech = (orientation == Qt::Horizontal ? viewport->width() : viewport->height());
@@ -2965,7 +2965,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
if (useGlobalMode && (i != stretchSection))
resizeMode = globalMode;
else
- resizeMode = (i == stretchSection ? QHeaderView::Stretch : visualIndexResizeMode(i));
+ resizeMode = (i == stretchSection ? QHeaderView::Stretch : headerSectionResizeMode(i));
if (resizeMode == QHeaderView::Stretch) {
++numberOfStretchedSections;
@@ -2997,7 +2997,6 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
int spanStartSection = 0;
int previousSectionLength = 0;
- const int lastVisibleSection = lastVisibleVisualIndex();
QHeaderView::ResizeMode previousSectionResizeMode = QHeaderView::Interactive;
@@ -3016,7 +3015,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
else
resizeMode = (i == stretchSection
? QHeaderView::Stretch
- : visualIndexResizeMode(i));
+ : newSectionResizeMode);
if (resizeMode == QHeaderView::Stretch && stretchSectionLength != -1) {
if (i == lastVisibleSection)
newSectionLength = qMax(stretchSectionLength, lastSectionSize);
@@ -3053,7 +3052,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
(sectionCount - spanStartSection) * previousSectionLength,
previousSectionResizeMode);
//Q_ASSERT(headerLength() == length);
-
+ resizeRecursionBlock = false;
viewport->update();
}
@@ -3470,11 +3469,10 @@ void QHeaderViewPrivate::setGlobalHeaderResizeMode(QHeaderView::ResizeMode mode)
int QHeaderViewPrivate::viewSectionSizeHint(int logical) const
{
- Q_Q(const QHeaderView);
- if (QAbstractItemView *parent = qobject_cast<QAbstractItemView*>(q->parent())) {
+ if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(parent)) {
return (orientation == Qt::Horizontal
- ? parent->sizeHintForColumn(logical)
- : parent->sizeHintForRow(logical));
+ ? view->sizeHintForColumn(logical)
+ : view->sizeHintForRow(logical));
}
return 0;
}
@@ -3560,7 +3558,7 @@ bool QHeaderViewPrivate::read(QDataStream &in)
in >> minimumSectionSize;
in >> align;
- defaultAlignment = (Qt::Alignment)align;
+ defaultAlignment = Qt::Alignment(align);
in >> global;
globalResizeMode = (QHeaderView::ResizeMode)global;
@@ -3570,9 +3568,9 @@ bool QHeaderViewPrivate::read(QDataStream &in)
return true;
}
-QT_END_NAMESPACE
+#endif // QT_NO_DATASTREAM
-#endif // QT_NO_DATASTREAEM
+QT_END_NAMESPACE
#endif // QT_NO_ITEMVIEWS
diff --git a/src/gui/itemviews/qheaderview.h b/src/gui/itemviews/qheaderview.h
index e2510ae..ff1c7ef 100644
--- a/src/gui/itemviews/qheaderview.h
+++ b/src/gui/itemviews/qheaderview.h
@@ -221,14 +221,13 @@ protected:
bool isIndexHidden(const QModelIndex &index) const;
QModelIndex moveCursor(CursorAction, Qt::KeyboardModifiers);
- void setSelection(const QRect&, QItemSelectionModel::SelectionFlags);
+ void setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags);
QRegion visualRegionForSelection(const QItemSelection &selection) const;
void initStyleOption(QStyleOptionHeader *option) const;
private:
Q_PRIVATE_SLOT(d_func(), void _q_sectionsRemoved(const QModelIndex &parent, int logicalFirst, int logicalLast))
Q_PRIVATE_SLOT(d_func(), void _q_layoutAboutToBeChanged())
- Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged())
Q_DECLARE_PRIVATE(QHeaderView)
Q_DISABLE_COPY(QHeaderView)
};
diff --git a/src/gui/itemviews/qheaderview_p.h b/src/gui/itemviews/qheaderview_p.h
index 35d1ad3..dc4b3de 100644
--- a/src/gui/itemviews/qheaderview_p.h
+++ b/src/gui/itemviews/qheaderview_p.h
@@ -90,6 +90,7 @@ public:
highlightSelected(false),
stretchLastSection(false),
cascadingResizing(false),
+ resizeRecursionBlock(false),
stretchSections(0),
contentsSections(0),
minimumSectionSize(-1),
@@ -169,10 +170,6 @@ public:
if (!sectionHidden.isEmpty()) sectionHidden.setBit(visual, hidden);
}
- inline QHeaderView::ResizeMode visualIndexResizeMode(int visual) const {
- return headerSectionResizeMode(visual);
- }
-
inline bool hasAutoResizeSections() const {
return stretchSections || stretchLastSection || contentsSections;
}
@@ -210,7 +207,7 @@ public:
}
inline bool sectionIsCascadable(int visual) const {
- return visualIndexResizeMode(visual) == QHeaderView::Interactive;
+ return headerSectionResizeMode(visual) == QHeaderView::Interactive;
}
inline int modelSectionCount() const {
@@ -230,7 +227,6 @@ public:
inline void executePostedResize() const {
if (delayedResize.isActive() && state == NoState) {
- delayedResize.stop();
const_cast<QHeaderView*>(q_func())->resizeSections();
}
}
@@ -274,6 +270,7 @@ public:
bool highlightSelected;
bool stretchLastSection;
bool cascadingResizing;
+ bool resizeRecursionBlock;
int stretchSections;
int contentsSections;
int defaultSectionSize;
diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp
index 94d3fce..84585dd 100644
--- a/src/gui/itemviews/qitemdelegate.cpp
+++ b/src/gui/itemviews/qitemdelegate.cpp
@@ -185,7 +185,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
data items from a model.
\ingroup model-view
- \mainclass
+
QItemDelegate can be used to provide custom display features and editor
widgets for item views based on QAbstractItemView subclasses. Using a
@@ -352,7 +352,10 @@ void QItemDelegate::setClipping(bool clip)
QString QItemDelegatePrivate::valueToText(const QVariant &value, const QStyleOptionViewItemV4 &option)
{
QString text;
- switch (value.type()) {
+ switch (value.userType()) {
+ case QMetaType::Float:
+ text = option.locale.toString(value.toFloat(), 'g');
+ break;
case QVariant::Double:
text = option.locale.toString(value.toDouble(), 'g', DBL_DIG);
break;
@@ -719,8 +722,6 @@ void QItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &o
//let's add the last line (after the last QChar::LineSeparator)
elided += option.fontMetrics.elidedText(text.mid(start),
option.textElideMode, textRect.width());
- if (end != -1)
- elided += QChar::LineSeparator;
}
d->textLayout.setText(elided);
textLayoutSize = d->doTextLayout(textRect.width());
@@ -861,6 +862,8 @@ void QItemDelegate::drawBackground(QPainter *painter,
/*!
\internal
+
+ Code duplicated in QCommonStylePrivate::viewItemLayout
*/
void QItemDelegate::doLayout(const QStyleOptionViewItem &option,
@@ -882,8 +885,10 @@ void QItemDelegate::doLayout(const QStyleOptionViewItem &option,
int w, h;
textRect->adjust(-textMargin, 0, textMargin, 0); // add width padding
- if (textRect->height() == 0 && !hasPixmap)
+ if (textRect->height() == 0 && (!hasPixmap || !hint)) {
+ //if there is no text, we still want to have a decent height for the item sizeHint and the editor size
textRect->setHeight(option.fontMetrics.height());
+ }
QSize pm(0, 0);
if (hasPixmap) {
@@ -1219,7 +1224,7 @@ bool QItemDelegate::eventFilter(QObject *object, QEvent *event)
if (editor->parentWidget())
editor->parentWidget()->setFocus();
return true;
- } else if (event->type() == QEvent::FocusOut || event->type() == QEvent::Hide) {
+ } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
//the Hide event will take care of he editors that are in fact complete dialogs
if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
QWidget *w = QApplication::focusWidget();
@@ -1234,12 +1239,7 @@ bool QItemDelegate::eventFilter(QObject *object, QEvent *event)
if (QDragManager::self() && QDragManager::self()->object != 0)
return false;
#endif
- // Opening a modal dialog will start a new eventloop
- // that will process the deleteLater event.
- if (QApplication::activeModalWidget()
- && !QApplication::activeModalWidget()->isAncestorOf(editor)
- && qobject_cast<QDialog*>(QApplication::activeModalWidget()))
- return false;
+
emit commitData(editor);
emit closeEditor(editor, NoHint);
}
@@ -1297,8 +1297,14 @@ bool QItemDelegate::editorEvent(QEvent *event,
return false;
}
- Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
+ Qt::CheckState state;
+ if ( flags & Qt::ItemIsTristate ) {
+ state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 );
+ } else {
+ state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
? Qt::Unchecked : Qt::Checked);
+ }
+
return model->setData(index, state, Qt::CheckStateRole);
}
@@ -1321,7 +1327,7 @@ QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index,
// set text alignment
value = index.data(Qt::TextAlignmentRole);
if (value.isValid())
- opt.displayAlignment = (Qt::Alignment)value.toInt();
+ opt.displayAlignment = Qt::Alignment(value.toInt());
// set foreground brush
value = index.data(Qt::ForegroundRole);
diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp
index b57a0e9..8369db7 100644
--- a/src/gui/itemviews/qitemselectionmodel.cpp
+++ b/src/gui/itemviews/qitemselectionmodel.cpp
@@ -270,67 +270,77 @@ QItemSelectionRange QItemSelectionRange::intersect(const QItemSelectionRange &ot
*/
-/*!
- Returns the list of model index items stored in the selection.
-*/
+/*
+ \internal
-QModelIndexList QItemSelectionRange::indexes() const
+ utility function for getting the indexes from a range
+ it avoid concatenating list and works on one
+ */
+
+static void indexesFromRange(const QItemSelectionRange &range, QModelIndexList &result)
{
- QModelIndex index;
- QModelIndexList result;
- if (isValid() && model()) {
- for (int column = left(); column <= right(); ++column) {
- for (int row = top(); row <= bottom(); ++row) {
- index = model()->index(row, column, parent());
- Qt::ItemFlags flags = model()->flags(index);
+ if (range.isValid() && range.model()) {
+ for (int column = range.left(); column <= range.right(); ++column) {
+ for (int row = range.top(); row <= range.bottom(); ++row) {
+ QModelIndex index = range.model()->index(row, column, range.parent());
+ Qt::ItemFlags flags = range.model()->flags(index);
if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
result.append(index);
}
}
}
- return result;
}
/*!
- \class QItemSelection
+ Returns the list of model index items stored in the selection.
+*/
- \brief The QItemSelection class manages information about selected items in a model.
+QModelIndexList QItemSelectionRange::indexes() const
+{
+ QModelIndexList result;
+ indexesFromRange(*this, result);
+ return result;
+}
- \ingroup model-view
+/*!
+ \class QItemSelection
- A QItemSelection describes the items in a model that have been
- selected by the user. A QItemSelection is basically a list of
- selection ranges, see QItemSelectionRange. It provides functions for
- creating and manipulating selections, and selecting a range of items
- from a model.
+ \brief The QItemSelection class manages information about selected items in a model.
- The QItemSelection class is one of the \l{Model/View Classes}
- and is part of Qt's \l{Model/View Programming}{model/view framework}.
+ \ingroup model-view
- An item selection can be constructed and initialized to contain a
- range of items from an existing model. The following example constructs
- a selection that contains a range of items from the given \c model,
- beginning at the \c topLeft, and ending at the \c bottomRight.
+ A QItemSelection describes the items in a model that have been
+ selected by the user. A QItemSelection is basically a list of
+ selection ranges, see QItemSelectionRange. It provides functions for
+ creating and manipulating selections, and selecting a range of items
+ from a model.
- \snippet doc/src/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp 0
+ The QItemSelection class is one of the \l{Model/View Classes}
+ and is part of Qt's \l{Model/View Programming}{model/view framework}.
- An empty item selection can be constructed, and later populated as
- required. So, if the model is going to be unavailable when we construct
- the item selection, we can rewrite the above code in the following way:
+ An item selection can be constructed and initialized to contain a
+ range of items from an existing model. The following example constructs
+ a selection that contains a range of items from the given \c model,
+ beginning at the \c topLeft, and ending at the \c bottomRight.
- \snippet doc/src/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp 1
+ \snippet doc/src/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp 0
- QItemSelection saves memory, and avoids unnecessary work, by working with
- selection ranges rather than recording the model item index for each
- item in the selection. Generally, an instance of this class will contain
- a list of non-overlapping selection ranges.
+ An empty item selection can be constructed, and later populated as
+ required. So, if the model is going to be unavailable when we construct
+ the item selection, we can rewrite the above code in the following way:
- Use merge() to merge one item selection into another without making
- overlapping ranges. Use split() to split one selection range into
- smaller ranges based on a another selection range.
+ \snippet doc/src/snippets/code/src_gui_itemviews_qitemselectionmodel.cpp 1
- \sa {Model/View Programming}, QItemSelectionModel
+ QItemSelection saves memory, and avoids unnecessary work, by working with
+ selection ranges rather than recording the model item index for each
+ item in the selection. Generally, an instance of this class will contain
+ a list of non-overlapping selection ranges.
+ Use merge() to merge one item selection into another without making
+ overlapping ranges. Use split() to split one selection range into
+ smaller ranges based on a another selection range.
+
+ \sa {Model/View Programming}, QItemSelectionModel
*/
/*!
@@ -404,19 +414,19 @@ QModelIndexList QItemSelection::indexes() const
QModelIndexList result;
QList<QItemSelectionRange>::const_iterator it = begin();
for (; it != end(); ++it)
- result += (*it).indexes();
+ indexesFromRange(*it, result);
return result;
}
/*!
- Merges the \a other selection with this QItemSelection using the
- \a command given. This method guarantees that no ranges are overlapping.
+ Merges the \a other selection with this QItemSelection using the
+ \a command given. This method guarantees that no ranges are overlapping.
- Note that only QItemSelectionModel::Select,
- QItemSelectionModel::Deselect, and QItemSelectionModel::Toggle are
- supported.
+ Note that only QItemSelectionModel::Select,
+ QItemSelectionModel::Deselect, and QItemSelectionModel::Toggle are
+ supported.
- \sa split()
+ \sa split()
*/
void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command)
{
@@ -468,10 +478,10 @@ void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::Sel
}
/*!
- Splits the selection \a range using the selection \a other range.
- Removes all items in \a other from \a range and puts the result in \a result.
- This can be compared with the semantics of the \e subtract operation of a set.
- \sa merge()
+ Splits the selection \a range using the selection \a other range.
+ Removes all items in \a other from \a range and puts the result in \a result.
+ This can be compared with the semantics of the \e subtract operation of a set.
+ \sa merge()
*/
void QItemSelection::split(const QItemSelectionRange &range,
@@ -518,11 +528,11 @@ void QItemSelection::split(const QItemSelectionRange &range,
}
/*!
- \internal
+ \internal
- returns a QItemSelection where all ranges have been expanded to:
- Rows: left: 0 and right: columnCount()-1
- Columns: top: 0 and bottom: rowCount()-1
+ returns a QItemSelection where all ranges have been expanded to:
+ Rows: left: 0 and right: columnCount()-1
+ Columns: top: 0 and bottom: rowCount()-1
*/
QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection &selection,
@@ -557,12 +567,13 @@ QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection
}
/*!
- \internal
+ \internal
*/
void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &parent,
int start, int end)
{
Q_Q(QItemSelectionModel);
+ finalize();
// update current index
if (currentIndex.isValid() && parent == currentIndex.parent()
@@ -580,15 +591,46 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
emit q->currentColumnChanged(currentIndex, old);
}
- // update selectionsx
- QModelIndex tl = model->index(start, 0, parent);
- QModelIndex br = model->index(end, model->columnCount(parent) - 1, parent);
- q->select(QItemSelection(tl, br), QItemSelectionModel::Deselect);
- finalize();
+ QItemSelection deselected;
+ QItemSelection::iterator it = ranges.begin();
+ while (it != ranges.end()) {
+ if (it->topLeft().parent() != parent) { // Check parents until reaching root or contained in range
+ QModelIndex itParent = it->topLeft().parent();
+ while (itParent.isValid() && itParent.parent() != parent)
+ itParent = itParent.parent();
+
+ if (parent.isValid() && start <= itParent.row() && itParent.row() <= end) {
+ deselected.append(*it);
+ it = ranges.erase(it);
+ } else {
+ ++it;
+ }
+ } else if (start <= it->bottom() && it->bottom() <= end // Full inclusion
+ && start <= it->top() && it->top() <= end) {
+ deselected.append(*it);
+ it = ranges.erase(it);
+ } else if (start <= it->top() && it->top() <= end) { // Top intersection
+ deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->left(), it->parent())));
+ *it = QItemSelectionRange(model->index(end + 1, it->left(), it->parent()), it->bottomRight());
+ ++it;
+ } else if (start <= it->bottom() && it->bottom() <= end) { // Bottom intersection
+ deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight()));
+ *it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent()));
+ ++it;
+ } else {
+ if (it->top() < start && end < it->bottom()) // Middle intersection (do nothing)
+ deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()),
+ model->index(end, it->left(), it->parent())));
+ ++it;
+ }
+ }
+
+ if (!deselected.isEmpty())
+ emit q->selectionChanged(QItemSelection(), deselected);
}
/*!
- \internal
+ \internal
*/
void QItemSelectionModelPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent,
int start, int end)
@@ -619,9 +661,9 @@ void QItemSelectionModelPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &p
}
/*!
- \internal
+ \internal
- Split selection ranges if columns are about to be inserted in the middle.
+ Split selection ranges if columns are about to be inserted in the middle.
*/
void QItemSelectionModelPrivate::_q_columnsAboutToBeInserted(const QModelIndex &parent,
int start, int end)
@@ -648,9 +690,9 @@ void QItemSelectionModelPrivate::_q_columnsAboutToBeInserted(const QModelIndex &
}
/*!
- \internal
+ \internal
- Split selection ranges if rows are about to be inserted in the middle.
+ Split selection ranges if rows are about to be inserted in the middle.
*/
void QItemSelectionModelPrivate::_q_rowsAboutToBeInserted(const QModelIndex &parent,
int start, int end)
@@ -677,11 +719,11 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeInserted(const QModelIndex &par
}
/*!
- \internal
+ \internal
- Split selection into individual (persistent) indexes. This is done in
- preparation for the layoutChanged() signal, where the indexes can be
- merged again.
+ Split selection into individual (persistent) indexes. This is done in
+ preparation for the layoutChanged() signal, where the indexes can be
+ merged again.
*/
void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged()
{
@@ -692,14 +734,15 @@ void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged()
if (ranges.isEmpty() && currentSelection.count() == 1) {
QItemSelectionRange range = currentSelection.first();
QModelIndex parent = range.parent();
- if (range.top() == 0
+ tableRowCount = model->rowCount(parent);
+ tableColCount = model->columnCount(parent);
+ if (tableRowCount * tableColCount > 100
+ && range.top() == 0
&& range.left() == 0
- && range.bottom() == model->rowCount(parent) - 1
- && range.right() == model->columnCount(parent) - 1) {
+ && range.bottom() == tableRowCount - 1
+ && range.right() == tableColCount - 1) {
tableSelected = true;
tableParent = parent;
- tableColCount = model->columnCount(parent);
- tableRowCount = model->rowCount(parent);
return;
}
}
@@ -715,10 +758,10 @@ void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged()
}
/*!
- \internal
+ \internal
- Merges \a indexes into an item selection made up of ranges.
- Assumes that the indexes are sorted.
+ Merges \a indexes into an item selection made up of ranges.
+ Assumes that the indexes are sorted.
*/
static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes)
{
@@ -763,9 +806,9 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes)
}
/*!
- \internal
+ \internal
- Merge the selected indexes into selection ranges again.
+ Merge the selected indexes into selection ranges again.
*/
void QItemSelectionModelPrivate::_q_layoutChanged()
{
@@ -807,41 +850,41 @@ void QItemSelectionModelPrivate::_q_layoutChanged()
}
/*!
- \class QItemSelectionModel
+ \class QItemSelectionModel
- \brief The QItemSelectionModel class keeps track of a view's selected items.
+ \brief The QItemSelectionModel class keeps track of a view's selected items.
- \ingroup model-view
+ \ingroup model-view
- A QItemSelectionModel keeps track of the selected items in a view, or
- in several views onto the same model. It also keeps track of the
- currently selected item in a view.
+ A QItemSelectionModel keeps track of the selected items in a view, or
+ in several views onto the same model. It also keeps track of the
+ currently selected item in a view.
- The QItemSelectionModel class is one of the \l{Model/View Classes}
- and is part of Qt's \l{Model/View Programming}{model/view framework}.
+ The QItemSelectionModel class is one of the \l{Model/View Classes}
+ and is part of Qt's \l{Model/View Programming}{model/view framework}.
- The selected items are stored using ranges. Whenever you want to
- modify the selected items use select() and provide either a
- QItemSelection, or a QModelIndex and a QItemSelectionModel::SelectionFlag.
+ The selected items are stored using ranges. Whenever you want to
+ modify the selected items use select() and provide either a
+ QItemSelection, or a QModelIndex and a QItemSelectionModel::SelectionFlag.
- The QItemSelectionModel takes a two layer approach to selection
- management, dealing with both selected items that have been committed
- and items that are part of the current selection. The current
- selected items are part of the current interactive selection (for
- example with rubber-band selection or keyboard-shift selections).
+ The QItemSelectionModel takes a two layer approach to selection
+ management, dealing with both selected items that have been committed
+ and items that are part of the current selection. The current
+ selected items are part of the current interactive selection (for
+ example with rubber-band selection or keyboard-shift selections).
- To update the currently selected items, use the bitwise OR of
- QItemSelectionModel::Current and any of the other SelectionFlags.
- If you omit the QItemSelectionModel::Current command, a new current
- selection will be created, and the previous one added to the whole
- selection. All functions operate on both layers; for example,
- selectedItems() will return items from both layers.
+ To update the currently selected items, use the bitwise OR of
+ QItemSelectionModel::Current and any of the other SelectionFlags.
+ If you omit the QItemSelectionModel::Current command, a new current
+ selection will be created, and the previous one added to the whole
+ selection. All functions operate on both layers; for example,
+ selectedItems() will return items from both layers.
- \sa {Model/View Programming}, QAbstractItemModel, {Chart Example}
+ \sa {Model/View Programming}, QAbstractItemModel, {Chart Example}
*/
/*!
- Constructs a selection model that operates on the specified item \a model.
+ Constructs a selection model that operates on the specified item \a model.
*/
QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model)
: QObject(*new QItemSelectionModelPrivate, model)
@@ -864,7 +907,7 @@ QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model)
}
/*!
- Constructs a selection model that operates on the specified item \a model with \a parent.
+ Constructs a selection model that operates on the specified item \a model with \a parent.
*/
QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *parent)
: QObject(*new QItemSelectionModelPrivate, parent)
@@ -887,7 +930,7 @@ QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *par
}
/*!
- \internal
+ \internal
*/
QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model)
: QObject(dd, model)
@@ -910,7 +953,7 @@ QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstra
}
/*!
- Destroys the selection model.
+ Destroys the selection model.
*/
QItemSelectionModel::~QItemSelectionModel()
{
@@ -932,10 +975,10 @@ QItemSelectionModel::~QItemSelectionModel()
}
/*!
- Selects the model item \a index using the specified \a command, and emits
- selectionChanged().
+ Selects the model item \a index using the specified \a command, and emits
+ selectionChanged().
- \sa QItemSelectionModel::SelectionFlags
+ \sa QItemSelectionModel::SelectionFlags
*/
void QItemSelectionModel::select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
{
@@ -944,37 +987,37 @@ void QItemSelectionModel::select(const QModelIndex &index, QItemSelectionModel::
}
/*!
- \fn void QItemSelectionModel::currentChanged(const QModelIndex &current, const QModelIndex &previous)
+ \fn void QItemSelectionModel::currentChanged(const QModelIndex &current, const QModelIndex &previous)
- This signal is emitted whenever the current item changes. The \a previous
- model item index is replaced by the \a current index as the selection's
- current item.
+ This signal is emitted whenever the current item changes. The \a previous
+ model item index is replaced by the \a current index as the selection's
+ current item.
- Note that this signal will not be emitted when the item model is reset.
+ Note that this signal will not be emitted when the item model is reset.
- \sa currentIndex() setCurrentIndex() selectionChanged()
+ \sa currentIndex() setCurrentIndex() selectionChanged()
*/
/*!
- \fn void QItemSelectionModel::currentColumnChanged(const QModelIndex &current, const QModelIndex &previous)
+ \fn void QItemSelectionModel::currentColumnChanged(const QModelIndex &current, const QModelIndex &previous)
- This signal is emitted if the \a current item changes and its column is
- different to the column of the \a previous current item.
+ This signal is emitted if the \a current item changes and its column is
+ different to the column of the \a previous current item.
- Note that this signal will not be emitted when the item model is reset.
+ Note that this signal will not be emitted when the item model is reset.
- \sa currentChanged() currentRowChanged() currentIndex() setCurrentIndex()
+ \sa currentChanged() currentRowChanged() currentIndex() setCurrentIndex()
*/
/*!
- \fn void QItemSelectionModel::currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
+ \fn void QItemSelectionModel::currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
- This signal is emitted if the \a current item changes and its row is
- different to the row of the \a previous current item.
+ This signal is emitted if the \a current item changes and its row is
+ different to the row of the \a previous current item.
- Note that this signal will not be emitted when the item model is reset.
+ Note that this signal will not be emitted when the item model is reset.
- \sa currentChanged() currentColumnChanged() currentIndex() setCurrentIndex()
+ \sa currentChanged() currentColumnChanged() currentIndex() setCurrentIndex()
*/
/*!
@@ -991,32 +1034,32 @@ void QItemSelectionModel::select(const QModelIndex &index, QItemSelectionModel::
*/
/*!
- \enum QItemSelectionModel::SelectionFlag
+ \enum QItemSelectionModel::SelectionFlag
- This enum describes the way the selection model will be updated.
+ This enum describes the way the selection model will be updated.
- \value NoUpdate No selection will be made.
- \value Clear The complete selection will be cleared.
- \value Select All specified indexes will be selected.
- \value Deselect All specified indexes will be deselected.
- \value Toggle All specified indexes will be selected or
- deselected depending on their current state.
- \value Current The current selection will be updated.
- \value Rows All indexes will be expanded to span rows.
- \value Columns All indexes will be expanded to span columns.
- \value SelectCurrent A combination of Select and Current, provided for
- convenience.
- \value ToggleCurrent A combination of Toggle and Current, provided for
- convenience.
- \value ClearAndSelect A combination of Clear and Select, provided for
- convenience.
+ \value NoUpdate No selection will be made.
+ \value Clear The complete selection will be cleared.
+ \value Select All specified indexes will be selected.
+ \value Deselect All specified indexes will be deselected.
+ \value Toggle All specified indexes will be selected or
+ deselected depending on their current state.
+ \value Current The current selection will be updated.
+ \value Rows All indexes will be expanded to span rows.
+ \value Columns All indexes will be expanded to span columns.
+ \value SelectCurrent A combination of Select and Current, provided for
+ convenience.
+ \value ToggleCurrent A combination of Toggle and Current, provided for
+ convenience.
+ \value ClearAndSelect A combination of Clear and Select, provided for
+ convenience.
*/
/*!
- Selects the item \a selection using the specified \a command, and emits
- selectionChanged().
+ Selects the item \a selection using the specified \a command, and emits
+ selectionChanged().
- \sa QItemSelectionModel::SelectionFlag
+ \sa QItemSelectionModel::SelectionFlag
*/
void QItemSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
{
@@ -1056,7 +1099,7 @@ void QItemSelectionModel::select(const QItemSelection &selection, QItemSelection
}
/*!
- Clears the selection model. Emits selectionChanged() and currentChanged().
+ Clears the selection model. Emits selectionChanged() and currentChanged().
*/
void QItemSelectionModel::clear()
{
@@ -1072,7 +1115,7 @@ void QItemSelectionModel::clear()
}
/*!
- Clears the selection model. Does not emit any signals.
+ Clears the selection model. Does not emit any signals.
*/
void QItemSelectionModel::reset()
{
@@ -1082,8 +1125,8 @@ void QItemSelectionModel::reset()
}
/*!
- \since 4.2
- Clears the selection in the selection model. Emits selectionChanged().
+ \since 4.2
+ Clears the selection in the selection model. Emits selectionChanged().
*/
void QItemSelectionModel::clearSelection()
{
@@ -1099,14 +1142,14 @@ void QItemSelectionModel::clearSelection()
/*!
- Sets the model item \a index to be the current item, and emits
- currentChanged(). The current item is used for keyboard navigation and
- focus indication; it is independent of any selected items, although a
- selected item can also be the current item.
+ Sets the model item \a index to be the current item, and emits
+ currentChanged(). The current item is used for keyboard navigation and
+ focus indication; it is independent of any selected items, although a
+ selected item can also be the current item.
- Depending on the specified \a command, the \a index can also become part
- of the current selection.
- \sa select()
+ Depending on the specified \a command, the \a index can also become part
+ of the current selection.
+ \sa select()
*/
void QItemSelectionModel::setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
{
@@ -1130,8 +1173,8 @@ void QItemSelectionModel::setCurrentIndex(const QModelIndex &index, QItemSelecti
}
/*!
- Returns the model item index for the current item, or an invalid index
- if there is no current item.
+ Returns the model item index for the current item, or an invalid index
+ if there is no current item.
*/
QModelIndex QItemSelectionModel::currentIndex() const
{
@@ -1139,7 +1182,7 @@ QModelIndex QItemSelectionModel::currentIndex() const
}
/*!
- Returns true if the given model item \a index is selected.
+ Returns true if the given model item \a index is selected.
*/
bool QItemSelectionModel::isSelected(const QModelIndex &index) const
{
@@ -1176,12 +1219,12 @@ bool QItemSelectionModel::isSelected(const QModelIndex &index) const
}
/*!
- Returns true if all items are selected in the \a row with the given
- \a parent.
+ Returns true if all items are selected in the \a row with the given
+ \a parent.
- Note that this function is usually faster than calling isSelected()
- on all items in the same row and that unselectable items are
- ignored.
+ Note that this function is usually faster than calling isSelected()
+ on all items in the same row and that unselectable items are
+ ignored.
*/
bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) const
{
@@ -1236,12 +1279,12 @@ bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) cons
}
/*!
- Returns true if all items are selected in the \a column with the given
- \a parent.
+ Returns true if all items are selected in the \a column with the given
+ \a parent.
- Note that this function is usually faster than calling isSelected()
- on all items in the same column and that unselectable items are
- ignored.
+ Note that this function is usually faster than calling isSelected()
+ on all items in the same column and that unselectable items are
+ ignored.
*/
bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent) const
{
@@ -1296,8 +1339,8 @@ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent
}
/*!
- Returns true if there are any items selected in the \a row with the given
- \a parent.
+ Returns true if there are any items selected in the \a row with the given
+ \a parent.
*/
bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &parent) const
{
@@ -1325,8 +1368,8 @@ bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &par
}
/*!
- Returns true if there are any items selected in the \a column with the given
- \a parent.
+ Returns true if there are any items selected in the \a column with the given
+ \a parent.
*/
bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelIndex &parent) const
{
@@ -1366,15 +1409,14 @@ bool QItemSelectionModel::hasSelection() const
QItemSelection sel = d->ranges;
sel.merge(d->currentSelection, d->currentCommand);
return !sel.isEmpty();
- }
- else {
+ } else {
return !(d->ranges.isEmpty() && d->currentSelection.isEmpty());
}
}
/*!
- Returns a list of all selected model item indexes. The list contains no
- duplicates, and is not sorted.
+ Returns a list of all selected model item indexes. The list contains no
+ duplicates, and is not sorted.
*/
QModelIndexList QItemSelectionModel::selectedIndexes() const
{
@@ -1385,10 +1427,10 @@ QModelIndexList QItemSelectionModel::selectedIndexes() const
}
/*!
- \since 4.2
- Returns the indexes in the given \a column for the rows where all columns are selected.
+ \since 4.2
+ Returns the indexes in the given \a column for the rows where all columns are selected.
- \sa selectedIndexes(), selectedColumns()
+ \sa selectedIndexes(), selectedColumns()
*/
QModelIndexList QItemSelectionModel::selectedRows(int column) const
@@ -1449,7 +1491,7 @@ QModelIndexList QItemSelectionModel::selectedColumns(int row) const
}
/*!
- Returns the selection ranges stored in the selection model.
+ Returns the selection ranges stored in the selection model.
*/
const QItemSelection QItemSelectionModel::selection() const
{
@@ -1469,7 +1511,7 @@ const QItemSelection QItemSelectionModel::selection() const
}
/*!
- Returns the item model operated on by the selection model.
+ Returns the item model operated on by the selection model.
*/
const QAbstractItemModel *QItemSelectionModel::model() const
{
@@ -1477,8 +1519,8 @@ const QAbstractItemModel *QItemSelectionModel::model() const
}
/*!
- Compares the two selections \a newSelection and \a oldSelection
- and emits selectionChanged() with the deselected and selected items.
+ Compares the two selections \a newSelection and \a oldSelection
+ and emits selectionChanged() with the deselected and selected items.
*/
void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelection,
const QItemSelection &oldSelection)
@@ -1553,7 +1595,7 @@ QDebug operator<<(QDebug dbg, const QItemSelectionRange &range)
{
#ifndef Q_BROKEN_DEBUG_STREAM
dbg.nospace() << "QItemSelectionRange(" << range.topLeft()
- << "," << range.bottomRight() << ")";
+ << ',' << range.bottomRight() << ')';
return dbg.space();
#else
qWarning("This compiler doesn't support streaming QItemSelectionRange to QDebug");
diff --git a/src/gui/itemviews/qitemselectionmodel_p.h b/src/gui/itemviews/qitemselectionmodel_p.h
index fadc3f9..7e39d1f 100644
--- a/src/gui/itemviews/qitemselectionmodel_p.h
+++ b/src/gui/itemviews/qitemselectionmodel_p.h
@@ -65,7 +65,7 @@ public:
QItemSelectionModelPrivate()
: model(0),
currentCommand(QItemSelectionModel::NoUpdate),
- tableSelected(false) {}
+ tableSelected(false), tableColCount(0), tableRowCount(0) {}
QItemSelection expandSelection(const QItemSelection &selection,
QItemSelectionModel::SelectionFlags command) const;
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index 35b44b4..fc801ad 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -1,4 +1,4 @@
-/***************************************************************************
+/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
\ingroup model-view
\ingroup advanced
- \mainclass
+
A QListView presents items stored in a model, either as a simple
non-hierarchical list, or as a collection of icons. This class is used
@@ -458,13 +458,13 @@ QSize QListView::gridSize() const
void QListView::setViewMode(ViewMode mode)
{
Q_D(QListView);
+ if (d->commonListView && d->viewMode == mode)
+ return;
d->viewMode = mode;
+ delete d->commonListView;
if (mode == ListMode) {
- delete d->dynamicListView;
- d->dynamicListView = 0;
- if (!d->staticListView)
- d->staticListView = new QStaticListViewBase(this, d);
+ d->commonListView = new QListModeViewBase(this, d);
if (!(d->modeProperties & QListViewPrivate::Wrap))
d->setWrapping(false);
if (!(d->modeProperties & QListViewPrivate::Spacing))
@@ -480,10 +480,7 @@ void QListView::setViewMode(ViewMode mode)
if (!(d->modeProperties & QListViewPrivate::SelectionRectVisible))
d->showElasticBand = false;
} else {
- delete d->staticListView;
- d->staticListView = 0;
- if (!d->dynamicListView)
- d->dynamicListView = new QDynamicListViewBase(this, d);
+ d->commonListView = new QIconModeViewBase(this, d);
if (!(d->modeProperties & QListViewPrivate::Wrap))
d->setWrapping(true);
if (!(d->modeProperties & QListViewPrivate::Spacing))
@@ -547,24 +544,12 @@ void QListView::setRowHidden(int row, bool hide)
{
Q_D(QListView);
const bool hidden = d->isHidden(row);
- if (d->viewMode == ListMode) {
- if (hide && !hidden)
- d->hiddenRows.append(d->model->index(row, 0));
- else if (!hide && hidden)
- d->hiddenRows.remove(d->hiddenRows.indexOf(d->model->index(row, 0)));
- d->doDelayedItemsLayout();
- } else {
- if (hide && !hidden) {
- d->dynamicListView->removeItem(row);
- d->hiddenRows.append(d->model->index(row, 0));
- } else if (!hide && hidden) {
- d->hiddenRows.remove(d->hiddenRows.indexOf(d->model->index(row, 0)));
- d->dynamicListView->insertItem(row);
- }
- if (d->resizeMode == Adjust)
- d->doDelayedItemsLayout();
- d->viewport->update();
- }
+ if (hide && !hidden)
+ d->commonListView->appendHiddenRow(row);
+ else if (!hide && hidden)
+ d->commonListView->removeHiddenRow(row);
+ d->doDelayedItemsLayout();
+ d->viewport->update();
}
/*!
@@ -573,7 +558,7 @@ void QListView::setRowHidden(int row, bool hide)
QRect QListView::visualRect(const QModelIndex &index) const
{
Q_D(const QListView);
- return d->mapToViewport(rectForIndex(index), d->viewMode == QListView::ListMode);
+ return d->mapToViewport(rectForIndex(index));
}
/*!
@@ -588,7 +573,7 @@ void QListView::scrollTo(const QModelIndex &index, ScrollHint hint)
const QRect rect = visualRect(index);
if (hint == EnsureVisible && d->viewport->rect().contains(rect)) {
- d->setDirtyRegion(rect);
+ d->viewport->update(rect);
return;
}
@@ -610,69 +595,17 @@ int QListViewPrivate::horizontalScrollToValue(const QModelIndex &index, const QR
const bool rightOf = q->isRightToLeft()
? rect.right() > area.right()
: (rect.right() > area.right()) && (rect.left() > area.left());
- int horizontalValue = q->horizontalScrollBar()->value();
-
- // ScrollPerItem
- if (q->horizontalScrollMode() == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) {
- const QListViewItem item = indexToListViewItem(index);
- const QRect rect = q->visualRect(index);
- horizontalValue = staticListView->horizontalPerItemValue(itemIndex(item),
- horizontalValue, area.width(),
- leftOf, rightOf, isWrapping(), hint, rect.width());
- } else { // ScrollPerPixel
- if (q->isRightToLeft()) {
- if (hint == QListView::PositionAtCenter) {
- horizontalValue += ((area.width() - rect.width()) / 2) - rect.left();
- } else {
- if (leftOf)
- horizontalValue -= rect.left();
- else if (rightOf)
- horizontalValue += qMin(rect.left(), area.width() - rect.right());
- }
- } else {
- if (hint == QListView::PositionAtCenter) {
- horizontalValue += rect.left() - ((area.width()- rect.width()) / 2);
- } else {
- if (leftOf)
- horizontalValue += rect.left();
- else if (rightOf)
- horizontalValue += qMin(rect.left(), rect.right() - area.width());
- }
- }
- }
- return horizontalValue;
+ return commonListView->horizontalScrollToValue(q->visualIndex(index), hint, leftOf, rightOf, area, rect);
}
int QListViewPrivate::verticalScrollToValue(const QModelIndex &index, const QRect &rect,
QListView::ScrollHint hint) const
{
Q_Q(const QListView);
-
const QRect area = viewport->rect();
const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top());
const bool below = (hint == QListView::EnsureVisible && rect.bottom() > area.bottom());
-
- int verticalValue = q->verticalScrollBar()->value();
-
- // ScrollPerItem
- if (q->verticalScrollMode() == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) {
- const QListViewItem item = indexToListViewItem(index);
- const QRect rect = q->visualRect(index);
- verticalValue = staticListView->verticalPerItemValue(itemIndex(item),
- verticalValue, area.height(),
- above, below, isWrapping(), hint, rect.height());
-
- } else { // ScrollPerPixel
- QRect adjusted = rect.adjusted(-spacing(), -spacing(), spacing(), spacing());
- if (hint == QListView::PositionAtTop || above)
- verticalValue += adjusted.top();
- else if (hint == QListView::PositionAtBottom || below)
- verticalValue += qMin(adjusted.top(), adjusted.bottom() - area.height() + 1);
- else if (hint == QListView::PositionAtCenter)
- verticalValue += adjusted.top() - ((area.height() - adjusted.height()) / 2);
- }
-
- return verticalValue;
+ return commonListView->verticalScrollToValue(q->visualIndex(index), hint, above, below, area, rect);
}
void QListViewPrivate::selectAll(QItemSelectionModel::SelectionFlags command)
@@ -709,6 +642,31 @@ void QListViewPrivate::selectAll(QItemSelectionModel::SelectionFlags command)
selectionModel->select(selection, command);
}
+/*!
+ \reimp
+
+ We have a QListView way of knowing what elements are on the viewport
+ through the intersectingSet function
+*/
+QItemViewPaintPairs QListViewPrivate::draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const
+{
+ Q_ASSERT(r);
+ Q_Q(const QListView);
+ QRect &rect = *r;
+ const QRect viewportRect = viewport->rect();
+ QItemViewPaintPairs ret;
+ const QSet<QModelIndex> visibleIndexes = intersectingSet(viewportRect).toList().toSet();
+ for (int i = 0; i < indexes.count(); ++i) {
+ const QModelIndex &index = indexes.at(i);
+ if (visibleIndexes.contains(index)) {
+ const QRect current = q->visualRect(index);
+ ret += qMakePair(current, index);
+ rect |= current;
+ }
+ }
+ rect &= viewportRect;
+ return ret;
+}
/*!
\internal
@@ -739,23 +697,12 @@ void QListView::setRootIndex(const QModelIndex &index)
Scroll the view contents by \a dx and \a dy.
*/
+
void QListView::scrollContentsBy(int dx, int dy)
{
Q_D(QListView);
-
d->delayedAutoScroll.stop(); // auto scroll was canceled by the user scrolling
-
- if (d->viewMode == ListMode)
- d->staticListView->scrollContentsBy(dx, dy);
- else if (state() == DragSelectingState)
- d->scrollElasticBandBy(isRightToLeft() ? -dx : dx, dy);
-
- d->scrollContentsBy(isRightToLeft() ? -dx : dx, dy);
-
- // update the dragged items
- if (d->viewMode == IconMode) // ### move to dynamic class
- if (!d->dynamicListView->draggedItems.isEmpty())
- d->setDirtyRegion(d->dynamicListView->draggedItemsRect().translated(dx, dy));
+ d->commonListView->scrollContentsBy(dx, dy, d->state == QListView::DragSelectingState);
}
/*!
@@ -784,9 +731,7 @@ QSize QListView::contentsSize() const
*/
void QListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
- Q_D(QListView);
- if (d->viewMode == IconMode)
- d->dynamicListView->dataChanged(topLeft, bottomRight);
+ d_func()->commonListView->dataChanged(topLeft, bottomRight);
QAbstractItemView::dataChanged(topLeft, bottomRight);
}
@@ -837,7 +782,7 @@ void QListView::mouseMoveEvent(QMouseEvent *e)
&& d->selectionMode != NoSelection) {
QRect rect(d->pressedPosition, e->pos() + QPoint(horizontalOffset(), verticalOffset()));
rect = rect.normalized();
- d->setDirtyRegion(d->mapToViewport(rect.united(d->elasticBand), d->viewMode == QListView::ListMode));
+ d->viewport->update(d->mapToViewport(rect.united(d->elasticBand)));
d->elasticBand = rect;
}
}
@@ -851,7 +796,7 @@ void QListView::mouseReleaseEvent(QMouseEvent *e)
QAbstractItemView::mouseReleaseEvent(e);
// #### move this implementation into a dynamic class
if (d->showElasticBand && d->elasticBand.isValid()) {
- d->setDirtyRegion(d->mapToViewport(d->elasticBand, d->viewMode == QListView::ListMode));
+ d->viewport->update(d->mapToViewport(d->elasticBand));
d->elasticBand = QRect();
}
}
@@ -908,69 +853,27 @@ void QListView::resizeEvent(QResizeEvent *e)
*/
void QListView::dragMoveEvent(QDragMoveEvent *e)
{
- // ### move implementation to dynamic
- Q_D(QListView);
- if (e->source() == this && d->viewMode == IconMode) {
- // the ignore by default
- e->ignore();
- if (d->canDecode(e)) {
- // get old dragged items rect
- QRect itemsRect = d->dynamicListView->itemsRect(d->dynamicListView->draggedItems);
- d->setDirtyRegion(itemsRect.translated(d->dynamicListView->draggedItemsDelta()));
- // update position
- d->dynamicListView->draggedItemsPos = e->pos();
- // get new items rect
- d->setDirtyRegion(itemsRect.translated(d->dynamicListView->draggedItemsDelta()));
- // set the item under the cursor to current
- QModelIndex index;
- if (d->movement == Snap) {
- QRect rect(d->dynamicListView->snapToGrid(e->pos() + d->offset()), d->gridSize());
- d->intersectingSet(rect);
- index = d->intersectVector.count() > 0
- ? d->intersectVector.last() : QModelIndex();
- } else {
- index = indexAt(e->pos());
- }
- // check if we allow drops here
- if (e->source() == this && d->dynamicListView->draggedItems.contains(index))
- e->accept(); // allow changing item position
- else if (d->model->flags(index) & Qt::ItemIsDropEnabled)
- e->accept(); // allow dropping on dropenabled items
- else if (!index.isValid())
- e->accept(); // allow dropping in empty areas
- }
- // do autoscrolling
- if (d->shouldAutoScroll(e->pos()))
- startAutoScroll();
- } else { // not internal
+ if (!d_func()->commonListView->filterDragMoveEvent(e))
QAbstractItemView::dragMoveEvent(e);
- }
}
+
/*!
\reimp
*/
void QListView::dragLeaveEvent(QDragLeaveEvent *e)
{
- // ### move implementation to dynamic
- Q_D(QListView);
- if (d->viewMode == IconMode) {
- d->viewport->update(d->dynamicListView->draggedItemsRect()); // erase the area
- d->dynamicListView->draggedItemsPos = QPoint(-1, -1); // don't draw the dragged items
- }
- QAbstractItemView::dragLeaveEvent(e);
+ if (!d_func()->commonListView->filterDragLeaveEvent(e))
+ QAbstractItemView::dragLeaveEvent(e);
}
/*!
\reimp
*/
-void QListView::dropEvent(QDropEvent *event)
+void QListView::dropEvent(QDropEvent *e)
{
- Q_D(QListView);
- if (event->source() == this && d->viewMode == IconMode)
- internalDrop(event); // ### move to dynamic
- else
- QAbstractItemView::dropEvent(event);
+ if (!d_func()->commonListView->filterDropEvent(e))
+ QAbstractItemView::dropEvent(e);
}
/*!
@@ -978,10 +881,7 @@ void QListView::dropEvent(QDropEvent *event)
*/
void QListView::startDrag(Qt::DropActions supportedActions)
{
- Q_D(QListView);
- if (d->viewMode == IconMode) // ### move to dynamic
- internalDrag(supportedActions);
- else
+ if (!d_func()->commonListView->filterStartDrag(supportedActions))
QAbstractItemView::startDrag(supportedActions);
}
@@ -993,41 +893,8 @@ void QListView::startDrag(Qt::DropActions supportedActions)
*/
void QListView::internalDrop(QDropEvent *event)
{
- Q_D(QListView);
- if (d->viewMode == QListView::ListMode)
- return;
-
- // ### move to dynamic class
- QPoint offset(horizontalOffset(), verticalOffset());
- QPoint end = event->pos() + offset;
- QPoint start = d->pressedPosition;
- QPoint delta = (d->movement == Snap ?
- d->dynamicListView->snapToGrid(end)
- - d->dynamicListView->snapToGrid(start) : end - start);
- QSize contents = d->contentsSize();
- QList<QModelIndex> indexes = d->selectionModel->selectedIndexes();
- for (int i = 0; i < indexes.count(); ++i) {
- QModelIndex index = indexes.at(i);
- QRect rect = rectForIndex(index);
- d->setDirtyRegion(d->mapToViewport(rect, d->viewMode == QListView::ListMode));
- QPoint dest = rect.topLeft() + delta;
- if (isRightToLeft())
- dest.setX(d->flipX(dest.x()) - rect.width());
- d->dynamicListView->moveItem(index.row(), dest);
- d->setDirtyRegion(visualRect(index));
- }
- stopAutoScroll();
- d->dynamicListView->draggedItems.clear();
- emit indexesMoved(indexes);
- event->accept(); // we have handled the event
- // if the size has not grown, we need to check if it has shrinked
- if (d->dynamicListView
- && (d->contentsSize().width() <= contents.width()
- || d->contentsSize().height() <= contents.height())) {
- d->dynamicListView->updateContentsSize();
- }
- if (d->contentsSize() != contents)
- updateGeometries();
+ // ### Qt5: remove that function
+ Q_UNUSED(event);
}
/*!
@@ -1038,31 +905,8 @@ void QListView::internalDrop(QDropEvent *event)
*/
void QListView::internalDrag(Qt::DropActions supportedActions)
{
- Q_D(QListView);
- if (d->viewMode == QListView::ListMode)
- return;
-
- // #### move to dynamic class
-
- // This function does the same thing as in QAbstractItemView::startDrag(),
- // plus adding viewitems to the draggedItems list.
- // We need these items to draw the drag items
- QModelIndexList indexes = d->selectionModel->selectedIndexes();
- if (indexes.count() > 0 ) {
- if (d->viewport->acceptDrops()) {
- QModelIndexList::ConstIterator it = indexes.constBegin();
- for (; it != indexes.constEnd(); ++it)
- if (d->model->flags(*it) & Qt::ItemIsDragEnabled
- && (*it).column() == d->column)
- d->dynamicListView->draggedItems.push_back(*it);
- }
- QDrag *drag = new QDrag(this);
- drag->setMimeData(d->model->mimeData(indexes));
- Qt::DropAction action = drag->exec(supportedActions, Qt::CopyAction);
- d->dynamicListView->draggedItems.clear();
- if (action == Qt::MoveAction)
- d->clearOrRemove();
- }
+ // ### Qt5: remove that function
+ Q_UNUSED(supportedActions);
}
#endif // QT_NO_DRAGANDDROP
@@ -1090,6 +934,7 @@ QStyleOptionViewItem QListView::viewOptions() const
return option;
}
+
/*!
\reimp
*/
@@ -1100,16 +945,8 @@ void QListView::paintEvent(QPaintEvent *e)
return;
QStyleOptionViewItemV4 option = d->viewOptionsV4();
QPainter painter(d->viewport);
- QRect area = e->rect();
- QVector<QModelIndex> toBeRendered;
-// QVector<QRect> rects = e->region().rects();
-// for (int i = 0; i < rects.size(); ++i) {
-// d->intersectingSet(rects.at(i).translated(horizontalOffset(), verticalOffset()));
-// toBeRendered += d->intersectVector;
-// }
- d->intersectingSet(e->rect().translated(horizontalOffset(), verticalOffset()), false);
- toBeRendered = d->intersectVector;
+ const QVector<QModelIndex> toBeRendered = d->intersectingSet(e->rect().translated(horizontalOffset(), verticalOffset()), false);
const QModelIndex current = currentIndex();
const QModelIndex hover = d->hover;
@@ -1194,18 +1031,7 @@ void QListView::paintEvent(QPaintEvent *e)
}
#ifndef QT_NO_DRAGANDDROP
- // #### move this implementation into a dynamic class
- if (d->viewMode == IconMode)
- if (!d->dynamicListView->draggedItems.isEmpty()
- && d->viewport->rect().contains(d->dynamicListView->draggedItemsPos)) {
- QPoint delta = d->dynamicListView->draggedItemsDelta();
- painter.translate(delta.x(), delta.y());
- d->dynamicListView->drawItems(&painter, d->dynamicListView->draggedItems);
- }
- // FIXME: Until the we can provide a proper drop indicator
- // in IconMode, it makes no sense to show it
- if (d->viewMode == ListMode)
- d->paintDropIndicator(&painter);
+ d->commonListView->paintDragDrop(&painter);
#endif
#ifndef QT_NO_RUBBERBAND
@@ -1231,9 +1057,9 @@ QModelIndex QListView::indexAt(const QPoint &p) const
{
Q_D(const QListView);
QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
- d->intersectingSet(rect);
- QModelIndex index = d->intersectVector.count() > 0
- ? d->intersectVector.last() : QModelIndex();
+ const QVector<QModelIndex> intersectVector = d->intersectingSet(rect);
+ QModelIndex index = intersectVector.count() > 0
+ ? intersectVector.last() : QModelIndex();
if (index.isValid() && visualRect(index).contains(p))
return index;
return QModelIndex();
@@ -1244,31 +1070,7 @@ QModelIndex QListView::indexAt(const QPoint &p) const
*/
int QListView::horizontalOffset() const
{
- Q_D(const QListView);
- // ### split into static and dynamic
- if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem && d->viewMode == ListMode) {
- if (d->isWrapping()) {
- if (d->flow == TopToBottom && !d->staticListView->segmentPositions.isEmpty()) {
- const int max = d->staticListView->segmentPositions.count() - 1;
- int currentValue = qBound(0, horizontalScrollBar()->value(), max);
- int position = d->staticListView->segmentPositions.at(currentValue);
- int maximumValue = qBound(0, horizontalScrollBar()->maximum(), max);
- int maximum = d->staticListView->segmentPositions.at(maximumValue);
- return (isRightToLeft() ? maximum - position : position);
- }
- //return 0;
- } else {
- if (d->flow == LeftToRight && !d->staticListView->flowPositions.isEmpty()) {
- int position = d->staticListView->flowPositions.at(horizontalScrollBar()->value());
- int maximum = d->staticListView->flowPositions.at(horizontalScrollBar()->maximum());
- return (isRightToLeft() ? maximum - position : position);
- }
- //return 0;
- }
- }
- return (isRightToLeft()
- ? horizontalScrollBar()->maximum() - horizontalScrollBar()->value()
- : horizontalScrollBar()->value());
+ return d_func()->commonListView->horizontalOffset();
}
/*!
@@ -1276,30 +1078,7 @@ int QListView::horizontalOffset() const
*/
int QListView::verticalOffset() const
{
- // ## split into static and dynamic
- Q_D(const QListView);
- if (verticalScrollMode() == QAbstractItemView::ScrollPerItem && d->viewMode == ListMode) {
- if (d->isWrapping()) {
- if (d->flow == LeftToRight && !d->staticListView->segmentPositions.isEmpty()) {
- int value = verticalScrollBar()->value();
- if (value >= d->staticListView->segmentPositions.count()) {
- //qWarning("QListView: Vertical scroll bar is out of bounds");
- return 0;
- }
- return d->staticListView->segmentPositions.at(value);
- }
- } else {
- if (d->flow == TopToBottom && !d->staticListView->flowPositions.isEmpty()) {
- int value = verticalScrollBar()->value();
- if (value > d->staticListView->flowPositions.count()) {
- //qWarning("QListView: Vertical scroll bar is out of bounds");
- return 0;
- }
- return d->staticListView->flowPositions.at(value) - d->spacing();
- }
- }
- }
- return verticalScrollBar()->value();
+ return d_func()->commonListView->verticalOffset();
}
/*!
@@ -1331,38 +1110,38 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
if (d->gridSize().isValid()) rect.setSize(d->gridSize());
QSize contents = d->contentsSize();
- d->intersectVector.clear();
+ QVector<QModelIndex> intersectVector;
switch (cursorAction) {
case MoveLeft:
- while (d->intersectVector.isEmpty()) {
+ while (intersectVector.isEmpty()) {
rect.translate(-rect.width(), 0);
if (rect.right() <= 0)
return current;
if (rect.left() < 0)
rect.setLeft(0);
- d->intersectingSet(rect);
- d->removeCurrentAndDisabled(&d->intersectVector, current);
+ intersectVector = d->intersectingSet(rect);
+ d->removeCurrentAndDisabled(&intersectVector, current);
}
- return d->closestIndex(initialRect, d->intersectVector);
+ return d->closestIndex(initialRect, intersectVector);
case MoveRight:
- while (d->intersectVector.isEmpty()) {
+ while (intersectVector.isEmpty()) {
rect.translate(rect.width(), 0);
if (rect.left() >= contents.width())
return current;
if (rect.right() > contents.width())
rect.setRight(contents.width());
- d->intersectingSet(rect);
- d->removeCurrentAndDisabled(&d->intersectVector, current);
+ intersectVector = d->intersectingSet(rect);
+ d->removeCurrentAndDisabled(&intersectVector, current);
}
- return d->closestIndex(initialRect, d->intersectVector);
+ return d->closestIndex(initialRect, intersectVector);
case MovePageUp:
rect.moveTop(rect.top() - d->viewport->height());
if (rect.top() < rect.height())
rect.moveTop(rect.height());
case MovePrevious:
case MoveUp:
- while (d->intersectVector.isEmpty()) {
+ while (intersectVector.isEmpty()) {
rect.translate(0, -rect.height());
if (rect.bottom() <= 0) {
#ifdef QT_KEYPAD_NAVIGATION
@@ -1378,17 +1157,17 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
}
if (rect.top() < 0)
rect.setTop(0);
- d->intersectingSet(rect);
- d->removeCurrentAndDisabled(&d->intersectVector, current);
+ intersectVector = d->intersectingSet(rect);
+ d->removeCurrentAndDisabled(&intersectVector, current);
}
- return d->closestIndex(initialRect, d->intersectVector);
+ return d->closestIndex(initialRect, intersectVector);
case MovePageDown:
rect.moveTop(rect.top() + d->viewport->height());
if (rect.bottom() > contents.height() - rect.height())
rect.moveBottom(contents.height() - rect.height());
case MoveNext:
case MoveDown:
- while (d->intersectVector.isEmpty()) {
+ while (intersectVector.isEmpty()) {
rect.translate(0, rect.height());
if (rect.top() >= contents.height()) {
#ifdef QT_KEYPAD_NAVIGATION
@@ -1405,10 +1184,10 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
}
if (rect.bottom() > contents.height())
rect.setBottom(contents.height());
- d->intersectingSet(rect);
- d->removeCurrentAndDisabled(&d->intersectVector, current);
+ intersectVector = d->intersectingSet(rect);
+ d->removeCurrentAndDisabled(&intersectVector, current);
}
- return d->closestIndex(initialRect, d->intersectVector);
+ return d->closestIndex(initialRect, intersectVector);
case MoveHome:
return d->model->index(0, d->column, d->root);
case MoveEnd:
@@ -1425,15 +1204,7 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
*/
QRect QListView::rectForIndex(const QModelIndex &index) const
{
- Q_D(const QListView);
- if (!d->isIndexValid(index)
- || index.parent() != d->root
- || index.column() != d->column
- || isIndexHidden(index))
- return QRect();
- d->executePostedLayout();
- QListViewItem item = d->indexToListViewItem(index);
- return d->viewItemRect(item);
+ return d_func()->rectForIndex(index);
}
/*!
@@ -1441,8 +1212,8 @@ QRect QListView::rectForIndex(const QModelIndex &index) const
Sets the contents position of the item at \a index in the model to the given
\a position.
- If the list view's movement mode is Static, this function will have no
- effect.
+ If the list view's movement mode is Static or its view mode is ListView,
+ this function will have no effect.
*/
void QListView::setPositionForIndex(const QPoint &position, const QModelIndex &index)
{
@@ -1454,15 +1225,7 @@ void QListView::setPositionForIndex(const QPoint &position, const QModelIndex &i
return;
d->executePostedLayout();
- if (index.row() >= d->dynamicListView->items.count())
- return;
- const QSize oldContents = d->contentsSize();
- d->setDirtyRegion(visualRect(index)); // update old position
- d->dynamicListView->moveItem(index.row(), position);
- d->setDirtyRegion(visualRect(index)); // update new position
-
- if (d->contentsSize() != oldContents)
- updateGeometries(); // update the scroll bars
+ d->commonListView->setPositionForIndex(position, index);
}
/*!
@@ -1483,10 +1246,10 @@ void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl
QItemSelection selection;
if (rect.width() == 1 && rect.height() == 1) {
- d->intersectingSet(rect.translated(horizontalOffset(), verticalOffset()));
+ const QVector<QModelIndex> intersectVector = d->intersectingSet(rect.translated(horizontalOffset(), verticalOffset()));
QModelIndex tl;
- if (!d->intersectVector.isEmpty())
- tl = d->intersectVector.last(); // special case for mouse press; only select the top item
+ if (!intersectVector.isEmpty())
+ tl = intersectVector.last(); // special case for mouse press; only select the top item
if (tl.isValid() && d->isIndexEnabled(tl))
selection.select(tl, tl);
} else {
@@ -1496,14 +1259,14 @@ void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl
QModelIndex tl, br;
// get the first item
const QRect topLeft(rect.left() + horizontalOffset(), rect.top() + verticalOffset(), 1, 1);
- d->intersectingSet(topLeft);
- if (!d->intersectVector.isEmpty())
- tl = d->intersectVector.last();
+ QVector<QModelIndex> intersectVector = d->intersectingSet(topLeft);
+ if (!intersectVector.isEmpty())
+ tl = intersectVector.last();
// get the last item
const QRect bottomRight(rect.right() + horizontalOffset(), rect.bottom() + verticalOffset(), 1, 1);
- d->intersectingSet(bottomRight);
- if (!d->intersectVector.isEmpty())
- br = d->intersectVector.last();
+ intersectVector = d->intersectingSet(bottomRight);
+ if (!intersectVector.isEmpty())
+ br = intersectVector.last();
// get the ranges
if (tl.isValid() && br.isValid()
@@ -1546,7 +1309,10 @@ void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl
}
// middle rectangle
if (top.bottom() < bottom.top()) {
- middle.setTop(top.bottom() + 1);
+ if (gridSize().isValid() && !gridSize().isNull())
+ middle.setTop(top.top() + gridSize().height());
+ else
+ middle.setTop(top.bottom() + 1);
middle.setLeft(qMin(top.left(), bottom.left()));
middle.setBottom(bottom.top() - 1);
middle.setRight(qMax(top.right(), bottom.right()));
@@ -1573,7 +1339,10 @@ void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl
// only set middle if the
middle.setTop(0);
middle.setBottom(ch);
- middle.setLeft(left.right() + 1);
+ if (gridSize().isValid() && !gridSize().isNull())
+ middle.setLeft(left.left() + gridSize().width());
+ else
+ middle.setLeft(left.right() + 1);
middle.setRight(right.left() - 1);
} else if (left.bottom() < right.top()) {
left.setBottom(right.top() - 1);
@@ -1610,6 +1379,10 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
if (!selection.at(i).isValid())
continue;
QModelIndex parent = selection.at(i).topLeft().parent();
+ //we only display the children of the root in a listview
+ //we're not interested in the other model indexes
+ if (parent != d->root)
+ continue;
int t = selection.at(i).topLeft().row();
int b = selection.at(i).bottomRight().row();
if (d->viewMode == IconMode || d->isWrapping()) { // in non-static mode, we have to go through all selected items
@@ -1618,8 +1391,8 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
} else { // in static mode, we can optimize a bit
while (t <= b && d->isHidden(t)) ++t;
while (b >= t && d->isHidden(b)) --b;
- const QModelIndex top = d->model->index(t, c, d->root);
- const QModelIndex bottom = d->model->index(b, c, d->root);
+ const QModelIndex top = d->model->index(t, c, parent);
+ const QModelIndex bottom = d->model->index(b, c, parent);
QRect rect(visualRect(top).topLeft(),
visualRect(bottom).bottomRight());
selectionRegion += QRegion(rect);
@@ -1635,14 +1408,16 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
QModelIndexList QListView::selectedIndexes() const
{
Q_D(const QListView);
- QModelIndexList viewSelected;
- QModelIndexList modelSelected;
- if (d->selectionModel)
- modelSelected = d->selectionModel->selectedIndexes();
- for (int i = 0; i < modelSelected.count(); ++i) {
- QModelIndex index = modelSelected.at(i);
+ if (!d->selectionModel)
+ return QModelIndexList();
+
+ QModelIndexList viewSelected = d->selectionModel->selectedIndexes();
+ for (int i = 0; i < viewSelected.count(); ++i) {
+ const QModelIndex &index = viewSelected.at(i);
if (!isIndexHidden(index) && index.parent() == d->root && index.column() == d->column)
- viewSelected.append(index);
+ ++i;
+ else
+ viewSelected.removeAt(i);
}
return viewSelected;
}
@@ -1686,99 +1461,8 @@ void QListView::updateGeometries()
QModelIndex index = d->model->index(0, d->column, d->root);
QStyleOptionViewItemV4 option = d->viewOptionsV4();
QSize step = d->itemSize(option, index);
-
- QSize csize = d->contentsSize();
- QSize vsize = d->viewport->size();
- QSize max = maximumViewportSize();
- if (max.width() >= d->contentsSize().width() && max.height() >= d->contentsSize().height())
- vsize = max;
-
- // ### reorder the logic
-
- // ### split into static and dynamic
-
- const bool vertical = verticalScrollMode() == QAbstractItemView::ScrollPerItem;
- const bool horizontal = horizontalScrollMode() == QAbstractItemView::ScrollPerItem;
-
- if (d->flow == TopToBottom) {
- if (horizontal && d->isWrapping() && d->viewMode == ListMode) {
- const QVector<int> segmentPositions = d->staticListView->segmentPositions;
- const int steps = segmentPositions.count() - 1;
- if (steps > 0) {
- int pageSteps = d->staticListView->perItemScrollingPageSteps(vsize.width(),
- csize.width(),
- isWrapping());
- horizontalScrollBar()->setSingleStep(1);
- horizontalScrollBar()->setPageStep(pageSteps);
- horizontalScrollBar()->setRange(0, steps - pageSteps);
- } else {
- horizontalScrollBar()->setRange(0, 0);
- }
- } else {
- horizontalScrollBar()->setSingleStep(step.width() + d->spacing());
- horizontalScrollBar()->setPageStep(vsize.width());
- horizontalScrollBar()->setRange(0, d->contentsSize().width() - vsize.width());
- }
- if (vertical && !d->isWrapping() && d->viewMode == ListMode) {
- const QVector<int> flowPositions = d->staticListView->flowPositions;
- const int steps = flowPositions.count() - 1;
- if (steps > 0) {
- int pageSteps = d->staticListView->perItemScrollingPageSteps(vsize.height(),
- csize.height(),
- isWrapping());
- verticalScrollBar()->setSingleStep(1);
- verticalScrollBar()->setPageStep(pageSteps);
- verticalScrollBar()->setRange(0, steps - pageSteps);
- } else {
- verticalScrollBar()->setRange(0, 0);
- }
- // } else if (vertical && d->isWrapping() && d->movement == Static) {
- // ### wrapped scrolling in flow direction
- } else {
- verticalScrollBar()->setSingleStep(step.height() + d->spacing());
- verticalScrollBar()->setPageStep(vsize.height());
- verticalScrollBar()->setRange(0, d->contentsSize().height() - vsize.height());
- }
- } else { // LeftToRight
- if (horizontal && !d->isWrapping() && d->viewMode == ListMode) {
- const QVector<int> flowPositions = d->staticListView->flowPositions;
- int steps = flowPositions.count() - 1;
- if (steps > 0) {
- int pageSteps = d->staticListView->perItemScrollingPageSteps(vsize.width(),
- csize.width(),
- isWrapping());
- horizontalScrollBar()->setSingleStep(1);
- horizontalScrollBar()->setPageStep(pageSteps);
- horizontalScrollBar()->setRange(0, steps - pageSteps);
- } else {
- horizontalScrollBar()->setRange(0, 0);
- }
- // } else if (horizontal && d->isWrapping() && d->movement == Static) {
- // ### wrapped scrolling in flow direction
- } else {
- horizontalScrollBar()->setSingleStep(step.width() + d->spacing());
- horizontalScrollBar()->setPageStep(vsize.width());
- horizontalScrollBar()->setRange(0, d->contentsSize().width() - vsize.width());
- }
- if (vertical && d->isWrapping() && d->viewMode == ListMode) {
- const QVector<int> segmentPositions = d->staticListView->segmentPositions;
- int steps = segmentPositions.count() - 1;
- if (steps > 0) {
- int pageSteps = d->staticListView->perItemScrollingPageSteps(vsize.height(),
- csize.height(),
- isWrapping());
- verticalScrollBar()->setSingleStep(1);
- verticalScrollBar()->setPageStep(pageSteps);
- verticalScrollBar()->setRange(0, steps - pageSteps);
- } else {
- verticalScrollBar()->setRange(0, 0);
- }
- } else {
- verticalScrollBar()->setSingleStep(step.height() + d->spacing());
- verticalScrollBar()->setPageStep(vsize.height());
- verticalScrollBar()->setRange(0, d->contentsSize().height() - vsize.height());
- }
- }
+ d->commonListView->updateHorizontalScrollBar(step);
+ d->commonListView->updateVerticalScrollBar(step);
}
QAbstractItemView::updateGeometries();
@@ -1927,8 +1611,7 @@ bool QListView::event(QEvent *e)
QListViewPrivate::QListViewPrivate()
: QAbstractItemViewPrivate(),
- dynamicListView(0),
- staticListView(0),
+ commonListView(0),
wrap(false),
space(0),
flow(QListView::TopToBottom),
@@ -1939,25 +1622,21 @@ QListViewPrivate::QListViewPrivate()
modeProperties(0),
column(0),
uniformItemSizes(false),
- batchSize(100)
+ batchSize(100),
+ showElasticBand(false)
{
}
QListViewPrivate::~QListViewPrivate()
{
- delete staticListView;
- delete dynamicListView;
+ delete commonListView;
}
void QListViewPrivate::clear()
{
- // ### split into dynamic and static
// initialization of data structs
cachedItemSize = QSize();
- if (viewMode == QListView::ListMode)
- staticListView->clear();
- else
- dynamicListView->clear();
+ commonListView->clear();
}
void QListViewPrivate::prepareItemsLayout()
@@ -1966,27 +1645,26 @@ void QListViewPrivate::prepareItemsLayout()
clear();
//take the size as if there were scrollbar in order to prevent scrollbar to blink
- layoutBounds = QRect(QPoint(0,0), q->maximumViewportSize());
+ layoutBounds = QRect(QPoint(), q->maximumViewportSize());
int frameAroundContents = 0;
if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents))
frameAroundContents = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2;
- int verticalMargin = vbarpolicy==Qt::ScrollBarAlwaysOff ? 0 :
- q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q->verticalScrollBar()) + frameAroundContents;
- int horizontalMargin = hbarpolicy==Qt::ScrollBarAlwaysOff ? 0 :
- q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q->horizontalScrollBar()) + frameAroundContents;
+
+ // maximumViewportSize() already takes scrollbar into account if policy is
+ // Qt::ScrollBarAlwaysOn but scrollbar extent must be deduced if policy
+ // is Qt::ScrollBarAsNeeded
+ int verticalMargin = vbarpolicy==Qt::ScrollBarAsNeeded
+ ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, vbar) + frameAroundContents
+ : 0;
+ int horizontalMargin = hbarpolicy==Qt::ScrollBarAsNeeded
+ ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, hbar) + frameAroundContents
+ : 0;
layoutBounds.adjust(0, 0, -verticalMargin, -horizontalMargin);
- int rowCount = model->rowCount(root);
- int colCount = model->columnCount(root);
- if (colCount <= 0)
- rowCount = 0; // no contents
- if (viewMode == QListView::ListMode) {
- staticListView->flowPositions.resize(rowCount);
- } else {
- dynamicListView->tree.create(qMax(rowCount - hiddenRows.count(), 0));
- }
+ int rowCount = model->columnCount(root) <= 0 ? 0 : model->rowCount(root);
+ commonListView->setRowCount(rowCount);
}
/*!
@@ -1994,7 +1672,6 @@ void QListViewPrivate::prepareItemsLayout()
*/
bool QListViewPrivate::doItemsLayout(int delta)
{
- // ### split into static and dynamic
int max = model->rowCount(root) - 1;
int first = batchStartRow();
int last = qMin(first + delta - 1, max);
@@ -2018,9 +1695,7 @@ bool QListViewPrivate::doItemsLayout(int delta)
info.flow = flow;
info.max = max;
- if (viewMode == QListView::ListMode)
- return staticListView->doBatchedItemLayout(info, max);
- return dynamicListView->doBatchedItemLayout(info, max);
+ return commonListView->doBatchedItemLayout(info, max);
}
QListViewItem QListViewPrivate::indexToListViewItem(const QModelIndex &index) const
@@ -2028,33 +1703,19 @@ QListViewItem QListViewPrivate::indexToListViewItem(const QModelIndex &index) co
if (!index.isValid() || isHidden(index.row()))
return QListViewItem();
- if (viewMode == QListView::ListMode)
- return staticListView->indexToListViewItem(index);
- return dynamicListView->indexToListViewItem(index);
-}
-
-
-int QListViewPrivate::itemIndex(const QListViewItem &item) const
-{
- if (viewMode == QListView::ListMode)
- return staticListView->itemIndex(item);
- return dynamicListView->itemIndex(item);
+ return commonListView->indexToListViewItem(index);
}
-QRect QListViewPrivate::mapToViewport(const QRect &rect, bool greedy) const
+QRect QListViewPrivate::mapToViewport(const QRect &rect, bool extend) const
{
Q_Q(const QListView);
if (!rect.isValid())
return rect;
- QRect result = rect;
- if (greedy)
- result = staticListView->mapToViewport(rect);
-
+ QRect result = extend ? commonListView->mapToViewport(rect) : rect;
int dx = -q->horizontalOffset();
int dy = -q->verticalOffset();
- result.adjust(dx, dy, dx, dy);
- return result;
+ return result.adjusted(dx, dy, dx, dy);
}
QModelIndex QListViewPrivate::closestIndex(const QRect &target,
@@ -2112,8 +1773,8 @@ QItemSelection QListViewPrivate::selection(const QRect &rect) const
{
QItemSelection selection;
QModelIndex tl, br;
- intersectingSet(rect);
- QVector<QModelIndex>::iterator it = intersectVector.begin();
+ const QVector<QModelIndex> intersectVector = intersectingSet(rect);
+ QVector<QModelIndex>::const_iterator it = intersectVector.begin();
for (; it != intersectVector.end(); ++it) {
if (!tl.isValid() && !br.isValid()) {
tl = br = *it;
@@ -2138,46 +1799,217 @@ QItemSelection QListViewPrivate::selection(const QRect &rect) const
}
/*
- * Static ListView Implementation
+ * Common ListView Implementation
+*/
+
+void QCommonListViewBase::appendHiddenRow(int row)
+{
+ dd->hiddenRows.append(dd->model->index(row, 0));
+}
+
+void QCommonListViewBase::removeHiddenRow(int row)
+{
+ dd->hiddenRows.remove(dd->hiddenRows.indexOf(dd->model->index(row, 0)));
+}
+
+void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step)
+{
+ horizontalScrollBar()->setSingleStep(step.width() + spacing());
+ horizontalScrollBar()->setPageStep(viewport()->width());
+ horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width());
+}
+
+void QCommonListViewBase::updateVerticalScrollBar(const QSize &step)
+{
+ verticalScrollBar()->setSingleStep(step.height() + spacing());
+ verticalScrollBar()->setPageStep(viewport()->height());
+ verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height());
+}
+
+void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/)
+{
+ dd->scrollContentsBy(isRightToLeft() ? -dx : dx, dy);
+}
+
+int QCommonListViewBase::verticalScrollToValue(int /*index*/, QListView::ScrollHint hint,
+ bool above, bool below, const QRect &area, const QRect &rect) const
+{
+ int verticalValue = verticalScrollBar()->value();
+ QRect adjusted = rect.adjusted(-spacing(), -spacing(), spacing(), spacing());
+ if (hint == QListView::PositionAtTop || above)
+ verticalValue += adjusted.top();
+ else if (hint == QListView::PositionAtBottom || below)
+ verticalValue += qMin(adjusted.top(), adjusted.bottom() - area.height() + 1);
+ else if (hint == QListView::PositionAtCenter)
+ verticalValue += adjusted.top() - ((area.height() - adjusted.height()) / 2);
+ return verticalValue;
+}
+
+int QCommonListViewBase::horizontalOffset() const
+{
+ return (isRightToLeft() ? horizontalScrollBar()->maximum() - horizontalScrollBar()->value() : horizontalScrollBar()->value());
+}
+
+int QCommonListViewBase::horizontalScrollToValue(const int /*index*/, QListView::ScrollHint hint,
+ bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
+{
+ int horizontalValue = horizontalScrollBar()->value();
+ if (isRightToLeft()) {
+ if (hint == QListView::PositionAtCenter) {
+ horizontalValue += ((area.width() - rect.width()) / 2) - rect.left();
+ } else {
+ if (leftOf)
+ horizontalValue -= rect.left();
+ else if (rightOf)
+ horizontalValue += qMin(rect.left(), area.width() - rect.right());
+ }
+ } else {
+ if (hint == QListView::PositionAtCenter) {
+ horizontalValue += rect.left() - ((area.width()- rect.width()) / 2);
+ } else {
+ if (leftOf)
+ horizontalValue += rect.left();
+ else if (rightOf)
+ horizontalValue += qMin(rect.left(), rect.right() - area.width());
+ }
+ }
+ return horizontalValue;
+}
+
+/*
+ * ListMode ListView Implementation
*/
-int QStaticListViewBase::verticalPerItemValue(int itemIndex, int verticalValue, int areaHeight,
- bool above, bool below, bool wrap,
- QListView::ScrollHint hint, int itemHeight) const
+#ifndef QT_NO_DRAGANDDROP
+void QListModeViewBase::paintDragDrop(QPainter *painter)
{
- int value = qBound(0, verticalValue, flowPositions.count() - 1);
- if (above)
- return perItemScrollToValue(itemIndex, value, areaHeight, QListView::PositionAtTop,
- Qt::Vertical,wrap, itemHeight);
- else if (below)
- return perItemScrollToValue(itemIndex, value, areaHeight, QListView::PositionAtBottom,
- Qt::Vertical, wrap, itemHeight);
- else if (hint != QListView::EnsureVisible)
- return perItemScrollToValue(itemIndex, value, areaHeight, hint, Qt::Vertical, wrap, itemHeight);
- return value;
+ // FIXME: Until the we can provide a proper drop indicator
+ // in IconMode, it makes no sense to show it
+ dd->paintDropIndicator(painter);
}
+#endif //QT_NO_DRAGANDDROP
-int QStaticListViewBase::horizontalPerItemValue(int itemIndex, int horizontalValue, int areaWidth,
- bool leftOf, bool rightOf, bool wrap,
- QListView::ScrollHint hint, int itemWidth) const
+void QListModeViewBase::updateVerticalScrollBar(const QSize &step)
{
- int value = qBound(0, horizontalValue, flowPositions.count() - 1);
+ if (verticalScrollMode() == QAbstractItemView::ScrollPerItem
+ && ((flow() == QListView::TopToBottom && !isWrapping())
+ || (flow() == QListView::LeftToRight && isWrapping()))) {
+ const int steps = (flow() == QListView::TopToBottom ? flowPositions : segmentPositions).count() - 1;
+ if (steps > 0) {
+ const int pageSteps = perItemScrollingPageSteps(viewport()->height(), contentsSize.height(), isWrapping());
+ verticalScrollBar()->setSingleStep(1);
+ verticalScrollBar()->setPageStep(pageSteps);
+ verticalScrollBar()->setRange(0, steps - pageSteps);
+ } else {
+ verticalScrollBar()->setRange(0, 0);
+ }
+ // } else if (vertical && d->isWrapping() && d->movement == Static) {
+ // ### wrapped scrolling in flow direction
+ } else {
+ QCommonListViewBase::updateVerticalScrollBar(step);
+ }
+}
+
+void QListModeViewBase::updateHorizontalScrollBar(const QSize &step)
+{
+ if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem
+ && ((flow() == QListView::TopToBottom && isWrapping())
+ || (flow() == QListView::LeftToRight && !isWrapping()))) {
+ int steps = (flow() == QListView::TopToBottom ? segmentPositions : flowPositions).count() - 1;
+ if (steps > 0) {
+ const int pageSteps = perItemScrollingPageSteps(viewport()->width(), contentsSize.width(), isWrapping());
+ horizontalScrollBar()->setSingleStep(1);
+ horizontalScrollBar()->setPageStep(pageSteps);
+ horizontalScrollBar()->setRange(0, steps - pageSteps);
+ } else {
+ horizontalScrollBar()->setRange(0, 0);
+ }
+ } else {
+ QCommonListViewBase::updateHorizontalScrollBar(step);
+ }
+}
+
+int QListModeViewBase::verticalScrollToValue(int index, QListView::ScrollHint hint,
+ bool above, bool below, const QRect &area, const QRect &rect) const
+{
+ if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
+ int value = qBound(0, verticalScrollBar()->value(), flowPositions.count() - 1);
+ if (above)
+ hint = QListView::PositionAtTop;
+ else if (below)
+ hint = QListView::PositionAtBottom;
+ if (hint == QListView::EnsureVisible)
+ return value;
+
+ return perItemScrollToValue(index, value, area.height(), hint, Qt::Vertical, isWrapping(), rect.height());
+ }
+
+ return QCommonListViewBase::verticalScrollToValue(index, hint, above, below, area, rect);
+}
+
+int QListModeViewBase::horizontalOffset() const
+{
+ if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
+ if (isWrapping()) {
+ if (flow() == QListView::TopToBottom && !segmentPositions.isEmpty()) {
+ const int max = segmentPositions.count() - 1;
+ int currentValue = qBound(0, horizontalScrollBar()->value(), max);
+ int position = segmentPositions.at(currentValue);
+ int maximumValue = qBound(0, horizontalScrollBar()->maximum(), max);
+ int maximum = segmentPositions.at(maximumValue);
+ return (isRightToLeft() ? maximum - position : position);
+ }
+ } else if (flow() == QListView::LeftToRight && !flowPositions.isEmpty()) {
+ int position = flowPositions.at(horizontalScrollBar()->value());
+ int maximum = flowPositions.at(horizontalScrollBar()->maximum());
+ return (isRightToLeft() ? maximum - position : position);
+ }
+ }
+ return QCommonListViewBase::horizontalOffset();
+}
+
+int QListModeViewBase::verticalOffset() const
+{
+ if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
+ if (isWrapping()) {
+ if (flow() == QListView::LeftToRight && !segmentPositions.isEmpty()) {
+ int value = verticalScrollBar()->value();
+ if (value >= segmentPositions.count())
+ return 0;
+ return segmentPositions.at(value);
+ }
+ } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) {
+ int value = verticalScrollBar()->value();
+ if (value > flowPositions.count())
+ return 0;
+ return flowPositions.at(value) - spacing();
+ }
+ }
+ return QCommonListViewBase::verticalOffset();
+}
+
+int QListModeViewBase::horizontalScrollToValue(int index, QListView::ScrollHint hint,
+ bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
+{
+ if (horizontalScrollMode() != QAbstractItemView::ScrollPerItem)
+ return QCommonListViewBase::horizontalScrollToValue(index, hint, leftOf, rightOf, area, rect);
+
+ int value = qBound(0, horizontalScrollBar()->value(), flowPositions.count() - 1);
if (leftOf)
- return perItemScrollToValue(itemIndex, value, areaWidth, QListView::PositionAtTop,
- Qt::Horizontal, wrap, itemWidth);
+ hint = QListView::PositionAtTop;
else if (rightOf)
- return perItemScrollToValue(itemIndex, value, areaWidth, QListView::PositionAtBottom,
- Qt::Horizontal, wrap, itemWidth);
- else if (hint != QListView::EnsureVisible)
- return perItemScrollToValue(itemIndex, value, areaWidth, hint, Qt::Horizontal, wrap, itemWidth);
- return value;
+ hint = QListView::PositionAtBottom;
+ if (hint == QListView::EnsureVisible)
+ return value;
+
+ return perItemScrollToValue(index, value, area.width(), hint, Qt::Horizontal, isWrapping(), rect.width());
}
-void QStaticListViewBase::scrollContentsBy(int &dx, int &dy)
+void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
{
// ### reorder this logic
- const int verticalValue = verticalScrollBarValue();
- const int horizontalValue = horizontalScrollBarValue();
+ const int verticalValue = verticalScrollBar()->value();
+ const int horizontalValue = horizontalScrollBar()->value();
const bool vertical = (verticalScrollMode() == QAbstractItemView::ScrollPerItem);
const bool horizontal = (horizontalScrollMode() == QAbstractItemView::ScrollPerItem);
@@ -2216,9 +2048,10 @@ void QStaticListViewBase::scrollContentsBy(int &dx, int &dy)
dx = previousCoordinate - currentCoordinate;
}
}
+ QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand);
}
-bool QStaticListViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max)
+bool QListModeViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max)
{
doStaticLayout(info);
if (batchStartRow > max) { // stop items layout
@@ -2230,7 +2063,7 @@ bool QStaticListViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, i
return false; // not done
}
-QListViewItem QStaticListViewBase::indexToListViewItem(const QModelIndex &index) const
+QListViewItem QListModeViewBase::indexToListViewItem(const QModelIndex &index) const
{
if (flowPositions.isEmpty()
|| segmentPositions.isEmpty()
@@ -2266,7 +2099,7 @@ QListViewItem QStaticListViewBase::indexToListViewItem(const QModelIndex &index)
return QListViewItem(QRect(pos, size), index.row());
}
-QPoint QStaticListViewBase::initStaticLayout(const QListViewLayoutInfo &info)
+QPoint QListModeViewBase::initStaticLayout(const QListViewLayoutInfo &info)
{
int x, y;
if (info.first == 0) {
@@ -2301,7 +2134,7 @@ QPoint QStaticListViewBase::initStaticLayout(const QListViewLayoutInfo &info)
/*!
\internal
*/
-void QStaticListViewBase::doStaticLayout(const QListViewLayoutInfo &info)
+void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info)
{
const bool useItemSize = !info.grid.isValid();
const QPoint topLeft = initStaticLayout(info);
@@ -2404,9 +2237,9 @@ void QStaticListViewBase::doStaticLayout(const QListViewLayoutInfo &info)
Finds the set of items intersecting with \a area.
In this function, itemsize is counted from topleft to the start of the next item.
*/
-void QStaticListViewBase::intersectingStaticSet(const QRect &area) const
+QVector<QModelIndex> QListModeViewBase::intersectingSet(const QRect &area) const
{
- clearIntersections();
+ QVector<QModelIndex> ret;
int segStartPosition;
int segEndPosition;
int flowStartPosition;
@@ -2423,7 +2256,7 @@ void QStaticListViewBase::intersectingStaticSet(const QRect &area) const
flowEndPosition = area.bottom();
}
if (segmentPositions.count() < 2 || flowPositions.isEmpty())
- return;
+ return ret;
// the last segment position is actually the edge of the last segment
const int segLast = segmentPositions.count() - 2;
int seg = qBinarySearch<int>(segmentPositions, segStartPosition, 0, segLast + 1);
@@ -2438,39 +2271,34 @@ void QStaticListViewBase::intersectingStaticSet(const QRect &area) const
continue;
QModelIndex index = modelIndex(row);
if (index.isValid())
- appendToIntersections(index);
+ ret += index;
#if 0 // for debugging
else
- qWarning("intersectingStaticSet: row %d was invalid", row);
+ qWarning("intersectingSet: row %d was invalid", row);
#endif
}
}
+ return ret;
}
-int QStaticListViewBase::itemIndex(const QListViewItem &item) const
-{
- return item.indexHint;
-}
-
-QRect QStaticListViewBase::mapToViewport(const QRect &rect) const
+QRect QListModeViewBase::mapToViewport(const QRect &rect) const
{
if (isWrapping())
return rect;
// If the listview is in "listbox-mode", the items are as wide as the view.
+ // But we don't shrink the items.
QRect result = rect;
- QSize vsize = viewport()->size();
- QSize csize = contentsSize;
if (flow() == QListView::TopToBottom) {
result.setLeft(spacing());
- result.setWidth(qMax(csize.width(), vsize.width()) - 2 * spacing());
+ result.setWidth(qMax(rect.width(), qMax(contentsSize.width(), viewport()->width()) - 2 * spacing()));
} else { // LeftToRight
result.setTop(spacing());
- result.setHeight(qMax(csize.height(), vsize.height()) - 2 * spacing());
+ result.setHeight(qMax(rect.height(), qMax(contentsSize.height(), viewport()->height()) - 2 * spacing()));
}
return result;
}
-int QStaticListViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const
+int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const
{
const QVector<int> positions = (wrap ? segmentPositions : flowPositions);
if (positions.isEmpty() || bounds <= length)
@@ -2498,7 +2326,7 @@ int QStaticListViewBase::perItemScrollingPageSteps(int length, int bounds, bool
return qMax(pageSteps, 1);
}
-int QStaticListViewBase::perItemScrollToValue(int index, int scrollValue, int viewportSize,
+int QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int viewportSize,
QAbstractItemView::ScrollHint hint,
Qt::Orientation orientation, bool wrap, int itemExtent) const
{
@@ -2558,7 +2386,7 @@ int QStaticListViewBase::perItemScrollToValue(int index, int scrollValue, int vi
return scrollValue;
}
-void QStaticListViewBase::clear()
+void QListModeViewBase::clear()
{
flowPositions.clear();
segmentPositions.clear();
@@ -2570,10 +2398,175 @@ void QStaticListViewBase::clear()
}
/*
- * Dynamic ListView Implementation
+ * IconMode ListView Implementation
*/
-void QDynamicListViewBase::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+void QIconModeViewBase::setPositionForIndex(const QPoint &position, const QModelIndex &index)
+{
+ if (index.row() >= items.count())
+ return;
+ const QSize oldContents = contentsSize;
+ qq->update(index); // update old position
+ moveItem(index.row(), position);
+ qq->update(index); // update new position
+
+ if (contentsSize != oldContents)
+ dd->viewUpdateGeometries(); // update the scroll bars
+}
+
+void QIconModeViewBase::appendHiddenRow(int row)
+{
+ if (row >= 0 && row < items.count()) //remove item
+ tree.removeLeaf(items.at(row).rect(), row);
+ QCommonListViewBase::appendHiddenRow(row);
+}
+
+void QIconModeViewBase::removeHiddenRow(int row)
+{
+ QCommonListViewBase::appendHiddenRow(row);
+ if (row >= 0 && row < items.count()) //insert item
+ tree.insertLeaf(items.at(row).rect(), row);
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QIconModeViewBase::paintDragDrop(QPainter *painter)
+{
+ if (!draggedItems.isEmpty() && viewport()->rect().contains(draggedItemsPos)) {
+ //we need to draw the items that arre dragged
+ painter->translate(draggedItemsDelta());
+ QStyleOptionViewItemV4 option = viewOptions();
+ option.state &= ~QStyle::State_MouseOver;
+ QVector<QModelIndex>::const_iterator it = draggedItems.begin();
+ QListViewItem item = indexToListViewItem(*it);
+ for (; it != draggedItems.end(); ++it) {
+ item = indexToListViewItem(*it);
+ option.rect = viewItemRect(item);
+ delegate(*it)->paint(painter, option, *it);
+ }
+ }
+}
+
+bool QIconModeViewBase::filterStartDrag(Qt::DropActions supportedActions)
+{
+ // This function does the same thing as in QAbstractItemView::startDrag(),
+ // plus adding viewitems to the draggedItems list.
+ // We need these items to draw the drag items
+ QModelIndexList indexes = dd->selectionModel->selectedIndexes();
+ if (indexes.count() > 0 ) {
+ if (viewport()->acceptDrops()) {
+ QModelIndexList::ConstIterator it = indexes.constBegin();
+ for (; it != indexes.constEnd(); ++it)
+ if (dd->model->flags(*it) & Qt::ItemIsDragEnabled
+ && (*it).column() == dd->column)
+ draggedItems.push_back(*it);
+ }
+ QDrag *drag = new QDrag(qq);
+ drag->setMimeData(dd->model->mimeData(indexes));
+ Qt::DropAction action = drag->exec(supportedActions, Qt::CopyAction);
+ draggedItems.clear();
+ if (action == Qt::MoveAction)
+ dd->clearOrRemove();
+ }
+ return true;
+}
+
+bool QIconModeViewBase::filterDropEvent(QDropEvent *e)
+{
+ if (e->source() != qq)
+ return false;
+
+ const QSize contents = contentsSize;
+ QPoint offset(horizontalOffset(), verticalOffset());
+ QPoint end = e->pos() + offset;
+ QPoint start = dd->pressedPosition;
+ QPoint delta = (dd->movement == QListView::Snap ? snapToGrid(end) - snapToGrid(start) : end - start);
+ QList<QModelIndex> indexes = dd->selectionModel->selectedIndexes();
+ for (int i = 0; i < indexes.count(); ++i) {
+ QModelIndex index = indexes.at(i);
+ QRect rect = dd->rectForIndex(index);
+ viewport()->update(mapToViewport(rect));
+ QPoint dest = rect.topLeft() + delta;
+ if (qq->isRightToLeft())
+ dest.setX(dd->flipX(dest.x()) - rect.width());
+ moveItem(index.row(), dest);
+ qq->update(index);
+ }
+ dd->stopAutoScroll();
+ draggedItems.clear();
+ dd->emitIndexesMoved(indexes);
+ e->accept(); // we have handled the event
+ // if the size has not grown, we need to check if it has shrinked
+ if (contentsSize != contents) {
+ if ((contentsSize.width() <= contents.width()
+ || contentsSize.height() <= contents.height())) {
+ updateContentsSize();
+ }
+ dd->viewUpdateGeometries();
+ }
+ return true;
+}
+
+bool QIconModeViewBase::filterDragLeaveEvent(QDragLeaveEvent *e)
+{
+ viewport()->update(draggedItemsRect()); // erase the area
+ draggedItemsPos = QPoint(-1, -1); // don't draw the dragged items
+ return QCommonListViewBase::filterDragLeaveEvent(e);
+}
+
+bool QIconModeViewBase::filterDragMoveEvent(QDragMoveEvent *e)
+{
+ if (e->source() != qq || !dd->canDecode(e))
+ return false;
+
+ // ignore by default
+ e->ignore();
+ // get old dragged items rect
+ QRect itemsRect = this->itemsRect(draggedItems);
+ viewport()->update(itemsRect.translated(draggedItemsDelta()));
+ // update position
+ draggedItemsPos = e->pos();
+ // get new items rect
+ viewport()->update(itemsRect.translated(draggedItemsDelta()));
+ // set the item under the cursor to current
+ QModelIndex index;
+ if (movement() == QListView::Snap) {
+ QRect rect(snapToGrid(e->pos() + offset()), gridSize());
+ const QVector<QModelIndex> intersectVector = intersectingSet(rect);
+ index = intersectVector.count() > 0 ? intersectVector.last() : QModelIndex();
+ } else {
+ index = qq->indexAt(e->pos());
+ }
+ // check if we allow drops here
+ if (draggedItems.contains(index))
+ e->accept(); // allow changing item position
+ else if (dd->model->flags(index) & Qt::ItemIsDropEnabled)
+ e->accept(); // allow dropping on dropenabled items
+ else if (!index.isValid())
+ e->accept(); // allow dropping in empty areas
+
+ // the event was treated. do autoscrolling
+ if (dd->shouldAutoScroll(e->pos()))
+ dd->startAutoScroll();
+ return true;
+}
+#endif // QT_NO_DRAGANDDROP
+
+void QIconModeViewBase::setRowCount(int rowCount)
+{
+ tree.create(qMax(rowCount - hiddenCount(), 0));
+}
+
+void QIconModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
+{
+ if (scrollElasticBand)
+ dd->scrollElasticBandBy(isRightToLeft() ? -dx : dx, dy);
+
+ QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand);
+ if (!draggedItems.isEmpty())
+ viewport()->update(draggedItemsRect().translated(dx, dy));
+}
+
+void QIconModeViewBase::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
if (column() >= topLeft.column() && column() <= bottomRight.column()) {
QStyleOptionViewItemV4 option = viewOptions();
@@ -2583,23 +2576,29 @@ void QDynamicListViewBase::dataChanged(const QModelIndex &topLeft, const QModelI
}
}
-bool QDynamicListViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max)
+bool QIconModeViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max)
{
if (info.last >= items.count()) {
- createItems(info.last + 1);
+ //first we create the items
+ QStyleOptionViewItemV4 option = viewOptions();
+ for (int row = items.count(); row <= info.last; ++row) {
+ QSize size = itemSize(option, modelIndex(row));
+ QListViewItem item(QRect(0, 0, size.width(), size.height()), row); // default pos
+ items.append(item);
+ }
doDynamicLayout(info);
}
return (batchStartRow > max); // done
}
-QListViewItem QDynamicListViewBase::indexToListViewItem(const QModelIndex &index) const
+QListViewItem QIconModeViewBase::indexToListViewItem(const QModelIndex &index) const
{
if (index.isValid() && index.row() < items.count())
return items.at(index.row());
return QListViewItem();
}
-void QDynamicListViewBase::initBspTree(const QSize &contents)
+void QIconModeViewBase::initBspTree(const QSize &contents)
{
// remove all items from the tree
int leafCount = tree.leafCount();
@@ -2616,7 +2615,7 @@ void QDynamicListViewBase::initBspTree(const QSize &contents)
tree.init(QRect(0, 0, contents.width(), contents.height()), type);
}
-QPoint QDynamicListViewBase::initDynamicLayout(const QListViewLayoutInfo &info)
+QPoint QIconModeViewBase::initDynamicLayout(const QListViewLayoutInfo &info)
{
int x, y;
if (info.first == 0) {
@@ -2638,7 +2637,7 @@ QPoint QDynamicListViewBase::initDynamicLayout(const QListViewLayoutInfo &info)
/*!
\internal
*/
-void QDynamicListViewBase::doDynamicLayout(const QListViewLayoutInfo &info)
+void QIconModeViewBase::doDynamicLayout(const QListViewLayoutInfo &info)
{
const bool useItemSize = !info.grid.isValid();
const QPoint topLeft = initDynamicLayout(info);
@@ -2672,7 +2671,7 @@ void QDynamicListViewBase::doDynamicLayout(const QListViewLayoutInfo &info)
if (moved.count() != items.count())
moved.resize(items.count());
- QRect rect(QPoint(0, 0), topLeft);
+ QRect rect(QPoint(), topLeft);
QListViewItem *item = 0;
for (int row = info.first; row <= info.last; ++row) {
item = &items[row];
@@ -2765,40 +2764,18 @@ void QDynamicListViewBase::doDynamicLayout(const QListViewLayoutInfo &info)
viewport()->update();
}
-void QDynamicListViewBase::intersectingDynamicSet(const QRect &area) const
+QVector<QModelIndex> QIconModeViewBase::intersectingSet(const QRect &area) const
{
- clearIntersections();
- QListViewPrivate *that = const_cast<QListViewPrivate*>(dd);
+ QIconModeViewBase *that = const_cast<QIconModeViewBase*>(this);
QBspTree::Data data(static_cast<void*>(that));
- that->dynamicListView->tree.climbTree(area, &QDynamicListViewBase::addLeaf, data);
-}
-
-void QDynamicListViewBase::createItems(int to)
-{
- int count = items.count();
- QSize size;
- QStyleOptionViewItemV4 option = viewOptions();
- for (int row = count; row < to; ++row) {
- size = itemSize(option, modelIndex(row));
- QListViewItem item(QRect(0, 0, size.width(), size.height()), row); // default pos
- items.append(item);
- }
+ QVector<QModelIndex> res;
+ that->interSectingVector = &res;
+ that->tree.climbTree(area, &QIconModeViewBase::addLeaf, data);
+ that->interSectingVector = 0;
+ return res;
}
-void QDynamicListViewBase::drawItems(QPainter *painter, const QVector<QModelIndex> &indexes) const
-{
- QStyleOptionViewItemV4 option = viewOptions();
- option.state &= ~QStyle::State_MouseOver;
- QVector<QModelIndex>::const_iterator it = indexes.begin();
- QListViewItem item = indexToListViewItem(*it);
- for (; it != indexes.end(); ++it) {
- item = indexToListViewItem(*it);
- option.rect = viewItemRect(item);
- delegate(*it)->paint(painter, option, *it);
- }
-}
-
-QRect QDynamicListViewBase::itemsRect(const QVector<QModelIndex> &indexes) const
+QRect QIconModeViewBase::itemsRect(const QVector<QModelIndex> &indexes) const
{
QVector<QModelIndex>::const_iterator it = indexes.begin();
QListViewItem item = indexToListViewItem(*it);
@@ -2810,7 +2787,7 @@ QRect QDynamicListViewBase::itemsRect(const QVector<QModelIndex> &indexes) const
return rect;
}
-int QDynamicListViewBase::itemIndex(const QListViewItem &item) const
+int QIconModeViewBase::itemIndex(const QListViewItem &item) const
{
if (!item.isValid())
return -1;
@@ -2846,39 +2823,27 @@ int QDynamicListViewBase::itemIndex(const QListViewItem &item) const
return -1;
}
-void QDynamicListViewBase::addLeaf(QVector<int> &leaf, const QRect &area,
- uint visited, QBspTree::Data data)
+void QIconModeViewBase::addLeaf(QVector<int> &leaf, const QRect &area,
+ uint visited, QBspTree::Data data)
{
QListViewItem *vi;
- QListViewPrivate *_this = static_cast<QListViewPrivate *>(data.ptr);
+ QIconModeViewBase *_this = static_cast<QIconModeViewBase *>(data.ptr);
for (int i = 0; i < leaf.count(); ++i) {
int idx = leaf.at(i);
- if (idx < 0 || idx >= _this->dynamicListView->items.count())
+ if (idx < 0 || idx >= _this->items.count())
continue;
- vi = &_this->dynamicListView->items[idx];
+ vi = &_this->items[idx];
Q_ASSERT(vi);
if (vi->isValid() && vi->rect().intersects(area) && vi->visited != visited) {
- QModelIndex index = _this->listViewItemToIndex(*vi);
+ QModelIndex index = _this->dd->listViewItemToIndex(*vi);
Q_ASSERT(index.isValid());
- _this->intersectVector.append(index);
+ _this->interSectingVector->append(index);
vi->visited = visited;
}
}
}
-void QDynamicListViewBase::insertItem(int index)
-{
- if (index >= 0 && index < items.count())
- tree.insertLeaf(items.at(index).rect(), index);
-}
-
-void QDynamicListViewBase::removeItem(int index)
-{
- if (index >= 0 && index < items.count())
- tree.removeLeaf(items.at(index).rect(), index);
-}
-
-void QDynamicListViewBase::moveItem(int index, const QPoint &dest)
+void QIconModeViewBase::moveItem(int index, const QPoint &dest)
{
// does not impact on the bintree itself or the contents rect
QListViewItem *item = &items[index];
@@ -2898,14 +2863,14 @@ void QDynamicListViewBase::moveItem(int index, const QPoint &dest)
moved.setBit(index, true);
}
-QPoint QDynamicListViewBase::snapToGrid(const QPoint &pos) const
+QPoint QIconModeViewBase::snapToGrid(const QPoint &pos) const
{
int x = pos.x() - (pos.x() % gridSize().width());
int y = pos.y() - (pos.y() % gridSize().height());
return QPoint(x, y);
}
-QPoint QDynamicListViewBase::draggedItemsDelta() const
+QPoint QIconModeViewBase::draggedItemsDelta() const
{
if (movement() == QListView::Snap) {
QPoint snapdelta = QPoint((offset().x() % gridSize().width()),
@@ -2915,7 +2880,7 @@ QPoint QDynamicListViewBase::draggedItemsDelta() const
return draggedItemsPos - pressedPosition();
}
-QRect QDynamicListViewBase::draggedItemsRect() const
+QRect QIconModeViewBase::draggedItemsRect() const
{
QRect rect = itemsRect(draggedItems);
rect.translate(draggedItemsDelta());
@@ -2934,7 +2899,7 @@ void QListViewPrivate::scrollElasticBandBy(int dx, int dy)
elasticBand.moveTop(elasticBand.top() - dy);
}
-void QDynamicListViewBase::clear()
+void QIconModeViewBase::clear()
{
tree.destroy();
items.clear();
@@ -2943,7 +2908,7 @@ void QDynamicListViewBase::clear()
batchSavedDeltaSeg = 0;
}
-void QDynamicListViewBase::updateContentsSize()
+void QIconModeViewBase::updateContentsSize()
{
QRect bounding;
for (int i = 0; i < items.count(); ++i)
@@ -2996,7 +2961,7 @@ int QListView::visualIndex(const QModelIndex &index) const
Q_D(const QListView);
d->executePostedLayout();
QListViewItem itm = d->indexToListViewItem(index);
- return d->itemIndex(itm);
+ return d->commonListView->itemIndex(itm);
}
QT_END_NAMESPACE
diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h
index 6294c11..9c6a0c2 100644
--- a/src/gui/itemviews/qlistview_p.h
+++ b/src/gui/itemviews/qlistview_p.h
@@ -67,8 +67,8 @@ QT_BEGIN_NAMESPACE
class QListViewItem
{
friend class QListViewPrivate;
- friend class QStaticListViewBase;
- friend class QDynamicListViewBase;
+ friend class QListModeViewBase;
+ friend class QIconModeViewBase;
public:
inline QListViewItem()
: x(-1), y(-1), w(0), h(0), indexHint(-1), visited(0xffff) {}
@@ -84,7 +84,7 @@ public:
inline bool operator!=(const QListViewItem &other) const
{ return !(*this == other); }
inline bool isValid() const
- { return (x > -1) && (y > -1) && (w > 0) && (h > 0) && (indexHint > -1); }
+ { return rect().isValid() && (indexHint > -1); }
inline void invalidate()
{ x = -1; y = -1; w = 0; h = 0; }
inline void resize(const QSize &size)
@@ -120,8 +120,42 @@ class QListViewPrivate;
class QCommonListViewBase
{
public:
- inline QCommonListViewBase(QListView *q, QListViewPrivate *d) : dd(d), qq(q) {}
-
+ inline QCommonListViewBase(QListView *q, QListViewPrivate *d) : dd(d), qq(q), batchStartRow(0), batchSavedDeltaSeg(0) {}
+ virtual ~QCommonListViewBase() {}
+
+ //common interface
+ virtual int itemIndex(const QListViewItem &item) const = 0;
+ virtual QListViewItem indexToListViewItem(const QModelIndex &index) const = 0;
+ virtual bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max) = 0;
+ virtual void clear() = 0;
+ virtual void setRowCount(int) = 0;
+ virtual QVector<QModelIndex> intersectingSet(const QRect &area) const = 0;
+
+ virtual int horizontalScrollToValue(int index, QListView::ScrollHint hint,
+ bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const;
+ virtual int verticalScrollToValue(int index, QListView::ScrollHint hint,
+ bool above, bool below, const QRect &area, const QRect &rect) const;
+ virtual void scrollContentsBy(int dx, int dy, bool scrollElasticBand);
+ virtual QRect mapToViewport(const QRect &rect) const {return rect;}
+ virtual int horizontalOffset() const;
+ virtual int verticalOffset() const { return verticalScrollBar()->value(); }
+ virtual void updateHorizontalScrollBar(const QSize &step);
+ virtual void updateVerticalScrollBar(const QSize &step);
+ virtual void dataChanged(const QModelIndex &, const QModelIndex &) { }
+ virtual void appendHiddenRow(int row);
+ virtual void removeHiddenRow(int row);
+ virtual void setPositionForIndex(const QPoint &, const QModelIndex &) { }
+
+#ifndef QT_NO_DRAGANDDROP
+ virtual void paintDragDrop(QPainter *painter) = 0;
+ virtual bool filterDragMoveEvent(QDragMoveEvent *) { return false; }
+ virtual bool filterDragLeaveEvent(QDragLeaveEvent *) { return false; }
+ virtual bool filterDropEvent(QDropEvent *) { return false; }
+ virtual bool filterStartDrag(Qt::DropActions) { return false; }
+#endif
+
+
+ //other inline members
inline int spacing() const;
inline bool isWrapping() const;
inline QSize gridSize() const;
@@ -133,8 +167,8 @@ public:
inline bool uniformItemSizes() const;
inline int column() const;
- inline int verticalScrollBarValue() const;
- inline int horizontalScrollBarValue() const;
+ inline QScrollBar *verticalScrollBar() const;
+ inline QScrollBar *horizontalScrollBar() const;
inline QListView::ScrollMode verticalScrollMode() const;
inline QListView::ScrollMode horizontalScrollMode() const;
@@ -153,116 +187,111 @@ public:
inline bool isHidden(int row) const;
inline int hiddenCount() const;
- inline void clearIntersections() const;
- inline void appendToIntersections(const QModelIndex &idx) const;
-
inline bool isRightToLeft() const;
QListViewPrivate *dd;
QListView *qq;
+ QSize contentsSize;
+ int batchStartRow;
+ int batchSavedDeltaSeg;
};
-// ### rename to QListModeViewBase
-class QStaticListViewBase : public QCommonListViewBase
+class QListModeViewBase : public QCommonListViewBase
{
- friend class QListViewPrivate;
public:
- QStaticListViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d),
- batchStartRow(0), batchSavedDeltaSeg(0), batchSavedPosition(0) {}
+ QListModeViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d) {}
QVector<int> flowPositions;
QVector<int> segmentPositions;
QVector<int> segmentStartRows;
QVector<int> segmentExtents;
- QSize contentsSize;
-
// used when laying out in batches
- int batchStartRow;
- int batchSavedDeltaSeg;
int batchSavedPosition;
+ //reimplementations
+ int itemIndex(const QListViewItem &item) const { return item.indexHint; }
+ QListViewItem indexToListViewItem(const QModelIndex &index) const;
bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max);
+ void clear();
+ void setRowCount(int rowCount) { flowPositions.resize(rowCount); }
+ QVector<QModelIndex> intersectingSet(const QRect &area) const;
+
+ int horizontalScrollToValue(int index, QListView::ScrollHint hint,
+ bool leftOf, bool rightOf,const QRect &area, const QRect &rect) const;
+ int verticalScrollToValue(int index, QListView::ScrollHint hint,
+ bool above, bool below, const QRect &area, const QRect &rect) const;
+ void scrollContentsBy(int dx, int dy, bool scrollElasticBand);
+ QRect mapToViewport(const QRect &rect) const;
+ int horizontalOffset() const;
+ int verticalOffset() const;
+ void updateHorizontalScrollBar(const QSize &step);
+ void updateVerticalScrollBar(const QSize &step);
+
+#ifndef QT_NO_DRAGANDDROP
+ void paintDragDrop(QPainter *painter);
+#endif
+private:
QPoint initStaticLayout(const QListViewLayoutInfo &info);
void doStaticLayout(const QListViewLayoutInfo &info);
- void intersectingStaticSet(const QRect &area) const;
-
- int itemIndex(const QListViewItem &item) const;
-
- int perItemScrollingPageSteps(int length, int bounds, bool wrap) const;
-
int perItemScrollToValue(int index, int value, int height,
QAbstractItemView::ScrollHint hint,
Qt::Orientation orientation, bool wrap, int extent) const;
-
- QRect mapToViewport(const QRect &rect) const;
-
- QListViewItem indexToListViewItem(const QModelIndex &index) const;
-
- void scrollContentsBy(int &dx, int &dy);
-
- int verticalPerItemValue(int itemIndex, int verticalValue, int areaHeight,
- bool above, bool below, bool wrap, QListView::ScrollHint hint, int itemHeight) const;
- int horizontalPerItemValue(int itemIndex, int horizontalValue, int areaWidth,
- bool leftOf, bool rightOf, bool wrap, QListView::ScrollHint hint, int itemWidth) const;
-
- void clear();
+ int perItemScrollingPageSteps(int length, int bounds, bool wrap) const;
};
-// ### rename to QIconModeViewBase
-class QDynamicListViewBase : public QCommonListViewBase
+class QIconModeViewBase : public QCommonListViewBase
{
- friend class QListViewPrivate;
public:
- QDynamicListViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d),
- batchStartRow(0), batchSavedDeltaSeg(0) {}
+ QIconModeViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d), interSectingVector(0) {}
QBspTree tree;
QVector<QListViewItem> items;
QBitArray moved;
- QSize contentsSize;
-
QVector<QModelIndex> draggedItems; // indices to the tree.itemVector
mutable QPoint draggedItemsPos;
// used when laying out in batches
- int batchStartRow;
- int batchSavedDeltaSeg;
+ QVector<QModelIndex> *interSectingVector; //used from within intersectingSet
- void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ //reimplementations
+ int itemIndex(const QListViewItem &item) const;
+ QListViewItem indexToListViewItem(const QModelIndex &index) const;
bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max);
+ void clear();
+ void setRowCount(int rowCount);
+ QVector<QModelIndex> intersectingSet(const QRect &area) const;
+
+ void scrollContentsBy(int dx, int dy, bool scrollElasticBand);
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void appendHiddenRow(int row);
+ void removeHiddenRow(int row);
+ void setPositionForIndex(const QPoint &position, const QModelIndex &index);
+
+#ifndef QT_NO_DRAGANDDROP
+ void paintDragDrop(QPainter *painter);
+ bool filterDragMoveEvent(QDragMoveEvent *);
+ bool filterDragLeaveEvent(QDragLeaveEvent *);
+ bool filterDropEvent(QDropEvent *e);
+ bool filterStartDrag(Qt::DropActions);
+#endif
+private:
void initBspTree(const QSize &contents);
QPoint initDynamicLayout(const QListViewLayoutInfo &info);
void doDynamicLayout(const QListViewLayoutInfo &info);
- void intersectingDynamicSet(const QRect &area) const;
-
static void addLeaf(QVector<int> &leaf, const QRect &area,
uint visited, QBspTree::Data data);
-
- void insertItem(int index);
- void removeItem(int index);
- void moveItem(int index, const QPoint &dest);
-
- int itemIndex(const QListViewItem &item) const;
-
- void createItems(int to);
- void drawItems(QPainter *painter, const QVector<QModelIndex> &indexes) const;
QRect itemsRect(const QVector<QModelIndex> &indexes) const;
-
- QPoint draggedItemsDelta() const;
QRect draggedItemsRect() const;
-
QPoint snapToGrid(const QPoint &pos) const;
-
- void scrollElasticBandBy(int dx, int dy);
-
- QListViewItem indexToListViewItem(const QModelIndex &index) const;
-
- void clear();
void updateContentsSize();
+ QPoint draggedItemsDelta() const;
+ void drawItems(QPainter *painter, const QVector<QModelIndex> &indexes) const;
+ void moveItem(int index, const QPoint &dest);
+
};
class QListViewPrivate: public QAbstractItemViewPrivate
@@ -277,26 +306,16 @@ public:
bool doItemsLayout(int num);
- inline void intersectingSet(const QRect &area, bool doLayout = true) const {
+ inline QVector<QModelIndex> intersectingSet(const QRect &area, bool doLayout = true) const {
if (doLayout) executePostedLayout();
QRect a = (q_func()->isRightToLeft() ? flipX(area.normalized()) : area.normalized());
- if (viewMode == QListView::ListMode) staticListView->intersectingStaticSet(a);
- else dynamicListView->intersectingDynamicSet(a);
+ return commonListView->intersectingSet(a);
}
- // ### FIXME:
- inline void resetBatchStartRow()
- { if (viewMode == QListView::ListMode) staticListView->batchStartRow = 0;
- else dynamicListView->batchStartRow = 0; }
- inline int batchStartRow() const
- { return (viewMode == QListView::ListMode
- ? staticListView->batchStartRow : dynamicListView->batchStartRow); }
- inline QSize contentsSize() const
- { return (viewMode == QListView::ListMode
- ? staticListView->contentsSize : dynamicListView->contentsSize); }
- inline void setContentsSize(int w, int h)
- { if (viewMode == QListView::ListMode) staticListView->contentsSize = QSize(w, h);
- else dynamicListView->contentsSize = QSize(w, h); }
+ inline void resetBatchStartRow() { commonListView->batchStartRow = 0; }
+ inline int batchStartRow() const { return commonListView->batchStartRow; }
+ inline QSize contentsSize() const { return commonListView->contentsSize; }
+ inline void setContentsSize(int w, int h) { commonListView->contentsSize = QSize(w, h); }
inline int flipX(int x) const
{ return qMax(viewport->width(), contentsSize().width()) - x; }
@@ -307,12 +326,22 @@ public:
inline QRect viewItemRect(const QListViewItem &item) const
{ if (q_func()->isRightToLeft()) return flipX(item.rect()); return item.rect(); }
- int itemIndex(const QListViewItem &item) const;
QListViewItem indexToListViewItem(const QModelIndex &index) const;
inline QModelIndex listViewItemToIndex(const QListViewItem &item) const
- { return model->index(itemIndex(item), column, root); }
+ { return model->index(commonListView->itemIndex(item), column, root); }
+
+ QRect rectForIndex(const QModelIndex &index) const
+ {
+ if (!isIndexValid(index) || index.parent() != root || index.column() != column || isHidden(index.row()))
+ return QRect();
+ executePostedLayout();
+ return viewItemRect(indexToListViewItem(index));
+ }
+
+ void viewUpdateGeometries() { q_func()->updateGeometries(); }
- QRect mapToViewport(const QRect &rect, bool greedy = false) const;
+
+ QRect mapToViewport(const QRect &rect, bool extend = true) const;
QModelIndex closestIndex(const QRect &target, const QVector<QModelIndex> &candidates) const;
QSize itemSize(const QStyleOptionViewItem &option, const QModelIndex &index) const;
@@ -351,9 +380,12 @@ public:
void scrollElasticBandBy(int dx, int dy);
- // ### FIXME: we only need one at a time
- QDynamicListViewBase *dynamicListView;
- QStaticListViewBase *staticListView;
+ QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const;
+
+ void emitIndexesMoved(const QModelIndexList &indexes) { emit q_func()->indexesMoved(indexes); }
+
+
+ QCommonListViewBase *commonListView;
// ### FIXME: see if we can move the members into the dynamic/static classes
@@ -383,9 +415,6 @@ public:
QRect layoutBounds;
- // used for intersecting set
- mutable QVector<QModelIndex> intersectVector;
-
// timers
QBasicTimer batchLayoutTimer;
@@ -414,8 +443,8 @@ inline QPoint QCommonListViewBase::pressedPosition() const { return dd->pressedP
inline bool QCommonListViewBase::uniformItemSizes() const { return dd->uniformItemSizes; }
inline int QCommonListViewBase::column() const { return dd->column; }
-inline int QCommonListViewBase::verticalScrollBarValue() const { return qq->verticalScrollBar()->value(); }
-inline int QCommonListViewBase::horizontalScrollBarValue() const { return qq->horizontalScrollBar()->value(); }
+inline QScrollBar *QCommonListViewBase::verticalScrollBar() const { return qq->verticalScrollBar(); }
+inline QScrollBar *QCommonListViewBase::horizontalScrollBar() const { return qq->horizontalScrollBar(); }
inline QListView::ScrollMode QCommonListViewBase::verticalScrollMode() const { return qq->verticalScrollMode(); }
inline QListView::ScrollMode QCommonListViewBase::horizontalScrollMode() const { return qq->horizontalScrollMode(); }
@@ -438,9 +467,6 @@ inline QAbstractItemDelegate *QCommonListViewBase::delegate(const QModelIndex &i
inline bool QCommonListViewBase::isHidden(int row) const { return dd->isHidden(row); }
inline int QCommonListViewBase::hiddenCount() const { return dd->hiddenRows.count(); }
-inline void QCommonListViewBase::clearIntersections() const { dd->intersectVector.clear(); }
-inline void QCommonListViewBase::appendToIntersections(const QModelIndex &idx) const { dd->intersectVector.append(idx); }
-
inline bool QCommonListViewBase::isRightToLeft() const { return qq->isRightToLeft(); }
QT_END_NAMESPACE
diff --git a/src/gui/itemviews/qlistwidget.cpp b/src/gui/itemviews/qlistwidget.cpp
index 94186b8..b0d5384 100644
--- a/src/gui/itemviews/qlistwidget.cpp
+++ b/src/gui/itemviews/qlistwidget.cpp
@@ -447,21 +447,20 @@ Qt::DropActions QListModel::supportedDropActions() const
\ingroup model-view
- QListWidgetItem is used to represent items in a list provided by the
- QListWidget class. Each item can hold several pieces of information,
- and will display these appropriately.
+ A QListWidgetItem represents a single item in a QListWidget. Each item can
+ hold several pieces of information, and will display them appropriately.
- The item view convenience classes use a classic item-based interface
- rather than a pure model/view approach. For a more flexible list view
- widget, consider using the QListView class with a standard model.
+ The item view convenience classes use a classic item-based interface rather
+ than a pure model/view approach. For a more flexible list view widget,
+ consider using the QListView class with a standard model.
- List items can be automatically inserted into a list when they are
- constructed by specifying the list widget:
+ List items can be inserted automatically into a list, when they are
+ constructed, by specifying the list widget:
\snippet doc/src/snippets/qlistwidget-using/mainwindow.cpp 2
- They can also be created without a parent widget, and later inserted into
- a list (see \l{QListWidget::insertItem()}).
+ Alternatively, list items can also be created without a parent widget, and
+ later inserted into a list using QListWidget::insertItem().
List items are typically used to display text() and an icon(). These are
set with the setText() and setIcon() functions. The appearance of the text
@@ -471,22 +470,24 @@ Qt::DropActions QListModel::supportedDropActions() const
with setToolTip(), setStatusTip(), and setWhatsThis().
By default, items are enabled, selectable, checkable, and can be the source
- of a drag and drop operation.
+ of drag and drop operations.
+
Each item's flags can be changed by calling setFlags() with the appropriate
- value (see \l{Qt::ItemFlags}). Checkable items can be checked, unchecked and
+ value (see Qt::ItemFlags). Checkable items can be checked, unchecked and
partially checked with the setCheckState() function. The corresponding
- checkState() function indicates what check state the item currently has.
+ checkState() function indicates the item's current check state.
+
+ The isHidden() function can be used to determine whether the item is
+ hidden. To hide an item, use setHidden().
- The isHidden() function can be used to determine whether the
- item is hidden. Items can be hidden with setHidden().
\section1 Subclassing
When subclassing QListWidgetItem to provide custom items, it is possible to
- define new types for them so that they can be distinguished from standard
- items. The constructors for subclasses that require this feature need to
- call the base class constructor with a new type value equal to or greater
- than \l UserType.
+ define new types for them enabling them to be distinguished from standard
+ items. For subclasses that require this feature, ensure that you call the
+ base class constructor with a new type value equal to or greater than
+ \l UserType, within \e your constructor.
\sa QListWidget, {Model/View Programming}, QTreeWidgetItem, QTableWidgetItem
*/
@@ -515,52 +516,58 @@ Qt::DropActions QListModel::supportedDropActions() const
/*!
\fn QListWidget *QListWidgetItem::listWidget() const
- Returns the list widget that contains the item.
+ Returns the list widget containing the item.
*/
/*!
- \fn void QListWidgetItem::setSelected(bool select)
- \since 4.2
+ \fn void QListWidgetItem::setSelected(bool select)
+ \since 4.2
- Sets the selected state of the item to \a select.
+ Sets the selected state of the item to \a select.
- \sa isSelected()
+ \sa isSelected()
*/
/*!
- \fn bool QListWidgetItem::isSelected() const
- \since 4.2
+ \fn bool QListWidgetItem::isSelected() const
+ \since 4.2
- Returns true if the item is selected, otherwise returns false.
+ Returns true if the item is selected; otherwise returns false.
- \sa setSelected()
+ \sa setSelected()
*/
/*!
- \fn void QListWidgetItem::setHidden(bool hide)
- \since 4.2
+ \fn void QListWidgetItem::setHidden(bool hide)
+ \since 4.2
- Hides the item if \a hide is true, otherwise shows the item.
+ Hides the item if \a hide is true; otherwise shows the item.
- \sa isHidden()
+ \sa isHidden()
*/
/*!
- \fn bool QListWidgetItem::isHidden() const
- \since 4.2
+ \fn bool QListWidgetItem::isHidden() const
+ \since 4.2
- Returns true if the item is hidden, otherwise returns false.
+ Returns true if the item is hidden; otherwise returns false.
- \sa setHidden()
+ \sa setHidden()
*/
/*!
\fn QListWidgetItem::QListWidgetItem(QListWidget *parent, int type)
Constructs an empty list widget item of the specified \a type with the
- given \a parent.
- If the parent is not specified, the item will need to be inserted into a
- list widget with QListWidget::insertItem().
+ given \a parent. If \a parent is not specified, the item will need to be
+ inserted into a list widget with QListWidget::insertItem().
+
+ This constructor inserts the item into the model of the parent that is
+ passed to the constructor. If the model is sorted then the behavior of the
+ insert is undetermined since the model will call the \c '<' operator method
+ on the item which, at this point, is not yet constructed. To avoid the
+ undetermined behavior, we recommend not to specify the parent and use
+ QListWidget::insertItem() instead.
\sa type()
*/
@@ -579,9 +586,15 @@ QListWidgetItem::QListWidgetItem(QListWidget *view, int type)
\fn QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *parent, int type)
Constructs an empty list widget item of the specified \a type with the
- given \a text and \a parent.
- If the parent is not specified, the item will need to be inserted into a
- list widget with QListWidget::insertItem().
+ given \a text and \a parent. If the parent is not specified, the item will
+ need to be inserted into a list widget with QListWidget::insertItem().
+
+ This constructor inserts the item into the model of the parent that is
+ passed to the constructor. If the model is sorted then the behavior of the
+ insert is undetermined since the model will call the \c '<' operator method
+ on the item which, at this point, is not yet constructed. To avoid the
+ undetermined behavior, we recommend not to specify the parent and use
+ QListWidget::insertItem() instead.
\sa type()
*/
@@ -602,9 +615,16 @@ QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *view, int typ
\fn QListWidgetItem::QListWidgetItem(const QIcon &icon, const QString &text, QListWidget *parent, int type)
Constructs an empty list widget item of the specified \a type with the
- given \a icon, \a text and \a parent.
- If the parent is not specified, the item will need to be inserted into a
- list widget with QListWidget::insertItem().
+ given \a icon, \a text and \a parent. If the parent is not specified, the
+ item will need to be inserted into a list widget with
+ QListWidget::insertItem().
+
+ This constructor inserts the item into the model of the parent that is
+ passed to the constructor. If the model is sorted then the behavior of the
+ insert is undetermined since the model will call the \c '<' operator method
+ on the item which, at this point, is not yet constructed. To avoid the
+ undetermined behavior, we recommend not to specify the parent and use
+ QListWidget::insertItem() instead.
\sa type()
*/
@@ -624,7 +644,7 @@ QListWidgetItem::QListWidgetItem(const QIcon &icon,const QString &text,
}
/*!
- Destroys the list item.
+ Destroys the list item.
*/
QListWidgetItem::~QListWidgetItem()
{
@@ -634,7 +654,7 @@ QListWidgetItem::~QListWidgetItem()
}
/*!
- Creates an exact copy of the item.
+ Creates an exact copy of the item.
*/
QListWidgetItem *QListWidgetItem::clone() const
{
@@ -642,11 +662,10 @@ QListWidgetItem *QListWidgetItem::clone() const
}
/*!
- This function sets the data for a given \a role to the given \a value (see
- \l{Qt::ItemDataRole}). Reimplement this function if you need
- extra roles or special behavior for certain roles.
+ Sets the data for a given \a role to the given \a value. Reimplement this
+ function if you need extra roles or special behavior for certain roles.
- \sa Qt::ItemDataRole, data()
+ \sa Qt::ItemDataRole, data()
*/
void QListWidgetItem::setData(int role, const QVariant &value)
{
@@ -668,9 +687,10 @@ void QListWidgetItem::setData(int role, const QVariant &value)
}
/*!
- This function returns the item's data for a given \a role (see
- Qt::ItemDataRole). Reimplement this function if you need
- extra roles or special behavior for certain roles.
+ Returns the item's data for a given \a role. Reimplement this function if
+ you need extra roles or special behavior for certain roles.
+
+ \sa Qt::ItemDataRole, setData()
*/
QVariant QListWidgetItem::data(int role) const
{
@@ -682,12 +702,13 @@ QVariant QListWidgetItem::data(int role) const
}
/*!
- Returns true if this item's text is less then \a other item's text;
- otherwise returns false.
+ Returns true if this item's text is less then \a other item's text;
+ otherwise returns false.
*/
bool QListWidgetItem::operator<(const QListWidgetItem &other) const
{
- return text() < other.text();
+ const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole);
+ return QAbstractItemModelPrivate::variantLessThan(v1, v2);
}
#ifndef QT_NO_DATASTREAM
@@ -711,12 +732,13 @@ void QListWidgetItem::write(QDataStream &out) const
{
out << d->values;
}
+#endif // QT_NO_DATASTREAM
/*!
\since 4.1
- Constructs a copy of \a other. Note that type() and listWidget()
- are not copied.
+ Constructs a copy of \a other. Note that type() and listWidget() are not
+ copied.
This function is useful when reimplementing clone().
@@ -731,8 +753,8 @@ QListWidgetItem::QListWidgetItem(const QListWidgetItem &other)
}
/*!
- Assigns \a other's data and flags to this item. Note that type()
- and listWidget() are not copied.
+ Assigns \a other's data and flags to this item. Note that type() and
+ listWidget() are not copied.
This function is useful when reimplementing clone().
@@ -745,6 +767,8 @@ QListWidgetItem &QListWidgetItem::operator=(const QListWidgetItem &other)
return *this;
}
+#ifndef QT_NO_DATASTREAM
+
/*!
\relates QListWidgetItem
@@ -778,9 +802,9 @@ QDataStream &operator>>(QDataStream &in, QListWidgetItem &item)
#endif // QT_NO_DATASTREAM
/*!
- \fn Qt::ItemFlags QListWidgetItem::flags() const
+ \fn Qt::ItemFlags QListWidgetItem::flags() const
- Returns the item flags for this item (see \l{Qt::ItemFlags}).
+ Returns the item flags for this item (see \l{Qt::ItemFlags}).
*/
/*!
@@ -824,15 +848,17 @@ QDataStream &operator>>(QDataStream &in, QListWidgetItem &item)
*/
/*!
- \fn QFont QListWidgetItem::font() const
+ \fn QFont QListWidgetItem::font() const
- Returns the font used to display this list item's text.
+ Returns the font used to display this list item's text.
*/
/*!
- \fn int QListWidgetItem::textAlignment() const
+ \fn int QListWidgetItem::textAlignment() const
+
+ Returns the text alignment for the list item.
- Returns the text alignment for the list item (see \l{Qt::AlignmentFlag}).
+ \sa Qt::AlignmentFlag
*/
/*!
@@ -878,26 +904,26 @@ QDataStream &operator>>(QDataStream &in, QListWidgetItem &item)
*/
/*!
- \fn QSize QListWidgetItem::sizeHint() const
- \since 4.1
+ \fn QSize QListWidgetItem::sizeHint() const
+ \since 4.1
- Returns the size hint set for the list item.
+ Returns the size hint set for the list item.
*/
/*!
- \fn void QListWidgetItem::setSizeHint(const QSize &size)
- \since 4.1
+ \fn void QListWidgetItem::setSizeHint(const QSize &size)
+ \since 4.1
- Sets the size hint for the list item to be \a size.
- If no size hint is set, the item delegate will compute the
- size hint based on the item data.
+ Sets the size hint for the list item to be \a size. If no size hint is set,
+ the item delegate will compute the size hint based on the item data.
*/
/*!
- \fn void QListWidgetItem::setFlags(Qt::ItemFlags flags)
+ \fn void QListWidgetItem::setFlags(Qt::ItemFlags flags)
- Sets the item flags for the list item to \a flags (see
- \l{Qt::ItemFlags}).
+ Sets the item flags for the list item to \a flags.
+
+ \sa Qt::ItemFlags
*/
void QListWidgetItem::setFlags(Qt::ItemFlags aflags) {
itemFlags = aflags;
@@ -926,10 +952,10 @@ void QListWidgetItem::setFlags(Qt::ItemFlags aflags) {
\fn void QListWidgetItem::setStatusTip(const QString &statusTip)
Sets the status tip for the list item to the text specified by
- \a statusTip. QListWidget mouse tracking needs to be enabled for this
+ \a statusTip. QListWidget mouseTracking needs to be enabled for this
feature to work.
- \sa statusTip() setToolTip() setWhatsThis()
+ \sa statusTip(), setToolTip(), setWhatsThis(), QWidget::setMouseTracking()
*/
/*!
@@ -937,29 +963,30 @@ void QListWidgetItem::setFlags(Qt::ItemFlags aflags) {
Sets the tooltip for the list item to the text specified by \a toolTip.
- \sa toolTip() setStatusTip() setWhatsThis()
+ \sa toolTip(), setStatusTip(), setWhatsThis()
*/
/*!
\fn void QListWidgetItem::setWhatsThis(const QString &whatsThis)
- Sets the "What's This?" help for the list item to the text specified
- by \a whatsThis.
+ Sets the "What's This?" help for the list item to the text specified by
+ \a whatsThis.
- \sa whatsThis() setStatusTip() setToolTip()
+ \sa whatsThis(), setStatusTip(), setToolTip()
*/
/*!
- \fn void QListWidgetItem::setFont(const QFont &font)
+ \fn void QListWidgetItem::setFont(const QFont &font)
- Sets the font used when painting the item to the given \a font.
+ Sets the font used when painting the item to the given \a font.
*/
/*!
- \fn void QListWidgetItem::setTextAlignment(int alignment)
+ \fn void QListWidgetItem::setTextAlignment(int alignment)
+
+ Sets the list item's text alignment to \a alignment.
- Sets the list item's text alignment to \a alignment (see
- \l{Qt::AlignmentFlag}).
+ \sa Qt::AlignmentFlag
*/
/*!
@@ -1014,51 +1041,51 @@ void QListWidgetPrivate::setup()
QObject::connect(q, SIGNAL(activated(QModelIndex)),
q, SLOT(_q_emitItemActivated(QModelIndex)));
QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
- QObject::connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_emitItemChanged(QModelIndex)));
QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
q, SIGNAL(itemSelectionChanged()));
- QObject::connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- QObject::connect(model(), SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
+ QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
}
void QListWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemPressed(model()->at(index.row()));
+ emit q->itemPressed(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemClicked(model()->at(index.row()));
+ emit q->itemClicked(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemDoubleClicked(model()->at(index.row()));
+ emit q->itemDoubleClicked(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemActivated(model()->at(index.row()));
+ emit q->itemActivated(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemEntered(model()->at(index.row()));
+ emit q->itemEntered(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemChanged(model()->at(index.row()));
+ emit q->itemChanged(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
@@ -1066,8 +1093,8 @@ void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
{
Q_Q(QListWidget);
QPersistentModelIndex persistentCurrent = current;
- QListWidgetItem *currentItem = model()->at(persistentCurrent.row());
- emit q->currentItemChanged(currentItem, model()->at(previous.row()));
+ QListWidgetItem *currentItem = listModel()->at(persistentCurrent.row());
+ emit q->currentItemChanged(currentItem, listModel()->at(previous.row()));
//persistentCurrent is invalid if something changed the model in response
//to the currentItemChanged signal emission and the item was removed
@@ -1082,14 +1109,14 @@ void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
void QListWidgetPrivate::_q_sort()
{
if (sortingEnabled)
- model()->sort(0, sortOrder);
+ model->sort(0, sortOrder);
}
void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight)
{
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid())
- model()->ensureSorted(topLeft.column(), sortOrder,
+ listModel()->ensureSorted(topLeft.column(), sortOrder,
topLeft.row(), bottomRight.row());
}
@@ -1098,12 +1125,12 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
\brief The QListWidget class provides an item-based list widget.
\ingroup model-view
- \mainclass
- QListWidget is a convenience class that provides a list view similar to
- the one supplied by QListView, but with a classic item-based interface
- for adding and removing items. QListWidget uses an internal model to
- manage each QListWidgetItem in the list.
+
+ QListWidget is a convenience class that provides a list view similar to the
+ one supplied by QListView, but with a classic item-based interface for
+ adding and removing items. QListWidget uses an internal model to manage
+ each QListWidgetItem in the list.
For a more flexible list view widget, use the QListView class with a
standard model.
@@ -1118,23 +1145,23 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
function.
There are two ways to add items to the list: they can be constructed with
- the list widget as their parent widget, or they can be constructed with
- no parent widget and added to the list later. If a list widget already
- exists when the items are constructed, the first method is easier to use:
+ the list widget as their parent widget, or they can be constructed with no
+ parent widget and added to the list later. If a list widget already exists
+ when the items are constructed, the first method is easier to use:
\snippet doc/src/snippets/qlistwidget-using/mainwindow.cpp 1
- If you need to insert a new item into the list at a particular position,
- it is more required to construct the item without a parent widget and
- use the insertItem() function to place it within the list. The list
- widget will take ownership of the item.
+ If you need to insert a new item into the list at a particular position, it
+ is more required to construct the item without a parent widget and use the
+ insertItem() function to place it within the list. The list widget will
+ take ownership of the item.
\snippet doc/src/snippets/qlistwidget-using/mainwindow.cpp 6
\snippet doc/src/snippets/qlistwidget-using/mainwindow.cpp 7
- For multiple items, insertItems() can be used instead. The number of
- items in the list is found with the count() function.
- To remove items from the list, use takeItem().
+ For multiple items, insertItems() can be used instead. The number of items
+ in the list is found with the count() function. To remove items from the
+ list, use takeItem().
The current item in the list can be found with currentItem(), and changed
with setCurrentItem(). The user can also change the current item by
@@ -1160,9 +1187,9 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
Inserts the \a item at the end of the list widget.
- \warning A QListWidgetItem can only be added to a
- QListWidget once. Adding the same QListWidgetItem multiple
- times to a QListWidget will result in undefined behavior.
+ \warning A QListWidgetItem can only be added to a QListWidget once. Adding
+ the same QListWidgetItem multiple times to a QListWidget will result in
+ undefined behavior.
\sa insertItem()
*/
@@ -1170,8 +1197,7 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
/*!
\fn void QListWidget::addItem(const QString &label)
- Inserts an item with the text \a label at the end of the list
- widget.
+ Inserts an item with the text \a label at the end of the list widget.
*/
/*!
@@ -1185,8 +1211,8 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
/*!
\fn void QListWidget::itemPressed(QListWidgetItem *item)
- This signal is emitted with the specified \a item when a mouse button is pressed
- on an item in the widget.
+ This signal is emitted with the specified \a item when a mouse button is
+ pressed on an item in the widget.
\sa itemClicked(), itemDoubleClicked()
*/
@@ -1194,8 +1220,8 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
/*!
\fn void QListWidget::itemClicked(QListWidgetItem *item)
- This signal is emitted with the specified \a item when a mouse button is clicked
- on an item in the widget.
+ This signal is emitted with the specified \a item when a mouse button is
+ clicked on an item in the widget.
\sa itemPressed(), itemDoubleClicked()
*/
@@ -1203,8 +1229,8 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
/*!
\fn void QListWidget::itemDoubleClicked(QListWidgetItem *item)
- This signal is emitted with the specified \a item when a mouse button is double
- clicked on an item in the widget.
+ This signal is emitted with the specified \a item when a mouse button is
+ double clicked on an item in the widget.
\sa itemClicked(), itemPressed()
*/
@@ -1212,20 +1238,21 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
/*!
\fn void QListWidget::itemActivated(QListWidgetItem *item)
- This signal is emitted when the \a item is activated. The \a item
- is activated when the user clicks or double clicks on it,
- depending on the system configuration. It is also activated when
- the user presses the activation key (on Windows and X11 this is
- the \gui Return key, on Mac OS X it is \key{Ctrl+0}).
+ This signal is emitted when the \a item is activated. The \a item is
+ activated when the user clicks or double clicks on it, depending on the
+ system configuration. It is also activated when the user presses the
+ activation key (on Windows and X11 this is the \gui Return key, on Mac OS
+ X it is \key{Ctrl+0}).
*/
/*!
\fn void QListWidget::itemEntered(QListWidgetItem *item)
- This signal is emitted when the mouse cursor enters an item. The
- \a item is the item entered. This signal is only emitted when
- mouseTracking is turned on, or when a mouse button is pressed
- while moving into an item.
+ This signal is emitted when the mouse cursor enters an item. The \a item is
+ the item entered. This signal is only emitted when mouseTracking is turned
+ on, or when a mouse button is pressed while moving into an item.
+
+ \sa QWidget::setMouseTracking()
*/
/*!
@@ -1237,24 +1264,28 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
/*!
\fn void QListWidget::currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
- This signal is emitted whenever the current item changes. The \a
- previous item is the item that previously had the focus, \a
- current is the new current item.
+ This signal is emitted whenever the current item changes.
+
+ \a previous is the item that previously had the focus; \a current is the
+ new current item.
*/
/*!
- \fn void QListWidget::currentTextChanged(const QString &currentText)
+ \fn void QListWidget::currentTextChanged(const QString &currentText)
+
+ This signal is emitted whenever the current item changes.
- This signal is emitted whenever the current item changes. The \a currentText
- is the text data in the current item. If there is no current item, the \a currentText
- is invalid.
+ \a currentText is the text data in the current item. If there is no current
+ item, the \a currentText is invalid.
*/
/*!
- \fn void QListWidget::currentRowChanged(int currentRow)
+ \fn void QListWidget::currentRowChanged(int currentRow)
- This signal is emitted whenever the current item changes. The \a currentRow
- is the row of the current item. If there is no current item, the \a currentRow is -1.
+ This signal is emitted whenever the current item changes.
+
+ \a currentRow is the row of the current item. If there is no current item,
+ the \a currentRow is -1.
*/
/*!
@@ -1262,15 +1293,15 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
This signal is emitted whenever the selection changes.
- \sa selectedItems() isItemSelected() currentItemChanged()
+ \sa selectedItems(), QListWidgetItem::isSelected(), currentItemChanged()
*/
/*!
- \since 4.3
+ \since 4.3
- \fn void QListWidget::removeItemWidget(QListWidgetItem *item)
+ \fn void QListWidget::removeItemWidget(QListWidgetItem *item)
- Removes the widget set on the given \a item.
+ Removes the widget set on the given \a item.
*/
/*!
@@ -1302,9 +1333,9 @@ QListWidget::~QListWidget()
QListWidgetItem *QListWidget::item(int row) const
{
Q_D(const QListWidget);
- if (row < 0 || row >= d->model()->rowCount())
+ if (row < 0 || row >= d->model->rowCount())
return 0;
- return d->model()->at(row);
+ return d->listModel()->at(row);
}
/*!
@@ -1316,7 +1347,7 @@ QListWidgetItem *QListWidget::item(int row) const
int QListWidget::row(const QListWidgetItem *item) const
{
Q_D(const QListWidget);
- return d->model()->index(const_cast<QListWidgetItem*>(item)).row();
+ return d->listModel()->index(const_cast<QListWidgetItem*>(item)).row();
}
@@ -1330,12 +1361,12 @@ void QListWidget::insertItem(int row, QListWidgetItem *item)
{
Q_D(QListWidget);
if (item && !item->view)
- d->model()->insert(row, item);
+ d->listModel()->insert(row, item);
}
/*!
- Inserts an item with the text \a label in the list widget at the
- position given by \a row.
+ Inserts an item with the text \a label in the list widget at the position
+ given by \a row.
\sa addItem()
*/
@@ -1343,7 +1374,7 @@ void QListWidget::insertItem(int row, QListWidgetItem *item)
void QListWidget::insertItem(int row, const QString &label)
{
Q_D(QListWidget);
- d->model()->insert(row, new QListWidgetItem(label));
+ d->listModel()->insert(row, new QListWidgetItem(label));
}
/*!
@@ -1356,15 +1387,15 @@ void QListWidget::insertItem(int row, const QString &label)
void QListWidget::insertItems(int row, const QStringList &labels)
{
Q_D(QListWidget);
- d->model()->insert(row, labels);
+ d->listModel()->insert(row, labels);
}
/*!
- Removes and returns the item from the given \a row in the list widget; otherwise
- returns 0.
+ Removes and returns the item from the given \a row in the list widget;
+ otherwise returns 0.
- Items removed from a list widget will not be managed by Qt, and will need to be
- deleted manually.
+ Items removed from a list widget will not be managed by Qt, and will need
+ to be deleted manually.
\sa insertItem(), addItem()
*/
@@ -1372,36 +1403,37 @@ void QListWidget::insertItems(int row, const QStringList &labels)
QListWidgetItem *QListWidget::takeItem(int row)
{
Q_D(QListWidget);
- if (row < 0 || row >= d->model()->rowCount())
+ if (row < 0 || row >= d->model->rowCount())
return 0;
- return d->model()->take(row);
+ return d->listModel()->take(row);
}
/*!
- \property QListWidget::count
- \brief the number of items in the list including any hidden items.
+ \property QListWidget::count
+ \brief the number of items in the list including any hidden items.
*/
int QListWidget::count() const
{
Q_D(const QListWidget);
- return d->model()->rowCount();
+ return d->model->rowCount();
}
/*!
- Returns the current item.
+ Returns the current item.
*/
QListWidgetItem *QListWidget::currentItem() const
{
Q_D(const QListWidget);
- return d->model()->at(currentIndex().row());
+ return d->listModel()->at(currentIndex().row());
}
/*!
- Sets the current item to \a item.
+ Sets the current item to \a item.
- Depending on the current selection mode, the item may also be selected.
+ Unless the selection mode is \l{QAbstractItemView::}{NoSelection},
+ the item is also be selected.
*/
void QListWidget::setCurrentItem(QListWidgetItem *item)
{
@@ -1409,8 +1441,8 @@ void QListWidget::setCurrentItem(QListWidgetItem *item)
}
/*!
- \since 4.4
- Set the current item to \a item, using the given \a command.
+ \since 4.4
+ Set the current item to \a item, using the given \a command.
*/
void QListWidget::setCurrentItem(QListWidgetItem *item, QItemSelectionModel::SelectionFlags command)
{
@@ -1418,10 +1450,10 @@ void QListWidget::setCurrentItem(QListWidgetItem *item, QItemSelectionModel::Sel
}
/*!
- \property QListWidget::currentRow
- \brief the row of the current item.
+ \property QListWidget::currentRow
+ \brief the row of the current item.
- Depending on the current selection mode, the row may also be selected.
+ Depending on the current selection mode, the row may also be selected.
*/
int QListWidget::currentRow() const
@@ -1432,7 +1464,7 @@ int QListWidget::currentRow() const
void QListWidget::setCurrentRow(int row)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(row);
+ QModelIndex index = d->listModel()->index(row);
if (d->selectionMode == SingleSelection)
selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
else if (d->selectionMode == NoSelection)
@@ -1442,14 +1474,14 @@ void QListWidget::setCurrentRow(int row)
}
/*!
- \since 4.4
+ \since 4.4
- Sets the current row to be the given \a row, using the given \a command,
+ Sets the current row to be the given \a row, using the given \a command,
*/
void QListWidget::setCurrentRow(int row, QItemSelectionModel::SelectionFlags command)
{
Q_D(QListWidget);
- d->selectionModel->setCurrentIndex(d->model()->index(row), command);
+ d->selectionModel->setCurrentIndex(d->listModel()->index(row), command);
}
/*!
@@ -1458,7 +1490,7 @@ void QListWidget::setCurrentRow(int row, QItemSelectionModel::SelectionFlags com
QListWidgetItem *QListWidget::itemAt(const QPoint &p) const
{
Q_D(const QListWidget);
- return d->model()->at(indexAt(p).row());
+ return d->listModel()->at(indexAt(p).row());
}
@@ -1471,23 +1503,23 @@ QListWidgetItem *QListWidget::itemAt(const QPoint &p) const
/*!
- Returns the rectangle on the viewport occupied by the item at \a item.
+ Returns the rectangle on the viewport occupied by the item at \a item.
*/
QRect QListWidget::visualItemRect(const QListWidgetItem *item) const
{
Q_D(const QListWidget);
- QModelIndex index = d->model()->index(const_cast<QListWidgetItem*>(item));
+ QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
return visualRect(index);
}
/*!
- Sorts all the items in the list widget according to the specified \a order.
+ Sorts all the items in the list widget according to the specified \a order.
*/
void QListWidget::sortItems(Qt::SortOrder order)
{
Q_D(QListWidget);
d->sortOrder = order;
- d->model()->sort(0, order);
+ d->listModel()->sort(0, order);
}
/*!
@@ -1495,8 +1527,10 @@ void QListWidget::sortItems(Qt::SortOrder order)
\property QListWidget::sortingEnabled
\brief whether sorting is enabled
- If this property is true, sorting is enabled for the list; if the
- property is false, sorting is not enabled. The default value is false.
+ If this property is true, sorting is enabled for the list; if the property
+ is false, sorting is not enabled.
+
+ The default value is false.
*/
void QListWidget::setSortingEnabled(bool enable)
{
@@ -1511,7 +1545,7 @@ bool QListWidget::isSortingEnabled() const
}
/*!
- \internal
+ \internal
*/
Qt::SortOrder QListWidget::sortOrder() const
{
@@ -1520,36 +1554,37 @@ Qt::SortOrder QListWidget::sortOrder() const
}
/*!
- Starts editing the \a item if it is editable.
+ Starts editing the \a item if it is editable.
*/
void QListWidget::editItem(QListWidgetItem *item)
{
Q_D(QListWidget);
- edit(d->model()->index(item));
+ edit(d->listModel()->index(item));
}
/*!
- Opens an editor for the given \a item. The editor remains open after editing.
+ Opens an editor for the given \a item. The editor remains open after
+ editing.
- \sa closePersistentEditor()
+ \sa closePersistentEditor()
*/
void QListWidget::openPersistentEditor(QListWidgetItem *item)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->listModel()->index(item);
QAbstractItemView::openPersistentEditor(index);
}
/*!
- Closes the persistent editor for the given \a item.
+ Closes the persistent editor for the given \a item.
- \sa openPersistentEditor()
+ \sa openPersistentEditor()
*/
void QListWidget::closePersistentEditor(QListWidgetItem *item)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->listModel()->index(item);
QAbstractItemView::closePersistentEditor(index);
}
@@ -1561,7 +1596,7 @@ void QListWidget::closePersistentEditor(QListWidgetItem *item)
QWidget *QListWidget::itemWidget(QListWidgetItem *item) const
{
Q_D(const QListWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->listModel()->index(item);
return QAbstractItemView::indexWidget(index);
}
@@ -1570,45 +1605,46 @@ QWidget *QListWidget::itemWidget(QListWidgetItem *item) const
Sets the \a widget to be displayed in the give \a item.
- This function should only be used to display static content in the place of a list
- widget item. If you want to display custom dynamic content or implement a custom
- editor widget, use QListView and subclass QItemDelegate instead.
+ This function should only be used to display static content in the place of
+ a list widget item. If you want to display custom dynamic content or
+ implement a custom editor widget, use QListView and subclass QItemDelegate
+ instead.
\sa {Delegate Classes}
*/
void QListWidget::setItemWidget(QListWidgetItem *item, QWidget *widget)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->listModel()->index(item);
QAbstractItemView::setIndexWidget(index, widget);
}
/*!
- Returns true if \a item is selected; otherwise returns false.
+ Returns true if \a item is selected; otherwise returns false.
- \obsolete
+ \obsolete
- This function is deprecated. Use \l{QListWidgetItem::isSelected()} instead.
+ This function is deprecated. Use QListWidgetItem::isSelected() instead.
*/
bool QListWidget::isItemSelected(const QListWidgetItem *item) const
{
Q_D(const QListWidget);
- QModelIndex index = d->model()->index(const_cast<QListWidgetItem*>(item));
+ QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
return selectionModel()->isSelected(index);
}
/*!
- Selects or deselects the given \a item depending on whether \a select is
- true of false.
+ Selects or deselects the given \a item depending on whether \a select is
+ true of false.
- \obsolete
+ \obsolete
- This function is deprecated. Use \l{QListWidgetItem::setSelected()} instead.
+ This function is deprecated. Use QListWidgetItem::setSelected() instead.
*/
void QListWidget::setItemSelected(const QListWidgetItem *item, bool select)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(const_cast<QListWidgetItem*>(item));
+ QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
if (d->selectionMode == SingleSelection) {
selectionModel()->select(index, select
@@ -1623,7 +1659,7 @@ void QListWidget::setItemSelected(const QListWidgetItem *item, bool select)
}
/*!
- Returns a list of all selected items in the list widget.
+ Returns a list of all selected items in the list widget.
*/
QList<QListWidgetItem*> QListWidget::selectedItems() const
@@ -1632,31 +1668,32 @@ QList<QListWidgetItem*> QListWidget::selectedItems() const
QModelIndexList indexes = selectionModel()->selectedIndexes();
QList<QListWidgetItem*> items;
for (int i = 0; i < indexes.count(); ++i)
- items.append(d->model()->at(indexes.at(i).row()));
+ items.append(d->listModel()->at(indexes.at(i).row()));
return items;
}
/*!
- Finds items with the text that matches the string \a text using the given \a flags.
+ Finds items with the text that matches the string \a text using the given
+ \a flags.
*/
QList<QListWidgetItem*> QListWidget::findItems(const QString &text, Qt::MatchFlags flags) const
{
Q_D(const QListWidget);
- QModelIndexList indexes = d->model()->match(model()->index(0, 0, QModelIndex()),
+ QModelIndexList indexes = d->listModel()->match(model()->index(0, 0, QModelIndex()),
Qt::DisplayRole, text, -1, flags);
QList<QListWidgetItem*> items;
for (int i = 0; i < indexes.size(); ++i)
- items.append(d->model()->at(indexes.at(i).row()));
+ items.append(d->listModel()->at(indexes.at(i).row()));
return items;
}
/*!
- Returns true if the \a item is explicitly hidden; otherwise returns false.
+ Returns true if the \a item is explicitly hidden; otherwise returns false.
- \obsolete
+ \obsolete
- This function is deprecated. Use \l{QListWidgetItem::isHidden()} instead.
+ This function is deprecated. Use QListWidgetItem::isHidden() instead.
*/
bool QListWidget::isItemHidden(const QListWidgetItem *item) const
{
@@ -1664,11 +1701,11 @@ bool QListWidget::isItemHidden(const QListWidgetItem *item) const
}
/*!
- If \a hide is true, the \a item will be hidden; otherwise it will be shown.
+ If \a hide is true, the \a item will be hidden; otherwise it will be shown.
- \obsolete
+ \obsolete
- This function is deprecated. Use \l{QListWidgetItem::setHidden()} instead.
+ This function is deprecated. Use QListWidgetItem::setHidden() instead.
*/
void QListWidget::setItemHidden(const QListWidgetItem *item, bool hide)
{
@@ -1676,28 +1713,28 @@ void QListWidget::setItemHidden(const QListWidgetItem *item, bool hide)
}
/*!
- Scrolls the view if necessary to ensure that the \a item is
- visible. The \a hint parameter specifies more precisely where the
- \a item should be located after the operation.
+ Scrolls the view if necessary to ensure that the \a item is visible.
+
+ \a hint specifies where the \a item should be located after the operation.
*/
void QListWidget::scrollToItem(const QListWidgetItem *item, QAbstractItemView::ScrollHint hint)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(const_cast<QListWidgetItem*>(item));
+ QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
QListView::scrollTo(index, hint);
}
/*!
Removes all items and selections in the view.
- \note All items will be permanently deleted.
+ \warning All items will be permanently deleted.
*/
void QListWidget::clear()
{
Q_D(QListWidget);
selectionModel()->clear();
- d->model()->clear();
+ d->listModel()->clear();
}
/*!
@@ -1708,7 +1745,7 @@ void QListWidget::clear()
*/
QStringList QListWidget::mimeTypes() const
{
- return d_func()->model()->QAbstractListModel::mimeTypes();
+ return d_func()->listModel()->QAbstractListModel::mimeTypes();
}
/*!
@@ -1716,20 +1753,19 @@ QStringList QListWidget::mimeTypes() const
\a items. The format used to describe the items is obtained from the
mimeTypes() function.
- If the list of items is empty, 0 is returned rather than a serialized
- empty list.
+ If the list of items is empty, 0 is returned instead of a serialized empty
+ list.
*/
QMimeData *QListWidget::mimeData(const QList<QListWidgetItem*>) const
{
- return d_func()->model()->internalMimeData();
+ return d_func()->listModel()->internalMimeData();
}
#ifndef QT_NO_DRAGANDDROP
/*!
- Handles the \a data supplied by an external drag and drop operation
- that ended with the given \a action in the given \a index.
- Returns true if the data and action can be handled by the model;
- otherwise returns false.
+ Handles \a data supplied by an external drag and drop operation that ended
+ with the given \a action in the given \a index. Returns true if \a data and
+ \a action can be handled by the model; otherwise returns false.
\sa supportedDropActions()
*/
@@ -1744,7 +1780,7 @@ bool QListWidget::dropMimeData(int index, const QMimeData *data, Qt::DropAction
row = -1;
column = -1;
}
- return d_func()->model()->QAbstractListModel::dropMimeData(data, action , row, column, idx);
+ return d_func()->listModel()->QAbstractListModel::dropMimeData(data, action , row, column, idx);
}
/*! \reimp */
@@ -1796,21 +1832,21 @@ void QListWidget::dropEvent(QDropEvent *event) {
}
/*!
- Returns the drop actions supported by this view.
+ Returns the drop actions supported by this view.
- \sa Qt::DropActions
+ \sa Qt::DropActions
*/
Qt::DropActions QListWidget::supportedDropActions() const
{
Q_D(const QListWidget);
- return d->model()->QAbstractListModel::supportedDropActions() | Qt::MoveAction;
+ return d->listModel()->QAbstractListModel::supportedDropActions() | Qt::MoveAction;
}
#endif // QT_NO_DRAGANDDROP
/*!
- Returns a list of pointers to the items contained in the \a data object.
- If the object was not created by a QListWidget in the same process, the list
- is empty.
+ Returns a list of pointers to the items contained in the \a data object. If
+ the object was not created by a QListWidget in the same process, the list
+ is empty.
*/
QList<QListWidgetItem*> QListWidget::items(const QMimeData *data) const
{
@@ -1821,29 +1857,29 @@ QList<QListWidgetItem*> QListWidget::items(const QMimeData *data) const
}
/*!
- Returns the QModelIndex assocated with the given \a item.
+ Returns the QModelIndex assocated with the given \a item.
*/
QModelIndex QListWidget::indexFromItem(QListWidgetItem *item) const
{
Q_D(const QListWidget);
- return d->model()->index(item);
+ return d->listModel()->index(item);
}
/*!
- Returns a pointer to the QListWidgetItem assocated with the given \a index.
+ Returns a pointer to the QListWidgetItem assocated with the given \a index.
*/
QListWidgetItem *QListWidget::itemFromIndex(const QModelIndex &index) const
{
Q_D(const QListWidget);
if (d->isIndexValid(index))
- return d->model()->at(index.row());
+ return d->listModel()->at(index.row());
return 0;
}
/*!
- \internal
+ \internal
*/
void QListWidget::setModel(QAbstractItemModel * /*model*/)
{
diff --git a/src/gui/itemviews/qlistwidget_p.h b/src/gui/itemviews/qlistwidget_p.h
index 13ef414..9820ba4 100644
--- a/src/gui/itemviews/qlistwidget_p.h
+++ b/src/gui/itemviews/qlistwidget_p.h
@@ -143,7 +143,7 @@ class QListWidgetPrivate : public QListViewPrivate
Q_DECLARE_PUBLIC(QListWidget)
public:
QListWidgetPrivate() : QListViewPrivate(), sortOrder(Qt::AscendingOrder), sortingEnabled(false) {}
- inline QListModel *model() const { return qobject_cast<QListModel*>(q_func()->model()); }
+ inline QListModel *listModel() const { return qobject_cast<QListModel*>(model); }
void setup();
void _q_emitItemPressed(const QModelIndex &index);
void _q_emitItemClicked(const QModelIndex &index);
@@ -163,7 +163,6 @@ class QListWidgetItemPrivate
public:
QListWidgetItemPrivate(QListWidgetItem *item) : q(item), theid(-1) {}
QListWidgetItem *q;
- int id;
QVector<QWidgetItemData> values;
int theid;
};
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index 36bbb74..df13df3 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -56,6 +56,15 @@ QT_BEGIN_NAMESPACE
typedef QList<QPair<QModelIndex, QPersistentModelIndex> > QModelIndexPairList;
+static inline QSet<int> qVectorToSet(const QVector<int> &vector)
+{
+ QSet<int> set;
+ set.reserve(vector.size());
+ for(int i=0; i < vector.size(); ++i)
+ set << vector.at(i);
+ return set;
+}
+
class QSortFilterProxyModelLessThan
{
public:
@@ -137,6 +146,7 @@ public:
const QModelIndex &source_parent) const;
QModelIndex proxy_to_source(const QModelIndex &proxyIndex) const;
QModelIndex source_to_proxy(const QModelIndex &sourceIndex) const;
+ bool can_create_mapping(const QModelIndex &source_parent) const;
void remove_from_mapping(const QModelIndex &source_parent);
@@ -164,6 +174,7 @@ public:
const QModelIndex &source_bottom_right);
void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int start, int end);
+ void _q_sourceAboutToBeReset();
void _q_sourceReset();
void _q_sourceLayoutAboutToBeChanged();
@@ -224,8 +235,8 @@ public:
QModelIndexPairList store_persistent_indexes();
void update_persistent_indexes(const QModelIndexPairList &source_indexes);
- void filter_changed();
- void handle_filter_changed(
+ void filter_changed(const QModelIndex &source_parent = QModelIndex());
+ QSet<int> handle_filter_changed(
QVector<int> &source_to_proxy, QVector<int> &proxy_to_source,
const QModelIndex &source_parent, Qt::Orientation orient);
@@ -345,6 +356,25 @@ QModelIndex QSortFilterProxyModelPrivate::source_to_proxy(const QModelIndex &sou
return create_index(proxy_row, proxy_column, it);
}
+bool QSortFilterProxyModelPrivate::can_create_mapping(const QModelIndex &source_parent) const
+{
+ if (source_parent.isValid()) {
+ QModelIndex source_grand_parent = source_parent.parent();
+ IndexMap::const_iterator it = source_index_mapping.constFind(source_grand_parent);
+ if (it == source_index_mapping.constEnd()) {
+ // Don't care, since we don't have mapping for the grand parent
+ return false;
+ }
+ Mapping *gm = it.value();
+ if (gm->proxy_rows.at(source_parent.row()) == -1 ||
+ gm->proxy_columns.at(source_parent.column()) == -1) {
+ // Don't care, since parent is filtered
+ return false;
+ }
+ }
+ return true;
+}
+
/*!
\internal
@@ -650,20 +680,8 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
return;
IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
if (it == source_index_mapping.constEnd()) {
- if (source_parent.isValid()) {
- QModelIndex source_grand_parent = source_parent.parent();
- it = source_index_mapping.constFind(source_grand_parent);
- if (it == source_index_mapping.constEnd()) {
- // Don't care, since we don't have mapping for the grand parent
- return;
- }
- Mapping *gm = it.value();
- if (gm->proxy_rows.at(source_parent.row()) == -1 ||
- gm->proxy_columns.at(source_parent.column()) == -1) {
- // Don't care, since parent is filtered
- return;
- }
- }
+ if (!can_create_mapping(source_parent))
+ return;
it = create_mapping(source_parent);
Mapping *m = it.value();
QModelIndex proxy_parent = q->mapFromSource(source_parent);
@@ -875,8 +893,8 @@ void QSortFilterProxyModelPrivate::proxy_item_range(
{
proxy_low = INT_MAX;
proxy_high = INT_MIN;
- foreach (int source_item, source_items) {
- int proxy_item = source_to_proxy.at(source_item);
+ for (int i = 0; i < source_items.count(); ++i) {
+ int proxy_item = source_to_proxy.at(source_items.at(i));
Q_ASSERT(proxy_item != -1);
if (proxy_item < proxy_low)
proxy_low = proxy_item;
@@ -937,34 +955,47 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes(
q->changePersistentIndexList(from, to);
}
+
/*!
\internal
Updates the proxy model (adds/removes rows) based on the
new filter.
*/
-void QSortFilterProxyModelPrivate::filter_changed()
+void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_parent)
{
- QMap<QModelIndex, Mapping *>::const_iterator it;
- for (it = source_index_mapping.constBegin(); it != source_index_mapping.constEnd(); ++it) {
- QModelIndex source_parent = it.key();
- Mapping *m = it.value();
- handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical);
- handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal);
+ IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
+ if (it == source_index_mapping.constEnd())
+ return;
+ Mapping *m = it.value();
+ QSet<int> rows_removed = handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical);
+ QSet<int> columns_removed = handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal);
+ QVector<QModelIndex>::iterator it2 = m->mapped_children.end();
+ while (it2 != m->mapped_children.begin()) {
+ --it2;
+ const QModelIndex source_child_index = *it2;
+ if (rows_removed.contains(source_child_index.row()) || columns_removed.contains(source_child_index.column())) {
+ it2 = m->mapped_children.erase(it2);
+ remove_from_mapping(source_child_index);
+ } else {
+ filter_changed(source_child_index);
+ }
}
}
/*!
\internal
+ returns the removed items indexes
*/
-void QSortFilterProxyModelPrivate::handle_filter_changed(
+QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
QVector<int> &source_to_proxy, QVector<int> &proxy_to_source,
const QModelIndex &source_parent, Qt::Orientation orient)
{
Q_Q(QSortFilterProxyModel);
// Figure out which mapped items to remove
QVector<int> source_items_remove;
- foreach (int source_item, proxy_to_source) {
+ for (int i = 0; i < proxy_to_source.count(); ++i) {
+ const int source_item = proxy_to_source.at(i);
if ((orient == Qt::Vertical)
? !q->filterAcceptsRow(source_item, source_parent)
: !q->filterAcceptsColumn(source_item, source_parent)) {
@@ -994,6 +1025,7 @@ void QSortFilterProxyModelPrivate::handle_filter_changed(
insert_source_items(source_to_proxy, proxy_to_source,
source_items_insert, source_parent, orient);
}
+ return qVectorToSet(source_items_remove);
}
void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &source_top_left,
@@ -1044,15 +1076,14 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
if (!source_rows_remove.isEmpty()) {
remove_source_items(m->proxy_rows, m->source_rows,
source_rows_remove, source_parent, Qt::Vertical);
- QSet<int> source_rows_remove_set = source_rows_remove.toList().toSet();
- QVector<QModelIndex>::iterator it = m->mapped_children.begin();
- while (it != m->mapped_children.end()) {
+ QSet<int> source_rows_remove_set = qVectorToSet(source_rows_remove);
+ QVector<QModelIndex>::iterator it = m->mapped_children.end();
+ while (it != m->mapped_children.begin()) {
+ --it;
const QModelIndex source_child_index = *it;
if (source_rows_remove_set.contains(source_child_index.row())) {
it = m->mapped_children.erase(it);
remove_from_mapping(source_child_index);
- } else {
- ++it;
}
}
}
@@ -1118,11 +1149,17 @@ void QSortFilterProxyModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation or
emit q->headerDataChanged(orientation, proxy_start, proxy_end);
}
+void QSortFilterProxyModelPrivate::_q_sourceAboutToBeReset()
+{
+ Q_Q(QSortFilterProxyModel);
+ q->beginResetModel();
+}
+
void QSortFilterProxyModelPrivate::_q_sourceReset()
{
Q_Q(QSortFilterProxyModel);
// All internal structures are deleted in clear()
- q->reset();
+ q->endResetModel();
update_source_sort_column();
if (dynamic_sortfilter)
sort();
@@ -1164,7 +1201,8 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted(
Q_UNUSED(end);
//Force the creation of a mapping now, even if its empty.
//We need it because the proxy can be acessed at the moment it emits rowsAboutToBeInserted in insert_source_items
- create_mapping(source_parent);
+ if (can_create_mapping(source_parent))
+ create_mapping(source_parent);
}
void QSortFilterProxyModelPrivate::_q_sourceRowsInserted(
@@ -1195,7 +1233,8 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsAboutToBeInserted(
Q_UNUSED(end);
//Force the creation of a mapping now, even if its empty.
//We need it because the proxy can be acessed at the moment it emits columnsAboutToBeInserted in insert_source_items
- create_mapping(source_parent);
+ if (can_create_mapping(source_parent))
+ create_mapping(source_parent);
}
void QSortFilterProxyModelPrivate::_q_sourceColumnsInserted(
@@ -1246,82 +1285,76 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved(
/*!
\since 4.1
\class QSortFilterProxyModel
- \brief The QSortFilterProxyModel class provides support for sorting and filtering data passed
- between another model and a view.
+ \brief The QSortFilterProxyModel class provides support for sorting and
+ filtering data passed between another model and a view.
\ingroup model-view
- QSortFilterProxyModel can be used for sorting items, filtering
- out items, or both. The model transforms the structure of a
- source model by mapping the model indexes it supplies to new
- indexes, corresponding to different locations, for views to use.
- This approach allows a given source model to be restructured as
- far as views are concerned without requiring any transformations
- on the underlying data, and without duplicating the data in
+ QSortFilterProxyModel can be used for sorting items, filtering out items,
+ or both. The model transforms the structure of a source model by mapping
+ the model indexes it supplies to new indexes, corresponding to different
+ locations, for views to use. This approach allows a given source model to
+ be restructured as far as views are concerned without requiring any
+ transformations on the underlying data, and without duplicating the data in
memory.
- Let's assume that we want to sort and filter the items provided
- by a custom model. The code to set up the model and the view, \e
- without sorting and filtering, would look like this:
+ Let's assume that we want to sort and filter the items provided by a custom
+ model. The code to set up the model and the view, \e without sorting and
+ filtering, would look like this:
\snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 1
- To add sorting and filtering support to \c MyItemModel, we need
- to create a QSortFilterProxyModel, call setSourceModel() with the
- \c MyItemModel as argument, and install the QSortFilterProxyModel
- on the view:
+ To add sorting and filtering support to \c MyItemModel, we need to create
+ a QSortFilterProxyModel, call setSourceModel() with the \c MyItemModel as
+ argument, and install the QSortFilterProxyModel on the view:
\snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 0
\snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 2
- At this point, neither sorting nor filtering is enabled; the
- original data is displayed in the view. Any changes made through
- the QSortFilterProxyModel are applied to the original model.
+ At this point, neither sorting nor filtering is enabled; the original data
+ is displayed in the view. Any changes made through the
+ QSortFilterProxyModel are applied to the original model.
- The QSortFilterProxyModel acts as a wrapper for the original
- model. If you need to convert source \l{QModelIndex}es to
- sorted/filtered model indexes or vice versa, use mapToSource(),
- mapFromSource(), mapSelectionToSource(), and
- mapSelectionFromSource().
+ The QSortFilterProxyModel acts as a wrapper for the original model. If you
+ need to convert source \l{QModelIndex}es to sorted/filtered model indexes
+ or vice versa, use mapToSource(), mapFromSource(), mapSelectionToSource(),
+ and mapSelectionFromSource().
- \note By default, the model does not dynamically re-sort and re-filter
- data whenever the original model changes. This behavior can be
- changed by setting the \l{QSortFilterProxyModel::dynamicSortFilter}
- {dynamicSortFilter} property.
+ \note By default, the model does not dynamically re-sort and re-filter data
+ whenever the original model changes. This behavior can be changed by
+ setting the \l{QSortFilterProxyModel::dynamicSortFilter}{dynamicSortFilter}
+ property.
- The \l{itemviews/basicsortfiltermodel}{Basic Sort/Filter Model}
- and \l{itemviews/customsortfiltermodel}{Custom Sort/Filter Model}
- examples illustrate how to use QSortFilterProxyModel to perform
- basic sorting and filtering and how to subclass it to implement
- custom behavior.
+ The \l{itemviews/basicsortfiltermodel}{Basic Sort/Filter Model} and
+ \l{itemviews/customsortfiltermodel}{Custom Sort/Filter Model} examples
+ illustrate how to use QSortFilterProxyModel to perform basic sorting and
+ filtering and how to subclass it to implement custom behavior.
\section1 Sorting
QTableView and QTreeView have a
- \l{QTreeView::sortingEnabled}{sortingEnabled} property that
- controls whether the user can sort the view by clicking the
- view's horizontal header. For example:
+ \l{QTreeView::sortingEnabled}{sortingEnabled} property that controls
+ whether the user can sort the view by clicking the view's horizontal
+ header. For example:
\snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 3
- When this feature is on (the default is off), clicking on a
- header section sorts the items according to that column. By
- clicking repeatedly, the user can alternate between ascending and
- descending order.
+ When this feature is on (the default is off), clicking on a header section
+ sorts the items according to that column. By clicking repeatedly, the user
+ can alternate between ascending and descending order.
\image qsortfilterproxymodel-sorting.png A sorted QTreeView
- Behind the scene, the view calls the sort() virtual function on
- the model to reorder the data in the model. To make your data
- sortable, you can either implement sort() in your model, or you
- use a QSortFilterProxyModel to wrap your model --
- QSortFilterProxyModel provides a generic sort() reimplementation
- that operates on the sortRole() (Qt::DisplayRole by default) of
- the items and that understands several data types, including \c
- int, QString, and QDateTime. For hierarchical models, sorting is
- applied recursively to all child items. String comparisons are
- case sensitive by default; this can be changed by setting the
- \l{QSortFilterProxyModel::}{sortCaseSensitivity} property.
+ Behind the scene, the view calls the sort() virtual function on the model
+ to reorder the data in the model. To make your data sortable, you can
+ either implement sort() in your model, or use a QSortFilterProxyModel to
+ wrap your model -- QSortFilterProxyModel provides a generic sort()
+ reimplementation that operates on the sortRole() (Qt::DisplayRole by
+ default) of the items and that understands several data types, including
+ \c int, QString, and QDateTime. For hierarchical models, sorting is applied
+ recursively to all child items. String comparisons are case sensitive by
+ default; this can be changed by setting the \l{QSortFilterProxyModel::}
+ {sortCaseSensitivity} property.
Custom sorting behavior is achieved by subclassing
QSortFilterProxyModel and reimplementing lessThan(), which is
@@ -1333,43 +1366,42 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved(
\l{itemviews/customsortfiltermodel}{Custom Sort/Filter Model}
example.)
- An alternative approach to sorting is to disable sorting on the
- view and to impose a certain order to the user. This is done by
- explicitly calling sort() with the desired column and order as
- arguments on the QSortFilterProxyModel (or on the original model
- if it implements sort()). For example:
+ An alternative approach to sorting is to disable sorting on the view and to
+ impose a certain order to the user. This is done by explicitly calling
+ sort() with the desired column and order as arguments on the
+ QSortFilterProxyModel (or on the original model if it implements sort()).
+ For example:
\snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 4
- QSortFilterProxyModel can be sorted by column -1, in which case it
- returns to the sort order of the underlying source model.
+ QSortFilterProxyModel can be sorted by column -1, in which case it returns
+ to the sort order of the underlying source model.
\section1 Filtering
- In addition to sorting, QSortFilterProxyModel can be used to hide
- items that don't match a certain filter. The filter is specified
- using a QRegExp object and is applied to the filterRole()
- (Qt::DisplayRole by default) of each item, for a given column.
- The QRegExp object can be used to match a regular expression, a
- wildcard pattern, or a fixed string. For example:
+ In addition to sorting, QSortFilterProxyModel can be used to hide items
+ that do not match a certain filter. The filter is specified using a QRegExp
+ object and is applied to the filterRole() (Qt::DisplayRole by default) of
+ each item, for a given column. The QRegExp object can be used to match a
+ regular expression, a wildcard pattern, or a fixed string. For example:
\snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 5
- For hierarchical models, the filter is applied recursively to all
- children. If a parent item doesn't match the filter, none of its
- children will be shown.
+ For hierarchical models, the filter is applied recursively to all children.
+ If a parent item doesn't match the filter, none of its children will be
+ shown.
- A common use case is to let the user specify the filter regexp,
- wildcard pattern, or fixed string in a QLineEdit and to connect
- the \l{QLineEdit::textChanged()}{textChanged()} signal to
- setFilterRegExp(), setFilterWildcard(), or setFilterFixedString()
- to reapply the filter.
+ A common use case is to let the user specify the filter regexp, wildcard
+ pattern, or fixed string in a QLineEdit and to connect the
+ \l{QLineEdit::textChanged()}{textChanged()} signal to setFilterRegExp(),
+ setFilterWildcard(), or setFilterFixedString() to reapply the filter.
Custom filtering behavior can be achieved by reimplementing the
filterAcceptsRow() and filterAcceptsColumn() functions. For
- example, the following implementation ignores the
- \l{QSortFilterProxyModel::filterKeyColumn}{filterKeyColumn}
- property and performs filtering on columns 0, 1, and 2:
+ example (from the \l{itemviews/customsortfiltermodel}
+ {Custom Sort/Filter Model} example), the following implementation ignores
+ the \l{QSortFilterProxyModel::filterKeyColumn}{filterKeyColumn} property
+ and performs filtering on columns 0, 1, and 2:
\snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 3
@@ -1379,24 +1411,24 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved(
If you are working with large amounts of filtering and have to invoke
invalidateFilter() repeatedly, using reset() may be more efficient,
- depending on the implementation of your model. However, note that reset()
- returns the proxy model to its original state, losing selection
- information, and will cause the proxy model to be repopulated.
+ depending on the implementation of your model. However, reset() returns the
+ proxy model to its original state, losing selection information, and will
+ cause the proxy model to be repopulated.
\section1 Subclassing
- \bold{Note:} Some general guidelines for subclassing models are
- available in the \l{Model Subclassing Reference}.
-
Since QAbstractProxyModel and its subclasses are derived from
- QAbstractItemModel, much of the same advice about subclassing normal
- models also applies to proxy models. In addition, it is worth noting
- that many of the default implementations of functions in this class
- are written so that they call the equivalent functions in the relevant
- source model. This simple proxying mechanism may need to be overridden
- for source models with more complex behavior; for example, if the
- source model provides a custom hasChildren() implementation, you
- should also provide one in the proxy model.
+ QAbstractItemModel, much of the same advice about subclassing normal models
+ also applies to proxy models. In addition, it is worth noting that many of
+ the default implementations of functions in this class are written so that
+ they call the equivalent functions in the relevant source model. This
+ simple proxying mechanism may need to be overridden for source models with
+ more complex behavior; for example, if the source model provides a custom
+ hasChildren() implementation, you should also provide one in the proxy
+ model.
+
+ \note Some general guidelines for subclassing models are available in the
+ \l{Model Subclassing Reference}.
\sa QAbstractProxyModel, QAbstractItemModel, {Model/View Programming},
{Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example}
@@ -1474,6 +1506,7 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
disconnect(d->model, SIGNAL(layoutChanged()),
this, SLOT(_q_sourceLayoutChanged()));
+ disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset()));
disconnect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset()));
QAbstractProxyModel::setSourceModel(sourceModel);
@@ -1514,6 +1547,7 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
connect(d->model, SIGNAL(layoutChanged()),
this, SLOT(_q_sourceLayoutChanged()));
+ connect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset()));
connect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset()));
d->clear_mapping();
@@ -1959,9 +1993,11 @@ Qt::SortOrder QSortFilterProxyModel::sortOrder() const
\brief the QRegExp used to filter the contents of the source model
Setting this property overwrites the current
- \l{QSortFilterProxyModel::filterCaseSensitivity}
- {filterCaseSensitivity}. By default, the QRegExp is an empty
- string matching all contents.
+ \l{QSortFilterProxyModel::filterCaseSensitivity}{filterCaseSensitivity}.
+ By default, the QRegExp is an empty string matching all contents.
+
+ If no QRegExp or an empty string is set, everything in the source model
+ will be accepted.
\sa filterCaseSensitivity, setFilterWildcard(), setFilterFixedString()
*/
@@ -2284,7 +2320,7 @@ bool QSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex
Q_D(const QSortFilterProxyModel);
QVariant l = (left.model() ? left.model()->data(left, d->sort_role) : QVariant());
QVariant r = (right.model() ? right.model()->data(right, d->sort_role) : QVariant());
- switch (l.type()) {
+ switch (l.userType()) {
case QVariant::Invalid:
return (r.type() == QVariant::Invalid);
case QVariant::Int:
@@ -2295,6 +2331,8 @@ bool QSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex
return l.toLongLong() < r.toLongLong();
case QVariant::ULongLong:
return l.toULongLong() < r.toULongLong();
+ case QMetaType::Float:
+ return l.toFloat() < r.toFloat();
case QVariant::Double:
return l.toDouble() < r.toDouble();
case QVariant::Char:
diff --git a/src/gui/itemviews/qsortfilterproxymodel.h b/src/gui/itemviews/qsortfilterproxymodel.h
index 896d79e..f448b1b 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.h
+++ b/src/gui/itemviews/qsortfilterproxymodel.h
@@ -177,6 +177,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right))
Q_PRIVATE_SLOT(d_func(), void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceAboutToBeReset())
Q_PRIVATE_SLOT(d_func(), void _q_sourceReset())
Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged())
Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged())
diff --git a/src/gui/itemviews/qstandarditemmodel.cpp b/src/gui/itemviews/qstandarditemmodel.cpp
index 4d68d52..f327c99 100644
--- a/src/gui/itemviews/qstandarditemmodel.cpp
+++ b/src/gui/itemviews/qstandarditemmodel.cpp
@@ -329,7 +329,6 @@ QStandardItemModelPrivate::QStandardItemModelPrivate()
*/
QStandardItemModelPrivate::~QStandardItemModelPrivate()
{
- delete root;
delete itemPrototype;
qDeleteAll(columnHeaderItems);
qDeleteAll(rowHeaderItems);
@@ -554,7 +553,7 @@ void QStandardItemModelPrivate::rowsInserted(QStandardItem *parent,
int row, int count)
{
Q_Q(QStandardItemModel);
- if (parent == root)
+ if (parent == root.data())
rowHeaderItems.insert(row, count, 0);
q->endInsertRows();
}
@@ -566,7 +565,7 @@ void QStandardItemModelPrivate::columnsInserted(QStandardItem *parent,
int column, int count)
{
Q_Q(QStandardItemModel);
- if (parent == root)
+ if (parent == root.data())
columnHeaderItems.insert(column, count, 0);
q->endInsertColumns();
}
@@ -578,7 +577,7 @@ void QStandardItemModelPrivate::rowsRemoved(QStandardItem *parent,
int row, int count)
{
Q_Q(QStandardItemModel);
- if (parent == root) {
+ if (parent == root.data()) {
for (int i = row; i < row + count; ++i) {
QStandardItem *oldItem = rowHeaderItems.at(i);
if (oldItem)
@@ -597,7 +596,7 @@ void QStandardItemModelPrivate::columnsRemoved(QStandardItem *parent,
int column, int count)
{
Q_Q(QStandardItemModel);
- if (parent == root) {
+ if (parent == root.data()) {
for (int i = column; i < column + count; ++i) {
QStandardItem *oldItem = columnHeaderItems.at(i);
if (oldItem)
@@ -778,8 +777,6 @@ QStandardItem &QStandardItem::operator=(const QStandardItem &other)
*/
QStandardItem::~QStandardItem()
{
- Q_D(QStandardItem);
- delete d;
}
/*!
@@ -790,7 +787,7 @@ QStandardItem::~QStandardItem()
QStandardItem *QStandardItem::parent() const
{
Q_D(const QStandardItem);
- if (!d->model || (d->model->d_func()->root != d->parent))
+ if (!d->model || (d->model->d_func()->root.data() != d->parent))
return d->parent;
return 0;
}
@@ -899,7 +896,7 @@ Qt::ItemFlags QStandardItem::flags() const
if (!v.isValid())
return (Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable
|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled);
- return ((Qt::ItemFlags)(v.toInt()));
+ return Qt::ItemFlags(v.toInt());
}
/*!
@@ -1742,18 +1739,23 @@ QList<QStandardItem*> QStandardItem::takeRow(int row)
Q_D(QStandardItem);
if ((row < 0) || (row >= rowCount()))
return QList<QStandardItem*>();
+ if (d->model)
+ d->model->d_func()->rowsAboutToBeRemoved(this, row, row);
QList<QStandardItem*> items;
- int index = d->childIndex(row, 0);
- for (int column = 0; column < d->columnCount(); ++column) {
- QStandardItem *ch = d->children.at(index);
- if (ch) {
- ch->d_func()->setParentAndModel(0, 0);
- d->children.replace(index, 0);
+ int index = d->childIndex(row, 0); // Will return -1 if there are no columns
+ if (index != -1) {
+ int col_count = d->columnCount();
+ for (int column = 0; column < col_count; ++column) {
+ QStandardItem *ch = d->children.at(index + column);
+ if (ch)
+ ch->d_func()->setParentAndModel(0, 0);
+ items.append(ch);
}
- items.append(ch);
- ++index;
+ d->children.remove(index, col_count);
}
- removeRow(row);
+ d->rows--;
+ if (d->model)
+ d->model->d_func()->rowsRemoved(this, row, 1);
return items;
}
@@ -1769,18 +1771,21 @@ QList<QStandardItem*> QStandardItem::takeColumn(int column)
Q_D(QStandardItem);
if ((column < 0) || (column >= columnCount()))
return QList<QStandardItem*>();
+ if (d->model)
+ d->model->d_func()->columnsAboutToBeRemoved(this, column, column);
QList<QStandardItem*> items;
- int index = d->childIndex(0, column);
- for (int row = 0; row < d->rowCount(); ++row) {
+
+ for (int row = d->rowCount() - 1; row >= 0; --row) {
+ int index = d->childIndex(row, column);
QStandardItem *ch = d->children.at(index);
- if (ch) {
+ if (ch)
ch->d_func()->setParentAndModel(0, 0);
- d->children.replace(index, 0);
- }
- items.append(ch);
- index += d->columnCount();
+ d->children.remove(index);
+ items.prepend(ch);
}
- removeColumn(column);
+ d->columns--;
+ if (d->model)
+ d->model->d_func()->columnsRemoved(this, column, 1);
return items;
}
@@ -1801,7 +1806,7 @@ bool QStandardItem::operator<(const QStandardItem &other) const
const int role = model() ? model()->sortRole() : Qt::DisplayRole;
const QVariant l = data(role), r = other.data(role);
// this code is copied from QSortFilterProxyModel::lessThan()
- switch (l.type()) {
+ switch (l.userType()) {
case QVariant::Invalid:
return (r.type() == QVariant::Invalid);
case QVariant::Int:
@@ -1812,6 +1817,8 @@ bool QStandardItem::operator<(const QStandardItem &other) const
return l.toLongLong() < r.toLongLong();
case QVariant::ULongLong:
return l.toULongLong() < r.toULongLong();
+ case QMetaType::Float:
+ return l.toFloat() < r.toFloat();
case QVariant::Double:
return l.toDouble() < r.toDouble();
case QVariant::Char:
@@ -1890,7 +1897,7 @@ void QStandardItem::read(QDataStream &in)
in >> d->values;
qint32 flags;
in >> flags;
- setFlags((Qt::ItemFlags)flags);
+ setFlags(Qt::ItemFlags(flags));
}
/*!
@@ -1938,7 +1945,7 @@ QDataStream &operator<<(QDataStream &out, const QStandardItem &item)
return out;
}
-#endif // !QT_NO_DATASTREAM
+#endif // QT_NO_DATASTREAM
/*!
\class QStandardItemModel
@@ -2079,8 +2086,7 @@ QStandardItemModel::~QStandardItemModel()
void QStandardItemModel::clear()
{
Q_D(QStandardItemModel);
- delete d->root;
- d->root = new QStandardItem;
+ d->root.reset(new QStandardItem);
d->root->d_func()->setModel(this);
qDeleteAll(d->columnHeaderItems);
d->columnHeaderItems.clear();
@@ -2227,7 +2233,7 @@ QStandardItem *QStandardItemModel::item(int row, int column) const
QStandardItem *QStandardItemModel::invisibleRootItem() const
{
Q_D(const QStandardItemModel);
- return d->root;
+ return d->root.data();
}
/*!
@@ -2729,7 +2735,7 @@ QModelIndex QStandardItemModel::index(int row, int column, const QModelIndex &pa
bool QStandardItemModel::insertColumns(int column, int count, const QModelIndex &parent)
{
Q_D(QStandardItemModel);
- QStandardItem *item = parent.isValid() ? itemFromIndex(parent) : d->root;
+ QStandardItem *item = parent.isValid() ? itemFromIndex(parent) : d->root.data();
if (item == 0)
return false;
return item->d_func()->insertColumns(column, count, QList<QStandardItem*>());
@@ -2741,7 +2747,7 @@ bool QStandardItemModel::insertColumns(int column, int count, const QModelIndex
bool QStandardItemModel::insertRows(int row, int count, const QModelIndex &parent)
{
Q_D(QStandardItemModel);
- QStandardItem *item = parent.isValid() ? itemFromIndex(parent) : d->root;
+ QStandardItem *item = parent.isValid() ? itemFromIndex(parent) : d->root.data();
if (item == 0)
return false;
return item->d_func()->insertRows(row, count, QList<QStandardItem*>());
@@ -2907,8 +2913,8 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
QStack<QStandardItem*> stack;
itemsSet.reserve(indexes.count());
stack.reserve(indexes.count());
- foreach (const QModelIndex &index, indexes) {
- QStandardItem *item = itemFromIndex(index);
+ for (int i = 0; i < indexes.count(); ++i) {
+ QStandardItem *item = itemFromIndex(indexes.at(i));
itemsSet << item;
stack.push(item);
}
diff --git a/src/gui/itemviews/qstandarditemmodel.h b/src/gui/itemviews/qstandarditemmodel.h
index 79b5702..2e7e112 100644
--- a/src/gui/itemviews/qstandarditemmodel.h
+++ b/src/gui/itemviews/qstandarditemmodel.h
@@ -240,7 +240,7 @@ protected:
QStandardItem(const QStandardItem &other);
QStandardItem(QStandardItemPrivate &dd);
QStandardItem &operator=(const QStandardItem &other);
- QStandardItemPrivate *d_ptr;
+ QScopedPointer<QStandardItemPrivate> d_ptr;
void emitDataChanged();
diff --git a/src/gui/itemviews/qstandarditemmodel_p.h b/src/gui/itemviews/qstandarditemmodel_p.h
index a429f49..de096b3 100644
--- a/src/gui/itemviews/qstandarditemmodel_p.h
+++ b/src/gui/itemviews/qstandarditemmodel_p.h
@@ -75,6 +75,7 @@ public:
parent(0),
rows(0),
columns(0),
+ q_ptr(0),
lastIndexOf(2)
{ }
virtual ~QStandardItemPrivate();
@@ -152,7 +153,7 @@ public:
inline QStandardItem *itemFromIndex(const QModelIndex &index) const {
Q_Q(const QStandardItemModel);
if (!index.isValid())
- return root;
+ return root.data();
if (index.model() != q)
return 0;
QStandardItem *parent = static_cast<QStandardItem*>(index.internalPointer());
@@ -177,7 +178,7 @@ public:
QVector<QStandardItem*> columnHeaderItems;
QVector<QStandardItem*> rowHeaderItems;
- QStandardItem *root;
+ QScopedPointer<QStandardItem> root;
const QStandardItem *itemPrototype;
int sortRole;
};
diff --git a/src/gui/itemviews/qstringlistmodel.cpp b/src/gui/itemviews/qstringlistmodel.cpp
index ad8d413..f8ae658 100644
--- a/src/gui/itemviews/qstringlistmodel.cpp
+++ b/src/gui/itemviews/qstringlistmodel.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
\brief The QStringListModel class provides a model that supplies strings to views.
\ingroup model-view
- \mainclass
+
QStringListModel is an editable model that can be used for simple
cases where you need to display a number of strings in a view
diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp
index b7ae1a1..ab77bda 100644
--- a/src/gui/itemviews/qstyleditemdelegate.cpp
+++ b/src/gui/itemviews/qstyleditemdelegate.cpp
@@ -112,7 +112,7 @@ public:
data items from a model.
\ingroup model-view
- \mainclass
+
\since 4.4
When displaying data from models in Qt item views, e.g., a
@@ -267,9 +267,10 @@ QStyledItemDelegate::~QStyledItemDelegate()
QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale& locale) const
{
QString text;
- switch (value.type()) {
+ switch (value.userType()) {
+ case QMetaType::Float:
case QVariant::Double:
- text = locale.toString(value.toDouble());
+ text = locale.toString(value.toReal());
break;
case QVariant::Int:
case QVariant::LongLong:
@@ -322,7 +323,7 @@ void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option,
value = index.data(Qt::TextAlignmentRole);
if (value.isValid() && !value.isNull())
- option->displayAlignment = (Qt::Alignment)value.toInt();
+ option->displayAlignment = Qt::Alignment(value.toInt());
value = index.data(Qt::ForegroundRole);
if (qVariantCanConvert<QBrush>(value))
@@ -671,7 +672,7 @@ bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event)
if (editor->parentWidget())
editor->parentWidget()->setFocus();
return true;
- } else if (event->type() == QEvent::FocusOut || event->type() == QEvent::Hide) {
+ } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
//the Hide event will take care of he editors that are in fact complete dialogs
if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
QWidget *w = QApplication::focusWidget();
@@ -686,13 +687,7 @@ bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event)
if (QDragManager::self() && QDragManager::self()->object != 0)
return false;
#endif
- // Opening a modal dialog will start a new eventloop
- // that will process the deleteLater event.
- QWidget *activeModalWidget = QApplication::activeModalWidget();
- if (activeModalWidget
- && !activeModalWidget->isAncestorOf(editor)
- && qobject_cast<QDialog*>(activeModalWidget))
- return false;
+
emit commitData(editor);
emit closeEditor(editor, NoHint);
}
@@ -752,8 +747,13 @@ bool QStyledItemDelegate::editorEvent(QEvent *event,
return false;
}
- Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
+ Qt::CheckState state;
+ if ( flags & Qt::ItemIsTristate ) {
+ state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 );
+ } else {
+ state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
? Qt::Unchecked : Qt::Checked);
+ }
return model->setData(index, state, Qt::CheckStateRole);
}
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp
index 876059c..c12af3b 100644
--- a/src/gui/itemviews/qtableview.cpp
+++ b/src/gui/itemviews/qtableview.cpp
@@ -59,6 +59,138 @@
QT_BEGIN_NAMESPACE
+/** \internal
+ Add a span to the collection. the collection takes the ownership.
+ */
+void QSpanCollection::addSpan(QSpanCollection::Span *span)
+{
+ spans.append(span);
+ Index::iterator it_y = index.lowerBound(-span->top());
+ if (it_y == index.end() || it_y.key() != -span->top()) {
+ //there is no spans that starts with the row in the index, so create a sublist for it.
+ SubIndex sub_index;
+ if (it_y != index.end()) {
+ //the previouslist is the list of spans that sarts _before_ the row of the span.
+ // and which may intersect this row.
+ const SubIndex previousList = it_y.value();
+ foreach(Span *s, previousList) {
+ //If a subspans intersect the row, we need to split it into subspans
+ if(s->bottom() >= span->top())
+ sub_index.insert(-s->left(), s);
+ }
+ }
+ it_y = index.insert(-span->top(), sub_index);
+ //we will insert span to *it_y in the later loop
+ }
+
+ //insert the span as supspan in all the lists that intesects the span
+ while(-it_y.key() <= span->bottom()) {
+ (*it_y).insert(-span->left(), span);
+ if(it_y == index.begin())
+ break;
+ --it_y;
+ }
+}
+
+
+/** \internal
+* Has to be called after the height and width of a span is changed.
+*
+* old_height is the height before the change
+*
+* if the size of the span is now 0x0 the span will be deleted.
+*/
+void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height)
+{
+ if (old_height < span->height()) {
+ //add the span as subspan in all the lists that intersect the new covered columns
+ Index::iterator it_y = index.lowerBound(-(span->top() + old_height - 1));
+ Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list
+ while (-it_y.key() <= span->bottom()) {
+ (*it_y).insert(-span->left(), span);
+ if(it_y == index.begin())
+ break;
+ --it_y;
+ }
+ } else if (old_height > span->height()) {
+ //remove the span from all the subspans lists that intersect the columns not covered anymore
+ Index::iterator it_y = index.lowerBound(-span->bottom());
+ Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list
+ while (-it_y.key() <= span->top() + old_height -1) {
+ if(-it_y.key() != span->bottom()) {
+ (*it_y).remove(-span->left());
+ if (it_y->isEmpty()) {
+ it_y = index.erase(it_y) - 1;
+ }
+ }
+ if(it_y == index.begin())
+ break;
+ --it_y;
+ }
+ }
+
+ if (span->width() == 0 && span->height() == 0) {
+ spans.removeOne(span);
+ delete span;
+ }
+}
+
+/** \internal
+ * \return a spans that spans over cell x,y (column,row) or 0 if there is none.
+ */
+QSpanCollection::Span *QSpanCollection::spanAt(int x, int y) const
+{
+ Index::const_iterator it_y = index.lowerBound(-y);
+ if (it_y == index.end())
+ return 0;
+ SubIndex::const_iterator it_x = (*it_y).lowerBound(-x);
+ if (it_x == (*it_y).end())
+ return 0;
+ Span *span = *it_x;
+ if (span->right() >= x && span->bottom() >= y)
+ return span;
+ return 0;
+}
+
+
+/** \internal
+* remove and deletes all spans inside the collection
+*/
+void QSpanCollection::clear()
+{
+ qDeleteAll(spans);
+ index.clear();
+ spans.clear();
+}
+
+/** \internal
+ * return a list to all the spans that spans over cells in the given rectangle
+ */
+QList<QSpanCollection::Span *> QSpanCollection::spansInRect(int x, int y, int w, int h) const
+{
+ QSet<Span *> list;
+ Index::const_iterator it_y = index.lowerBound(-y);
+ if(it_y == index.end())
+ --it_y;
+ while(-it_y.key() <= y + h) {
+ SubIndex::const_iterator it_x = (*it_y).lowerBound(-x);
+ if (it_x == (*it_y).end())
+ --it_x;
+ while(-it_x.key() <= x + w) {
+ Span *s = *it_x;
+ if (s->bottom() >= y && s->right() >= x)
+ list << s;
+ if (it_x == (*it_y).begin())
+ break;
+ --it_x;
+ }
+ if(it_y == index.begin())
+ break;
+ --it_y;
+ }
+ return list.toList();
+}
+
class QTableCornerButton : public QAbstractButton
{
Q_OBJECT
@@ -149,35 +281,40 @@ void QTableViewPrivate::trimHiddenSelections(QItemSelectionRange *range) const
*/
void QTableViewPrivate::setSpan(int row, int column, int rowSpan, int columnSpan)
{
- if (row < 0 || column < 0 || rowSpan < 0 || columnSpan < 0)
+ if (row < 0 || column < 0 || rowSpan <= 0 || columnSpan <= 0) {
+ qWarning() << "QTableView::setSpan: invalid span given: (" << row << ',' << column << ',' << rowSpan << ',' << columnSpan << ')';
return;
- Span sp(row, column, rowSpan, columnSpan);
- QList<Span>::iterator it;
- for (it = spans.begin(); it != spans.end(); ++it) {
- if (((*it).top() == sp.top()) && ((*it).left() == sp.left())) {
- if ((sp.height() == 1) && (sp.width() == 1))
- spans.erase(it); // "Implicit" span (1, 1), no need to store it
- else
- *it = sp; // Replace
+ }
+ QSpanCollection::Span *sp = spans.spanAt(column, row);
+ if (sp) {
+ if (sp->top() != row || sp->left() != column) {
+ qWarning() << "QTableView::setSpan: span cannot overlap";
return;
}
+ if (rowSpan == 1 && columnSpan == 1) {
+ rowSpan = columnSpan = 0;
+ }
+ const int old_height = sp->height();
+ sp->m_bottom = row + rowSpan - 1;
+ sp->m_right = column + columnSpan - 1;
+ spans.updateSpan(sp, old_height);
+ return;
}
- spans.append(sp);
+ sp = new QSpanCollection::Span(row, column, rowSpan, columnSpan);
+ spans.addSpan(sp);
}
/*!
\internal
Gets the span information for the cell at (\a row, \a column).
*/
-QTableViewPrivate::Span QTableViewPrivate::span(int row, int column) const
+QSpanCollection::Span QTableViewPrivate::span(int row, int column) const
{
- QList<Span>::const_iterator it;
- for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
- Span span = *it;
- if (isInSpan(row, column, span))
- return span;
- }
- return Span(row, column, 1, 1);
+ QSpanCollection::Span *sp = spans.spanAt(column, row);
+ if (sp)
+ return *sp;
+
+ return QSpanCollection::Span(row, column, 1, 1);
}
/*!
@@ -233,67 +370,9 @@ bool QTableViewPrivate::spanContainsSection(const QHeaderView *header, int logic
/*!
\internal
- Returns true if one or more spans intersect column \a column.
-*/
-bool QTableViewPrivate::spansIntersectColumn(int column) const
-{
- QList<Span>::const_iterator it;
- for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
- Span span = *it;
- if (spanContainsColumn(column, span.left(), span.width()))
- return true;
- }
- return false;
-}
-
-/*!
- \internal
- Returns true if one or more spans intersect row \a row.
-*/
-bool QTableViewPrivate::spansIntersectRow(int row) const
-{
- QList<Span>::const_iterator it;
- for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
- Span span = *it;
- if (spanContainsRow(row, span.top(), span.height()))
- return true;
- }
- return false;
-}
-
-/*!
- \internal
- Returns true if one or more spans intersect one or more columns.
-*/
-bool QTableViewPrivate::spansIntersectColumns(const QList<int> &columns) const
-{
- QList<int>::const_iterator it;
- for (it = columns.constBegin(); it != columns.constEnd(); ++it) {
- if (spansIntersectColumn(*it))
- return true;
- }
- return false;
-}
-
-/*!
- \internal
- Returns true if one or more spans intersect one or more rows.
-*/
-bool QTableViewPrivate::spansIntersectRows(const QList<int> &rows) const
-{
- QList<int>::const_iterator it;
- for (it = rows.constBegin(); it != rows.constEnd(); ++it) {
- if (spansIntersectRow(*it))
- return true;
- }
- return false;
-}
-
-/*!
- \internal
Returns the visual rect for the given \a span.
*/
-QRect QTableViewPrivate::visualSpanRect(const Span &span) const
+QRect QTableViewPrivate::visualSpanRect(const QSpanCollection::Span &span) const
{
Q_Q(const QTableView);
// vertical
@@ -319,42 +398,54 @@ QRect QTableViewPrivate::visualSpanRect(const Span &span) const
preparation for the main drawing loop.
\a drawn is a QBitArray of visualRowCountxvisualCoulumnCount which say if particular cell has been drawn
*/
-void QTableViewPrivate::drawAndClipSpans(const QRect &area, QPainter *painter,
+void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter,
const QStyleOptionViewItemV4 &option, QBitArray *drawn,
int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn)
{
bool alternateBase = false;
QRegion region = viewport->rect();
- QList<Span>::const_iterator it;
- for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
- Span span = *it;
+ QList<QSpanCollection::Span *> visibleSpans;
+ bool sectionMoved = verticalHeader->sectionsMoved() || horizontalHeader->sectionsMoved();
- int row = span.top();
- int col = span.left();
+ if (!sectionMoved) {
+ visibleSpans = spans.spansInRect(logicalColumn(firstVisualColumn), logicalRow(firstVisualRow),
+ lastVisualColumn - firstVisualColumn + 1, lastVisualRow - firstVisualRow + 1);
+ } else {
+ QSet<QSpanCollection::Span *> set;
+ for(int x = firstVisualColumn; x <= lastVisualColumn; x++)
+ for(int y = firstVisualRow; y <= lastVisualRow; y++)
+ set.insert(spans.spanAt(x,y));
+ set.remove(0);
+ visibleSpans = set.toList();
+ }
+
+ foreach (QSpanCollection::Span *span, visibleSpans) {
+ int row = span->top();
+ int col = span->left();
if (isHidden(row, col))
continue;
QModelIndex index = model->index(row, col, root);
if (!index.isValid())
continue;
- QRect rect = visualSpanRect(span);
+ QRect rect = visualSpanRect(*span);
rect.translate(scrollDelayOffset);
- if (!rect.intersects(area))
+ if (!area.intersects(rect))
continue;
QStyleOptionViewItemV4 opt = option;
opt.rect = rect;
- alternateBase = alternatingColors && (span.top() & 1);
+ alternateBase = alternatingColors && (span->top() & 1);
if (alternateBase)
opt.features |= QStyleOptionViewItemV2::Alternate;
else
opt.features &= ~QStyleOptionViewItemV2::Alternate;
drawCell(painter, opt, index);
region -= rect;
- for (int r = span.top(); r <= span.bottom(); ++r) {
+ for (int r = span->top(); r <= span->bottom(); ++r) {
const int vr = visualRow(r);
if (vr < firstVisualRow || vr > lastVisualRow)
continue;
- for (int c = span.left(); c <= span.right(); ++c) {
+ for (int c = span->left(); c <= span->right(); ++c) {
const int vc = visualColumn(c);
if (vc < firstVisualColumn || vc > lastVisualColumn)
continue;
@@ -397,8 +488,7 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4
opt.state |= QStyle::State_HasFocus;
}
- if (opt.features & QStyleOptionViewItemV2::Alternate)
- painter->fillRect(opt.rect, opt.palette.brush(QPalette::AlternateBase));
+ q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, q);
if (const QWidget *widget = editorForIndex(index).editor) {
painter->save();
@@ -418,7 +508,7 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4
\ingroup model-view
\ingroup advanced
- \mainclass
+
A QTableView implements a table view that displays items from a
model. This class is used to provide standard tables that were
@@ -753,7 +843,8 @@ void QTableView::paintEvent(QPaintEvent *event)
uint x = horizontalHeader->length() - horizontalHeader->offset() - (rightToLeft ? 0 : 1);
uint y = verticalHeader->length() - verticalHeader->offset() - 1;
- QVector<QRect> rects = event->region().rects();
+ const QRegion region = event->region().translated(offset);
+ const QVector<QRect> rects = region.rects();
//firstVisualRow is the visual index of the first visible row. lastVisualRow is the visual index of the last visible Row.
//same goes for ...VisualColumn
@@ -773,9 +864,13 @@ void QTableView::paintEvent(QPaintEvent *event)
QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1));
+ if (d->hasSpans()) {
+ d->drawAndClipSpans(region, &painter, option, &drawn,
+ firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
+ }
+
for (int i = 0; i < rects.size(); ++i) {
QRect dirtyArea = rects.at(i);
- dirtyArea.translate(offset);
dirtyArea.setBottom(qMin(dirtyArea.bottom(), int(y)));
if (rightToLeft) {
dirtyArea.setLeft(qMax(dirtyArea.left(), d->viewport->width() - int(x)));
@@ -783,10 +878,6 @@ void QTableView::paintEvent(QPaintEvent *event)
dirtyArea.setRight(qMin(dirtyArea.right(), int(x)));
}
- if (d->hasSpans())
- d->drawAndClipSpans(dirtyArea, &painter, option, &drawn,
- firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
-
// get the horizontal start and end visual sections
int left = horizontalHeader->visualIndexAt(dirtyArea.left());
int right = horizontalHeader->visualIndexAt(dirtyArea.right());
@@ -913,7 +1004,7 @@ QModelIndex QTableView::indexAt(const QPoint &pos) const
int c = columnAt(pos.x());
if (r >= 0 && c >= 0) {
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(r, c);
+ QSpanCollection::Span span = d->span(r, c);
r = span.top();
c = span.left();
}
@@ -1011,14 +1102,14 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
--visualRow;
if (d->hasSpans()) {
int row = d->logicalRow(visualRow);
- QTableViewPrivate::Span span = d->span(row, current.column());
+ QSpanCollection::Span span = d->span(row, current.column());
visualRow = d->visualRow(span.top());
visualColumn = d->visualColumn(span.left());
}
break;
case MoveDown:
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(current.row(), current.column());
+ QSpanCollection::Span span = d->span(current.row(), current.column());
visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
}
#ifdef QT_KEYPAD_NAVIGATION
@@ -1030,7 +1121,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
++visualRow;
if (d->hasSpans()) {
int row = d->logicalRow(visualRow);
- QTableViewPrivate::Span span = d->span(row, current.column());
+ QSpanCollection::Span span = d->span(row, current.column());
visualColumn = d->visualColumn(span.left());
}
break;
@@ -1058,7 +1149,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
--visualColumn;
if (d->hasSpans()) {
int column = d->logicalColumn(visualColumn);
- QTableViewPrivate::Span span = d->span(current.row(), column);
+ QSpanCollection::Span span = d->span(current.row(), column);
visualRow = d->visualRow(span.top());
visualColumn = d->visualColumn(span.left());
}
@@ -1078,7 +1169,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
} // else MoveRight
case MoveRight:
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(current.row(), current.column());
+ QSpanCollection::Span span = d->span(current.row(), current.column());
visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
}
++visualColumn;
@@ -1086,7 +1177,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
++visualColumn;
if (d->hasSpans()) {
int column = d->logicalColumn(visualColumn);
- QTableViewPrivate::Span span = d->span(current.row(), column);
+ QSpanCollection::Span span = d->span(current.row(), column);
visualRow = d->visualRow(span.top());
}
break;
@@ -1106,17 +1197,16 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
visualRow = bottom;
break;
case MovePageUp: {
- int top = 0;
- while (top < bottom && d->isVisualRowHiddenOrDisabled(top, visualColumn))
- ++top;
- int newRow = qMax(rowAt(visualRect(current).top() - d->viewport->height()), top);
- return d->model->index(qBound(0, newRow, bottom), current.column(), d->root);
+ int newRow = rowAt(visualRect(current).top() - d->viewport->height());
+ if (newRow == -1)
+ newRow = d->logicalRow(0);
+ return d->model->index(newRow, current.column(), d->root);
}
case MovePageDown: {
- int newRow = qMin(rowAt(visualRect(current).bottom() + d->viewport->height()), bottom);
- if (newRow < 0)
- newRow = bottom;
- return d->model->index(qBound(0, newRow, bottom), current.column(), d->root);
+ int newRow = rowAt(visualRect(current).bottom() + d->viewport->height());
+ if (newRow == -1)
+ newRow = d->logicalRow(bottom);
+ return d->model->index(newRow, current.column(), d->root);
}}
int logicalRow = d->logicalRow(visualRow);
@@ -1161,9 +1251,8 @@ void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionF
int right = qMax(d->visualColumn(tl.column()), d->visualColumn(br.column()));
do {
expanded = false;
- QList<QTableViewPrivate::Span>::const_iterator it;
- for (it = d->spans.constBegin(); it != d->spans.constEnd(); ++it) {
- QTableViewPrivate::Span span = *it;
+ foreach (QSpanCollection::Span *it, d->spans.spans) {
+ const QSpanCollection::Span &span = *it;
int t = d->visualRow(span.top());
int l = d->visualColumn(span.left());
int b = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
@@ -1253,7 +1342,7 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
bool verticalMoved = verticalHeader()->sectionsMoved();
bool horizontalMoved = horizontalHeader()->sectionsMoved();
- if ((verticalMoved && horizontalMoved) || d->hasSpans()) {
+ if ((verticalMoved && horizontalMoved) || (d->hasSpans() && (verticalMoved || horizontalMoved))) {
for (int i = 0; i < selection.count(); ++i) {
QItemSelectionRange range = selection.at(i);
if (range.parent() != d->root || !range.isValid())
@@ -1296,9 +1385,19 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
if (range.parent() != d->root || !range.isValid())
continue;
d->trimHiddenSelections(&range);
- QRect tl = visualRect(range.topLeft());
- QRect br = visualRect(range.bottomRight());
- selectionRegion += QRegion(tl|br);
+
+ const int rtop = rowViewportPosition(range.top());
+ const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
+ const int rleft = columnViewportPosition(range.left());
+ const int rright = columnViewportPosition(range.right()) + columnWidth(range.right());
+ selectionRegion += QRect(QPoint(rleft, rtop), QPoint(rright, rbottom));
+ if (d->hasSpans()) {
+ foreach (QSpanCollection::Span *s,
+ d->spans.spansInRect(range.left(), range.top(), range.width(), range.height())) {
+ if (range.contains(s->top(), s->left(), range.parent()))
+ selectionRegion += d->visualSpanRect(*s);
+ }
+ }
}
}
@@ -1428,6 +1527,8 @@ void QTableView::updateGeometries()
++columnsInViewport;
}
}
+ columnsInViewport = qMax(columnsInViewport, 1); //there must be always at least 1 column
+
if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
const int visibleColumns = columnCount - d->horizontalHeader->hiddenSectionCount();
horizontalScrollBar()->setRange(0, visibleColumns - columnsInViewport);
@@ -1454,6 +1555,8 @@ void QTableView::updateGeometries()
++rowsInViewport;
}
}
+ rowsInViewport = qMax(rowsInViewport, 1); //there must be always at least 1 row
+
if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
const int visibleRows = rowCount - d->verticalHeader->hiddenSectionCount();
verticalScrollBar()->setRange(0, visibleRows - rowsInViewport);
@@ -1743,14 +1846,14 @@ void QTableView::setSortingEnabled(bool enable)
disconnect(horizontalHeader(), SIGNAL(sectionPressed(int)),
this, SLOT(selectColumn(int)));
connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(sortByColumn(int)));
+ this, SLOT(sortByColumn(int)), Qt::UniqueConnection);
sortByColumn(horizontalHeader()->sortIndicatorSection(),
horizontalHeader()->sortIndicatorOrder());
} else {
connect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
- this, SLOT(_q_selectColumn(int)));
+ this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection);
connect(horizontalHeader(), SIGNAL(sectionPressed(int)),
- this, SLOT(selectColumn(int)));
+ this, SLOT(selectColumn(int)), Qt::UniqueConnection);
disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
this, SLOT(sortByColumn(int)));
}
@@ -1874,7 +1977,7 @@ QRect QTableView::visualRect(const QModelIndex &index) const
d->executePostedLayout();
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(index.row(), index.column());
+ QSpanCollection::Span span = d->span(index.row(), index.column());
return d->visualSpanRect(span);
}
@@ -1903,7 +2006,7 @@ void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
|| isIndexHidden(index))
return;
- QTableViewPrivate::Span span;
+ QSpanCollection::Span span;
if (d->hasSpans())
span = d->span(index.row(), index.column());
@@ -1936,7 +2039,7 @@ void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
if (positionAtRight || hint == PositionAtCenter || positionAtLeft) {
int hiddenSections = 0;
if (d->horizontalHeader->sectionsHidden()) {
- for (int s = horizontalIndex; s >= 0; --s) {
+ for (int s = horizontalIndex - 1; s >= 0; --s) {
int column = d->horizontalHeader->logicalIndex(s);
if (d->horizontalHeader->isSectionHidden(column))
++hiddenSections;
@@ -1991,7 +2094,7 @@ void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
if (hint == PositionAtBottom || hint == PositionAtCenter || hint == PositionAtTop) {
int hiddenSections = 0;
if (d->verticalHeader->sectionsHidden()) {
- for (int s = verticalIndex; s >= 0; --s) {
+ for (int s = verticalIndex - 1; s >= 0; --s) {
int row = d->verticalHeader->logicalIndex(s);
if (d->verticalHeader->isSectionHidden(row))
++hiddenSections;
@@ -2010,7 +2113,7 @@ void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
}
}
- d->setDirtyRegion(visualRect(index));
+ update(index);
}
/*!
@@ -2058,7 +2161,7 @@ void QTableView::timerEvent(QTimerEvent *event)
QRect rect;
int viewportHeight = d->viewport->height();
int viewportWidth = d->viewport->width();
- if (d->hasSpans() && d->spansIntersectColumns(d->columnsToUpdate)) {
+ if (d->hasSpans()) {
rect = QRect(0, 0, viewportWidth, viewportHeight);
} else {
for (int i = d->columnsToUpdate.size()-1; i >= 0; --i) {
@@ -2083,7 +2186,7 @@ void QTableView::timerEvent(QTimerEvent *event)
int viewportHeight = d->viewport->height();
int viewportWidth = d->viewport->width();
int top;
- if (d->hasSpans() && d->spansIntersectRows(d->rowsToUpdate)) {
+ if (d->hasSpans()) {
top = 0;
} else {
top = viewportHeight;
@@ -2114,7 +2217,7 @@ void QTableView::rowMoved(int, int oldIndex, int newIndex)
updateGeometries();
int logicalOldIndex = d->verticalHeader->logicalIndex(oldIndex);
int logicalNewIndex = d->verticalHeader->logicalIndex(newIndex);
- if (d->hasSpans() && (d->spansIntersectRow(logicalOldIndex) || d->spansIntersectRow(logicalNewIndex))) {
+ if (d->hasSpans()) {
d->viewport->update();
} else {
int oldTop = rowViewportPosition(logicalOldIndex);
@@ -2142,7 +2245,7 @@ void QTableView::columnMoved(int, int oldIndex, int newIndex)
updateGeometries();
int logicalOldIndex = d->horizontalHeader->logicalIndex(oldIndex);
int logicalNewIndex = d->horizontalHeader->logicalIndex(newIndex);
- if (d->hasSpans() && (d->spansIntersectColumn(logicalOldIndex) || d->spansIntersectColumn(logicalNewIndex))) {
+ if (d->hasSpans()) {
d->viewport->update();
} else {
int oldLeft = columnViewportPosition(logicalOldIndex);
@@ -2325,7 +2428,7 @@ bool QTableView::isIndexHidden(const QModelIndex &index) const
if (isRowHidden(index.row()) || isColumnHidden(index.column()))
return true;
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(index.row(), index.column());
+ QSpanCollection::Span span = d->span(index.row(), index.column());
return !((span.top() == index.row()) && (span.left() == index.column()));
}
return false;
diff --git a/src/gui/itemviews/qtableview_p.h b/src/gui/itemviews/qtableview_p.h
index 7c0aa58..cd49dce 100644
--- a/src/gui/itemviews/qtableview_p.h
+++ b/src/gui/itemviews/qtableview_p.h
@@ -53,12 +53,69 @@
// We mean it.
//
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QSet>
+#include <QtCore/QDebug>
#include "private/qabstractitemview_p.h"
#ifndef QT_NO_TABLEVIEW
QT_BEGIN_NAMESPACE
+/** \internal
+*
+* This is a list of span with a binary index to look up quickly a span at a certain index.
+*
+* The index is a map of map.
+* spans are mentaly divided into sub spans so that the start of any subspans doesn't overlap
+* with any other subspans. There is no real representation of the subspans.
+* The key of the first map is the row where the subspan starts, the value of the first map is
+* a list (map) of all subspans that starts at the same row. It is indexed with its row
+*/
+class QSpanCollection
+{
+public:
+ struct Span
+ {
+ int m_top;
+ int m_left;
+ int m_bottom;
+ int m_right;
+ Span()
+ : m_top(-1), m_left(-1), m_bottom(-1), m_right(-1) { }
+ Span(int row, int column, int rowCount, int columnCount)
+ : m_top(row), m_left(column), m_bottom(row+rowCount-1), m_right(column+columnCount-1) { }
+ inline int top() const { return m_top; }
+ inline int left() const { return m_left; }
+ inline int bottom() const { return m_bottom; }
+ inline int right() const { return m_right; }
+ inline int height() const { return m_bottom - m_top + 1; }
+ inline int width() const { return m_right - m_left + 1; }
+ };
+
+ ~QSpanCollection()
+ {
+ qDeleteAll(spans);
+ }
+
+ void addSpan(Span *span);
+ void updateSpan(Span *span, int old_height);
+ Span *spanAt(int x, int y) const;
+ void clear();
+ QList<Span *> spansInRect(int x, int y, int w, int h) const;
+
+ QList<Span *> spans; //lists of all spans
+private:
+ //the indexes are negative so the QMap::lowerBound do what i need.
+ typedef QMap<int, Span *> SubIndex;
+ typedef QMap<int, SubIndex> Index;
+ Index index;
+};
+
+Q_DECLARE_TYPEINFO ( QSpanCollection::Span, Q_MOVABLE_TYPE);
+
+
class QTableViewPrivate : public QAbstractItemViewPrivate
{
Q_DECLARE_PUBLIC(QTableView)
@@ -98,11 +155,7 @@ public:
int sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const;
int sectionSpanSize(const QHeaderView *header, int logical, int span) const;
bool spanContainsSection(const QHeaderView *header, int logical, int spanLogical, int span) const;
- bool spansIntersectColumn(int column) const;
- bool spansIntersectRow(int row) const;
- bool spansIntersectColumns(const QList<int> &columns) const;
- bool spansIntersectRows(const QList<int> &rows) const;
- void drawAndClipSpans(const QRect &area, QPainter *painter,
+ void drawAndClipSpans(const QRegion &area, QPainter *painter,
const QStyleOptionViewItemV4 &option, QBitArray *drawn,
int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn);
void drawCell(QPainter *painter, const QStyleOptionViewItemV4 &option, const QModelIndex &index);
@@ -121,27 +174,10 @@ public:
bool sortingEnabled;
bool geometryRecursionBlock;
- struct Span
- {
- int m_top;
- int m_left;
- int m_bottom;
- int m_right;
- Span()
- : m_top(-1), m_left(-1), m_bottom(-1), m_right(-1) { }
- Span(int row, int column, int rowCount, int columnCount)
- : m_top(row), m_left(column), m_bottom(row+rowCount-1), m_right(column+columnCount-1) { }
- inline int top() const { return m_top; }
- inline int left() const { return m_left; }
- inline int bottom() const { return m_bottom; }
- inline int right() const { return m_right; }
- inline int height() const { return m_bottom - m_top + 1; }
- inline int width() const { return m_right - m_left + 1; }
- };
- QList<Span> spans;
+ QSpanCollection spans;
void setSpan(int row, int column, int rowSpan, int columnSpan);
- Span span(int row, int column) const;
+ QSpanCollection::Span span(int row, int column) const;
inline int rowSpan(int row, int column) const {
return span(row, column).height();
}
@@ -149,17 +185,7 @@ public:
return span(row, column).width();
}
inline bool hasSpans() const {
- return !spans.isEmpty();
- }
- inline bool spanContainsRow(int row, int spanRow, int span) const {
- return spanContainsSection(verticalHeader, row, spanRow, span);
- }
- inline bool spanContainsColumn(int column, int spanColumn, int span) const {
- return spanContainsSection(horizontalHeader, column, spanColumn, span);
- }
- inline bool isInSpan(int row, int column, const Span &span) const {
- return spanContainsRow(row, span.top(), span.height())
- && spanContainsColumn(column, span.left(), span.width());
+ return !spans.spans.isEmpty();
}
inline int rowSpanHeight(int row, int span) const {
return sectionSpanSize(verticalHeader, row, span);
@@ -194,7 +220,7 @@ public:
return isColumnHidden(c) || !isCellEnabled(r, c);
}
- QRect visualSpanRect(const Span &span) const;
+ QRect visualSpanRect(const QSpanCollection::Span &span) const;
void _q_selectRow(int row);
void _q_selectColumn(int column);
diff --git a/src/gui/itemviews/qtablewidget.cpp b/src/gui/itemviews/qtablewidget.cpp
index 891cbcc..af0885d 100644
--- a/src/gui/itemviews/qtablewidget.cpp
+++ b/src/gui/itemviews/qtablewidget.cpp
@@ -226,6 +226,8 @@ QTableWidgetItem *QTableModel::takeItem(int row, int column)
itm->view = 0;
itm->d->id = -1;
tableItems[i] = 0;
+ QModelIndex ind = index(itm);
+ emit dataChanged(ind, ind);
}
return itm;
}
@@ -530,24 +532,6 @@ void QTableModel::sort(int column, Qt::SortOrder order)
emit layoutChanged();
}
-bool QTableModel::canConvertToDouble(const QVariant &value)
-{
- switch (value.type()) {
- case QVariant::Bool:
- case QVariant::Int:
- case QVariant::UInt:
- case QVariant::LongLong:
- case QVariant::ULongLong:
- case QVariant::Double:
- case QVariant::Char:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-
/*
\internal
@@ -1410,9 +1394,7 @@ QVariant QTableWidgetItem::data(int role) const
bool QTableWidgetItem::operator<(const QTableWidgetItem &other) const
{
const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole);
- if (QTableModel::canConvertToDouble(v1) && QTableModel::canConvertToDouble(v2))
- return v1.toDouble() < v2.toDouble();
- return v1.toString() < v2.toString();
+ return QAbstractItemModelPrivate::variantLessThan(v1, v2);
}
#ifndef QT_NO_DATASTREAM
@@ -1506,7 +1488,7 @@ QTableWidgetItem &QTableWidgetItem::operator=(const QTableWidgetItem &other)
\brief The QTableWidget class provides an item-based table view with a default model.
\ingroup model-view
- \mainclass
+
Table widgets provide standard table display facilities for applications.
The items in a QTableWidget are provided by QTableWidgetItem.
@@ -1588,7 +1570,7 @@ void QTableWidgetPrivate::setup()
QObject::connect(q, SIGNAL(activated(QModelIndex)), q, SLOT(_q_emitItemActivated(QModelIndex)));
QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
// model signals
- QObject::connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_emitItemChanged(QModelIndex)));
// selection signals
QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
@@ -1596,15 +1578,15 @@ void QTableWidgetPrivate::setup()
QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
q, SIGNAL(itemSelectionChanged()));
// sorting
- QObject::connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- QObject::connect(model(), SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
+ QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
}
void QTableWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemPressed(item);
emit q->cellPressed(index.row(), index.column());
}
@@ -1612,7 +1594,7 @@ void QTableWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemClicked(item);
emit q->cellClicked(index.row(), index.column());
}
@@ -1620,7 +1602,7 @@ void QTableWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemDoubleClicked(item);
emit q->cellDoubleClicked(index.row(), index.column());
}
@@ -1628,7 +1610,7 @@ void QTableWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemActivated(item);
emit q->cellActivated(index.row(), index.column());
}
@@ -1636,7 +1618,7 @@ void QTableWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemEntered(item);
emit q->cellEntered(index.row(), index.column());
}
@@ -1644,7 +1626,7 @@ void QTableWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemChanged(item);
emit q->cellChanged(index.row(), index.column());
}
@@ -1653,8 +1635,8 @@ void QTableWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
const QModelIndex &previous)
{
Q_Q(QTableWidget);
- QTableWidgetItem *currentItem = model()->item(current);
- QTableWidgetItem *previousItem = model()->item(previous);
+ QTableWidgetItem *currentItem = tableModel()->item(current);
+ QTableWidgetItem *previousItem = tableModel()->item(previous);
if (currentItem || previousItem)
emit q->currentItemChanged(currentItem, previousItem);
emit q->currentCellChanged(current.row(), current.column(), previous.row(), previous.column());
@@ -1662,23 +1644,21 @@ void QTableWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
void QTableWidgetPrivate::_q_sort()
{
- Q_Q(QTableWidget);
if (sortingEnabled) {
- int column = q->horizontalHeader()->sortIndicatorSection();
- Qt::SortOrder order = q->horizontalHeader()->sortIndicatorOrder();
- model()->sort(column, order);
+ int column = horizontalHeader->sortIndicatorSection();
+ Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
+ model->sort(column, order);
}
}
void QTableWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight)
{
- Q_Q(QTableWidget);
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()) {
- int column = q->horizontalHeader()->sortIndicatorSection();
+ int column = horizontalHeader->sortIndicatorSection();
if (column >= topLeft.column() && column <= bottomRight.column()) {
- Qt::SortOrder order = q->horizontalHeader()->sortIndicatorOrder();
- model()->ensureSorted(column, order, topLeft.row(), bottomRight.row());
+ Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
+ tableModel()->ensureSorted(column, order, topLeft.row(), bottomRight.row());
}
}
}
@@ -1739,7 +1719,7 @@ void QTableWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
This signal is emitted whenever the selection changes.
- \sa selectedItems() isItemSelected()
+ \sa selectedItems() QTableWidgetItem::isSelected()
*/
@@ -1882,7 +1862,7 @@ QTableWidget::~QTableWidget()
void QTableWidget::setRowCount(int rows)
{
Q_D(QTableWidget);
- d->model()->setRowCount(rows);
+ d->tableModel()->setRowCount(rows);
}
/*!
@@ -1892,7 +1872,7 @@ void QTableWidget::setRowCount(int rows)
int QTableWidget::rowCount() const
{
Q_D(const QTableWidget);
- return d->model()->rowCount();
+ return d->model->rowCount();
}
/*!
@@ -1905,7 +1885,7 @@ int QTableWidget::rowCount() const
void QTableWidget::setColumnCount(int columns)
{
Q_D(QTableWidget);
- d->model()->setColumnCount(columns);
+ d->tableModel()->setColumnCount(columns);
}
/*!
@@ -1915,7 +1895,7 @@ void QTableWidget::setColumnCount(int columns)
int QTableWidget::columnCount() const
{
Q_D(const QTableWidget);
- return d->model()->columnCount();
+ return d->model->columnCount();
}
/*!
@@ -1924,7 +1904,7 @@ int QTableWidget::columnCount() const
int QTableWidget::row(const QTableWidgetItem *item) const
{
Q_D(const QTableWidget);
- return d->model()->index(item).row();
+ return d->tableModel()->index(item).row();
}
/*!
@@ -1933,7 +1913,7 @@ int QTableWidget::row(const QTableWidgetItem *item) const
int QTableWidget::column(const QTableWidgetItem *item) const
{
Q_D(const QTableWidget);
- return d->model()->index(item).column();
+ return d->tableModel()->index(item).column();
}
@@ -1946,7 +1926,7 @@ int QTableWidget::column(const QTableWidgetItem *item) const
QTableWidgetItem *QTableWidget::item(int row, int column) const
{
Q_D(const QTableWidget);
- return d->model()->item(row, column);
+ return d->tableModel()->item(row, column);
}
/*!
@@ -1975,7 +1955,7 @@ void QTableWidget::setItem(int row, int column, QTableWidgetItem *item)
qWarning("QTableWidget: cannot insert an item that is already owned by another QTableWidget");
} else {
item->view = this;
- d->model()->setItem(row, column, item);
+ d->tableModel()->setItem(row, column, item);
}
} else {
delete takeItem(row, column);
@@ -1988,7 +1968,7 @@ void QTableWidget::setItem(int row, int column, QTableWidgetItem *item)
QTableWidgetItem *QTableWidget::takeItem(int row, int column)
{
Q_D(QTableWidget);
- QTableWidgetItem *item = d->model()->takeItem(row, column);
+ QTableWidgetItem *item = d->tableModel()->takeItem(row, column);
if (item)
item->view = 0;
return item;
@@ -2000,7 +1980,7 @@ QTableWidgetItem *QTableWidget::takeItem(int row, int column)
QTableWidgetItem *QTableWidget::verticalHeaderItem(int row) const
{
Q_D(const QTableWidget);
- return d->model()->verticalHeaderItem(row);
+ return d->tableModel()->verticalHeaderItem(row);
}
/*!
@@ -2011,7 +1991,7 @@ void QTableWidget::setVerticalHeaderItem(int row, QTableWidgetItem *item)
Q_D(QTableWidget);
if (item) {
item->view = this;
- d->model()->setVerticalHeaderItem(row, item);
+ d->tableModel()->setVerticalHeaderItem(row, item);
} else {
delete takeVerticalHeaderItem(row);
}
@@ -2024,7 +2004,7 @@ void QTableWidget::setVerticalHeaderItem(int row, QTableWidgetItem *item)
QTableWidgetItem *QTableWidget::takeVerticalHeaderItem(int row)
{
Q_D(QTableWidget);
- QTableWidgetItem *itm = d->model()->takeVerticalHeaderItem(row);
+ QTableWidgetItem *itm = d->tableModel()->takeVerticalHeaderItem(row);
if (itm)
itm->view = 0;
return itm;
@@ -2037,7 +2017,7 @@ QTableWidgetItem *QTableWidget::takeVerticalHeaderItem(int row)
QTableWidgetItem *QTableWidget::horizontalHeaderItem(int column) const
{
Q_D(const QTableWidget);
- return d->model()->horizontalHeaderItem(column);
+ return d->tableModel()->horizontalHeaderItem(column);
}
/*!
@@ -2048,7 +2028,7 @@ void QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem *item)
Q_D(QTableWidget);
if (item) {
item->view = this;
- d->model()->setHorizontalHeaderItem(column, item);
+ d->tableModel()->setHorizontalHeaderItem(column, item);
} else {
delete takeHorizontalHeaderItem(column);
}
@@ -2061,7 +2041,7 @@ void QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem *item)
QTableWidgetItem *QTableWidget::takeHorizontalHeaderItem(int column)
{
Q_D(QTableWidget);
- QTableWidgetItem *itm = d->model()->takeHorizontalHeaderItem(column);
+ QTableWidgetItem *itm = d->tableModel()->takeHorizontalHeaderItem(column);
if (itm)
itm->view = 0;
return itm;
@@ -2073,7 +2053,7 @@ QTableWidgetItem *QTableWidget::takeHorizontalHeaderItem(int column)
void QTableWidget::setVerticalHeaderLabels(const QStringList &labels)
{
Q_D(QTableWidget);
- QTableModel *model = d->model();
+ QTableModel *model = d->tableModel();
QTableWidgetItem *item = 0;
for (int i = 0; i < model->rowCount() && i < labels.count(); ++i) {
item = model->verticalHeaderItem(i);
@@ -2091,7 +2071,7 @@ void QTableWidget::setVerticalHeaderLabels(const QStringList &labels)
void QTableWidget::setHorizontalHeaderLabels(const QStringList &labels)
{
Q_D(QTableWidget);
- QTableModel *model = d->model();
+ QTableModel *model = d->tableModel();
QTableWidgetItem *item = 0;
for (int i = 0; i < model->columnCount() && i < labels.count(); ++i) {
item = model->horizontalHeaderItem(i);
@@ -2131,21 +2111,21 @@ int QTableWidget::currentColumn() const
QTableWidgetItem *QTableWidget::currentItem() const
{
Q_D(const QTableWidget);
- return d->model()->item(currentIndex());
+ return d->tableModel()->item(currentIndex());
}
/*!
Sets the current item to \a item.
- Depending on the current \l{QAbstractItemView::SelectionMode}{selection mode},
- the item may also be selected.
+ Unless the selection mode is \l{QAbstractItemView::}{NoSelection},
+ the item is also be selected.
\sa currentItem(), setCurrentCell()
*/
void QTableWidget::setCurrentItem(QTableWidgetItem *item)
{
Q_D(QTableWidget);
- setCurrentIndex(d->model()->index(item));
+ setCurrentIndex(d->tableModel()->index(item));
}
/*!
@@ -2158,7 +2138,7 @@ void QTableWidget::setCurrentItem(QTableWidgetItem *item)
void QTableWidget::setCurrentItem(QTableWidgetItem *item, QItemSelectionModel::SelectionFlags command)
{
Q_D(QTableWidget);
- d->selectionModel->setCurrentIndex(d->model()->index(item), command);
+ d->selectionModel->setCurrentIndex(d->tableModel()->index(item), command);
}
/*!
@@ -2197,7 +2177,7 @@ void QTableWidget::setCurrentCell(int row, int column, QItemSelectionModel::Sele
void QTableWidget::sortItems(int column, Qt::SortOrder order)
{
Q_D(QTableWidget);
- d->model()->sort(column, order);
+ d->model->sort(column, order);
horizontalHeader()->setSortIndicator(column, order);
}
@@ -2226,7 +2206,7 @@ void QTableWidget::editItem(QTableWidgetItem *item)
Q_D(QTableWidget);
if (!item)
return;
- edit(d->model()->index(item));
+ edit(d->tableModel()->index(item));
}
/*!
@@ -2239,7 +2219,7 @@ void QTableWidget::openPersistentEditor(QTableWidgetItem *item)
Q_D(QTableWidget);
if (!item)
return;
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->tableModel()->index(item);
QAbstractItemView::openPersistentEditor(index);
}
@@ -2253,7 +2233,7 @@ void QTableWidget::closePersistentEditor(QTableWidgetItem *item)
Q_D(QTableWidget);
if (!item)
return;
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->tableModel()->index(item);
QAbstractItemView::closePersistentEditor(index);
}
@@ -2303,7 +2283,7 @@ void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
bool QTableWidget::isItemSelected(const QTableWidgetItem *item) const
{
Q_D(const QTableWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->tableModel()->index(item);
return selectionModel()->isSelected(index);
}
@@ -2317,7 +2297,7 @@ bool QTableWidget::isItemSelected(const QTableWidgetItem *item) const
void QTableWidget::setItemSelected(const QTableWidgetItem *item, bool select)
{
Q_D(QTableWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->tableModel()->index(item);
selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
}
@@ -2374,7 +2354,7 @@ QList<QTableWidgetItem*> QTableWidget::selectedItems()
QModelIndex index = indexes.at(i);
if (isIndexHidden(index))
continue;
- QTableWidgetItem *item = d->model()->item(index);
+ QTableWidgetItem *item = d->tableModel()->item(index);
if (item)
items.append(item);
}
@@ -2390,11 +2370,11 @@ QList<QTableWidgetItem*> QTableWidget::findItems(const QString &text, Qt::MatchF
Q_D(const QTableWidget);
QModelIndexList indexes;
for (int column = 0; column < columnCount(); ++column)
- indexes += d->model()->match(model()->index(0, column, QModelIndex()),
+ indexes += d->model->match(model()->index(0, column, QModelIndex()),
Qt::DisplayRole, text, -1, flags);
QList<QTableWidgetItem*> items;
for (int i = 0; i < indexes.size(); ++i)
- items.append(d->model()->item(indexes.at(i)));
+ items.append(d->tableModel()->item(indexes.at(i)));
return items;
}
@@ -2428,7 +2408,7 @@ int QTableWidget::visualColumn(int logicalColumn) const
QTableWidgetItem *QTableWidget::itemAt(const QPoint &p) const
{
Q_D(const QTableWidget);
- return d->model()->item(indexAt(p));
+ return d->tableModel()->item(indexAt(p));
}
/*!
@@ -2439,7 +2419,7 @@ QRect QTableWidget::visualItemRect(const QTableWidgetItem *item) const
Q_D(const QTableWidget);
if (!item)
return QRect();
- QModelIndex index = d->model()->index(const_cast<QTableWidgetItem*>(item));
+ QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
Q_ASSERT(index.isValid());
return visualRect(index);
}
@@ -2455,7 +2435,7 @@ void QTableWidget::scrollToItem(const QTableWidgetItem *item, QAbstractItemView:
Q_D(QTableWidget);
if (!item)
return;
- QModelIndex index = d->model()->index(const_cast<QTableWidgetItem*>(item));
+ QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
Q_ASSERT(index.isValid());
QTableView::scrollTo(index, hint);
}
@@ -2468,7 +2448,7 @@ void QTableWidget::scrollToItem(const QTableWidgetItem *item, QAbstractItemView:
const QTableWidgetItem *QTableWidget::itemPrototype() const
{
Q_D(const QTableWidget);
- return d->model()->itemPrototype();
+ return d->tableModel()->itemPrototype();
}
/*!
@@ -2487,7 +2467,7 @@ const QTableWidgetItem *QTableWidget::itemPrototype() const
void QTableWidget::setItemPrototype(const QTableWidgetItem *item)
{
Q_D(QTableWidget);
- d->model()->setItemPrototype(item);
+ d->tableModel()->setItemPrototype(item);
}
/*!
@@ -2496,7 +2476,7 @@ void QTableWidget::setItemPrototype(const QTableWidgetItem *item)
void QTableWidget::insertRow(int row)
{
Q_D(QTableWidget);
- d->model()->insertRows(row);
+ d->tableModel()->insertRows(row);
}
/*!
@@ -2505,7 +2485,7 @@ void QTableWidget::insertRow(int row)
void QTableWidget::insertColumn(int column)
{
Q_D(QTableWidget);
- d->model()->insertColumns(column);
+ d->tableModel()->insertColumns(column);
}
/*!
@@ -2514,7 +2494,7 @@ void QTableWidget::insertColumn(int column)
void QTableWidget::removeRow(int row)
{
Q_D(QTableWidget);
- d->model()->removeRows(row);
+ d->tableModel()->removeRows(row);
}
/*!
@@ -2523,7 +2503,7 @@ void QTableWidget::removeRow(int row)
void QTableWidget::removeColumn(int column)
{
Q_D(QTableWidget);
- d->model()->removeColumns(column);
+ d->tableModel()->removeColumns(column);
}
/*!
@@ -2536,7 +2516,7 @@ void QTableWidget::clear()
{
Q_D(QTableWidget);
selectionModel()->clear();
- d->model()->clear();
+ d->tableModel()->clear();
}
/*!
@@ -2550,7 +2530,7 @@ void QTableWidget::clearContents()
{
Q_D(QTableWidget);
selectionModel()->clear();
- d->model()->clearContents();
+ d->tableModel()->clearContents();
}
/*!
@@ -2561,7 +2541,7 @@ void QTableWidget::clearContents()
*/
QStringList QTableWidget::mimeTypes() const
{
- return d_func()->model()->QAbstractTableModel::mimeTypes();
+ return d_func()->tableModel()->QAbstractTableModel::mimeTypes();
}
/*!
@@ -2574,7 +2554,7 @@ QStringList QTableWidget::mimeTypes() const
*/
QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*>) const
{
- return d_func()->model()->internalMimeData();
+ return d_func()->tableModel()->internalMimeData();
}
/*!
@@ -2596,7 +2576,7 @@ bool QTableWidget::dropMimeData(int row, int column, const QMimeData *data, Qt::
column = -1;
}
#endif
- return d_func()->model()->QAbstractTableModel::dropMimeData(data, action , row, column, idx);
+ return d_func()->tableModel()->QAbstractTableModel::dropMimeData(data, action , row, column, idx);
}
/*!
@@ -2606,7 +2586,7 @@ bool QTableWidget::dropMimeData(int row, int column, const QMimeData *data, Qt::
*/
Qt::DropActions QTableWidget::supportedDropActions() const
{
- return d_func()->model()->QAbstractTableModel::supportedDropActions() | Qt::MoveAction;
+ return d_func()->tableModel()->QAbstractTableModel::supportedDropActions() | Qt::MoveAction;
}
/*!
@@ -2630,7 +2610,7 @@ QList<QTableWidgetItem*> QTableWidget::items(const QMimeData *data) const
QModelIndex QTableWidget::indexFromItem(QTableWidgetItem *item) const
{
Q_D(const QTableWidget);
- return d->model()->index(item);
+ return d->tableModel()->index(item);
}
/*!
@@ -2640,7 +2620,7 @@ QModelIndex QTableWidget::indexFromItem(QTableWidgetItem *item) const
QTableWidgetItem *QTableWidget::itemFromIndex(const QModelIndex &index) const
{
Q_D(const QTableWidget);
- return d->model()->item(index);
+ return d->tableModel()->item(index);
}
/*!
diff --git a/src/gui/itemviews/qtablewidget_p.h b/src/gui/itemviews/qtablewidget_p.h
index fdfbc20..a80c1ee 100644
--- a/src/gui/itemviews/qtablewidget_p.h
+++ b/src/gui/itemviews/qtablewidget_p.h
@@ -144,7 +144,6 @@ public:
const QPair<QTableWidgetItem*,int> &right);
static bool itemGreaterThan(const QPair<QTableWidgetItem*,int> &left,
const QPair<QTableWidgetItem*,int> &right);
- static bool canConvertToDouble(const QVariant &value);
void ensureSorted(int column, Qt::SortOrder order, int start, int end);
QVector<QTableWidgetItem*> columnItems(int column) const;
@@ -190,7 +189,7 @@ class QTableWidgetPrivate : public QTableViewPrivate
Q_DECLARE_PUBLIC(QTableWidget)
public:
QTableWidgetPrivate() : QTableViewPrivate() {}
- inline QTableModel *model() const { return qobject_cast<QTableModel*>(q_func()->model()); }
+ inline QTableModel *tableModel() const { return qobject_cast<QTableModel*>(model); }
void setup();
// view signals
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index 99cbacc..a5b4044 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
\ingroup model-view
\ingroup advanced
- \mainclass
+
A QTreeView implements a tree representation of items from a
model. This class is used to provide standard hierarchical lists that
@@ -238,11 +238,6 @@ void QTreeView::setModel(QAbstractItemModel *model)
connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(rowsRemoved(QModelIndex,int,int)));
- connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
-
connect(d->model, SIGNAL(modelAboutToBeReset()), SLOT(_q_modelAboutToBeReset()));
if (d->sortingEnabled)
@@ -267,10 +262,6 @@ void QTreeView::setSelectionModel(QItemSelectionModel *selectionModel)
Q_D(QTreeView);
Q_ASSERT(selectionModel);
if (d->selectionModel) {
- if (d->allColumnsShowFocus) {
- QObject::disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_currentChanged(QModelIndex,QModelIndex)));
- }
// support row editing
disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
d->model, SLOT(submit()));
@@ -280,10 +271,6 @@ void QTreeView::setSelectionModel(QItemSelectionModel *selectionModel)
QAbstractItemView::setSelectionModel(selectionModel);
if (d->selectionModel) {
- if (d->allColumnsShowFocus) {
- QObject::connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_currentChanged(QModelIndex,QModelIndex)));
- }
// support row editing
connect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
d->model, SLOT(submit()));
@@ -680,10 +667,9 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto
// refresh the height cache here; we don't really lose anything by getting the size hint,
// since QAbstractItemView::dataChanged() will get the visualRect for the items anyway
- QModelIndex top = topLeft.sibling(topLeft.row(), 0);
- int topViewIndex = d->viewIndex(top);
+ int topViewIndex = d->viewIndex(topLeft);
if (topViewIndex == 0)
- d->defaultItemHeight = indexRowSizeHint(top);
+ d->defaultItemHeight = indexRowSizeHint(topLeft);
bool sizeChanged = false;
if (topViewIndex != -1) {
if (topLeft == bottomRight) {
@@ -691,8 +677,7 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto
d->invalidateHeightCache(topViewIndex);
sizeChanged = (oldHeight != d->itemHeight(topViewIndex));
} else {
- QModelIndex bottom = bottomRight.sibling(bottomRight.row(), 0);
- int bottomViewIndex = d->viewIndex(bottom);
+ int bottomViewIndex = d->viewIndex(bottomRight);
for (int i = topViewIndex; i <= bottomViewIndex; ++i) {
int oldHeight = d->itemHeight(i);
d->invalidateHeightCache(i);
@@ -853,7 +838,7 @@ void QTreeView::setSortingEnabled(bool enable)
// because otherwise it will not call sort on the model.
sortByColumn(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
connect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(_q_sortIndicatorChanged(int, Qt::SortOrder)));
+ this, SLOT(_q_sortIndicatorChanged(int, Qt::SortOrder)), Qt::UniqueConnection);
} else {
disconnect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
this, SLOT(_q_sortIndicatorChanged(int, Qt::SortOrder)));
@@ -908,15 +893,6 @@ void QTreeView::setAllColumnsShowFocus(bool enable)
Q_D(QTreeView);
if (d->allColumnsShowFocus == enable)
return;
- if (d->selectionModel) {
- if (enable) {
- QObject::connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_currentChanged(QModelIndex,QModelIndex)));
- } else {
- QObject::disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_currentChanged(QModelIndex,QModelIndex)));
- }
- }
d->allColumnsShowFocus = enable;
d->viewport->update();
}
@@ -1119,18 +1095,22 @@ void QTreeView::scrollTo(const QModelIndex &index, ScrollHint hint)
} else if (hint == PositionAtTop || (hint == EnsureVisible && item < top)) {
verticalScrollBar()->setValue(item);
} else { // PositionAtBottom or PositionAtCenter
- int itemLocation = item;
+ const int currentItemHeight = d->itemHeight(item);
int y = (hint == PositionAtCenter
- ? area.height() / 2
+ //we center on the current item with a preference to the top item (ie. -1)
+ ? area.height() / 2 + currentItemHeight - 1
+ //otherwise we simply take the whole space
: area.height());
- while (y > 0 && item > 0)
- y -= d->itemHeight(item--);
- // end up half over the top of the area
- if (y < 0 && item < itemLocation)
- ++item;
- // end up half over the bottom of the area
- if (item >= 0 && item < itemLocation)
- ++item;
+ if (y > currentItemHeight) {
+ while (item >= 0) {
+ y -= d->itemHeight(item);
+ if (y < 0) { //there is no more space left
+ item++;
+ break;
+ }
+ item--;
+ }
+ }
verticalScrollBar()->setValue(item);
}
} else { // ScrollPerPixel
@@ -1142,7 +1122,7 @@ void QTreeView::scrollTo(const QModelIndex &index, ScrollHint hint)
if (rect.isEmpty()) {
// nothing to do
} else if (hint == EnsureVisible && area.contains(rect)) {
- d->setDirtyRegion(rect);
+ d->viewport->update(rect);
// nothing to do
} else {
bool above = (hint == EnsureVisible
@@ -1274,10 +1254,13 @@ void QTreeView::paintEvent(QPaintEvent *event)
Q_D(QTreeView);
d->executePostedLayout();
QPainter painter(viewport());
+#ifndef QT_NO_ANIMATION
if (d->isAnimating()) {
- drawTree(&painter, event->region() - d->animationRect());
+ drawTree(&painter, event->region() - d->animatedOperation.rect());
d->drawAnimatedOperation(&painter);
- } else {
+ } else
+#endif //QT_NO_ANIMATION
+ {
drawTree(&painter, event->region());
#ifndef QT_NO_DRAGANDDROP
d->paintDropIndicator(&painter);
@@ -1313,20 +1296,20 @@ bool QTreeViewPrivate::expandOrCollapseItemAtPos(const QPoint &pos)
{
Q_Q(QTreeView);
// we want to handle mousePress in EditingState (persistent editors)
- if ((q->state() != QAbstractItemView::NoState
- && q->state() != QAbstractItemView::EditingState)
+ if ((state != QAbstractItemView::NoState
+ && state != QAbstractItemView::EditingState)
|| !viewport->rect().contains(pos))
return true;
int i = itemDecorationAt(pos);
- if ((i != -1) && q->itemsExpandable() && hasVisibleChildren(viewItems.at(i).index)) {
+ if ((i != -1) && itemsExpandable && hasVisibleChildren(viewItems.at(i).index)) {
if (viewItems.at(i).expanded)
collapse(i, true);
else
expand(i, true);
if (!isAnimating()) {
q->updateGeometries();
- q->viewport()->update();
+ viewport->update();
}
return true;
}
@@ -1342,6 +1325,50 @@ void QTreeViewPrivate::_q_modelDestroyed()
}
/*!
+ \reimp
+
+ We have a QTreeView way of knowing what elements are on the viewport
+*/
+QItemViewPaintPairs QTreeViewPrivate::draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const
+{
+ Q_ASSERT(r);
+ return QAbstractItemViewPrivate::draggablePaintPairs(indexes, r);
+ Q_Q(const QTreeView);
+ QRect &rect = *r;
+ const QRect viewportRect = viewport->rect();
+ int itemOffset = 0;
+ int row = firstVisibleItem(&itemOffset);
+ QPair<int, int> startEnd = startAndEndColumns(viewportRect);
+ QVector<int> columns;
+ for (int i = startEnd.first; i <= startEnd.second; ++i) {
+ int logical = header->logicalIndex(i);
+ if (!header->isSectionHidden(logical))
+ columns += logical;
+ }
+ QSet<QModelIndex> visibleIndexes;
+ for (; itemOffset < viewportRect.bottom() && row < viewItems.count(); ++row) {
+ const QModelIndex &index = viewItems.at(row).index;
+ for (int colIndex = 0; colIndex < columns.count(); ++colIndex)
+ visibleIndexes += index.sibling(index.row(), columns.at(colIndex));
+ itemOffset += itemHeight(row);
+ }
+
+ //now that we have the visible indexes, we can try to find those which are selected
+ QItemViewPaintPairs ret;
+ for (int i = 0; i < indexes.count(); ++i) {
+ const QModelIndex &index = indexes.at(i);
+ if (visibleIndexes.contains(index)) {
+ const QRect current = q->visualRect(index);
+ ret += qMakePair(current, index);
+ rect |= current;
+ }
+ }
+ rect &= viewportRect;
+ return ret;
+}
+
+
+/*!
\since 4.2
Draws the part of the tree intersecting the given \a region using the specified
\a painter.
@@ -1548,7 +1575,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
? logicalIndexBeforeLeft
: logicalIndices.at(currentLogicalSection - 1);
if (columnCount == 1 || (nextLogicalSection == 0 && prevLogicalSection == -1)
- || (headerSection == 0 && nextLogicalSection == -1))
+ || (headerSection == 0 && nextLogicalSection == -1) || spanning)
opt.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
else if (headerSection == 0 || (nextLogicalSection != 0 && prevLogicalSection == -1))
opt.viewItemPosition = QStyleOptionViewItemV4::Beginning;
@@ -1817,10 +1844,10 @@ void QTreeView::mouseDoubleClickEvent(QMouseEvent *event)
if (i == -1)
return; // user clicked outside the items
- const QModelIndex &index = d->viewItems.at(i).index;
+ const QPersistentModelIndex firstColumnIndex = d->viewItems.at(i).index;
int column = d->header->logicalIndexAt(event->x());
- QPersistentModelIndex persistent = index.sibling(index.row(), column);
+ QPersistentModelIndex persistent = firstColumnIndex.sibling(firstColumnIndex.row(), column);
if (d->pressedIndex != persistent) {
mousePressEvent(event);
@@ -1843,10 +1870,10 @@ void QTreeView::mouseDoubleClickEvent(QMouseEvent *event)
if (d->itemsExpandable
&& d->expandsOnDoubleClick
&& d->hasVisibleChildren(persistent)) {
- if (!((i < d->viewItems.count()) && (d->viewItems.at(i).index == persistent))) {
+ if (!((i < d->viewItems.count()) && (d->viewItems.at(i).index == firstColumnIndex))) {
// find the new index of the item
for (i = 0; i < d->viewItems.count(); ++i) {
- if (d->viewItems.at(i).index == persistent)
+ if (d->viewItems.at(i).index == firstColumnIndex)
break;
}
if (i == d->viewItems.count())
@@ -2074,7 +2101,8 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
const bool useTopIndex = (cursorAction == MoveUp || cursorAction == MovePrevious);
int index = useTopIndex ? INT_MAX : INT_MIN;
const QItemSelection selection = d->selectionModel->selection();
- foreach (const QItemSelectionRange &range, selection) {
+ for (int i = 0; i < selection.count(); ++i) {
+ const QItemSelectionRange &range = selection.at(i);
int candidate = d->viewIndex(useTopIndex ? range.topLeft() : range.bottomRight());
if (candidate >= 0)
index = useTopIndex ? qMin(index, candidate) : qMax(index, candidate);
@@ -2424,14 +2452,10 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end)
? d->viewItems.count()
: d->viewItems.at(parentItem).total) - 1;
- int firstColumn = 0;
- while (isColumnHidden(firstColumn) && firstColumn < header()->count() - 1)
- ++firstColumn;
-
const int delta = end - start + 1;
QVector<QTreeViewItem> insertedItems(delta);
for (int i = 0; i < delta; ++i) {
- insertedItems[i].index = d->model->index(i + start, firstColumn, parent);
+ insertedItems[i].index = d->model->index(i + start, 0, parent);
insertedItems[i].level = childLevel;
}
if (d->viewItems.isEmpty())
@@ -2614,7 +2638,7 @@ void QTreeView::expandAll()
d->viewItems[i].expanded = true;
d->layout(i);
QModelIndex idx = d->viewItems.at(i).index;
- d->expandedIndexes.insert(idx.sibling(idx.row(), 0));
+ d->expandedIndexes.insert(idx);
}
updateGeometries();
d->viewport->update();
@@ -2773,15 +2797,14 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const
if (isRightToLeft()) {
start = (start == -1 ? count - 1 : start);
- end = (end == -1 ? 0 : end);
+ end = 0;
} else {
start = (start == -1 ? 0 : start);
- end = (end == -1 ? count - 1 : end);
+ end = count - 1;
}
- int tmp = start;
- start = qMin(start, end);
- end = qMax(tmp, end);
+ if (end < start)
+ qSwap(end, start);
int height = -1;
QStyleOptionViewItemV4 option = d->viewOptionsV4();
@@ -2829,7 +2852,7 @@ int QTreeView::rowHeight(const QModelIndex &index) const
}
/*!
- \reimp
+ \internal
*/
void QTreeView::horizontalScrollbarAction(int action)
{
@@ -2861,10 +2884,9 @@ void QTreeViewPrivate::initialize()
header->setStretchLastSection(true);
header->setDefaultAlignment(Qt::AlignLeft|Qt::AlignVCenter);
q->setHeader(header);
-
- // animation
- QObject::connect(&timeline, SIGNAL(frameChanged(int)), q, SLOT(_q_animate()));
- QObject::connect(&timeline, SIGNAL(finished()), q, SLOT(_q_endAnimatedOperation()), Qt::QueuedConnection);
+#ifndef QT_NO_ANIMATION
+ QObject::connect(&animatedOperation, SIGNAL(finished()), q, SLOT(_q_endAnimatedOperation()));
+#endif //QT_NO_ANIMATION
}
void QTreeViewPrivate::expand(int item, bool emitSignal)
@@ -2874,10 +2896,11 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
if (item == -1 || viewItems.at(item).expanded)
return;
+#ifndef QT_NO_ANIMATION
if (emitSignal && animationsEnabled)
- prepareAnimatedOperation(item, AnimatedOperation::Expand);
-
- QAbstractItemView::State oldState = q->state();
+ prepareAnimatedOperation(item, QVariantAnimation::Forward);
+#endif //QT_NO_ANIMATION
+ QAbstractItemView::State oldState = state;
q->setState(QAbstractItemView::ExpandingState);
const QModelIndex index = viewItems.at(item).index;
storeExpanded(index);
@@ -2887,8 +2910,10 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
if (emitSignal) {
emit q->expanded(index);
+#ifndef QT_NO_ANIMATION
if (animationsEnabled)
beginAnimatedOperation();
+#endif //QT_NO_ANIMATION
}
if (model->canFetchMore(index))
model->fetchMore(index);
@@ -2912,10 +2937,12 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal)
if (it == expandedIndexes.end() || viewItems.at(item).expanded == false)
return; // nothing to do
+#ifndef QT_NO_ANIMATION
if (emitSignal && animationsEnabled)
- prepareAnimatedOperation(item, AnimatedOperation::Collapse);
+ prepareAnimatedOperation(item, QVariantAnimation::Backward);
+#endif //QT_NO_ANIMATION
- QAbstractItemView::State oldState = q->state();
+ QAbstractItemView::State oldState = state;
q->setState(QAbstractItemView::CollapsingState);
expandedIndexes.erase(it);
viewItems[item].expanded = false;
@@ -2932,29 +2959,33 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal)
if (emitSignal) {
emit q->collapsed(modelIndex);
+#ifndef QT_NO_ANIMATION
if (animationsEnabled)
beginAnimatedOperation();
+#endif //QT_NO_ANIMATION
}
}
-void QTreeViewPrivate::prepareAnimatedOperation(int item, AnimatedOperation::Type type)
+#ifndef QT_NO_ANIMATION
+void QTreeViewPrivate::prepareAnimatedOperation(int item, QVariantAnimation::Direction direction)
{
animatedOperation.item = item;
- animatedOperation.type = type;
+ animatedOperation.viewport = viewport;
+ animatedOperation.setDirection(direction);
int top = coordinateForItem(item) + itemHeight(item);
QRect rect = viewport->rect();
rect.setTop(top);
- if (type == AnimatedOperation::Collapse) {
+ if (direction == QVariantAnimation::Backward) {
const int limit = rect.height() * 2;
int h = 0;
int c = item + viewItems.at(item).total + 1;
for (int i = item + 1; i < c && h < limit; ++i)
h += itemHeight(i);
rect.setHeight(h);
- animatedOperation.duration = h;
+ animatedOperation.setEndValue(top + h);
}
- animatedOperation.top = top;
+ animatedOperation.setStartValue(top);
animatedOperation.before = renderTreeToPixmapForAnimation(rect);
}
@@ -2963,50 +2994,29 @@ void QTreeViewPrivate::beginAnimatedOperation()
Q_Q(QTreeView);
QRect rect = viewport->rect();
- rect.setTop(animatedOperation.top);
- if (animatedOperation.type == AnimatedOperation::Expand) {
+ rect.setTop(animatedOperation.top());
+ if (animatedOperation.direction() == QVariantAnimation::Forward) {
const int limit = rect.height() * 2;
int h = 0;
int c = animatedOperation.item + viewItems.at(animatedOperation.item).total + 1;
for (int i = animatedOperation.item + 1; i < c && h < limit; ++i)
h += itemHeight(i);
rect.setHeight(h);
- animatedOperation.duration = h;
+ animatedOperation.setEndValue(animatedOperation.top() + h);
}
animatedOperation.after = renderTreeToPixmapForAnimation(rect);
q->setState(QAbstractItemView::AnimatingState);
-
- timeline.stop();
- timeline.setDuration(250);
- timeline.setFrameRange(animatedOperation.top, animatedOperation.top + animatedOperation.duration);
- timeline.start();
-}
-
-void QTreeViewPrivate::_q_endAnimatedOperation()
-{
- Q_Q(QTreeView);
- animatedOperation.before = QPixmap();
- animatedOperation.after = QPixmap();
- q->setState(QAbstractItemView::NoState);
- q->updateGeometries();
- viewport->update();
-}
-
-void QTreeViewPrivate::_q_animate()
-{
- QRect rect = viewport->rect();
- rect.moveTop(animatedOperation.top);
- viewport->repaint(rect);
+ animatedOperation.start(); //let's start the animation
}
void QTreeViewPrivate::drawAnimatedOperation(QPainter *painter) const
{
- int start = timeline.startFrame();
- int end = timeline.endFrame();
- bool collapsing = animatedOperation.type == AnimatedOperation::Collapse;
- int current = collapsing ? end - timeline.currentFrame() + start : timeline.currentFrame();
+ const int start = animatedOperation.startValue().toInt(),
+ end = animatedOperation.endValue().toInt(),
+ current = animatedOperation.currentValue().toInt();
+ bool collapsing = animatedOperation.direction() == QVariantAnimation::Backward;
const QPixmap top = collapsing ? animatedOperation.before : animatedOperation.after;
painter->drawPixmap(0, start, top, 0, end - current - 1, top.width(), top.height());
const QPixmap bottom = collapsing ? animatedOperation.after : animatedOperation.before;
@@ -3049,26 +3059,14 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons
return pixmap;
}
-void QTreeViewPrivate::_q_currentChanged(const QModelIndex &current, const QModelIndex &previous)
+void QTreeViewPrivate::_q_endAnimatedOperation()
{
Q_Q(QTreeView);
- if (previous.isValid()) {
- QRect previousRect = q->visualRect(previous);
- if (allColumnsShowFocus) {
- previousRect.setX(0);
- previousRect.setWidth(viewport->width());
- }
- viewport->update(previousRect);
- }
- if (current.isValid()) {
- QRect currentRect = q->visualRect(current);
- if (allColumnsShowFocus) {
- currentRect.setX(0);
- currentRect.setWidth(viewport->width());
- }
- viewport->update(currentRect);
- }
+ q->setState(QAbstractItemView::NoState);
+ q->updateGeometries();
+ viewport->update();
}
+#endif //QT_NO_ANIMATION
void QTreeViewPrivate::_q_modelAboutToBeReset()
{
@@ -3077,16 +3075,16 @@ void QTreeViewPrivate::_q_modelAboutToBeReset()
void QTreeViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
- Q_UNUSED(parent);
if (start <= 0 && 0 <= end)
viewItems.clear();
+ QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(parent, start, end);
}
void QTreeViewPrivate::_q_columnsRemoved(const QModelIndex &parent, int start, int end)
{
- Q_UNUSED(parent);
if (start <= 0 && 0 <= end)
doDelayedItemsLayout();
+ QAbstractItemViewPrivate::_q_columnsRemoved(parent, start, end);
}
void QTreeViewPrivate::layout(int i)
@@ -3094,10 +3092,6 @@ void QTreeViewPrivate::layout(int i)
Q_Q(QTreeView);
QModelIndex current;
QModelIndex parent = (i < 0) ? (QModelIndex)root : modelIndex(i);
- // modelIndex() will return an index that don't have a parent if column 0 is hidden,
- // so we must make sure that parent points to the actual parent that has children.
- if (parent != root)
- parent = model->index(parent.row(), 0, parent.parent());
if (i>=0 && !parent.isValid()) {
//modelIndex() should never return something invalid for the real items.
@@ -3132,13 +3126,9 @@ void QTreeViewPrivate::layout(int i)
int last = 0;
int children = 0;
- int firstColumn = 0;
- while (header->isSectionHidden(firstColumn) && firstColumn < header->count())
- ++firstColumn;
-
for (int j = first; j < first + count; ++j) {
- current = model->index(j - first, firstColumn, parent);
- if (isRowHidden(current.sibling(current.row(), 0))) {
+ current = model->index(j - first, 0, parent);
+ if (isRowHidden(current)) {
++hidden;
last = j - hidden + children;
} else {
@@ -3219,19 +3209,18 @@ int QTreeViewPrivate::itemHeight(int item) const
*/
int QTreeViewPrivate::coordinateForItem(int item) const
{
- Q_Q(const QTreeView);
if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
if (uniformRowHeights)
- return (item * defaultItemHeight) - q->verticalScrollBar()->value();
+ return (item * defaultItemHeight) - vbar->value();
// ### optimize (spans or caching)
int y = 0;
for (int i = 0; i < viewItems.count(); ++i) {
if (i == item)
- return y - q->verticalScrollBar()->value();
+ return y - vbar->value();
y += itemHeight(i);
}
} else { // ScrollPerItem
- int topViewItemIndex = q->verticalScrollBar()->value();
+ int topViewItemIndex = vbar->value();
if (uniformRowHeights)
return defaultItemHeight * (item - topViewItemIndex);
if (item >= topViewItemIndex) {
@@ -3271,7 +3260,6 @@ int QTreeViewPrivate::coordinateForItem(int item) const
*/
int QTreeViewPrivate::itemAtCoordinate(int coordinate) const
{
- Q_Q(const QTreeView);
const int itemCount = viewItems.count();
if (itemCount == 0)
return -1;
@@ -3279,19 +3267,19 @@ int QTreeViewPrivate::itemAtCoordinate(int coordinate) const
return -1;
if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
if (uniformRowHeights) {
- const int viewItemIndex = (coordinate + q->verticalScrollBar()->value()) / defaultItemHeight;
+ const int viewItemIndex = (coordinate + vbar->value()) / defaultItemHeight;
return ((viewItemIndex >= itemCount || viewItemIndex < 0) ? -1 : viewItemIndex);
}
// ### optimize
int viewItemCoordinate = 0;
- const int contentsCoordinate = coordinate + q->verticalScrollBar()->value();
+ const int contentsCoordinate = coordinate + vbar->value();
for (int viewItemIndex = 0; viewItemIndex < viewItems.count(); ++viewItemIndex) {
viewItemCoordinate += itemHeight(viewItemIndex);
if (viewItemCoordinate >= contentsCoordinate)
return (viewItemIndex >= itemCount ? -1 : viewItemIndex);
}
} else { // ScrollPerItem
- int topViewItemIndex = q->verticalScrollBar()->value();
+ int topViewItemIndex = vbar->value();
if (uniformRowHeights) {
if (coordinate < 0)
coordinate -= defaultItemHeight - 1;
@@ -3321,15 +3309,11 @@ int QTreeViewPrivate::itemAtCoordinate(int coordinate) const
int QTreeViewPrivate::viewIndex(const QModelIndex &_index) const
{
- Q_Q(const QTreeView);
if (!_index.isValid() || viewItems.isEmpty())
return -1;
const int totalCount = viewItems.count();
- int firstColumn = 0;
- while (q->isColumnHidden(firstColumn) && firstColumn < header->count())
- ++firstColumn;
- const QModelIndex index = _index.sibling(_index.row(), firstColumn);
+ const QModelIndex index = _index.sibling(_index.row(), 0);
// A quick check near the last item to see if we are just incrementing
@@ -3387,8 +3371,7 @@ QModelIndex QTreeViewPrivate::modelIndex(int i, int column) const
int QTreeViewPrivate::firstVisibleItem(int *offset) const
{
- Q_Q(const QTreeView);
- const int value = q->verticalScrollBar()->value();
+ const int value = vbar->value();
if (verticalScrollMode == QAbstractItemView::ScrollPerItem) {
if (offset)
*offset = 0;
@@ -3465,9 +3448,9 @@ void QTreeViewPrivate::updateScrollBars()
if (verticalScrollMode == QAbstractItemView::ScrollPerItem) {
if (!viewItems.isEmpty())
itemsInViewport = qMax(1, itemsInViewport);
- q->verticalScrollBar()->setRange(0, viewItems.count() - itemsInViewport);
- q->verticalScrollBar()->setPageStep(itemsInViewport);
- q->verticalScrollBar()->setSingleStep(1);
+ vbar->setRange(0, viewItems.count() - itemsInViewport);
+ vbar->setPageStep(itemsInViewport);
+ vbar->setSingleStep(1);
} else { // scroll per pixel
int contentsHeight = 0;
if (uniformRowHeights) {
@@ -3476,9 +3459,9 @@ void QTreeViewPrivate::updateScrollBars()
for (int i = 0; i < viewItems.count(); ++i)
contentsHeight += itemHeight(i);
}
- q->verticalScrollBar()->setRange(0, contentsHeight - viewportSize.height());
- q->verticalScrollBar()->setPageStep(viewportSize.height());
- q->verticalScrollBar()->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
+ vbar->setRange(0, contentsHeight - viewportSize.height());
+ vbar->setPageStep(viewportSize.height());
+ vbar->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
}
const int columnCount = header->count();
@@ -3494,23 +3477,23 @@ void QTreeViewPrivate::updateScrollBars()
if (columnCount > 0)
columnsInViewport = qMax(1, columnsInViewport);
if (horizontalScrollMode == QAbstractItemView::ScrollPerItem) {
- q->horizontalScrollBar()->setRange(0, columnCount - columnsInViewport);
- q->horizontalScrollBar()->setPageStep(columnsInViewport);
- q->horizontalScrollBar()->setSingleStep(1);
+ hbar->setRange(0, columnCount - columnsInViewport);
+ hbar->setPageStep(columnsInViewport);
+ hbar->setSingleStep(1);
} else { // scroll per pixel
const int horizontalLength = header->length();
const QSize maxSize = q->maximumViewportSize();
- if (maxSize.width() >= horizontalLength && q->verticalScrollBar()->maximum() <= 0)
+ if (maxSize.width() >= horizontalLength && vbar->maximum() <= 0)
viewportSize = maxSize;
- q->horizontalScrollBar()->setPageStep(viewportSize.width());
- q->horizontalScrollBar()->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
- q->horizontalScrollBar()->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
+ hbar->setPageStep(viewportSize.width());
+ hbar->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
+ hbar->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
}
}
int QTreeViewPrivate::itemDecorationAt(const QPoint &pos) const
{
- const_cast<QTreeView *>(q_func())->executeDelayedItemsLayout();
+ executePostedLayout();
int x = pos.x();
int column = header->logicalIndexAt(x);
if (column != 0)
@@ -3576,7 +3559,8 @@ QList<QPair<int, int> > QTreeViewPrivate::columnRanges(const QModelIndex &topInd
QPair<int, int> current;
current.first = -2; // -1 is not enough because -1+1 = 0
current.second = -2;
- foreach (int logicalColumn, logicalIndexes) {
+ for(int i = 0; i < logicalIndexes.count(); ++i) {
+ const int logicalColumn = logicalIndexes.at(i);
if (current.second + 1 != logicalColumn) {
if (current.first != -2) {
//let's save the current one
@@ -3811,6 +3795,21 @@ void QTreeView::currentChanged(const QModelIndex &current, const QModelIndex &pr
}
#endif
QAbstractItemView::currentChanged(current, previous);
+
+ if (allColumnsShowFocus()) {
+ if (previous.isValid()) {
+ QRect previousRect = visualRect(previous);
+ previousRect.setX(0);
+ previousRect.setWidth(viewport()->width());
+ viewport()->update(previousRect);
+ }
+ if (current.isValid()) {
+ QRect currentRect = visualRect(current);
+ currentRect.setX(0);
+ currentRect.setWidth(viewport()->width());
+ viewport()->update(currentRect);
+ }
+ }
}
/*!
diff --git a/src/gui/itemviews/qtreeview.h b/src/gui/itemviews/qtreeview.h
index b8f42d0..c87b453 100644
--- a/src/gui/itemviews/qtreeview.h
+++ b/src/gui/itemviews/qtreeview.h
@@ -144,19 +144,20 @@ public:
void sortByColumn(int column, Qt::SortOrder order);
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void selectAll();
+
Q_SIGNALS:
void expanded(const QModelIndex &index);
void collapsed(const QModelIndex &index);
public Q_SLOTS:
- void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void hideColumn(int column);
void showColumn(int column);
void expand(const QModelIndex &index);
void collapse(const QModelIndex &index);
void resizeColumnToContents(int column);
void sortByColumn(int column);
- void selectAll();
void expandAll();
void collapseAll();
void expandToDepth(int depth);
@@ -222,14 +223,11 @@ private:
Q_DECLARE_PRIVATE(QTreeView)
Q_DISABLE_COPY(QTreeView)
+#ifndef QT_NO_ANIMATION
Q_PRIVATE_SLOT(d_func(), void _q_endAnimatedOperation())
- Q_PRIVATE_SLOT(d_func(), void _q_animate())
- Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(const QModelIndex&, const QModelIndex &))
- Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeRemoved(const QModelIndex &, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_columnsRemoved(const QModelIndex &, int, int))
+#endif //QT_NO_ANIMATION
Q_PRIVATE_SLOT(d_func(), void _q_modelAboutToBeReset())
Q_PRIVATE_SLOT(d_func(), void _q_sortIndicatorChanged(int column, Qt::SortOrder order))
- Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed())
};
#endif // QT_NO_TREEVIEW
diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h
index 3f9b8c8..a38dd25 100644
--- a/src/gui/itemviews/qtreeview_p.h
+++ b/src/gui/itemviews/qtreeview_p.h
@@ -54,6 +54,7 @@
//
#include "private/qabstractitemview_p.h"
+#include <QtCore/qvariantanimation.h>
#ifndef QT_NO_TREEVIEW
@@ -81,42 +82,41 @@ public:
uniformRowHeights(false), rootDecoration(true),
itemsExpandable(true), sortingEnabled(false),
expandsOnDoubleClick(true),
- allColumnsShowFocus(false),
+ allColumnsShowFocus(false), current(0), spanning(false),
animationsEnabled(false), columnResizeTimerID(0),
autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false) {}
~QTreeViewPrivate() {}
void initialize();
- struct AnimatedOperation
+ QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const;
+
+#ifndef QT_NO_ANIMATION
+ struct AnimatedOperation : public QVariantAnimation
{
- enum Type { Expand, Collapse };
int item;
- int top;
- int duration;
- Type type;
QPixmap before;
QPixmap after;
- };
-
- void expand(int item, bool emitSignal);
- void collapse(int item, bool emitSignal);
-
- void prepareAnimatedOperation(int item, AnimatedOperation::Type type);
+ QWidget *viewport;
+ AnimatedOperation() : item(0) { setEasingCurve(QEasingCurve::InOutQuad); }
+ int top() const { return startValue().toInt(); }
+ QRect rect() const { QRect rect = viewport->rect(); rect.moveTop(top()); return rect; }
+ void updateCurrentValue(const QVariant &) { viewport->update(rect()); }
+ void updateState(State, State state) { if (state == Stopped) before = after = QPixmap(); }
+ } animatedOperation;
+ void prepareAnimatedOperation(int item, QVariantAnimation::Direction d);
void beginAnimatedOperation();
- void _q_endAnimatedOperation();
void drawAnimatedOperation(QPainter *painter) const;
QPixmap renderTreeToPixmapForAnimation(const QRect &rect) const;
+ void _q_endAnimatedOperation();
+#endif //QT_NO_ANIMATION
- inline QRect animationRect() const
- { return QRect(0, animatedOperation.top, viewport->width(),
- viewport->height() - animatedOperation.top); }
+ void expand(int item, bool emitSignal);
+ void collapse(int item, bool emitSignal);
- void _q_currentChanged(const QModelIndex&, const QModelIndex&);
void _q_columnsAboutToBeRemoved(const QModelIndex &, int, int);
void _q_columnsRemoved(const QModelIndex &, int, int);
void _q_modelAboutToBeReset();
- void _q_animate();
void _q_sortIndicatorChanged(int column, Qt::SortOrder order);
void _q_modelDestroyed();
@@ -177,8 +177,6 @@ public:
// used when expanding and collapsing items
QSet<QPersistentModelIndex> expandedIndexes;
- QStack<bool> expandParent;
- AnimatedOperation animatedOperation;
bool animationsEnabled;
inline bool storeExpanded(const QPersistentModelIndex &idx) {
diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp
index 52f3d5d..7d6439f 100644
--- a/src/gui/itemviews/qtreewidget.cpp
+++ b/src/gui/itemviews/qtreewidget.cpp
@@ -75,7 +75,7 @@ public:
\brief The QTreeModel class manages the items stored in a tree view.
\ingroup model-view
- \mainclass
+
*/
/*!
@@ -577,7 +577,7 @@ void QTreeModel::sort(int column, Qt::SortOrder order)
if (column < 0 || column >= columnCount())
return;
- //layoutAboutToBeChanged and layoutChanged will be called by sortChildren
+ //layoutAboutToBeChanged and layoutChanged will be called by sortChildren
rootItem->sortChildren(column, order, true);
}
@@ -853,7 +853,7 @@ void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items, int column, Qt::SortO
items->replace(r, item);
for (int c = 0; c < colCount; ++c) {
QModelIndex from = createIndex(oldRow, c, item);
- if (static_cast<QAbstractItemModelPrivate *>(d_ptr)->persistent.indexes.contains(from)) {
+ if (static_cast<QAbstractItemModelPrivate *>(d_ptr.data())->persistent.indexes.contains(from)) {
QModelIndex to = createIndex(r, c, item);
fromList << from;
toList << to;
@@ -1768,6 +1768,7 @@ QVariant QTreeWidgetItem::data(int column, int role) const
// special case for check state in tristate
if (children.count() && (itemFlags & Qt::ItemIsTristate))
return childrenCheckState(column);
+ // fallthrough intended
default:
if (column >= 0 && column < values.size()) {
const QVector<QWidgetItemData> &column_values = values.at(column);
@@ -1787,7 +1788,9 @@ QVariant QTreeWidgetItem::data(int column, int role) const
bool QTreeWidgetItem::operator<(const QTreeWidgetItem &other) const
{
int column = view ? view->sortColumn() : 0;
- return text(column) < other.text(column);
+ const QVariant v1 = data(column, Qt::DisplayRole);
+ const QVariant v2 = other.data(column, Qt::DisplayRole);
+ return QAbstractItemModelPrivate::variantLessThan(v1, v2);
}
#ifndef QT_NO_DATASTREAM
@@ -1827,6 +1830,7 @@ void QTreeWidgetItem::write(QDataStream &out) const
{
out << values << d->display;
}
+#endif // QT_NO_DATASTREAM
/*!
\since 4.1
@@ -1863,8 +1867,6 @@ QTreeWidgetItem &QTreeWidgetItem::operator=(const QTreeWidgetItem &other)
return *this;
}
-#endif // QT_NO_DATASTREAM
-
/*!
Appends the \a child item to the list of children.
@@ -2071,11 +2073,13 @@ QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
void QTreeWidgetItemPrivate::sortChildren(int column, Qt::SortOrder order, bool climb)
{
QTreeModel *model = (q->view ? qobject_cast<QTreeModel*>(q->view->model()) : 0);
+ if (!model)
+ return;
model->sortItems(&q->children, column, order);
if (climb) {
QList<QTreeWidgetItem*>::iterator it = q->children.begin();
for (; it != q->children.end(); ++it) {
- //here we call the private object's method to avoid emitting
+ //here we call the private object's method to avoid emitting
//the layoutAboutToBeChanged and layoutChanged signals
(*it)->d->sortChildren(column, order, climb);
}
@@ -2277,11 +2281,10 @@ void QTreeWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
void QTreeWidgetPrivate::_q_sort()
{
- Q_Q(QTreeWidget);
if (sortingEnabled) {
- int column = q->header()->sortIndicatorSection();
- Qt::SortOrder order = q->header()->sortIndicatorOrder();
- model()->sort(column, order);
+ int column = header->sortIndicatorSection();
+ Qt::SortOrder order = header->sortIndicatorOrder();
+ treeModel()->sort(column, order);
}
}
@@ -2290,7 +2293,7 @@ void QTreeWidgetPrivate::_q_selectionChanged(const QItemSelection &selected, con
Q_Q(QTreeWidget);
QModelIndexList indices = selected.indexes();
int i;
- QTreeModel *m = model();
+ QTreeModel *m = treeModel();
for (i = 0; i < indices.count(); ++i) {
QTreeWidgetItem *item = m->item(indices.at(i));
item->d->selected = true;
@@ -2308,13 +2311,12 @@ void QTreeWidgetPrivate::_q_selectionChanged(const QItemSelection &selected, con
void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight)
{
- Q_Q(QTreeWidget);
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
- && !model()->sortPendingTimer.isActive()) {
- int column = q->header()->sortIndicatorSection();
+ && !treeModel()->sortPendingTimer.isActive()) {
+ int column = header->sortIndicatorSection();
if (column >= topLeft.column() && column <= bottomRight.column()) {
- Qt::SortOrder order = q->header()->sortIndicatorOrder();
- model()->ensureSorted(column, order, topLeft.row(),
+ Qt::SortOrder order = header->sortIndicatorOrder();
+ treeModel()->ensureSorted(column, order, topLeft.row(),
bottomRight.row(), topLeft.parent());
}
}
@@ -2327,7 +2329,7 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
tree model.
\ingroup model-view
- \mainclass
+
The QTreeWidget class is a convenience class that provides a standard
tree widget with a classic item-based interface similar to that used by
@@ -2436,7 +2438,7 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
\note This signal will not be emitted if an item changes its state when
expandAll() is invoked.
- \sa isItemExpanded(), itemCollapsed(), expandItem()
+ \sa QTreeWidgetItem::isExpanded(), itemCollapsed(), expandItem()
*/
/*!
@@ -2448,7 +2450,7 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
\note This signal will not be emitted if an item changes its state when
collapseAll() is invoked.
- \sa isItemExpanded(), itemExpanded(), collapseItem()
+ \sa QTreeWidgetItem::isExpanded(), itemExpanded(), collapseItem()
*/
/*!
@@ -2542,7 +2544,7 @@ QTreeWidget::~QTreeWidget()
int QTreeWidget::columnCount() const
{
Q_D(const QTreeWidget);
- return d->model()->columnCount();
+ return d->model->columnCount();
}
/*
@@ -2554,7 +2556,7 @@ void QTreeWidget::setColumnCount(int columns)
Q_D(QTreeWidget);
if (columns < 0)
return;
- d->model()->setColumnCount(columns);
+ d->treeModel()->setColumnCount(columns);
}
/*!
@@ -2571,7 +2573,7 @@ void QTreeWidget::setColumnCount(int columns)
QTreeWidgetItem *QTreeWidget::invisibleRootItem() const
{
Q_D(const QTreeWidget);
- return d->model()->rootItem;
+ return d->treeModel()->rootItem;
}
/*!
@@ -2584,7 +2586,7 @@ QTreeWidgetItem *QTreeWidget::invisibleRootItem() const
QTreeWidgetItem *QTreeWidget::topLevelItem(int index) const
{
Q_D(const QTreeWidget);
- return d->model()->rootItem->child(index);
+ return d->treeModel()->rootItem->child(index);
}
/*!
@@ -2599,7 +2601,7 @@ QTreeWidgetItem *QTreeWidget::topLevelItem(int index) const
int QTreeWidget::topLevelItemCount() const
{
Q_D(const QTreeWidget);
- return d->model()->rootItem->childCount();
+ return d->treeModel()->rootItem->childCount();
}
/*!
@@ -2613,7 +2615,7 @@ int QTreeWidget::topLevelItemCount() const
void QTreeWidget::insertTopLevelItem(int index, QTreeWidgetItem *item)
{
Q_D(QTreeWidget);
- d->model()->rootItem->insertChild(index, item);
+ d->treeModel()->rootItem->insertChild(index, item);
}
/*!
@@ -2638,7 +2640,7 @@ void QTreeWidget::addTopLevelItem(QTreeWidgetItem *item)
QTreeWidgetItem *QTreeWidget::takeTopLevelItem(int index)
{
Q_D(QTreeWidget);
- return d->model()->rootItem->takeChild(index);
+ return d->treeModel()->rootItem->takeChild(index);
}
/*!
@@ -2647,8 +2649,8 @@ QTreeWidgetItem *QTreeWidget::takeTopLevelItem(int index)
int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item)
{
Q_D(QTreeWidget);
- d->model()->executePendingSort();
- return d->model()->rootItem->children.indexOf(item);
+ d->treeModel()->executePendingSort();
+ return d->treeModel()->rootItem->children.indexOf(item);
}
/*!
@@ -2660,8 +2662,8 @@ int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item)
int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- d->model()->executePendingSort();
- return d->model()->rootItem->children.indexOf(item);
+ d->treeModel()->executePendingSort();
+ return d->treeModel()->rootItem->children.indexOf(item);
}
/*!
@@ -2676,7 +2678,7 @@ int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item) const
void QTreeWidget::insertTopLevelItems(int index, const QList<QTreeWidgetItem*> &items)
{
Q_D(QTreeWidget);
- d->model()->rootItem->insertChildren(index, items);
+ d->treeModel()->rootItem->insertChildren(index, items);
}
/*!
@@ -2698,7 +2700,7 @@ void QTreeWidget::addTopLevelItems(const QList<QTreeWidgetItem*> &items)
QTreeWidgetItem *QTreeWidget::headerItem() const
{
Q_D(const QTreeWidget);
- return d->model()->headerItem;
+ return d->treeModel()->headerItem;
}
/*!
@@ -2719,16 +2721,16 @@ void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
int oldCount = columnCount();
if (oldCount < item->columnCount())
- d->model()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount());
+ d->treeModel()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount());
else
- d->model()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount);
- delete d->model()->headerItem;
- d->model()->headerItem = item;
+ d->treeModel()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount);
+ delete d->treeModel()->headerItem;
+ d->treeModel()->headerItem = item;
if (oldCount < item->columnCount())
- d->model()->endInsertColumns();
+ d->treeModel()->endInsertColumns();
else
- d->model()->endRemoveColumns();
- d->model()->headerDataChanged(Qt::Horizontal, 0, oldCount);
+ d->treeModel()->endRemoveColumns();
+ d->treeModel()->headerDataChanged(Qt::Horizontal, 0, oldCount);
}
@@ -2745,8 +2747,7 @@ void QTreeWidget::setHeaderLabels(const QStringList &labels)
Q_D(QTreeWidget);
if (columnCount() < labels.count())
setColumnCount(labels.count());
- QTreeModel *model = d->model();
- QTreeWidgetItem *item = model->headerItem;
+ QTreeWidgetItem *item = d->treeModel()->headerItem;
for (int i = 0; i < labels.count(); ++i)
item->setText(i, labels.at(i));
}
@@ -2783,7 +2784,8 @@ int QTreeWidget::currentColumn() const
/*!
Sets the current \a item in the tree widget.
- Depending on the current selection mode, the item may also be selected.
+ Unless the selection mode is \l{QAbstractItemView::}{NoSelection},
+ the item is also be selected.
\sa currentItem(), currentItemChanged()
*/
@@ -2874,7 +2876,7 @@ void QTreeWidget::sortItems(int column, Qt::SortOrder order)
{
Q_D(QTreeWidget);
header()->setSortIndicator(column, order);
- d->model()->sort(column, order);
+ d->model->sort(column, order);
}
/*!
@@ -3041,7 +3043,7 @@ QList<QTreeWidgetItem*> QTreeWidget::selectedItems() const
QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFlags flags, int column) const
{
Q_D(const QTreeWidget);
- QModelIndexList indexes = d->model()->match(model()->index(0, column, QModelIndex()),
+ QModelIndexList indexes = d->model->match(model()->index(0, column, QModelIndex()),
Qt::DisplayRole, text, -1, flags);
QList<QTreeWidgetItem*> items;
for (int i = 0; i < indexes.size(); ++i)
@@ -3059,11 +3061,11 @@ QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFla
bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return header()->isHidden();
if (d->hiddenIndexes.isEmpty())
return false;
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
return d->isRowHidden(d->index(item));
}
@@ -3079,7 +3081,7 @@ bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const
void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
{
Q_D(QTreeWidget);
- if (item == d->model()->headerItem) {
+ if (item == d->treeModel()->headerItem) {
header()->setHidden(hide);
} else {
const QModelIndex index = d->index(item);
@@ -3099,7 +3101,7 @@ void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
bool QTreeWidget::isItemExpanded(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
return isExpanded(d->index(item));
}
@@ -3109,14 +3111,14 @@ bool QTreeWidget::isItemExpanded(const QTreeWidgetItem *item) const
\sa expandItem(), collapseItem(), itemExpanded()
- \obsolete
+ \obsolete
- This function is deprecated. Use \l{QTreeWidgetItem::setExpanded()} instead.
+ This function is deprecated. Use \l{QTreeWidgetItem::setExpanded()} instead.
*/
void QTreeWidget::setItemExpanded(const QTreeWidgetItem *item, bool expand)
{
Q_D(QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
setExpanded(d->index(item), expand);
}
@@ -3131,7 +3133,7 @@ void QTreeWidget::setItemExpanded(const QTreeWidgetItem *item, bool expand)
bool QTreeWidget::isFirstItemColumnSpanned(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return false; // We can't set the header items to spanning
const QModelIndex index = d->index(item);
return isFirstColumnSpanned(index.row(), index.parent());
@@ -3148,7 +3150,7 @@ bool QTreeWidget::isFirstItemColumnSpanned(const QTreeWidgetItem *item) const
void QTreeWidget::setFirstItemColumnSpanned(const QTreeWidgetItem *item, bool span)
{
Q_D(QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return; // We can't set header items to spanning
const QModelIndex index = d->index(item);
setFirstColumnSpanned(index.row(), index.parent(), span);
@@ -3162,7 +3164,7 @@ void QTreeWidget::setFirstItemColumnSpanned(const QTreeWidgetItem *item, bool sp
QTreeWidgetItem *QTreeWidget::itemAbove(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return 0;
const QModelIndex index = d->index(item);
const QModelIndex above = indexAbove(index);
@@ -3177,7 +3179,7 @@ QTreeWidgetItem *QTreeWidget::itemAbove(const QTreeWidgetItem *item) const
QTreeWidgetItem *QTreeWidget::itemBelow(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return 0;
const QModelIndex index = d->index(item);
const QModelIndex below = indexBelow(index);
@@ -3217,7 +3219,7 @@ void QTreeWidget::scrollToItem(const QTreeWidgetItem *item, QAbstractItemView::S
void QTreeWidget::expandItem(const QTreeWidgetItem *item)
{
Q_D(QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
expand(d->index(item));
}
@@ -3230,7 +3232,7 @@ void QTreeWidget::expandItem(const QTreeWidgetItem *item)
void QTreeWidget::collapseItem(const QTreeWidgetItem *item)
{
Q_D(QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
collapse(d->index(item));
}
@@ -3247,7 +3249,7 @@ void QTreeWidget::clear()
{
Q_D(QTreeWidget);
selectionModel()->clear();
- d->model()->clear();
+ d->treeModel()->clear();
}
/*!
@@ -3272,7 +3274,7 @@ QStringList QTreeWidget::mimeTypes() const
QMimeData *QTreeWidget::mimeData(const QList<QTreeWidgetItem*> items) const
{
Q_D(const QTreeWidget);
- if (d->model()->cachedIndexes.isEmpty()) {
+ if (d->treeModel()->cachedIndexes.isEmpty()) {
QList<QModelIndex> indexes;
for (int i = 0; i < items.count(); ++i) {
QTreeWidgetItem *item = items.at(i);
@@ -3280,9 +3282,9 @@ QMimeData *QTreeWidget::mimeData(const QList<QTreeWidgetItem*> items) const
indexes << indexFromItem(item, c);
}
}
- return model()->QAbstractItemModel::mimeData(indexes);
+ return d->model->QAbstractItemModel::mimeData(indexes);
}
- return d->model()->internalMimeData();
+ return d->treeModel()->internalMimeData();
}
/*!
@@ -3426,7 +3428,7 @@ bool QTreeWidget::event(QEvent *e)
{
Q_D(QTreeWidget);
if (e->type() == QEvent::Polish)
- d->model()->executePendingSort();
+ d->treeModel()->executePendingSort();
return QTreeView::event(e);
}
diff --git a/src/gui/itemviews/qtreewidget_p.h b/src/gui/itemviews/qtreewidget_p.h
index 5543ead..872645b 100644
--- a/src/gui/itemviews/qtreewidget_p.h
+++ b/src/gui/itemviews/qtreewidget_p.h
@@ -219,12 +219,11 @@ class QTreeWidgetPrivate : public QTreeViewPrivate
Q_DECLARE_PUBLIC(QTreeWidget)
public:
QTreeWidgetPrivate() : QTreeViewPrivate(), explicitSortColumn(-1) {}
- inline QTreeModel *model() const
- { return qobject_cast<QTreeModel*>(q_func()->model()); }
+ inline QTreeModel *treeModel() const { return qobject_cast<QTreeModel*>(model); }
inline QModelIndex index(const QTreeWidgetItem *item, int column = 0) const
- { return model()->index(item, column); }
+ { return treeModel()->index(item, column); }
inline QTreeWidgetItem *item(const QModelIndex &index) const
- { return model()->item(index); }
+ { return treeModel()->item(index); }
void _q_emitItemPressed(const QModelIndex &index);
void _q_emitItemClicked(const QModelIndex &index);
void _q_emitItemDoubleClicked(const QModelIndex &index);
diff --git a/src/gui/itemviews/qtreewidgetitemiterator.cpp b/src/gui/itemviews/qtreewidgetitemiterator.cpp
index 3f99b5e..1a4df1f 100644
--- a/src/gui/itemviews/qtreewidgetitemiterator.cpp
+++ b/src/gui/itemviews/qtreewidgetitemiterator.cpp
@@ -97,7 +97,7 @@ QTreeWidgetItemIterator::QTreeWidgetItemIterator(QTreeWidget *widget, IteratorFl
Q_ASSERT(widget);
QTreeModel *model = qobject_cast<QTreeModel*>(widget->model());
Q_ASSERT(model);
- d_ptr = new QTreeWidgetItemIteratorPrivate(this, model);
+ d_ptr.reset(new QTreeWidgetItemIteratorPrivate(this, model));
model->iterators.append(this);
if (!model->rootItem->children.isEmpty()) current = model->rootItem->children.first();
if (current && !matchesFlags(current))
@@ -150,7 +150,6 @@ QTreeWidgetItemIterator::QTreeWidgetItemIterator(QTreeWidgetItem *item, Iterator
QTreeWidgetItemIterator::~QTreeWidgetItemIterator()
{
d_func()->m_model->iterators.removeAll(this);
- delete d_ptr;
}
/*!
diff --git a/src/gui/itemviews/qtreewidgetitemiterator.h b/src/gui/itemviews/qtreewidgetitemiterator.h
index aaf01fb..45a5505 100644
--- a/src/gui/itemviews/qtreewidgetitemiterator.h
+++ b/src/gui/itemviews/qtreewidgetitemiterator.h
@@ -43,6 +43,7 @@
#define QTREEWIDGETITEMITERATOR_H
#include <QtCore/qglobal.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -105,7 +106,7 @@ public:
private:
bool matchesFlags(const QTreeWidgetItem *item) const;
- QTreeWidgetItemIteratorPrivate *d_ptr;
+ QScopedPointer<QTreeWidgetItemIteratorPrivate> d_ptr;
QTreeWidgetItem *current;
IteratorFlags flags;
Q_DECLARE_PRIVATE(QTreeWidgetItemIterator)
diff --git a/src/gui/itemviews/qtreewidgetitemiterator_p.h b/src/gui/itemviews/qtreewidgetitemiterator_p.h
index 23b6121..532b963 100644
--- a/src/gui/itemviews/qtreewidgetitemiterator_p.h
+++ b/src/gui/itemviews/qtreewidgetitemiterator_p.h
@@ -73,7 +73,8 @@ public:
}
QTreeWidgetItemIteratorPrivate(const QTreeWidgetItemIteratorPrivate& other)
- : m_currentIndex(other.m_currentIndex), m_model(other.m_model), m_parentIndex(other.m_parentIndex)
+ : m_currentIndex(other.m_currentIndex), m_model(other.m_model),
+ m_parentIndex(other.m_parentIndex), q_ptr(other.q_ptr)
{
}
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index cb2b014..8489817 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -7,6 +7,7 @@ PRECOMPILED_HEADER = kernel/qt_gui_pch.h
KERNEL_P= kernel
HEADERS += \
kernel/qaction.h \
+ kernel/qaction_p.h \
kernel/qactiongroup.h \
kernel/qapplication.h \
kernel/qapplication_p.h \
@@ -41,7 +42,11 @@ HEADERS += \
kernel/qwidgetaction.h \
kernel/qwidgetaction_p.h \
kernel/qwindowdefs.h \
- kernel/qkeymapper_p.h
+ kernel/qkeymapper_p.h \
+ kernel/qgesture.h \
+ kernel/qgesture_p.h \
+ kernel/qstandardgestures.h \
+ kernel/qstandardgestures_p.h
SOURCES += \
kernel/qaction.cpp \
@@ -70,7 +75,9 @@ SOURCES += \
kernel/qwhatsthis.cpp \
kernel/qwidget.cpp \
kernel/qwidgetaction.cpp \
- kernel/qkeymapper.cpp
+ kernel/qkeymapper.cpp \
+ kernel/qgesture.cpp \
+ kernel/qstandardgestures.cpp
win32 {
DEFINES += QT_NO_DIRECTDRAW
@@ -90,11 +97,33 @@ win32 {
!contains(DEFINES, QT_NO_DIRECTDRAW):LIBS += ddraw.lib
}
+symbian {
+ SOURCES += \
+ kernel/qapplication_s60.cpp \
+ kernel/qeventdispatcher_s60.cpp \
+ kernel/qwidget_s60.cpp \
+ kernel/qcursor_s60.cpp \
+ kernel/qdesktopwidget_s60.cpp \
+ kernel/qkeymapper_s60.cpp\
+ kernel/qclipboard_s60.cpp\
+ kernel/qdnd_s60.cpp \
+ kernel/qsound_s60.cpp
+
+ HEADERS += \
+ kernel/qt_s60_p.h \
+ kernel/qeventdispatcher_s60_p.h
+ LIBS += -lbafl -lestor
+
+ INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
+}
+
+
unix:x11 {
INCLUDEPATH += ../3rdparty/xorg
HEADERS += \
kernel/qx11embed_x11.h \
- kernel/qx11info_x11.h
+ kernel/qx11info_x11.h \
+ kernel/qkde_p.h
SOURCES += \
kernel/qapplication_x11.cpp \
@@ -108,7 +137,8 @@ unix:x11 {
kernel/qwidgetcreate_x11.cpp \
kernel/qx11embed_x11.cpp \
kernel/qx11info_x11.cpp \
- kernel/qkeymapper_x11.cpp
+ kernel/qkeymapper_x11.cpp \
+ kernel/qkde.cpp
contains(QT_CONFIG, glib) {
SOURCES += \
@@ -116,7 +146,7 @@ unix:x11 {
HEADERS += \
kernel/qguieventdispatcher_glib_p.h
QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
- LIBS +=$$QT_LIBS_GLIB
+ LIBS_PRIVATE +=$$QT_LIBS_GLIB
}
SOURCES += \
kernel/qeventdispatcher_x11.cpp
@@ -164,24 +194,26 @@ embedded {
qcocoaview_mac_p.h \
qcocoaapplication_mac_p.h \
qcocoaapplicationdelegate_mac_p.h \
+ qmultitouch_mac_p.h
OBJECTIVE_SOURCES += \
kernel/qcursor_mac.mm \
kernel/qdnd_mac.mm \
kernel/qsound_mac.mm \
kernel/qapplication_mac.mm \
- kernel/qwidget_mac.mm \
- kernel/qcocoapanel_mac.mm \
- kernel/qcocoaview_mac.mm \
- kernel/qcocoawindow_mac.mm \
- kernel/qcocoawindowdelegate_mac.mm \
+ kernel/qwidget_mac.mm \
+ kernel/qcocoapanel_mac.mm \
+ kernel/qcocoaview_mac.mm \
+ kernel/qcocoawindow_mac.mm \
+ kernel/qcocoawindowdelegate_mac.mm \
kernel/qcocoamenuloader_mac.mm \
kernel/qcocoaapplication_mac.mm \
kernel/qcocoaapplicationdelegate_mac.mm \
kernel/qt_cocoa_helpers_mac.mm \
- kernel/qdesktopwidget_mac.mm \
+ kernel/qdesktopwidget_mac.mm \
kernel/qeventdispatcher_mac.mm \
- kernel/qcocoawindowcustomthemeframe_mac.mm
+ kernel/qcocoawindowcustomthemeframe_mac.mm \
+ kernel/qmultitouch_mac.mm \
HEADERS += \
kernel/qt_cocoa_helpers_mac_p.h \
@@ -189,13 +221,13 @@ embedded {
kernel/qcocoaapplicationdelegate_mac_p.h \
kernel/qeventdispatcher_mac_p.h
- MENU_NIB.files = mac/qt_menu.nib
- MENU_NIB.path = Resources
+ MENU_NIB.files = mac/qt_menu.nib
+ MENU_NIB.path = Resources
MENU_NIB.version = Versions
- QMAKE_BUNDLE_DATA += MENU_NIB
- RESOURCES += mac/maccursors.qrc
+ QMAKE_BUNDLE_DATA += MENU_NIB
+ RESOURCES += mac/macresources.qrc
- LIBS += -framework AppKit
+ LIBS_PRIVATE += -framework AppKit
}
wince*: {
diff --git a/src/gui/kernel/mac.pri b/src/gui/kernel/mac.pri
index 415fe0a..1538510 100644
--- a/src/gui/kernel/mac.pri
+++ b/src/gui/kernel/mac.pri
@@ -1,4 +1,4 @@
!x11:!embedded:mac {
- LIBS += -framework Carbon -lz
+ LIBS_PRIVATE += -framework Carbon -lz
*-mwerks:INCLUDEPATH += compat
}
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
index 27d90c6..d2a25fd 100644
--- a/src/gui/kernel/qaction.cpp
+++ b/src/gui/kernel/qaction.cpp
@@ -76,12 +76,13 @@ static QString qt_strippedText(QString s)
s.remove(i-1,1);
}
return s.trimmed();
-};
+}
QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0),
visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false),
- menuRole(QAction::TextHeuristicRole), iconVisibleInMenu(-1)
+ menuRole(QAction::TextHeuristicRole), softKeyRole(QAction::OptionsSoftKey),
+ priority(QAction::NormalPriority), iconVisibleInMenu(-1)
{
#ifdef QT3_SUPPORT
static int qt_static_action_id = -1;
@@ -136,25 +137,31 @@ void QActionPrivate::redoGrab(QShortcutMap &map)
void QActionPrivate::redoGrabAlternate(QShortcutMap &map)
{
Q_Q(QAction);
- foreach (int id, alternateShortcutIds)
- if (id)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ if (const int id = alternateShortcutIds.at(i))
map.removeShortcut(id, q);
+ }
alternateShortcutIds.clear();
if (alternateShortcuts.isEmpty())
return;
- foreach (const QKeySequence& alternate, alternateShortcuts) {
+ for(int i = 0; i < alternateShortcuts.count(); ++i) {
+ const QKeySequence& alternate = alternateShortcuts.at(i);
if (!alternate.isEmpty())
alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext));
else
alternateShortcutIds.append(0);
}
if (!enabled) {
- foreach (int id, alternateShortcutIds)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ const int id = alternateShortcutIds.at(i);
map.setShortcutEnabled(false, id, q);
+ }
}
if (!autorepeat) {
- foreach (int id, alternateShortcutIds)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ const int id = alternateShortcutIds.at(i);
map.setShortcutAutoRepeat(false, id, q);
+ }
}
}
@@ -163,9 +170,10 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
Q_Q(QAction);
if (shortcutId)
map.setShortcutEnabled(enable, shortcutId, q);
- foreach (int id, alternateShortcutIds)
- if (id)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ if (const int id = alternateShortcutIds.at(i))
map.setShortcutEnabled(enable, id, q);
+ }
}
#endif // QT_NO_SHORTCUT
@@ -175,8 +183,8 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
\brief The QAction class provides an abstract user interface
action that can be inserted into widgets.
- \ingroup application
- \mainclass
+ \ingroup mainwindow-classes
+
\omit
* parent and widget are different
@@ -622,8 +630,10 @@ QAction::~QAction()
#ifndef QT_NO_SHORTCUT
if (d->shortcutId && qApp) {
qApp->d_func()->shortcutMap.removeShortcut(d->shortcutId, this);
- foreach (int id, d->alternateShortcutIds)
+ for(int i = 0; i < d->alternateShortcutIds.count(); ++i) {
+ const int id = d->alternateShortcutIds.at(i);
qApp->d_func()->shortcutMap.removeShortcut(id, this);
+ }
}
#endif
}
@@ -905,6 +915,52 @@ QString QAction::whatsThis() const
return d->whatsthis;
}
+/*!
+ \enum QAction::Priority
+ \since 4.6
+
+ This enum defines priorities for actions in user interface.
+
+ \value LowPriority The action should not be prioritized in
+ the user interface.
+
+ \value NormalPriority
+
+ \value HighPriority The action should be prioritized in
+ the user interface.
+
+ \sa priority
+*/
+
+
+/*!
+ \property QAction::priority
+ \since 4.6
+
+ \brief the actions's priority in the user interface.
+
+ This property can be set to indicate how the action should be prioritized
+ in the user interface.
+
+ For instance, when toolbars have the Qt::ToolButtonTextBesideIcon
+ mode set, then actions with LowPriority will not show the text
+ labels.
+*/
+void QAction::setPriority(Priority priority)
+{
+ Q_D(QAction);
+ if (d->priority == priority)
+ return;
+
+ d->priority = priority;
+ d->sendDataChanged();
+}
+
+QAction::Priority QAction::priority() const
+{
+ Q_D(const QAction);
+ return d->priority;
+}
/*!
\property QAction::checkable
@@ -1158,6 +1214,8 @@ void QAction::activate(ActionEvent event)
// the checked action of an exclusive group cannot be unchecked
if (d->checked && (d->group && d->group->isExclusive()
&& d->group->checkedAction() == this)) {
+ if (guard)
+ emit triggered(true);
QMetaObject::removeGuard(&guard);
return;
}
@@ -1355,6 +1413,32 @@ QAction::MenuRole QAction::menuRole() const
}
/*!
+ \property QAction::softKeyRole
+ \brief the action's softkey role
+ \since 4.6
+
+ This indicates what softkey action this action is. Usually used on mobile
+ platforms to map QActions to hardware keys.
+
+ The softkey role can be changed any time.
+*/
+void QAction::setSoftKeyRole(SoftKeyRole softKeyRole)
+{
+ Q_D(QAction);
+ if (d->softKeyRole == softKeyRole)
+ return;
+
+ d->softKeyRole = softKeyRole;
+ d->sendDataChanged();
+}
+
+QAction::SoftKeyRole QAction::softKeyRole() const
+{
+ Q_D(const QAction);
+ return d->softKeyRole;
+}
+
+/*!
\property QAction::iconVisibleInMenu
\brief Whether or not an action should show an icon in a menu
\since 4.4
@@ -1375,7 +1459,7 @@ QAction::MenuRole QAction::menuRole() const
void QAction::setIconVisibleInMenu(bool visible)
{
Q_D(QAction);
- if (visible != (bool)d->iconVisibleInMenu) {
+ if (d->iconVisibleInMenu == -1 || visible != bool(d->iconVisibleInMenu)) {
int oldValue = d->iconVisibleInMenu;
d->iconVisibleInMenu = visible;
// Only send data changed if we really need to.
diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h
index d8d76a5..ef547ef 100644
--- a/src/gui/kernel/qaction.h
+++ b/src/gui/kernel/qaction.h
@@ -67,28 +67,39 @@ class Q_GUI_EXPORT QAction : public QObject
Q_DECLARE_PRIVATE(QAction)
Q_ENUMS(MenuRole)
- Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable)
+ Q_ENUMS(SoftKeyRole)
+ Q_ENUMS(Priority)
+ Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed)
Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled)
- Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
- Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
- Q_PROPERTY(QString text READ text WRITE setText)
- Q_PROPERTY(QString iconText READ iconText WRITE setIconText)
- Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip)
- Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip)
- Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
- Q_PROPERTY(QFont font READ font WRITE setFont)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed)
+ Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed)
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed)
+ Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed)
+ Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed)
+ Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed)
+ Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed)
#ifndef QT_NO_SHORTCUT
- Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
- Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext)
- Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat)
+ Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed)
+ Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed)
+ Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed)
#endif
- Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
- Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole)
- Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed)
+ Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
+ Q_PROPERTY(SoftKeyRole softKeyRole READ softKeyRole WRITE setSoftKeyRole NOTIFY changed)
+ Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
+ Q_PROPERTY(Priority priority READ priority WRITE setPriority)
public:
enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole,
AboutRole, PreferencesRole, QuitRole };
+ enum SoftKeyRole { OptionsSoftKey, SelectSoftKey, BackSoftKey, NextSoftKey, PreviousSoftKey,
+ OkSoftKey, CancelSoftKey, EditSoftKey, ViewSoftKey, BackSpaceSoftKey,
+ EndEditSoftKey, RevertEditSoftKey, DeselectSoftKey, FinishSoftKey,
+ MenuSoftKey, ContextMenuSoftKey, ExitSoftKey };
+ enum Priority { LowPriority = 0,
+ NormalPriority = 128,
+ HighPriority = 256};
explicit QAction(QObject* parent);
QAction(const QString &text, QObject* parent);
QAction(const QIcon &icon, const QString &text, QObject* parent);
@@ -123,6 +134,9 @@ public:
void setWhatsThis(const QString &what);
QString whatsThis() const;
+ void setPriority(Priority priority);
+ Priority priority() const;
+
#ifndef QT_NO_MENU
QMenu *menu() const;
void setMenu(QMenu *menu);
@@ -168,6 +182,9 @@ public:
void setMenuRole(MenuRole menuRole);
MenuRole menuRole() const;
+ void setSoftKeyRole(SoftKeyRole softKeyRole);
+ SoftKeyRole softKeyRole() const;
+
void setIconVisibleInMenu(bool visible);
bool isIconVisibleInMenu() const;
diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h
index 5c6017c..34eccb2 100644
--- a/src/gui/kernel/qaction_p.h
+++ b/src/gui/kernel/qaction_p.h
@@ -102,6 +102,8 @@ public:
uint separator : 1;
uint fontSet : 1;
QAction::MenuRole menuRole;
+ QAction::SoftKeyRole softKeyRole;
+ QAction::Priority priority;
int iconVisibleInMenu : 3; // Only has values -1, 0, and 1
QList<QWidget *> widgets;
#ifndef QT_NO_GRAPHICSVIEW
diff --git a/src/gui/kernel/qactiongroup.cpp b/src/gui/kernel/qactiongroup.cpp
index f1b7a50..daf3a2a 100644
--- a/src/gui/kernel/qactiongroup.cpp
+++ b/src/gui/kernel/qactiongroup.cpp
@@ -100,7 +100,7 @@ void QActionGroupPrivate::_q_actionHovered()
\class QActionGroup
\brief The QActionGroup class groups actions together.
- \ingroup application
+ \ingroup mainwindow-classes
In some situations it is useful to group actions together. For
example, if you have a \gui{Left Align} action, a \gui{Right
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 327f5ce..f049a58 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
#include "qabstracteventdispatcher.h"
#include "qaccessible.h"
#include "qapplication.h"
@@ -74,6 +75,9 @@
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
+#endif
+
+#if defined(Q_WS_X11) || defined(Q_WS_S60)
#include "qinputcontextfactory.h"
#endif
@@ -85,11 +89,12 @@
#include <stdlib.h>
#include "qapplication_p.h"
+#include "qevent_p.h"
#include "qwidget_p.h"
#include "qapplication.h"
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qdatetime.h"
#include "qguifunctions_wince.h"
extern bool qt_wince_is_smartphone(); //qguifunctions_wince.cpp
@@ -97,19 +102,22 @@ extern bool qt_wince_is_mobile(); //qguifunctions_wince.cpp
extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp
#endif
+#include "qdatetime.h"
+
+#ifdef QT_MAC_USE_COCOA
+#include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
//#define ALIEN_DEBUG
static void initResources()
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
Q_INIT_RESOURCE(qstyle_wince);
#else
Q_INIT_RESOURCE(qstyle);
#endif
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
- Q_INIT_RESOURCE(qpaintengine_d3d);
-#endif
Q_INIT_RESOURCE(qmessagebox);
#if !defined(QT_NO_PRINTDIALOG)
Q_INIT_RESOURCE(qprintdialog);
@@ -130,9 +138,11 @@ QInputContext *QApplicationPrivate::inputContext = 0;
bool QApplicationPrivate::quitOnLastWindowClosed = true;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
int QApplicationPrivate::autoMaximizeThreshold = -1;
bool QApplicationPrivate::autoSipEnabled = false;
+#else
+bool QApplicationPrivate::autoSipEnabled = true;
#endif
QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type)
@@ -173,16 +183,13 @@ QApplicationPrivate::~QApplicationPrivate()
\brief The QApplication class manages the GUI application's control
flow and main settings.
- \ingroup application
- \mainclass
-
QApplication contains the main event loop, where all events from the window
system and other sources are processed and dispatched. It also handles the
- application's initialization and finalization, and provides session
- management. In addition, it handles most system-wide and application-wide
- settings.
+ application's initialization, finalization, and provides session
+ management. In addition, QApplication handles most of the system-wide and
+ application-wide settings.
- For any GUI application using Qt, there is precisely one QApplication
+ For any GUI application using Qt, there is precisely \bold one QApplication
object, no matter whether the application has 0, 1, 2 or more windows at
any given time. For non-GUI Qt applications, use QCoreApplication instead,
as it does not depend on the \l QtGui library.
@@ -238,9 +245,9 @@ QApplicationPrivate::~QApplicationPrivate()
saveState() for details.
\endlist
- The QApplication object does so much initialization. Hence, it \e{must} be
+ Since the QApplication object does so much initialization, it \e{must} be
created before any other objects related to the user interface are created.
- Since QApplication also deals with common command line arguments, it is
+ QApplication also deals with common command line arguments. Hence, it is
usually a good idea to create it \e before any interpretation or
modification of \c argv is done in the application itself.
@@ -394,6 +401,7 @@ Qt::MouseButtons QApplicationPrivate::mouse_buttons = Qt::NoButton;
Qt::KeyboardModifiers QApplicationPrivate::modifier_buttons = Qt::NoModifier;
QStyle *QApplicationPrivate::app_style = 0; // default application style
+QString QApplicationPrivate::styleOverride; // style override
#ifndef QT_NO_STYLE_STYLESHEET
QString QApplicationPrivate::styleSheet; // default application stylesheet
@@ -408,7 +416,7 @@ QPalette *QApplicationPrivate::set_pal = 0; // default palette set by pro
QGraphicsSystem *QApplicationPrivate::graphics_system = 0; // default graphics system
QString QApplicationPrivate::graphics_system_name; // graphics system id - for delayed initialization
-Q_GLOBAL_STATIC(QMutex, applicationFontMutex);
+Q_GLOBAL_STATIC(QMutex, applicationFontMutex)
QFont *QApplicationPrivate::app_font = 0; // default application font
QFont *QApplicationPrivate::sys_font = 0; // default system font
QFont *QApplicationPrivate::set_font = 0; // default font set by programmer
@@ -430,7 +438,12 @@ bool Q_GUI_EXPORT qt_tab_all_widgets = true;
bool qt_in_tab_key_event = false;
int qt_antialiasing_threshold = -1;
static int drag_time = 500;
+#ifdef Q_OS_SYMBIAN
+// The screens are a bit too small to for your thumb when using only 4 pixels drag distance.
+static int drag_distance = 8;
+#else
static int drag_distance = 4;
+#endif
static Qt::LayoutDirection layout_direction = Qt::LeftToRight;
QSize QApplicationPrivate::app_strut = QSize(0,0); // no default application strut
bool QApplicationPrivate::animate_ui = true;
@@ -441,12 +454,15 @@ bool QApplicationPrivate::animate_tooltip = false;
bool QApplicationPrivate::fade_tooltip = false;
bool QApplicationPrivate::animate_toolbox = false;
bool QApplicationPrivate::widgetCount = false;
-QString* QApplicationPrivate::styleOverride = 0;
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
bool QApplicationPrivate::inSizeMove = false;
#endif
#ifdef QT_KEYPAD_NAVIGATION
+# if defined(Q_OS_SYMBIAN)
+bool QApplicationPrivate::keypadNavigation = true;
+# else
bool QApplicationPrivate::keypadNavigation = false;
+# endif
QWidget *QApplicationPrivate::oldEditFocus = 0;
#endif
@@ -466,15 +482,12 @@ static inline bool isAlien(QWidget *widget)
// ######## move to QApplicationPrivate
// Default application palettes and fonts (per widget type)
-
-typedef QHash<QByteArray, QPalette> PaletteHash;
Q_GLOBAL_STATIC(PaletteHash, app_palettes)
PaletteHash *qt_app_palettes_hash()
{
return app_palettes();
}
-typedef QHash<QByteArray, QFont> FontHash;
Q_GLOBAL_STATIC(FontHash, app_fonts)
FontHash *qt_app_fonts_hash()
{
@@ -494,8 +507,6 @@ QWidgetList * qt_modal_stack=0; // stack of modal widgets
*/
void QApplicationPrivate::process_cmdline()
{
- Q_Q(QApplication);
- Q_UNUSED(q);// only static members being used.
// process platform-indep command line
if (!qt_is_gui_used || !argc)
return;
@@ -540,7 +551,7 @@ void QApplicationPrivate::process_cmdline()
#endif
} else if (qstrcmp(arg, "-reverse") == 0) {
force_reverse = true;
- q->setLayoutDirection(Qt::RightToLeft);
+ QApplication::setLayoutDirection(Qt::RightToLeft);
} else if (qstrcmp(arg, "-widgetcount") == 0) {
widgetCount = true;
} else if (arg == "-graphicssystem" && i < argc-1) {
@@ -553,9 +564,7 @@ void QApplicationPrivate::process_cmdline()
delete app_style;
app_style = 0;
}
- if (!styleOverride)
- styleOverride = new QString;
- *styleOverride = s;
+ styleOverride = s;
}
}
@@ -620,13 +629,6 @@ void QApplicationPrivate::process_cmdline()
and QPixmaps. Available options are \c{raster} and \c{opengl}.
\endlist
- The Windows version of Qt supports an additional command line option, if
- Direct3D support has been compiled into Qt:
- \list
- \o -direct3d will make the Direct3D paint engine the default widget
- paint engine in Qt. \bold {This functionality is experimental.}
- \endlist
-
The X11 version of Qt supports some traditional X11 command line options:
\list
\o -display \e display, sets the X display (default is $DISPLAY).
@@ -686,9 +688,9 @@ QApplication::QApplication(int &argc, char **argv, int _internal)
On X11, the window system is initialized if \a GUIenabled is true. If
\a GUIenabled is false, the application does not connect to the X server.
- On Windows and Macintosh, currently the window system is always
- initialized, regardless of the value of GUIenabled. This may change in
- future versions of Qt.
+ On Windows and Mac OS, currently the window system is always initialized,
+ regardless of the value of GUIenabled. This may change in future versions
+ of Qt.
The following example shows how to create an application that uses a
graphical interface when available.
@@ -833,6 +835,12 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv,
#endif // Q_WS_X11
extern void qInitDrawhelperAsm();
+extern int qRegisterGuiVariant();
+extern int qUnregisterGuiVariant();
+#ifndef QT_NO_STATEMACHINE
+extern int qRegisterGuiStateMachine();
+extern int qUnregisterGuiStateMachine();
+#endif
/*!
\fn void QApplicationPrivate::initialize()
@@ -842,12 +850,15 @@ extern void qInitDrawhelperAsm();
void QApplicationPrivate::initialize()
{
QWidgetPrivate::mapper = new QWidgetMapper;
- QWidgetPrivate::uncreatedWidgets = new QWidgetSet;
+ QWidgetPrivate::allWidgets = new QWidgetSet;
if (qt_appType != QApplication::Tty)
(void) QApplication::style(); // trigger creation of application style
// trigger registering of QVariant's GUI types
- extern int qRegisterGuiVariant();
qRegisterGuiVariant();
+#ifndef QT_NO_STATEMACHINE
+ // trigger registering of QStateMachine's GUI types
+ qRegisterGuiStateMachine();
+#endif
is_app_running = true; // no longer starting up
@@ -860,13 +871,7 @@ void QApplicationPrivate::initialize()
if (qgetenv("QT_USE_NATIVE_WINDOWS").toInt() > 0)
q->setAttribute(Qt::AA_NativeWindows);
-#if defined(Q_WS_WIN)
- // Alien is not currently working on Windows 98
- if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
- q->setAttribute(Qt::AA_NativeWindows);
-#endif
-
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#ifdef QT_AUTO_MAXIMIZE_THRESHOLD
autoMaximizeThreshold = QT_AUTO_MAXIMIZE_THRESHOLD;
#else
@@ -875,7 +880,7 @@ void QApplicationPrivate::initialize()
else
autoMaximizeThreshold = -1;
#endif //QT_AUTO_MAXIMIZE_THRESHOLD
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
// Set up which span functions should be used in raster engine...
qInitDrawhelperAsm();
@@ -893,6 +898,8 @@ void QApplicationPrivate::initialize()
QApplicationPrivate::wheel_scroll_lines = 3;
#endif
#endif
+
+ initializeMultitouch();
}
/*!
@@ -987,23 +994,14 @@ QApplication::~QApplication()
qt_clipboard = 0;
#endif
- // delete widget mapper
- if (QWidgetPrivate::mapper) {
- QWidgetMapper * myMapper = QWidgetPrivate::mapper;
- QWidgetPrivate::mapper = 0;
- for (QWidgetMapper::Iterator it = myMapper->begin(); it != myMapper->end(); ++it) {
- register QWidget *w = *it;
- if (!w->parent()) // window
- w->destroy(true, true);
- }
- delete myMapper;
- }
+ delete QWidgetPrivate::mapper;
+ QWidgetPrivate::mapper = 0;
- // delete uncreated widgets
- if (QWidgetPrivate::uncreatedWidgets) {
- QWidgetSet *mySet = QWidgetPrivate::uncreatedWidgets;
- QWidgetPrivate::uncreatedWidgets = 0;
- for (QWidgetSet::Iterator it = mySet->begin(); it != mySet->end(); ++it) {
+ // delete all widgets
+ if (QWidgetPrivate::allWidgets) {
+ QWidgetSet *mySet = QWidgetPrivate::allWidgets;
+ QWidgetPrivate::allWidgets = 0;
+ for (QWidgetSet::ConstIterator it = mySet->constBegin(); it != mySet->constEnd(); ++it) {
register QWidget *w = *it;
if (!w->parent()) // window
w->destroy(true, true);
@@ -1043,6 +1041,8 @@ QApplication::~QApplication()
delete QDragManager::self();
#endif
+ d->cleanupMultitouch();
+
qt_cleanup();
if (QApplicationPrivate::widgetCount)
@@ -1069,8 +1069,11 @@ QApplication::~QApplication()
QApplicationPrivate::fade_tooltip = false;
QApplicationPrivate::widgetCount = false;
+#ifndef QT_NO_STATEMACHINE
+ // trigger unregistering of QStateMachine's GUI types
+ qUnregisterGuiStateMachine();
+#endif
// trigger unregistering of QVariant's GUI types
- extern int qUnregisterGuiVariant();
qUnregisterGuiVariant();
}
@@ -1197,21 +1200,22 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis
\since 4.4
\brief defines a threshold for auto maximizing widgets
- The auto maximize threshold is only available as part of Qt for Windows CE.
+ \bold{The auto maximize threshold is only available as part of Qt for
+ Windows CE.}
This property defines a threshold for the size of a window as a percentage
of the screen size. If the minimum size hint of a window exceeds the
- threshold, calling show() will then cause the window to be maximized
+ threshold, calling show() will cause the window to be maximized
automatically.
- Setting the threshold to be 100 or greater means that it will cause it to
- always be maximized. Setting it to be 50 means that the widget is maximized
- if the vertical minimum size hint is at least 50% of the vertical screen
- size.
+ Setting the threshold to 100 or greater means that the widget will always
+ be maximized. Alternatively, setting the threshold to 50 means that the
+ widget will be maximized only if the vertical minimum size hint is at least
+ 50% of the vertical screen size.
- If -1 is specified then this will disable the feature.
+ Setting the threshold to -1 disables the feature.
- On Windows CE the default is -1 (i.e. it is disabled).
+ On Windows CE the default is -1 (i.e., it is disabled).
On Windows Mobile the default is 40.
*/
@@ -1220,14 +1224,18 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis
\since 4.5
\brief toggles automatic SIP (software input panel) visibility
- The auto SIP property is only available as part of Qt for Windows CE.
-
- Set this property to true to automatically display the SIP when entering
+ Set this property to \c true to automatically display the SIP when entering
widgets that accept keyboard input. This property only affects widgets with
- the WA_InputMethodEnabled attribute set.
+ the WA_InputMethodEnabled attribute set, and is typically used to launch
+ a virtual keyboard on devices which have very few or no keys.
+
+ \bold{ The property only has an effect on platforms which use software input
+ panels, such as Windows CE and Symbian.}
+
+ The default is platform dependent.
*/
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void QApplication::setAutoMaximizeThreshold(const int threshold)
{
QApplicationPrivate::autoMaximizeThreshold = threshold;
@@ -1237,6 +1245,7 @@ int QApplication::autoMaximizeThreshold() const
{
return QApplicationPrivate::autoMaximizeThreshold;
}
+#endif
void QApplication::setAutoSipEnabled(const bool enabled)
{
@@ -1247,7 +1256,6 @@ bool QApplication::autoSipEnabled() const
{
return QApplicationPrivate::autoSipEnabled;
}
-#endif
#ifndef QT_NO_STYLE_STYLESHEET
@@ -1289,44 +1297,14 @@ QStyle *QApplication::style()
return 0;
}
-#if defined(Q_WS_X11)
- if(!QApplicationPrivate::styleOverride)
- QApplicationPrivate::x11_initialize_style(); // run-time search for default style
-#endif
if (!QApplicationPrivate::app_style) {
// Compile-time search for default style
//
QString style;
- if (QApplicationPrivate::styleOverride) {
- style = *QApplicationPrivate::styleOverride;
- delete QApplicationPrivate::styleOverride;
- QApplicationPrivate::styleOverride = 0;
- } else {
-#if defined(Q_WS_WIN) && defined(Q_OS_WINCE)
- if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc())
- style = QLatin1String("WindowsMobile");
- else
- style = QLatin1String("WindowsCE");
-
-#elif defined(Q_WS_WIN)
- if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
- && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
- style = QLatin1String("WindowsVista");
- else if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
- && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
- style = QLatin1String("WindowsXP");
- else
- style = QLatin1String("Windows"); // default styles for Windows
-#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS)
- style = QLatin1String("CDE"); // default style for X11 on Solaris
-#elif defined(Q_WS_X11) && defined(Q_OS_IRIX)
- style = QLatin1String("SGI"); // default style for X11 on IRIX
-#elif defined(Q_WS_X11) || defined(Q_WS_QWS)
- style = QLatin1String("Plastique"); // default style for X11 and small devices
-#elif defined(Q_WS_MAC)
- style = QLatin1String("Macintosh"); // default style for all Mac's
-#endif
- }
+ if (!QApplicationPrivate::styleOverride.isEmpty())
+ style = QApplicationPrivate::styleOverride;
+ else
+ style = QApplicationPrivate::desktopStyleKey();
QStyle *&app_style = QApplicationPrivate::app_style;
app_style = QStyleFactory::create(style);
@@ -1414,7 +1392,6 @@ void QApplication::setStyle(QStyle *style)
} else
#endif // QT_NO_STYLE_STYLESHEET
QApplicationPrivate::app_style = style;
-
QApplicationPrivate::app_style->setParent(qApp); // take ownership
// take care of possible palette requirements of certain gui
@@ -1551,7 +1528,7 @@ int QApplication::colorSpec()
strategy. Use this option if your application uses buttons, menus,
texts and pixmaps with few colors. With this option, the
application uses system global colors. This works fine for most
- applications under X11, but on Windows machines it may cause
+ applications under X11, but on the Windows platform, it may cause
dithering of non-standard colors.
\o QApplication::CustomColor. Use this option if your application
needs a small number of custom colors. On X11, this option is the
@@ -1938,6 +1915,44 @@ void QApplicationPrivate::setSystemFont(const QFont &font)
QApplication::setFont(*sys_font);
}
+/*! \internal
+*/
+QString QApplicationPrivate::desktopStyleKey()
+{
+QString desktopstyle;
+#if defined(Q_WS_WIN) && defined(Q_WS_WINCE)
+ if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc())
+ desktopstyle = QLatin1String("WindowsMobile");
+ else
+ desktopstyle = QLatin1String("WindowsCE");
+
+#elif defined(Q_WS_WIN)
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ desktopstyle = QLatin1String("WindowsVista");
+ else if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ desktopstyle = QLatin1String("WindowsXP");
+ else
+ desktopstyle = QLatin1String("Windows"); // default styles for Windows
+#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS)
+ desktopstyle = QLatin1String("CDE"); // default style for X11 on Solaris
+#elif defined(Q_WS_S60)
+ desktopstyle = QLatin1String("S60"); // default style for Symbian with S60
+#elif defined(Q_OS_SYMBIAN)
+ desktopstyle = QLatin1String("Windows"); // default style for Symbian without S60
+#elif defined(Q_WS_X11) && defined(Q_OS_IRIX)
+ desktopstyle = QLatin1String("SGI"); // default style for X11 on IRIX
+#elif defined(Q_WS_QWS)
+ desktopstyle = QLatin1String("Plastique"); // default style for X11 and small devices
+#elif defined(Q_WS_X11)
+ desktopstyle = QApplicationPrivate::x11_desktop_style(); // default runtime dependant style for X11
+#elif defined(Q_WS_MAC)
+ desktopstyle = QLatin1String("Macintosh"); // default style for all Mac's
+#endif
+ return desktopstyle;
+}
+
/*!
\property QApplication::windowIcon
\brief the default window icon
@@ -2010,12 +2025,9 @@ QWidgetList QApplication::topLevelWidgets()
QWidgetList QApplication::allWidgets()
{
- QWidgetList list;
- if (QWidgetPrivate::mapper)
- list += QWidgetPrivate::mapper->values();
- if (QWidgetPrivate::uncreatedWidgets)
- list += QWidgetPrivate::uncreatedWidgets->toList();
- return list;
+ if (QWidgetPrivate::allWidgets)
+ return QWidgetPrivate::allWidgets->toList();
+ return QWidgetList();
}
/*!
@@ -2080,6 +2092,16 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
prev->setEditFocus(false);
}
#endif
+#ifndef QT_NO_IM
+ if (focus) {
+ QInputContext *prevIc;
+ prevIc = prev->inputContext();
+ if (prevIc && prevIc != focus->inputContext()) {
+ QEvent closeSIPEvent(QEvent::CloseSoftwareInputPanel);
+ QApplication::sendEvent(prev, &closeSIPEvent);
+ }
+ }
+#endif
QFocusEvent out(QEvent::FocusOut, reason);
QPointer<QWidget> that = prev;
QApplication::sendEvent(prev, &out);
@@ -2089,8 +2111,9 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
if(focus && QApplicationPrivate::focus_widget == focus) {
if (focus->testAttribute(Qt::WA_InputMethodEnabled)) {
QInputContext *qic = focus->inputContext();
- if (qic && focus_widget->testAttribute(Qt::WA_WState_Created))
- qic->setFocusWidget( focus_widget );
+ if (qic && focus->testAttribute(Qt::WA_WState_Created)
+ && focus->isEnabled())
+ qic->setFocusWidget(focus);
}
QFocusEvent in(QEvent::FocusIn, reason);
QPointer<QWidget> that = focus;
@@ -2309,10 +2332,6 @@ bool QApplication::event(QEvent *e)
} else if (te->timerId() == d->toolTipFallAsleep.timerId()) {
d->toolTipFallAsleep.stop();
}
-#ifdef QT_MAC_USE_COCOA
- } else if (e->type() == QEvent::CocoaRequestModal) {
- d->_q_runAppModalWindow();
-#endif
}
return QCoreApplication::event(e);
}
@@ -2576,14 +2595,14 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) {
QEvent leaveEvent(QEvent::Leave);
for (int i = 0; i < leaveList.size(); ++i) {
w = leaveList.at(i);
- if (!qApp->activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
+ if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
#if defined(Q_WS_WIN) || defined(Q_WS_X11)
if (leaveAfterRelease == w)
leaveAfterRelease = 0;
#endif
QApplication::sendEvent(w, &leaveEvent);
if (w->testAttribute(Qt::WA_Hover) &&
- (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) {
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
Q_ASSERT(instance());
QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos));
qApp->d_func()->notify_helper(w, &he);
@@ -2594,10 +2613,10 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) {
QEvent enterEvent(QEvent::Enter);
for (int i = 0; i < enterList.size(); ++i) {
w = enterList.at(i);
- if (!qApp->activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
+ if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
QApplication::sendEvent(w, &enterEvent);
if (w->testAttribute(Qt::WA_Hover) &&
- (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) {
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
QHoverEvent he(QEvent::HoverEnter, w->mapFromGlobal(posEnter), QPoint(-1, -1));
qApp->d_func()->notify_helper(w, &he);
}
@@ -2671,7 +2690,7 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
widget = widget->window();
if (!modalState())
return false;
- if (qApp->activePopupWidget() == widget)
+ if (QApplication::activePopupWidget() == widget)
return false;
for (int i = 0; i < qt_modal_stack->size(); ++i) {
@@ -2760,7 +2779,7 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
void QApplicationPrivate::enterModal(QWidget *widget)
{
QSet<QWidget*> blocked;
- QList<QWidget*> windows = qApp->topLevelWidgets();
+ QList<QWidget*> windows = QApplication::topLevelWidgets();
for (int i = 0; i < windows.count(); ++i) {
QWidget *window = windows.at(i);
if (window->windowType() != Qt::Tool && isBlockedByModal(window))
@@ -2769,7 +2788,7 @@ void QApplicationPrivate::enterModal(QWidget *widget)
enterModal_sys(widget);
- windows = qApp->topLevelWidgets();
+ windows = QApplication::topLevelWidgets();
QEvent e(QEvent::WindowBlocked);
for (int i = 0; i < windows.count(); ++i) {
QWidget *window = windows.at(i);
@@ -2783,7 +2802,7 @@ void QApplicationPrivate::enterModal(QWidget *widget)
void QApplicationPrivate::leaveModal(QWidget *widget)
{
QSet<QWidget*> blocked;
- QList<QWidget*> windows = qApp->topLevelWidgets();
+ QList<QWidget*> windows = QApplication::topLevelWidgets();
for (int i = 0; i < windows.count(); ++i) {
QWidget *window = windows.at(i);
if (window->windowType() != Qt::Tool && isBlockedByModal(window))
@@ -2792,7 +2811,7 @@ void QApplicationPrivate::leaveModal(QWidget *widget)
leaveModal_sys(widget);
- windows = qApp->topLevelWidgets();
+ windows = QApplication::topLevelWidgets();
QEvent e(QEvent::WindowUnblocked);
for (int i = 0; i < windows.count(); ++i) {
QWidget *window = windows.at(i);
@@ -2815,7 +2834,7 @@ bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop)
*rettop = top;
// the active popup widget always gets the input event
- if (qApp->activePopupWidget())
+ if (QApplication::activePopupWidget())
return true;
#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
@@ -2849,7 +2868,7 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint
QWidget *receiver = candidate;
if (!mouseGrabber)
- mouseGrabber = buttonDown ? buttonDown : alienWidget;
+ mouseGrabber = (buttonDown && !isBlockedByModal(buttonDown)) ? buttonDown : alienWidget;
if (mouseGrabber && mouseGrabber != candidate) {
receiver = mouseGrabber;
@@ -2868,7 +2887,8 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint
*/
bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
QWidget *alienWidget, QWidget *nativeWidget,
- QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver)
+ QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
+ bool spontaneous)
{
Q_ASSERT(receiver);
Q_ASSERT(event);
@@ -2881,7 +2901,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
QPointer<QWidget> receiverGuard = receiver;
QPointer<QWidget> nativeGuard = nativeWidget;
QPointer<QWidget> alienGuard = alienWidget;
- QPointer<QWidget> activePopupWidget = qApp->activePopupWidget();
+ QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget();
const bool graphicsWidget = nativeWidget->testAttribute(Qt::WA_DontShowOnScreen);
@@ -2921,7 +2941,11 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
// We need this quard in case someone opens a modal dialog / popup. If that's the case
// leaveAfterRelease is set to null, but we shall not update lastMouseReceiver.
const bool wasLeaveAfterRelease = leaveAfterRelease != 0;
- bool result = QApplication::sendSpontaneousEvent(receiver, event);
+ bool result;
+ if (spontaneous)
+ result = QApplication::sendSpontaneousEvent(receiver, event);
+ else
+ result = QApplication::sendEvent(receiver, event);
if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease
&& !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) {
@@ -3477,6 +3501,15 @@ void QApplication::changeOverrideCursor(const QCursor &cursor)
if (qApp->d_func()->cursor_list.isEmpty())
return;
qApp->d_func()->cursor_list.removeFirst();
+#ifdef QT_MAC_USE_COCOA
+ // We use native NSCursor stacks in Cocoa. The currentCursor is the
+ // top of this stack. So to avoid flickering of cursor, we have to
+ // change the cusor instead of pop-ing the existing OverrideCursor
+ // and pushing the new one.
+ qApp->d_func()->cursor_list.prepend(cursor);
+ qt_cocoaChangeOverrideCursor(cursor);
+ return;
+#endif
setOverrideCursor(cursor);
}
#endif
@@ -3496,7 +3529,7 @@ void QApplication::changeOverrideCursor(const QCursor &cursor)
It is necessary to call this function to start event handling. The main
event loop receives events from the window system and dispatches these to
the application widgets.
-
+
Generally, no user interaction can take place before calling exec(). As a
special case, modal widgets like QMessageBox can be used before calling
exec(), because modal widgets call exec() to start a local event loop.
@@ -3507,12 +3540,12 @@ void QApplication::changeOverrideCursor(const QCursor &cursor)
We recommend that you connect clean-up code to the
\l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your
- application's \c{main()} function because on some platforms the
- QApplication::exec() call may not return. For example, on Windows when the
- user logs off, the system terminates the process after Qt closes all
- top-level windows. Hence, there is no guarantee that the application will
- have time to exit its event loop and execute code at the end of the
- \c{main()} function after the QApplication::exec() call.
+ application's \c{main()} function. This is because, on some platforms the
+ QApplication::exec() call may not return. For example, on the Windows
+ platform, when the user logs off, the system terminates the process after Qt
+ closes all top-level windows. Hence, there is \e{no guarantee} that the
+ application will have time to exit its event loop and execute code at the
+ end of the \c{main()} function, after the QApplication::exec() call.
\sa quitOnLastWindowClosed, quit(), exit(), processEvents(),
QCoreApplication::exec()
@@ -3562,20 +3595,18 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QApplicationPrivate::mouse_buttons |= me->button();
else
QApplicationPrivate::mouse_buttons &= ~me->button();
- }
+ }
#if !defined(QT_NO_WHEELEVENT) || !defined(QT_NO_TABLETEVENT)
- else if (
+ else if (false
# ifndef QT_NO_WHEELEVENT
- e->type() == QEvent::Wheel
-# else
- false
+ || e->type() == QEvent::Wheel
# endif
# ifndef QT_NO_TABLETEVENT
- || e->type() == QEvent::TabletMove
- || e->type() == QEvent::TabletPress
- || e->type() == QEvent::TabletRelease
+ || e->type() == QEvent::TabletMove
+ || e->type() == QEvent::TabletPress
+ || e->type() == QEvent::TabletRelease
# endif
- ) {
+ ) {
QInputEvent *ie = static_cast<QInputEvent*>(e);
QApplicationPrivate::modifier_buttons = ie->modifiers();
}
@@ -3709,19 +3740,18 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QPoint relpos = mouse->pos();
if (e->spontaneous()) {
+#ifndef QT_NO_IM
+ QInputContext *ic = w->inputContext();
+ if (ic
+ && w->testAttribute(Qt::WA_InputMethodEnabled)
+ && ic->filterEvent(mouse))
+ return true;
+#endif
if (e->type() == QEvent::MouseButtonPress) {
- QWidget *fw = w;
- while (fw) {
- if (fw->isEnabled()
- && QApplicationPrivate::shouldSetFocus(fw, Qt::ClickFocus)) {
- fw->setFocus(Qt::MouseFocusReason);
- break;
- }
- if (fw->isWindow())
- break;
- fw = fw->parentWidget();
- }
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
+ Qt::ClickFocus,
+ Qt::MouseFocusReason);
}
// ### Qt 5 These dynamic tool tips should be an OPT-IN feature. Some platforms
@@ -3787,7 +3817,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos);
while (w) {
if (w->testAttribute(Qt::WA_Hover) &&
- (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) {
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
QHoverEvent he(QEvent::HoverMove, relpos, relpos - diff);
d->notify_helper(w, &he);
}
@@ -3810,17 +3840,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
bool eventAccepted = wheel->isAccepted();
if (e->spontaneous()) {
- QWidget *fw = w;
- while (fw) {
- if (fw->isEnabled()
- && QApplicationPrivate::shouldSetFocus(fw, Qt::WheelFocus)) {
- fw->setFocus(Qt::MouseFocusReason);
- break;
- }
- if (fw->isWindow())
- break;
- fw = fw->parentWidget();
- }
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
+ Qt::WheelFocus,
+ Qt::MouseFocusReason);
}
while (w) {
@@ -4025,7 +4047,72 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
}
break;
#endif
+ case QEvent::TouchBegin:
+ // Note: TouchUpdate and TouchEnd events are never propagated
+ {
+ QWidget *widget = static_cast<QWidget *>(receiver);
+ QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e);
+ bool eventAccepted = touchEvent->isAccepted();
+ if (widget->testAttribute(Qt::WA_AcceptTouchEvents) && e->spontaneous()) {
+ // give the widget focus if the focus policy allows it
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget,
+ Qt::ClickFocus,
+ Qt::MouseFocusReason);
+ }
+ while (widget) {
+ // first, try to deliver the touch event
+ bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents);
+ touchEvent->setWidget(widget);
+ touchEvent->setAccepted(acceptTouchEvents);
+ res = acceptTouchEvents && d->notify_helper(widget, touchEvent);
+ eventAccepted = touchEvent->isAccepted();
+ widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, res && eventAccepted);
+ touchEvent->spont = false;
+ if (res && eventAccepted) {
+ // the first widget to accept the TouchBegin gets an implicit grab.
+ for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
+ const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i);
+ d->widgetForTouchPointId[touchPoint.id()] = widget;
+ }
+ break;
+ } else if (widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) {
+ break;
+ }
+ widget = widget->parentWidget();
+ d->updateTouchPointsForWidget(widget, touchEvent);
+ }
+
+ touchEvent->setAccepted(eventAccepted);
+ break;
+ }
+ case QEvent::RequestSoftwareInputPanel:
+ case QEvent::CloseSoftwareInputPanel:
+#ifndef QT_NO_IM
+ if (receiver->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ QInputContext *ic = w->inputContext();
+ if (ic && ic->filterEvent(e)) {
+ break;
+ }
+ }
+#endif
+ res = d->notify_helper(receiver, e);
+ break;
+
+ case QEvent::NativeGesture:
+ {
+ // only propagate the first gesture event (after the GID_BEGIN)
+ QWidget *w = static_cast<QWidget *>(receiver);
+ while (w) {
+ e->ignore();
+ res = d->notify_helper(w, e);
+ if ((res && e->isAccepted()) || w->isWindow())
+ break;
+ w = w->parentWidget();
+ }
+ break;
+ }
default:
res = d->notify_helper(receiver, e);
break;
@@ -4043,10 +4130,10 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
if (receiver->isWidgetType()) {
QWidget *widget = static_cast<QWidget *>(receiver);
-#if !defined(Q_OS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
+#if !defined(Q_WS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
// toggle HasMouse widget state on enter and leave
if ((e->type() == QEvent::Enter || e->type() == QEvent::DragEnter) &&
- (!qApp->activePopupWidget() || qApp->activePopupWidget() == widget->window()))
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == widget->window()))
widget->setAttribute(Qt::WA_UnderMouse, true);
else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave)
widget->setAttribute(Qt::WA_UnderMouse, false);
@@ -4072,9 +4159,6 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
\class QSessionManager
\brief The QSessionManager class provides access to the session manager.
- \ingroup application
- \ingroup environment
-
A session manager in a desktop environment (in which Qt GUI applications
live) keeps track of a session, which is a group of running applications,
each of which has a particular state. The state of an application contains
@@ -4373,13 +4457,13 @@ HRESULT qt_CoCreateGuid(GUID* guid)
{
// We will use the following information to create the GUID
// 1. absolute path to application
- wchar_t tempFilename[512];
- if (!GetModuleFileNameW(0, tempFilename, 512))
+ wchar_t tempFilename[MAX_PATH];
+ if (!GetModuleFileName(0, tempFilename, MAX_PATH))
return S_FALSE;
- unsigned int hash = qHash(QString::fromUtf16((const unsigned short *) tempFilename));
+ unsigned int hash = qHash(QString::fromWCharArray(tempFilename));
guid->Data1 = hash;
// 2. creation time of file
- QFileInfo info(QString::fromUtf16((const unsigned short *) tempFilename));
+ QFileInfo info(QString::fromWCharArray(tempFilename));
guid->Data2 = qHash(info.created().toTime_t());
// 3. current system time
guid->Data3 = qHash(QDateTime::currentDateTime().toTime_t());
@@ -4413,10 +4497,10 @@ QSessionManager::QSessionManager(QApplication * app, QString &id, QString &key)
GUID guid;
CoCreateGuid(&guid);
StringFromGUID2(guid, guidstr, 40);
- id = QString::fromUtf16((ushort*)guidstr);
+ id = QString::fromWCharArray(guidstr);
CoCreateGuid(&guid);
StringFromGUID2(guid, guidstr, 40);
- key = QString::fromUtf16((ushort*)guidstr);
+ key = QString::fromWCharArray(guidstr);
#endif
d->sessionId = id;
d->sessionKey = key;
@@ -4576,9 +4660,9 @@ void QSessionManager::requestPhase2()
\oldcode
app.setWinStyleHighlightColor(color);
\newcode
- QPalette palette(qApp->palette());
+ QPalette palette(QApplication::palette());
palette.setColor(QPalette::Highlight, color);
- qApp->setPalette(palette);
+ QApplication::setPalette(palette);
\endcode
*/
@@ -4597,7 +4681,7 @@ void QSessionManager::requestPhase2()
/*!
\fn const QColor &QApplication::winStyleHighlightColor()
- Use qApp->palette().color(QPalette::Active, QPalette::Highlight) instead.
+ Use QApplication::palette().color(QPalette::Active, QPalette::Highlight) instead.
*/
/*!
@@ -4687,7 +4771,7 @@ void QApplicationPrivate::emitLastWindowClosed()
If \a enable is true, Qt::Key_Up and Qt::Key_Down are used to change focus.
- This feature is available in Qt for Embedded Linux only.
+ This feature is available in Qt for Embedded Linux and Symbian only.
\sa keypadNavigationEnabled()
*/
@@ -4698,9 +4782,9 @@ void QApplication::setKeypadNavigationEnabled(bool enable)
/*!
Returns true if Qt is set to use keypad navigation; otherwise returns
- false. The default is false.
+ false. The default value is true on Symbian, but false on other platforms.
- This feature is available in Qt for Embedded Linux only.
+ This feature is available in Qt for Embedded Linux and Symbian only.
\sa setKeypadNavigationEnabled()
*/
@@ -4724,7 +4808,7 @@ bool QApplication::keypadNavigationEnabled()
On Mac OS X, this works more at the application level and will cause the
application icon to bounce in the dock.
- On Windows this causes the window's taskbar entry to flash for a time. If
+ On Windows, this causes the window's taskbar entry to flash for a time. If
\a msec is zero, the flashing will stop and the taskbar entry will turn a
different color (currently orange).
@@ -4741,24 +4825,22 @@ bool QApplication::keypadNavigationEnabled()
caret display. Usually the text cursor is displayed for half the cursor
flash time, then hidden for the same amount of time, but this may vary.
- The default value on X11 is 1000 milliseconds. On Windows, the control
- panel value is used. Widgets should not cache this value since it may be
- changed at any time by the user changing the global desktop settings.
+ The default value on X11 is 1000 milliseconds. On Windows, the
+ \gui{Control Panel} value is used and setting this property sets the cursor
+ flash time for all applications.
- \note On Microsoft Windows, setting this property sets the cursor flash
- time for all applications.
+ We recommend that widgets do not cache this value as it may change at any
+ time if the user changes the global desktop settings.
*/
/*!
\property QApplication::doubleClickInterval
- \brief the time limit in milliseconds that distinguishes a double click from two
- consecutive mouse clicks
-
- The default value on X11 is 400 milliseconds. On Windows and Mac OS X, the
- operating system's value is used.
+ \brief the time limit in milliseconds that distinguishes a double click
+ from two consecutive mouse clicks
- On Microsoft Windows, calling this function sets the double click interval
- for all applications.
+ The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
+ operating system's value is used. However, on Windows and Symbian OS,
+ calling this function sets the double click interval for all applications.
*/
/*!
@@ -4767,7 +4849,7 @@ bool QApplication::keypadNavigationEnabled()
from two consecutive key presses
\since 4.2
- The default value on X11 is 400 milliseconds. On Windows and Mac OS X, the
+ The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
operating system's value is used.
*/
@@ -4832,7 +4914,7 @@ bool QApplication::keypadNavigationEnabled()
You need not have a main widget; connecting lastWindowClosed() to quit()
is an alternative.
- For X11, this function also resizes and moves the main widget according
+ On X11, this function also resizes and moves the main widget according
to the \e -geometry command-line option, so you should set the default
geometry (using \l QWidget::setGeometry()) before calling setMainWidget().
@@ -4861,9 +4943,10 @@ bool QApplication::keypadNavigationEnabled()
Application cursors are stored on an internal stack. setOverrideCursor()
pushes the cursor onto the stack, and restoreOverrideCursor() pops the
active cursor off the stack. changeOverrideCursor() changes the curently
- active application override cursor. Every setOverrideCursor() must
- eventually be followed by a corresponding restoreOverrideCursor(),
- otherwise the stack will never be emptied.
+ active application override cursor.
+
+ Every setOverrideCursor() must eventually be followed by a corresponding
+ restoreOverrideCursor(), otherwise the stack will never be emptied.
Example:
\snippet doc/src/snippets/code/src_gui_kernel_qapplication_x11.cpp 0
@@ -4916,8 +4999,7 @@ void QApplication::setInputContext(QInputContext *inputContext)
qWarning("QApplication::setInputContext: called with 0 input context");
return;
}
- if (d->inputContext)
- delete d->inputContext;
+ delete d->inputContext;
d->inputContext = inputContext;
}
@@ -4941,6 +5023,11 @@ QInputContext *QApplication::inputContext() const
qic = QInputContextFactory::create(QLatin1String("xim"), that);
that->d_func()->inputContext = qic;
}
+#elif defined(Q_WS_S60)
+ if (!d->inputContext) {
+ QApplication *that = const_cast<QApplication *>(this);
+ that->d_func()->inputContext = QInputContextFactory::create(QString::fromLatin1("coefep"), that);
+ }
#endif
return d->inputContext;
}
@@ -4958,6 +5045,8 @@ uint QApplicationPrivate::currentPlatform(){
platform |= KB_Gnome;
if (X11->desktopEnvironment == DE_CDE)
platform |= KB_CDE;
+#elif defined(Q_OS_SYMBIAN)
+ platform = KB_S60;
#endif
return platform;
}
@@ -4992,6 +5081,23 @@ Qt::LayoutDirection QApplication::keyboardInputDirection()
return qt_keymapper_private()->keyboardInputDirection;
}
+void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget,
+ Qt::FocusPolicy focusPolicy,
+ Qt::FocusReason focusReason)
+{
+ QWidget *focusWidget = widget;
+ while (focusWidget) {
+ if (focusWidget->isEnabled()
+ && QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) {
+ focusWidget->setFocus(focusReason);
+ break;
+ }
+ if (focusWidget->isWindow())
+ break;
+ focusWidget = focusWidget->parentWidget();
+ }
+}
+
bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
{
QWidget *f = w;
@@ -5027,19 +5133,19 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
*/
/*! \fn QDecoration* QApplication::qwsSetDecoration(const QString &decoration)
- \overload
+ \overload
- Requests a QDecoration object for \a decoration from the QDecorationFactory.
+ Requests a QDecoration object for \a decoration from the
+ QDecorationFactory.
- The string must be one of the QDecorationFactory::keys(). Keys are
- case insensitive.
+ The string must be one of the QDecorationFactory::keys(). Keys are case
+ insensitive.
- A later call to the QApplication constructor will override the
- requested style when a "-style" option is passed in as a commandline
- parameter.
+ A later call to the QApplication constructor will override the requested
+ style when a "-style" option is passed in as a commandline parameter.
- Returns 0 if an unknown \a decoration is passed, otherwise the QStyle object
- returned is set as the application's GUI style.
+ Returns 0 if an unknown \a decoration is passed, otherwise the QStyle object
+ returned is set as the application's GUI style.
*/
/*!
@@ -5136,6 +5242,211 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
This normally takes some time. Does nothing on other platforms.
*/
+void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
+{
+ for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
+ QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i];
+
+ // preserve the sub-pixel resolution
+ QRectF rect = touchPoint.screenRect();
+ const QPointF screenPos = rect.center();
+ const QPointF delta = screenPos - screenPos.toPoint();
+
+ rect.moveCenter(widget->mapFromGlobal(screenPos.toPoint()) + delta);
+ touchPoint.setRect(rect);
+ touchPoint.setStartPos(widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta);
+ touchPoint.setLastPos(widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta);
+ }
+}
+
+void QApplicationPrivate::initializeMultitouch()
+{
+ widgetForTouchPointId.clear();
+ appCurrentTouchPoints.clear();
+
+ initializeMultitouch_sys();
+}
+
+void QApplicationPrivate::cleanupMultitouch()
+{
+ cleanupMultitouch_sys();
+
+ widgetForTouchPointId.clear();
+ appCurrentTouchPoints.clear();
+}
+
+int QApplicationPrivate::findClosestTouchPointId(const QPointF &screenPos)
+{
+ int closestTouchPointId = -1;
+ qreal closestDistance = qreal(0.);
+ foreach (const QTouchEvent::TouchPoint &touchPoint, appCurrentTouchPoints) {
+ qreal distance = QLineF(screenPos, touchPoint.screenPos()).length();
+ if (closestTouchPointId == -1 || distance < closestDistance) {
+ closestTouchPointId = touchPoint.id();
+ closestDistance = distance;
+ }
+ }
+ return closestTouchPointId;
+}
+
+void QApplicationPrivate::translateRawTouchEvent(QWidget *window,
+ QTouchEvent::DeviceType deviceType,
+ const QList<QTouchEvent::TouchPoint> &touchPoints)
+{
+ QApplicationPrivate *d = self;
+ typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints;
+ QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents;
+
+ for (int i = 0; i < touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint touchPoint = touchPoints.at(i);
+
+ // update state
+ QWidget *widget = 0;
+ switch (touchPoint.state()) {
+ case Qt::TouchPointPressed:
+ {
+ if (deviceType == QTouchEvent::TouchPad) {
+ // on touch-pads, send all touch points to the same widget
+ widget = d->widgetForTouchPointId.isEmpty()
+ ? 0
+ : d->widgetForTouchPointId.constBegin().value();
+ }
+
+ if (!widget) {
+ // determine which widget this event will go to
+ if (!window)
+ window = QApplication::topLevelAt(touchPoint.screenPos().toPoint());
+ if (!window)
+ continue;
+ widget = window->childAt(window->mapFromGlobal(touchPoint.screenPos().toPoint()));
+ if (!widget)
+ widget = window;
+ }
+
+ if (deviceType == QTouchEvent::TouchScreen) {
+ int closestTouchPointId = d->findClosestTouchPointId(touchPoint.screenPos());
+ QWidget *closestWidget = d->widgetForTouchPointId.value(closestTouchPointId);
+ if (closestWidget
+ && (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) {
+ widget = closestWidget;
+ }
+ }
+
+ d->widgetForTouchPointId[touchPoint.id()] = widget;
+ touchPoint.setStartScreenPos(touchPoint.screenPos());
+ touchPoint.setLastScreenPos(touchPoint.screenPos());
+ touchPoint.setStartNormalizedPos(touchPoint.normalizedPos());
+ touchPoint.setLastNormalizedPos(touchPoint.normalizedPos());
+ if (touchPoint.pressure() < qreal(0.))
+ touchPoint.setPressure(qreal(1.));
+ d->appCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
+ break;
+ }
+ case Qt::TouchPointReleased:
+ {
+ widget = d->widgetForTouchPointId.take(touchPoint.id());
+ if (!widget)
+ continue;
+
+ QTouchEvent::TouchPoint previousTouchPoint = d->appCurrentTouchPoints.take(touchPoint.id());
+ touchPoint.setStartScreenPos(previousTouchPoint.startScreenPos());
+ touchPoint.setLastScreenPos(previousTouchPoint.screenPos());
+ touchPoint.setStartNormalizedPos(previousTouchPoint.startNormalizedPos());
+ touchPoint.setLastNormalizedPos(previousTouchPoint.normalizedPos());
+ if (touchPoint.pressure() < qreal(0.))
+ touchPoint.setPressure(qreal(0.));
+ break;
+ }
+ default:
+ widget = d->widgetForTouchPointId.value(touchPoint.id());
+ if (!widget)
+ continue;
+
+ Q_ASSERT(d->appCurrentTouchPoints.contains(touchPoint.id()));
+ QTouchEvent::TouchPoint previousTouchPoint = d->appCurrentTouchPoints.value(touchPoint.id());
+ touchPoint.setStartScreenPos(previousTouchPoint.startScreenPos());
+ touchPoint.setLastScreenPos(previousTouchPoint.screenPos());
+ touchPoint.setStartNormalizedPos(previousTouchPoint.startNormalizedPos());
+ touchPoint.setLastNormalizedPos(previousTouchPoint.normalizedPos());
+ if (touchPoint.pressure() < qreal(0.))
+ touchPoint.setPressure(qreal(1.));
+ d->appCurrentTouchPoints[touchPoint.id()] = touchPoint;
+ break;
+ }
+ Q_ASSERT(widget != 0);
+
+ // make the *scene* functions return the same as the *screen* functions
+ touchPoint.setSceneRect(touchPoint.screenRect());
+ touchPoint.setStartScenePos(touchPoint.startScreenPos());
+ touchPoint.setLastScenePos(touchPoint.lastScreenPos());
+
+ StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[widget];
+ maskAndPoints.first |= touchPoint.state();
+ if (touchPoint.isPrimary())
+ maskAndPoints.first |= Qt::TouchPointPrimary;
+ maskAndPoints.second.append(touchPoint);
+ }
+
+ if (widgetsNeedingEvents.isEmpty())
+ return;
+
+ QHash<QWidget *, StatesAndTouchPoints>::ConstIterator it = widgetsNeedingEvents.constBegin();
+ const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd();
+ for (; it != end; ++it) {
+ QWidget *widget = it.key();
+ if (!QApplicationPrivate::tryModalHelper(widget, 0))
+ continue;
+
+ QEvent::Type eventType;
+ switch (it.value().first & Qt::TouchPointStateMask) {
+ case Qt::TouchPointPressed:
+ eventType = QEvent::TouchBegin;
+ break;
+ case Qt::TouchPointReleased:
+ eventType = QEvent::TouchEnd;
+ break;
+ case Qt::TouchPointStationary:
+ // don't send the event if nothing changed
+ continue;
+ default:
+ eventType = QEvent::TouchUpdate;
+ break;
+ }
+
+ QTouchEvent touchEvent(eventType,
+ deviceType,
+ QApplication::keyboardModifiers(),
+ it.value().first,
+ it.value().second);
+ updateTouchPointsForWidget(widget, &touchEvent);
+
+ switch (touchEvent.type()) {
+ case QEvent::TouchBegin:
+ {
+ // if the TouchBegin handler recurses, we assume that means the event
+ // has been implicitly accepted and continue to send touch events
+ widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
+ (void ) QApplication::sendSpontaneousEvent(widget, &touchEvent);
+ break;
+ }
+ default:
+ if (widget->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent)) {
+ if (touchEvent.type() == QEvent::TouchEnd)
+ widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, false);
+ (void) QApplication::sendSpontaneousEvent(widget, &touchEvent);
+ }
+ break;
+ }
+ }
+}
+
+Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window,
+ QTouchEvent::DeviceType deviceType,
+ const QList<QTouchEvent::TouchPoint> &touchPoints)
+{
+ QApplicationPrivate::translateRawTouchEvent(window, deviceType, touchPoints);
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index 5060d22..92cf0f8 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -61,6 +61,10 @@
QT_BEGIN_HEADER
+#if defined(Q_OS_SYMBIAN)
+class TWsEvent;
+#endif
+
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
@@ -84,6 +88,7 @@ class QApplicationPrivate;
#endif
#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))
+
class Q_GUI_EXPORT QApplication : public QCoreApplication
{
Q_OBJECT
@@ -102,10 +107,10 @@ class Q_GUI_EXPORT QApplication : public QCoreApplication
#ifndef QT_NO_STYLE_STYLESHEET
Q_PROPERTY(QString styleSheet READ styleSheet WRITE setStyleSheet)
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
Q_PROPERTY(int autoMaximizeThreshold READ autoMaximizeThreshold WRITE setAutoMaximizeThreshold)
- Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled)
#endif
+ Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled)
public:
enum Type { Tty, GuiClient, GuiServer };
@@ -223,6 +228,12 @@ public:
virtual int x11ClientMessage(QWidget*, XEvent*, bool passive_only);
int x11ProcessEvent(XEvent*);
#endif
+#if defined(Q_OS_SYMBIAN)
+ int s60ProcessEvent(TWsEvent *event);
+ virtual bool s60EventFilter(TWsEvent *aEvent);
+ void symbianHandleCommand(int command);
+ void symbianResourceChange(int type);
+#endif
#if defined(Q_WS_QWS)
virtual bool qwsEventFilter(QWSEvent *);
int qwsProcessEvent(QWSEvent*);
@@ -239,7 +250,6 @@ public:
void winFocus(QWidget *, bool);
static void winMouseButtonUp();
#endif
-
#ifndef QT_NO_SESSIONMANAGER
// session management
bool isSessionRestored() const;
@@ -281,12 +291,12 @@ public Q_SLOTS:
#ifndef QT_NO_STYLE_STYLESHEET
void setStyleSheet(const QString& sheet);
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void setAutoMaximizeThreshold(const int threshold);
int autoMaximizeThreshold() const;
+#endif
void setAutoSipEnabled(const bool enabled);
bool autoSipEnabled() const;
-#endif
static void closeAllWindows();
static void aboutQt();
@@ -375,13 +385,12 @@ private:
friend class QDirectPainterPrivate;
#endif
-#if defined(Q_WS_WIN)
- friend QApplicationPrivate* getQApplicationPrivateInternal();
-#endif
-
#if defined(Q_WS_MAC) || defined(Q_WS_X11)
Q_PRIVATE_SLOT(d_func(), void _q_alertTimeOut())
#endif
+#if defined(QT_RX71_MULTITOUCH)
+ Q_PRIVATE_SLOT(d_func(), void _q_readRX71MultiTouchEvents())
+#endif
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
index f440b00..ea5efb0 100644
--- a/src/gui/kernel/qapplication_mac.mm
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -154,13 +154,16 @@
#define kThemeBrushAlternatePrimaryHighlightColor -5
#endif
+#define kCMDeviceUnregisteredNotification CFSTR("CMDeviceUnregisteredNotification")
+#define kCMDefaultDeviceNotification CFSTR("CMDefaultDeviceNotification")
+#define kCMDeviceProfilesNotification CFSTR("CMDeviceProfilesNotification")
+#define kCMDefaultDeviceProfileNotification CFSTR("CMDefaultDeviceProfileNotification")
QT_BEGIN_NAMESPACE
//for qt_mac.h
QPaintDevice *qt_mac_safe_pdev = 0;
QList<QMacWindowChangeEvent*> *QMacWindowChangeEvent::change_events = 0;
-extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp
/*****************************************************************************
Internal variables and functions
@@ -523,9 +526,9 @@ void qt_mac_update_os_settings()
for(int i = 0; mac_widget_fonts[i].qt_class; i++) {
QFont fnt = qfontForThemeFont(mac_widget_fonts[i].font_key);
bool set_font = true;
- QHash<QByteArray, QFont> *hash = qt_app_fonts_hash();
+ FontHash *hash = qt_app_fonts_hash();
if (!hash->isEmpty()) {
- QHash<QByteArray, QFont>::const_iterator it
+ FontHash::const_iterator it
= hash->constFind(mac_widget_fonts[i].qt_class);
if (it != hash->constEnd())
set_font = (fnt != *it);
@@ -624,10 +627,9 @@ void QApplicationPrivate::initializeWidgetPaletteHash()
}
bool set_palette = true;
- extern QHash<QByteArray, QPalette> *qt_app_palettes_hash(); //qapplication.cpp
- QHash<QByteArray, QPalette> *phash = qt_app_palettes_hash();
+ PaletteHash *phash = qt_app_palettes_hash();
if (!phash->isEmpty()) {
- QHash<QByteArray, QPalette>::const_iterator it
+ PaletteHash::const_iterator it
= phash->constFind(mac_widget_colors[i].qt_class);
if (it != phash->constEnd())
set_palette = (pal != *it);
@@ -1040,16 +1042,34 @@ void qt_release_app_proc_handler()
#endif
}
+void qt_color_profile_changed(CFNotificationCenterRef, void *, CFStringRef, const void *,
+ CFDictionaryRef)
+{
+ QCoreGraphicsPaintEngine::cleanUpMacColorSpaces();
+}
/* platform specific implementations */
void qt_init(QApplicationPrivate *priv, int)
{
if (qt_is_gui_used) {
CGDisplayRegisterReconfigurationCallback(qt_mac_display_change_callbk, 0);
+ CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
+ CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
+ kCMDeviceUnregisteredNotification, 0,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+ CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
+ kCMDefaultDeviceNotification, 0,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+ CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
+ kCMDeviceProfilesNotification, 0,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+ CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
+ kCMDefaultDeviceProfileNotification, 0,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
ProcessSerialNumber psn;
if (GetCurrentProcess(&psn) == noErr) {
// Jambi needs to transform itself since most people aren't "used"
// to putting things in bundles, but other people may actually not
- // want to tranform the process (running as a helper or somethng)
+ // want to tranform the process (running as a helper or something)
// so don't do that for them. This means checking both LSUIElement
// and LSBackgroundOnly. If you set them both... well, you
// shouldn't do that.
@@ -1196,10 +1216,6 @@ void qt_init(QApplicationPrivate *priv, int)
[qtMenuLoader release];
}
#endif
- if (QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
- extern void qt_mac_set_native_menubar(bool);
- qt_mac_set_native_menubar(false);
- }
// Register for Carbon tablet proximity events on the event monitor target.
// This means that we should receive proximity events even when we aren't the active application.
if (!tablet_proximity_handler) {
@@ -1228,6 +1244,12 @@ void qt_release_apple_event_handler()
void qt_cleanup()
{
CGDisplayRemoveReconfigurationCallback(qt_mac_display_change_callbk, 0);
+ CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
+ CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceUnregisteredNotification, 0);
+ CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceNotification, 0);
+ CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceProfilesNotification, 0);
+ CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceProfileNotification, 0);
+
#ifndef QT_MAC_USE_COCOA
qt_release_app_proc_handler();
if (app_proc_handlerUPP) {
@@ -1355,29 +1377,6 @@ QWidget *QApplication::topLevelAt(const QPoint &p)
#endif
}
-static QWidget *qt_mac_recursive_widgetAt(QWidget *widget, int x, int y)
-{
- if (!widget)
- return 0;
- const QObjectList kids = widget->children();
- for(int i = kids.size()-1; i >= 0; --i) {
- if ( QWidget *kid = qobject_cast<QWidget*>(kids.at(i)) ) {
- if (kid->isVisible() && !kid->isTopLevel() &&
- !kid->testAttribute(Qt::WA_TransparentForMouseEvents)) {
- const int wx=kid->x(), wy=kid->y(),
- wx2=wx+kid->width(), wy2=wy+kid->height();
- if (x >= wx && y >= wy && x < wx2 && y < wy2) {
- const QRegion mask = kid->mask();
- if (!mask.isEmpty() && !mask.contains(QPoint(x-wx, y-wy)))
- continue;
- return qt_mac_recursive_widgetAt(kid, x-wx, y-wy);
- }
- }
- }
- }
- return widget;
-}
-
/*****************************************************************************
Main event loop
*****************************************************************************/
@@ -1410,13 +1409,8 @@ void QApplicationPrivate::enterModal_sys(QWidget *widget)
qt_button_down = 0;
#ifdef QT_MAC_USE_COCOA
- if (!qt_mac_is_macsheet(widget)) {
- // Add a new, empty (null), NSModalSession to the stack.
- // The next time we spin the event dispatcher, it will
- // check the stack, and recurse into a modal session for it:
- QCocoaModalSessionInfo info = {widget, 0};
- QEventDispatcherMacPrivate::cocoaModalSessionStack.push(info);
- }
+ if (!qt_mac_is_macsheet(widget))
+ QEventDispatcherMacPrivate::beginModalSession(widget);
#endif
}
@@ -1442,7 +1436,7 @@ void QApplicationPrivate::leaveModal_sys(QWidget *widget)
}
#ifdef QT_MAC_USE_COCOA
if (!qt_mac_is_macsheet(widget))
- QEventDispatcherMacPrivate::rebuildModalSessionStack(true);
+ QEventDispatcherMacPrivate::endModalSession(widget);
#endif
}
#ifdef DEBUG_MODAL_EVENTS
@@ -1453,21 +1447,6 @@ void QApplicationPrivate::leaveModal_sys(QWidget *widget)
qt_event_request_menubarupdate();
}
-#if defined(QT_MAC_USE_COCOA)
-void QApplicationPrivate::_q_runAppModalWindow()
-{
- if (QEventDispatcherMacPrivate::blockCocoaRequestModal) {
- // Just postpone the event until the event dispatcher tells
- // us (by releasing the block) that it is OK to recurse into
- // a new event loop for our non-execing modal window:
- qApp->postEvent(qApp, new QEvent(QEvent::CocoaRequestModal));
- } else {
- // Recurse into a new event loop for the current app modal window:
- threadData->eventDispatcher->processEvents(QEventLoop::DialogExec);
- }
-}
-#endif
-
QWidget *QApplicationPrivate::tryModalHelper_sys(QWidget *top)
{
#ifndef QT_MAC_USE_COCOA
@@ -1654,15 +1633,6 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
bool inNonClientArea = false;
GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0,
sizeof(where), 0, &where);
- if(ekind == kEventMouseMoved && qt_mac_app_fullscreen &&
- QApplication::desktop()->screenNumber(QPoint(where.h, where.v)) ==
- QApplication::desktop()->primaryScreen()) {
- if(where.v <= 0)
- ShowMenuBar();
- else if(qt_mac_window_at(where.h, where.v, 0) != inMenuBar)
- HideMenuBar();
- }
-
#if defined(DEBUG_MOUSE_MAPS)
const char *edesc = 0;
switch(ekind) {
@@ -1759,7 +1729,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
if(window) {
HIViewRef hiview;
if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) {
- widget = QWidget::find((WId)hiview);;
+ widget = QWidget::find((WId)hiview);
if (widget) {
// Make sure we didn't pass over a widget with a "fake hole" in it.
QWidget *otherWidget = QApplication::widgetAt(where.h, where.v);
@@ -1876,9 +1846,10 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
tablet_button_state = new_tablet_button_state;
QMacTabletHash *tabletHash = qt_mac_tablet_hash();
- if (!tabletHash->contains(tabletPointRec.deviceID)) {
- qWarning("QCocoaView handleTabletEvent: This tablet device is unknown"
- " (received no proximity event for it). Discarding event.");
+ if (!tabletHash->contains(tabletPointRec.deviceID) && t != QEvent::TabletRelease) {
+ // Never discard TabletRelease events as they may be delivered *after* TabletLeaveProximity events
+ qWarning("handleTabletEvent: This tablet device is unknown"
+ " (received no proximity event for it). Discarding event.");
return false;
}
QTabletDeviceData &deviceData = tabletHash->operator[](tabletPointRec.deviceID);
@@ -1920,8 +1891,13 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
tp, rotation, z, modifiers, deviceData.tabletUniqueID);
QApplication::sendSpontaneousEvent(widget, &e);
if (e.isAccepted()) {
+ if (t == QEvent::TabletPress) {
+ qt_button_down = widget;
+ } else if (t == QEvent::TabletRelease) {
+ qt_button_down = 0;
+ }
#if defined(DEBUG_MOUSE_MAPS)
- qDebug("Bail out early due to table acceptance");
+ qDebug("Bail out early due to tablet acceptance");
#endif
break;
}
@@ -2968,4 +2944,9 @@ void onApplicationChangedActivation( bool activated )
#endif
}
+void QApplicationPrivate::initializeMultitouch_sys()
+{ }
+void QApplicationPrivate::cleanupMultitouch_sys()
+{ }
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 9090c35..3b6cd43 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -55,6 +55,7 @@
//
#include "QtGui/qapplication.h"
+#include "QtGui/qevent.h"
#include "QtGui/qfont.h"
#include "QtGui/qcursor.h"
#include "QtGui/qregion.h"
@@ -77,11 +78,10 @@ class QClipboard;
class QGraphicsScene;
class QGraphicsSystem;
class QInputContext;
-class QKeyEvent;
-class QMouseEvent;
class QObject;
-class QWheelEvent;
class QWidget;
+class QGestureManager;
+class QSocketNotifier;
extern bool qt_is_gui_used;
#ifndef QT_NO_CLIPBOARD
@@ -100,6 +100,7 @@ extern QSysInfo::MacVersion qt_macver;
#if defined(Q_WS_QWS)
class QWSManager;
class QDirectPainter;
+struct QWSServerCleaner { ~QWSServerCleaner(); };
#endif
#ifndef QT_NO_TABLET
@@ -158,17 +159,19 @@ inline QPointF QTabletDeviceData::scaleCoord(int coordX, int coordY,
int outOriginY, int outExtentY) const
{
QPointF ret;
+
if (sign(outExtentX) == sign(maxX))
- ret.setX(((coordX - minX) * qAbs(outExtentX) / qAbs(qreal(maxX))) + outOriginX);
+ ret.setX(((coordX - minX) * qAbs(outExtentX) / qAbs(qreal(maxX - minX))) + outOriginX);
else
- ret.setX(((qAbs(maxX) - (coordX - minX)) * qAbs(outExtentX) / qAbs(qreal(maxX)))
+ ret.setX(((qAbs(maxX) - (coordX - minX)) * qAbs(outExtentX) / qAbs(qreal(maxX - minX)))
+ outOriginX);
if (sign(outExtentY) == sign(maxY))
- ret.setY(((coordY - minY) * qAbs(outExtentY) / qAbs(qreal(maxY))) + outOriginY);
+ ret.setY(((coordY - minY) * qAbs(outExtentY) / qAbs(qreal(maxY - minY))) + outOriginY);
else
- ret.setY(((qAbs(maxY) - (coordY - minY)) * qAbs(outExtentY) / qAbs(qreal(maxY)))
+ ret.setY(((qAbs(maxY) - (coordY - minY)) * qAbs(outExtentY) / qAbs(qreal(maxY - minY)))
+ outOriginY);
+
return ret;
}
#endif
@@ -189,6 +192,90 @@ extern "C" {
}
#endif
+#if defined(Q_WS_WIN)
+typedef BOOL (WINAPI *PtrRegisterTouchWindow)(HWND, ULONG);
+typedef BOOL (WINAPI *PtrGetTouchInputInfo)(HANDLE, UINT, PVOID, int);
+typedef BOOL (WINAPI *PtrCloseTouchInputHandle)(HANDLE);
+
+typedef BOOL (WINAPI *PtrGetGestureInfo)(HANDLE, PVOID);
+typedef BOOL (WINAPI *PtrGetGestureExtraArgs)(HANDLE, UINT, PBYTE);
+typedef BOOL (WINAPI *PtrCloseGestureInfoHandle)(HANDLE);
+typedef BOOL (WINAPI *PtrSetGestureConfig)(HWND, DWORD, UINT, PVOID, UINT);
+typedef BOOL (WINAPI *PtrGetGestureConfig)(HWND, DWORD, DWORD, PUINT, PVOID, UINT);
+
+typedef BOOL (WINAPI *PtrBeginPanningFeedback)(HWND);
+typedef BOOL (WINAPI *PtrUpdatePanningFeedback)(HWND, LONG, LONG, BOOL);
+typedef BOOL (WINAPI *PtrEndPanningFeedback)(HWND, BOOL);
+
+#ifndef WM_GESTURE
+# define WM_GESTURE 0x0119
+
+# define GID_BEGIN 1
+# define GID_END 2
+# define GID_ZOOM 3
+# define GID_PAN 4
+# define GID_ROTATE 5
+# define GID_TWOFINGERTAP 6
+# define GID_ROLLOVER 7
+
+typedef struct tagGESTUREINFO
+{
+ UINT cbSize;
+ DWORD dwFlags;
+ DWORD dwID;
+ HWND hwndTarget;
+ POINTS ptsLocation;
+ DWORD dwInstanceID;
+ DWORD dwSequenceID;
+ ULONGLONG ullArguments;
+ UINT cbExtraArgs;
+} GESTUREINFO;
+
+# define GC_PAN 0x00000001
+# define GC_PAN_WITH_SINGLE_FINGER_VERTICALLY 0x00000002
+# define GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY 0x00000004
+
+# define GC_ZOOM 0x00000001
+# define GC_ROTATE 0x00000001
+
+typedef struct tagGESTURECONFIG
+{
+ DWORD dwID;
+ DWORD dwWant;
+ DWORD dwBlock;
+} GESTURECONFIG;
+
+# define GID_ROTATE_ANGLE_FROM_ARGUMENT(arg) ((((double)(arg) / 65535.0) * 4.0 * 3.14159265) - 2.0*3.14159265)
+
+#endif // WM_GESTURE
+
+#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES)
+#undef GID_ZOOM
+#define GID_ZOOM 0xf000
+#undef GID_ROTATE
+#define GID_ROTATE 0xf001
+#undef GID_TWOFINGERTAP
+#define GID_TWOFINGERTAP 0xf002
+#undef GID_ROLLOVER
+#define GID_ROLLOVER 0xf003
+#endif
+
+#endif // Q_WS_WIN
+
+class QPanGesture;
+class QPinchGesture;
+class QSwipeGesture;
+
+struct QStandardGestures
+{
+ QPanGesture *pan;
+ QPinchGesture *pinch;
+ QSwipeGesture *swipe;
+
+ QStandardGestures() : pan(0), pinch(0), swipe(0) { }
+};
+
+
class QScopedLoopLevelCounter
{
QThreadData *threadData;
@@ -200,6 +287,12 @@ public:
{ --threadData->loopLevel; }
};
+typedef QHash<QByteArray, QFont> FontHash;
+FontHash *qt_app_fonts_hash();
+
+typedef QHash<QByteArray, QPalette> PaletteHash;
+PaletteHash *qt_app_palettes_hash();
+
class Q_GUI_EXPORT QApplicationPrivate : public QCoreApplicationPrivate
{
Q_DECLARE_PUBLIC(QApplication)
@@ -209,7 +302,7 @@ public:
#if defined(Q_WS_X11)
#ifndef QT_NO_SETTINGS
- static QString kdeHome();
+ static QString x11_desktop_style();
static bool x11_apply_settings();
#endif
static void reset_instance_pointer();
@@ -219,10 +312,11 @@ public:
#endif
static bool quitOnLastWindowClosed;
static void emitLastWindowClosed();
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
static int autoMaximizeThreshold;
- static bool autoSipEnabled;
#endif
+ static bool autoSipEnabled;
+ static QString desktopStyleKey();
static QGraphicsSystem *graphicsSystem()
#if !defined(Q_WS_QWS)
@@ -233,7 +327,6 @@ public:
void createEventDispatcher();
QString appName() const;
-
static void dispatchEnterLeave(QWidget *enter, QWidget *leave);
//modality
@@ -270,6 +363,7 @@ public:
KB_KDE = 8,
KB_Gnome = 16,
KB_CDE = 32,
+ KB_S60 = 64,
KB_All = 0xffff
};
@@ -358,7 +452,7 @@ public:
#ifdef Q_WS_MAC
static bool native_modal_dialog_active;
#endif
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
static bool inSizeMove;
#endif
@@ -382,6 +476,7 @@ public:
#ifdef Q_WS_QWS
QPointer<QWSManager> last_manager;
+ QWSServerCleaner qwsServerCleaner;
# ifndef QT_NO_DIRECTPAINTER
QMap<WId, QDirectPainter *> *directPainters;
# endif
@@ -392,7 +487,7 @@ public:
static QApplicationPrivate *instance() { return self; }
- static QString *styleOverride;
+ static QString styleOverride;
static int app_compile_version;
@@ -405,12 +500,6 @@ public:
void _q_alertTimeOut();
QHash<QWidget *, QTimer *> alertTimerHash;
#endif
-#if defined(QT_MAC_USE_COCOA)
- void _q_runAppModalWindow();
-#endif
-#if defined(QT_MAC_USE_COCOA)
- void _q_runModalWindow();
-#endif
#ifndef QT_NO_STYLE_STYLESHEET
static QString styleSheet;
#endif
@@ -419,20 +508,90 @@ public:
QEvent::Type type, Qt::MouseButtons buttons,
QWidget *buttonDown, QWidget *alienWidget);
static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget,
- QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver);
+ QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
+ bool spontaneous = true);
+#ifdef Q_OS_SYMBIAN
+ static TUint resolveS60ScanCode(TInt scanCode, TUint keysym);
+#endif
#if defined(Q_WS_WIN) || defined(Q_WS_X11)
void sendSyntheticEnterLeave(QWidget *widget);
#endif
+ QMap<int, QWidget *> widgetForTouchPointId;
+ QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints;
+ static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
+ void initializeMultitouch();
+ void initializeMultitouch_sys();
+ void cleanupMultitouch();
+ void cleanupMultitouch_sys();
+ int findClosestTouchPointId(const QPointF &screenPos);
+ void appendTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
+ void removeTouchPoint(int touchPointId);
+ static void translateRawTouchEvent(QWidget *widget,
+ QTouchEvent::DeviceType deviceType,
+ const QList<QTouchEvent::TouchPoint> &touchPoints);
+
+ typedef QMap<QWidget*, QStandardGestures> WidgetStandardGesturesMap;
+ WidgetStandardGesturesMap widgetGestures;
+
+#if defined(Q_WS_WIN)
+ static PtrRegisterTouchWindow RegisterTouchWindow;
+ static PtrGetTouchInputInfo GetTouchInputInfo;
+ static PtrCloseTouchInputHandle CloseTouchInputHandle;
+
+ QHash<DWORD, int> touchInputIDToTouchPointID;
+ bool translateTouchEvent(const MSG &msg);
+
+ PtrGetGestureInfo GetGestureInfo;
+ PtrGetGestureExtraArgs GetGestureExtraArgs;
+ PtrCloseGestureInfoHandle CloseGestureInfoHandle;
+ PtrSetGestureConfig SetGestureConfig;
+ PtrGetGestureConfig GetGestureConfig;
+ PtrBeginPanningFeedback BeginPanningFeedback;
+ PtrUpdatePanningFeedback UpdatePanningFeedback;
+ PtrEndPanningFeedback EndPanningFeedback;
+ QWidget *gestureWidget;
+#endif
+
+#ifdef QT_RX71_MULTITOUCH
+ bool hasRX71MultiTouch;
+
+ struct RX71TouchPointState {
+ QSocketNotifier *socketNotifier;
+ QTouchEvent::TouchPoint touchPoint;
+
+ int minX, maxX, scaleX;
+ int minY, maxY, scaleY;
+ int minZ, maxZ;
+ };
+ QList<RX71TouchPointState> allRX71TouchPoints;
+
+ bool readRX71MultiTouchEvents(int deviceNumber);
+ void fakeMouseEventFromRX71TouchEvent();
+ void _q_readRX71MultiTouchEvents();
+#endif
+
private:
#ifdef Q_WS_QWS
QMap<const QScreen*, QRect> maxWindowRects;
#endif
+#ifdef Q_OS_SYMBIAN
+ static QHash<TInt, TUint> scanCodeCache;
+#endif
+
static QApplicationPrivate *self;
+
+ static void giveFocusAccordingToFocusPolicy(QWidget *w,
+ Qt::FocusPolicy focusPolicy,
+ Qt::FocusReason focusReason);
static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy);
};
+Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window,
+ QTouchEvent::DeviceType deviceType,
+ const QList<QTouchEvent::TouchPoint> &touchPoints);
+
QT_END_NAMESPACE
#endif // QAPPLICATION_P_H
diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp
index 1cdd1b4..e3bd786 100644
--- a/src/gui/kernel/qapplication_qws.cpp
+++ b/src/gui/kernel/qapplication_qws.cpp
@@ -72,6 +72,7 @@
//#include "qwsregionmanager_qws.h"
#include "qwindowsystem_qws.h"
#include "private/qwindowsystem_p.h"
+#include "qdecorationfactory_qws.h"
#include "qwsdisplay_qws.h"
#include "private/qwsdisplay_qws_p.h"
@@ -101,7 +102,11 @@
#include <locale.h>
#include <errno.h>
#include <fcntl.h>
-#include <sys/time.h>
+#ifdef Q_OS_VXWORKS
+# include <sys/times.h>
+#else
+# include <sys/time.h>
+#endif
#include <sys/stat.h>
#include <sys/types.h>
@@ -118,6 +123,8 @@
#endif
#endif
+QT_BEGIN_NAMESPACE
+
#ifndef QT_NO_DIRECTPAINTER
class QDirectPainter;
extern void qt_directpainter_region(QDirectPainter *dp, const QRegion &alloc, int type);
@@ -157,11 +164,9 @@ int qt_servershmid = -1;
bool qws_overrideCursor = false;
#ifndef QT_NO_QWS_MANAGER
-#include "qdecorationfactory_qws.h"
-QT_BEGIN_NAMESPACE
+extern Q_GUI_EXPORT QWSServer *qwsServer;
-QT_USE_NAMESPACE
static QDecoration *qws_decoration = 0;
#endif
@@ -194,28 +199,35 @@ QString qws_dataDir()
static QString result;
if (!result.isEmpty())
return result;
- QByteArray dataDir = QString(QLatin1String("/tmp/qtembedded-%1")).arg(qws_display_id).toLocal8Bit();
- if (mkdir(dataDir, 0700)) {
+ QByteArray dataDir;
+#ifdef QT_QWS_TEMP_DIR
+ dataDir = QT_QWS_TEMP_DIR;
+#else
+ dataDir = "/tmp";
+#endif
+ dataDir += "/qtembedded-";
+ dataDir += QByteArray::number(qws_display_id);
+ if (QT_MKDIR(dataDir, 0700)) {
if (errno != EEXIST) {
qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData());
}
}
- struct stat buf;
- if (lstat(dataDir, &buf))
+ QT_STATBUF buf;
+ if (QT_LSTAT(dataDir, &buf))
qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData());
if (!S_ISDIR(buf.st_mode))
qFatal("%s is not a directory", dataDir.constData());
-#ifndef Q_OS_INTEGRITY
+#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS)
if (buf.st_uid != getuid())
qFatal("Qt for Embedded Linux data directory is not owned by user %d", getuid());
if ((buf.st_mode & 0677) != 0600)
qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData());
#endif
- dataDir += "/";
+ dataDir += '/';
result = QString::fromLocal8Bit(dataDir);
return result;
@@ -224,7 +236,7 @@ QString qws_dataDir()
// Get the filename of the pipe Qt for Embedded Linux uses for server/client comms
Q_GUI_EXPORT QString qws_qtePipeFilename()
{
- return (qws_dataDir() + QString(QLatin1String(QTE_PIPE)).arg(qws_display_id));
+ return (qws_dataDir() + QString::fromLatin1(QTE_PIPE).arg(qws_display_id));
}
static void setMaxWindowRect(const QRect &rect)
@@ -485,8 +497,13 @@ QList<QWSCommand*> *qt_get_server_queue()
void qt_server_enqueue(const QWSCommand *command)
{
QWSCommand *copy = QWSCommand::factory(command->type);
- copy->copyFrom(command);
- outgoing.append(copy);
+ QT_TRY {
+ copy->copyFrom(command);
+ outgoing.append(copy);
+ } QT_CATCH(...) {
+ delete copy;
+ QT_RETHROW;
+ }
}
QWSDisplay::Data::Data(QObject* parent, bool singleProcess)
@@ -662,7 +679,7 @@ void QWSDisplay::Data::sendSynchronousCommand(QWSCommand & cmd)
int QWSDisplay::Data::takeId()
{
int unusedIdCount = unused_identifiers.count();
- if (unusedIdCount == 10)
+ if (unusedIdCount <= 10)
create(15);
if (unusedIdCount == 0) {
create(1); // Make sure we have an incoming id to wait for, just in case we're recursive
@@ -2015,8 +2032,8 @@ bool QApplicationPrivate::qws_apply_settings()
// read new QStyle
QString stylename = settings.value(QLatin1String("style")).toString();
if (QCoreApplication::startingUp()) {
- if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride)
- QApplicationPrivate::styleOverride = new QString(stylename);
+ if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull())
+ QApplicationPrivate::styleOverride = stylename;
} else {
QApplication::setStyle(stylename);
}
@@ -2284,7 +2301,8 @@ void qt_init(QApplicationPrivate *priv, int type)
qt_appType = QApplication::Type(type);
qws_single_process = true;
QWSServer::startup(flags);
- setenv("QWS_DISPLAY", qws_display_spec.constData(), 0);
+ if (!display) // if not already set
+ qputenv("QWS_DISPLAY", qws_display_spec);
}
if(qt_is_gui_used) {
@@ -2299,7 +2317,7 @@ void qt_init(QApplicationPrivate *priv, int type)
qws_decoration = QApplication::qwsSetDecoration(decoration);
#endif // QT_NO_QWS_MANAGER
#ifndef QT_NO_QWS_INPUTMETHODS
- qApp->setInputContext(new QWSInputContext);
+ qApp->setInputContext(new QWSInputContext(qApp));
#endif
}
@@ -2352,7 +2370,7 @@ void qt_cleanup()
QString QApplicationPrivate::appName() const // get application name
{
- return ::appName;
+ return QT_PREPEND_NAMESPACE(appName);
}
/*****************************************************************************
@@ -3546,10 +3564,10 @@ bool QETWidget::translateKeyEvent(const QWSKeyEvent *event, bool grab) /* grab i
#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
if (type == QEvent::KeyPress && !grab
- && static_cast<QApplicationPrivate*>(qApp->d_ptr)->use_compat()) {
+ && static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->use_compat()) {
// send accel events if the keyboard is not grabbed
QKeyEvent a(type, code, state, text, autor, int(text.length()));
- if (static_cast<QApplicationPrivate*>(qApp->d_ptr)->qt_tryAccelEvent(this, &a))
+ if (static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->qt_tryAccelEvent(this, &a))
return true;
}
#else
@@ -3749,4 +3767,19 @@ void QApplication::setArgs(int c, char **v)
d->argv = v;
}
+void QApplicationPrivate::initializeMultitouch_sys()
+{ }
+void QApplicationPrivate::cleanupMultitouch_sys()
+{ }
+
+/* \internal
+ This is used to clean up the qws server
+ in case the QApplication constructor threw an exception
+*/
+QWSServerCleaner::~QWSServerCleaner()
+{
+ if (qwsServer && qws_single_process)
+ QWSServer::closedown();
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
new file mode 100644
index 0000000..14ed48d
--- /dev/null
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -0,0 +1,1212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication_p.h"
+#include "qsessionmanager.h"
+#include "qevent.h"
+#include "qeventdispatcher_s60_p.h"
+#include "qwidget.h"
+#include "qdesktopwidget.h"
+#include "private/qbackingstore_p.h"
+#include "qt_s60_p.h"
+#include "private/qevent_p.h"
+#include "qstring.h"
+#include "qdebug.h"
+#include "qimage.h"
+#include "private/qkeymapper_p.h"
+#include "private/qfont_p.h"
+#ifndef QT_NO_STYLE_S60
+#include "private/qs60style_p.h"
+#endif
+#include "private/qwindowsurface_s60_p.h"
+#include "qpaintengine.h"
+#include "private/qmenubar_p.h"
+
+#include "apgwgnam.h" // For CApaWindowGroupName
+#include <MdaAudioTonePlayer.h> // For CMdaAudioToneUtility
+
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+#include "qinputcontext.h"
+#include <private/qcoefepinputcontext_p.h>
+#endif // !defined(QT_NO_IM) && defined(Q_WS_S60)
+
+#include "private/qstylesheetstyle_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_DEBUG)
+static bool appNoGrab = false; // Grabbing enabled
+#endif
+static bool app_do_modal = false; // modal mode
+Q_GLOBAL_STATIC(QS60Data, qt_s60Data);
+
+extern bool qt_sendSpontaneousEvent(QObject*,QEvent*);
+extern QWidgetList *qt_modal_stack; // stack of modal widgets
+extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
+
+QWidget *qt_button_down = 0; // widget got last button-down
+
+QS60Data* qGlobalS60Data()
+{
+ return qt_s60Data();
+}
+
+bool qt_nograb() // application no-grab option
+{
+#if defined(QT_DEBUG)
+ return appNoGrab;
+#else
+ return false;
+#endif
+}
+
+// Modified from http://www3.symbian.com/faq.nsf/0/0F1464EE96E737E780256D5E00503DD1?OpenDocument
+class QS60Beep : public CBase, public MMdaAudioToneObserver
+{
+public:
+ static QS60Beep* NewL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration);
+ void Play();
+ ~QS60Beep();
+private:
+ void ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration);
+ void MatoPrepareComplete(TInt aError);
+ void MatoPlayComplete(TInt aError);
+private:
+ typedef enum
+ {
+ EBeepNotPrepared,
+ EBeepPrepared,
+ EBeepPlaying
+ } TBeepState;
+private:
+ CMdaAudioToneUtility* iToneUtil;
+ TBeepState iState;
+ TInt iFrequency;
+ TTimeIntervalMicroSeconds iDuration;
+};
+
+QS60Beep::~QS60Beep()
+{
+ delete iToneUtil;
+}
+
+QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
+{
+ QS60Beep* self=new (ELeave) QS60Beep();
+ CleanupStack::PushL(self);
+ self->ConstructL(aFrequency, aDuration);
+ CleanupStack::Pop();
+ return self;
+};
+
+void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
+{
+ iToneUtil=CMdaAudioToneUtility::NewL(*this);
+ iState=EBeepNotPrepared;
+ iFrequency=aFrequency;
+ iDuration=aDuration;
+ iToneUtil->PrepareToPlayTone(iFrequency,iDuration);
+}
+
+void QS60Beep::Play()
+{
+ if(iState!=EBeepNotPrepared){
+ if(iState==EBeepPlaying) {
+ iToneUtil->CancelPlay();
+ iState=EBeepPrepared;
+ }
+ }
+
+ iToneUtil->Play();
+ iState=EBeepPlaying;
+}
+
+void QS60Beep::MatoPrepareComplete(TInt aError)
+{
+ if(aError==KErrNone) {
+ iState=EBeepPrepared;
+ }
+}
+
+void QS60Beep::MatoPlayComplete(TInt aError)
+{
+ Q_UNUSED(aError);
+ iState=EBeepPrepared;
+}
+
+
+QHash<TInt, TUint> QApplicationPrivate::scanCodeCache;
+
+static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers)
+{
+ Qt::KeyboardModifiers result = Qt::NoModifier;
+
+ if (s60Modifiers & EModifierKeypad)
+ result |= Qt::KeypadModifier;
+ if (s60Modifiers & EModifierShift || s60Modifiers & EModifierLeftShift
+ || s60Modifiers & EModifierRightShift)
+ result |= Qt::ShiftModifier;
+ if (s60Modifiers & EModifierCtrl || s60Modifiers & EModifierLeftCtrl
+ || s60Modifiers & EModifierRightCtrl)
+ result |= Qt::ControlModifier;
+ if (s60Modifiers & EModifierAlt || s60Modifiers & EModifierLeftAlt
+ || s60Modifiers & EModifierRightAlt)
+ result |= Qt::AltModifier;
+
+ return result;
+}
+
+static void mapS60MouseEventTypeToQt(QEvent::Type *type, Qt::MouseButton *button, const TPointerEvent *pEvent)
+{
+ switch (pEvent->iType) {
+ case TPointerEvent::EButton1Down:
+ *type = QEvent::MouseButtonPress;
+ *button = Qt::LeftButton;
+ break;
+ case TPointerEvent::EButton1Up:
+ *type = QEvent::MouseButtonRelease;
+ *button = Qt::LeftButton;
+ break;
+ case TPointerEvent::EButton2Down:
+ *type = QEvent::MouseButtonPress;
+ *button = Qt::MidButton;
+ break;
+ case TPointerEvent::EButton2Up:
+ *type = QEvent::MouseButtonRelease;
+ *button = Qt::MidButton;
+ break;
+ case TPointerEvent::EButton3Down:
+ *type = QEvent::MouseButtonPress;
+ *button = Qt::RightButton;
+ break;
+ case TPointerEvent::EButton3Up:
+ *type = QEvent::MouseButtonRelease;
+ *button = Qt::RightButton;
+ break;
+ case TPointerEvent::EDrag:
+ *type = QEvent::MouseMove;
+ *button = Qt::NoButton;
+ break;
+ case TPointerEvent::EMove:
+ // Qt makes no distinction between move and drag
+ *type = QEvent::MouseMove;
+ *button = Qt::NoButton;
+ break;
+ default:
+ *type = QEvent::None;
+ *button = Qt::NoButton;
+ break;
+ }
+ if (pEvent->iModifiers & EModifierDoubleClick){
+ *type = QEvent::MouseButtonDblClick;
+ }
+
+ if (*type == QEvent::MouseButtonPress || *type == QEvent::MouseButtonDblClick)
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | (*button);
+ else if (*type == QEvent::MouseButtonRelease)
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~(*button));
+
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & Qt::MouseButtonMask;
+}
+
+//### Can be replaced with CAknLongTapDetector if animation is required.
+//NOTE: if CAknLongTapDetector is used make sure it gets variated out of 3.1 and 3.2,.
+//also MLongTapObserver needs to be changed to MAknLongTapDetectorCallBack if CAknLongTapDetector is used.
+class QLongTapTimer : public CTimer
+{
+public:
+ static QLongTapTimer* NewL(QAbstractLongTapObserver *observer);
+ QLongTapTimer(QAbstractLongTapObserver *observer);
+ void ConstructL();
+public:
+ void PointerEventL(const TPointerEvent &event);
+ void RunL();
+protected:
+private:
+ QAbstractLongTapObserver *m_observer;
+ TPointerEvent m_event;
+ QPoint m_pressedCoordinates;
+ int m_dragDistance;
+};
+
+QLongTapTimer* QLongTapTimer::NewL(QAbstractLongTapObserver *observer)
+{
+ QLongTapTimer* self = new QLongTapTimer(observer);
+ self->ConstructL();
+ return self;
+}
+void QLongTapTimer::ConstructL()
+{
+ CTimer::ConstructL();
+}
+
+QLongTapTimer::QLongTapTimer(QAbstractLongTapObserver *observer):CTimer(CActive::EPriorityHigh)
+{
+ m_observer = observer;
+ m_dragDistance = qApp->startDragDistance();
+ CActiveScheduler::Add(this);
+}
+
+void QLongTapTimer::PointerEventL(const TPointerEvent& event)
+{
+ if ( event.iType == TPointerEvent::EDrag || event.iType == TPointerEvent::EButtonRepeat)
+ {
+ QPoint diff(QPoint(event.iPosition.iX,event.iPosition.iY) - m_pressedCoordinates);
+ if (diff.manhattanLength() < m_dragDistance)
+ return;
+ }
+ Cancel();
+ m_event = event;
+ if (event.iType == TPointerEvent::EButton1Down)
+ {
+ m_pressedCoordinates = QPoint(event.iPosition.iX,event.iPosition.iY);
+ // must be same as KLongTapDelay in aknlongtapdetector.h
+ After(800000);
+ }
+}
+void QLongTapTimer::RunL()
+{
+ if (m_observer)
+ m_observer->HandleLongTapEventL(m_event.iPosition, m_event.iParentPosition);
+}
+
+QSymbianControl::QSymbianControl(QWidget *w)
+ : CCoeControl(), qwidget(w), m_ignoreFocusChanged(false)
+{
+}
+
+void QSymbianControl::ConstructL(bool topLevel, bool desktop)
+{
+ if (!desktop)
+ {
+ if (topLevel)
+ CreateWindowL(S60->windowGroup());
+
+ SetFocusing(true);
+ m_longTapDetector = QLongTapTimer::NewL(this);
+ }
+}
+
+QSymbianControl::~QSymbianControl()
+{
+ S60->appUi()->RemoveFromStack(this);
+ delete m_longTapDetector;
+}
+
+void QSymbianControl::setWidget(QWidget *w)
+{
+ qwidget = w;
+}
+void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation )
+{
+ QWidget *alienWidget;
+ QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY);
+ QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY);
+ alienWidget = qwidget->childAt(widgetPos);
+ if (!alienWidget)
+ alienWidget = qwidget;
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~Qt::LeftButton);
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | Qt::RightButton;
+ QMouseEvent mEvent(QEvent::MouseButtonPress, alienWidget->mapFrom(qwidget, widgetPos), globalPos,
+ Qt::RightButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier);
+
+ bool res = sendMouseEvent(alienWidget, &mEvent);
+
+#if !defined(QT_NO_CONTEXTMENU)
+ QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, mEvent.modifiers());
+ qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent);
+#endif
+
+ m_previousEventLongTap = true;
+}
+
+void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent)
+{
+ m_longTapDetector->PointerEventL(pEvent);
+ QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent));
+}
+
+void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
+{
+ //### refactor me, getting too complex
+ QMouseEvent::Type type;
+ Qt::MouseButton button;
+ mapS60MouseEventTypeToQt(&type, &button, &pEvent);
+
+ if (m_previousEventLongTap)
+ if (type == QEvent::MouseButtonRelease){
+ button = Qt::RightButton;
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton;
+ m_previousEventLongTap = false;
+ }
+ if (type == QMouseEvent::None)
+ return;
+
+ // store events for later sending/saving
+ QWidget *alienWidget;
+ typedef QPair<QWidget*,QMouseEvent> Event;
+ QList<Event > events;
+
+ QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY);
+ TPoint controlScreenPos = PositionRelativeToScreen();
+ QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos;
+
+ if (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick)
+ {
+ // get the button press target
+ alienWidget = qwidget->childAt(widgetPos);
+ if (!alienWidget)
+ alienWidget = qwidget;
+ S60->mousePressTarget = alienWidget;
+ //pointer grab
+ SetGloballyCapturing(ETrue);
+ SetPointerCapture(ETrue);
+ }
+ else if (type == QEvent::MouseButtonRelease)
+ {
+ //release pointer grab
+ SetGloballyCapturing(EFalse);
+ SetPointerCapture(EFalse);
+ }
+ alienWidget = S60->mousePressTarget;
+
+ if (alienWidget != S60->lastPointerEventTarget)
+ if (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove)
+ {
+ //moved to another widget, create enter and leave events
+ if (S60->lastPointerEventTarget)
+ {
+ QMouseEvent mEventLeave(QEvent::Leave, S60->lastPointerEventTarget->mapFromGlobal(S60->lastCursorPos), S60->lastCursorPos,
+ button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers));
+ events.append(Event(S60->lastPointerEventTarget,mEventLeave));
+ }
+ QMouseEvent mEventEnter(QEvent::Enter, alienWidget->mapFromGlobal(globalPos), globalPos,
+ button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers));
+
+ events.append(Event(alienWidget,mEventEnter));
+ }
+ S60->lastCursorPos = globalPos;
+ S60->lastPointerEventPos = widgetPos;
+ S60->lastPointerEventTarget = alienWidget;
+ if (alienWidget)
+ {
+ QMouseEvent mEvent(type, alienWidget->mapFromGlobal(globalPos), globalPos,
+ button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers));
+ events.append(Event(alienWidget,mEvent));
+ QEventDispatcherS60 *dispatcher;
+ // It is theoretically possible for someone to install a different event dispatcher.
+ if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(alienWidget->d_func()->threadData->eventDispatcher)) != 0) {
+ if (dispatcher->excludeUserInputEvents()) {
+ for (int i=0;i < events.count();++i)
+ {
+ Event next = events[i];
+ dispatcher->saveInputEvent(this, next.first, new QMouseEvent(next.second));
+ }
+ return;
+ }
+ }
+ }
+ for (int i=0;i < events.count();++i)
+ {
+ Event next = events[i];
+ sendMouseEvent(next.first, &(next.second));
+ }
+}
+
+bool QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent)
+{
+ return qt_sendSpontaneousEvent(widget, mEvent);
+}
+
+TKeyResponse QSymbianControl::OfferKeyEventL(const TKeyEvent& keyEvent, TEventCode type)
+{
+ TKeyResponse r = EKeyWasNotConsumed;
+ QT_TRYCATCH_LEAVING(r = OfferKeyEvent(keyEvent, type));
+ return r;
+}
+
+TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type)
+{
+ switch (type) {
+ //case EEventKeyDown: // <-- Intentionally left out. See below.
+ case EEventKeyUp:
+ case EEventKey:
+ {
+ // S60 has a confusing way of delivering key events. There are three types of
+ // events: EKeyEvent, EKeyEventDown and EKeyEventUp. When a key is pressed, the
+ // two first events are generated. When releasing the key, the last one is
+ // generated.
+ // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp events,
+ // we need to do some special tricks to map it to the Qt way. First, we completely
+ // discard EKeyEventDown events, since they are redundant. Second, since
+ // EKeyEventUp does not give us a keysym, we need to cache the keysyms from
+ // the EKeyEvent events. This is what resolveS60ScanCode does.
+
+
+ // ### hackish way to send Qt application to background when pressing right softkey
+ /*
+ if( keyEvent.iScanCode == EStdKeyDevice1 ) {
+ S60->window_group->SetOrdinalPosition(-1);
+ qApp->setActiveWindow(0);
+ return EKeyWasNotConsumed;
+ }
+ */
+
+ TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode,
+ keyEvent.iCode);
+ int keyCode;
+ if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) {
+ // Normal characters keys.
+ keyCode = s60Keysym;
+ } else {
+ // Special S60 keys.
+ keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym);
+ }
+ Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
+ QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
+ mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
+ false, 1, keyEvent.iScanCode, s60Keysym, mods);
+// WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
+// if (!wid)
+// Could happen if window isn't shown yet.
+// return EKeyWasNotConsumed;
+ QWidget *widget;
+ widget = QWidget::keyboardGrabber();
+ if (!widget) {
+ if (QApplicationPrivate::popupWidgets != 0) {
+ widget = QApplication::activePopupWidget()->focusWidget();
+ if (!widget) {
+ widget = QApplication::activePopupWidget();
+ }
+ } else {
+ widget = QApplicationPrivate::focus_widget;
+ if (!widget) {
+ widget = qwidget;
+ }
+ }
+ }
+
+ QEventDispatcherS60 *dispatcher;
+ // It is theoretically possible for someone to install a different event dispatcher.
+ if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) {
+ if (dispatcher->excludeUserInputEvents()) {
+ dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent));
+ return EKeyWasConsumed;
+ }
+ }
+ return sendKeyEvent(widget, &qKeyEvent);
+ }
+ }
+ return EKeyWasNotConsumed;
+}
+
+void QSymbianControl::sendInputEvent(QWidget *widget, QInputEvent *inputEvent)
+{
+ switch (inputEvent->type()) {
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ sendKeyEvent(widget, static_cast<QKeyEvent *>(inputEvent));
+ break;
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ sendMouseEvent(widget, static_cast<QMouseEvent *>(inputEvent));
+ break;
+ default:
+ // Shouldn't get here.
+ Q_ASSERT_X(0 == 1, "QSymbianControl::sendInputEvent()", "inputEvent->type() is unknown");
+ break;
+ }
+}
+
+TKeyResponse QSymbianControl::sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent)
+{
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+ if (widget && widget->isEnabled() && widget->testAttribute(Qt::WA_InputMethodEnabled)) {
+ QInputContext *qic = widget->inputContext();
+ if(qic && qic->filterEvent(keyEvent))
+ return EKeyWasConsumed;
+ }
+#endif // !defined(QT_NO_IM) && defined(Q_WS_S60)
+
+ if (widget && qt_sendSpontaneousEvent(widget, keyEvent))
+ if (keyEvent->isAccepted())
+ return EKeyWasConsumed;
+
+ return EKeyWasNotConsumed;
+}
+
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+TCoeInputCapabilities QSymbianControl::InputCapabilities() const
+{
+ QWidget *w = 0;
+
+ if(qwidget->hasFocus()) {
+ w = qwidget;
+ } else {
+ w = qwidget->focusWidget();
+ }
+
+ QCoeFepInputContext *ic;
+ if (w && w->isEnabled() && w->testAttribute(Qt::WA_InputMethodEnabled)
+ && (ic = qobject_cast<QCoeFepInputContext *>(w->inputContext()))) {
+ return ic->inputCapabilities();
+ } else {
+ return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0);
+ }
+}
+#endif
+
+void QSymbianControl::Draw(const TRect& r) const
+{
+ QWindowSurface *surface = qwidget->windowSurface();
+ if (!surface)
+ return;
+
+ QPaintEngine *engine = surface->paintDevice()->paintEngine();
+ if (!engine)
+ return;
+ if (engine->type() == QPaintEngine::Raster) {
+ QS60WindowSurface *s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
+ CFbsBitmap *bitmap = s60Surface->symbianBitmap();
+ CWindowGc &gc = SystemGc();
+ if (qwidget->d_func()->isOpaque)
+ gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
+ gc.BitBlt(r.iTl, bitmap, r);
+ } else {
+ surface->flush(qwidget, QRegion(qt_TRect2QRect(r)), QPoint());
+ }
+}
+
+void QSymbianControl::SizeChanged()
+{
+ CCoeControl::SizeChanged();
+
+ QSize oldSize = qwidget->size();
+ QSize newSize(Size().iWidth, Size().iHeight);
+
+ if (oldSize != newSize) {
+ QRect cr = qwidget->geometry();
+ cr.setSize(newSize);
+ qwidget->data->crect = cr;
+ if (qwidget->isVisible()) {
+ QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData();
+ bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+ if (!slowResize && tlwExtra)
+ tlwExtra->inTopLevelResize = true;
+ QResizeEvent e(newSize, oldSize);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ if (!qwidget->testAttribute(Qt::WA_StaticContents))
+ qwidget->d_func()->syncBackingStore();
+ if (!slowResize && tlwExtra)
+ tlwExtra->inTopLevelResize = false;
+ }
+ }
+}
+
+void QSymbianControl::PositionChanged()
+{
+ CCoeControl::PositionChanged();
+
+ QPoint oldPos = qwidget->geometry().topLeft();
+ QPoint newPos(Position().iX, Position().iY);
+
+ if (oldPos != newPos) {
+ QRect cr = qwidget->geometry();
+ cr.moveTopLeft(newPos);
+ qwidget->data->crect = cr;
+ QTLWExtra *top = qwidget->d_func()->maybeTopData();
+ if (top)
+ top->normalGeometry = cr;
+ if (qwidget->isVisible()) {
+ QMoveEvent e(newPos, oldPos);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ } else {
+ QMoveEvent * e = new QMoveEvent(newPos, oldPos);
+ QApplication::postEvent(qwidget, e);
+ }
+ }
+}
+
+void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
+{
+ if (m_ignoreFocusChanged)
+ return;
+
+ // Popups never get focused, but still receive the FocusChanged when they are hidden.
+ if (QApplicationPrivate::popupWidgets != 0
+ || (qwidget->windowType() & Qt::Popup) == Qt::Popup)
+ return;
+
+ QEvent *deferredFocusEvent = new QEvent(QEvent::SymbianDeferredFocusChanged);
+ QApplication::postEvent(qwidget, deferredFocusEvent);
+}
+
+void QSymbianControl::HandleResourceChange(int resourceType)
+{
+ switch (resourceType) {
+ case KInternalStatusPaneChange:
+ qwidget->d_func()->setWindowIcon_sys(true);
+ break;
+ case KUidValueCoeFontChangeEvent:
+ // font change event
+ break;
+#ifdef Q_WS_S60
+ case KEikDynamicLayoutVariantSwitch:
+ {
+ if (qwidget->isFullScreen()) {
+ SetExtentToWholeScreen();
+ } else if (qwidget->isMaximized()) {
+ TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ SetExtent(r.iTl, r.Size());
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ CCoeControl::HandleResourceChange(resourceType);
+
+}
+void QSymbianControl::CancelLongTapTimer()
+{
+ m_longTapDetector->Cancel();
+}
+
+TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id)
+{
+ if (id.iUid == ETypeId)
+ return id.MakePtr(this);
+
+ return CCoeControl::MopSupplyObject(id);
+}
+
+void qt_init(QApplicationPrivate * /* priv */, int)
+{
+#ifdef QT_NO_DEBUG
+ if (!qgetenv("QT_S60_AUTO_FLUSH_WSERV").isEmpty())
+#endif
+ S60->wsSession().SetAutoFlush(ETrue);
+
+ S60->updateScreenSize();
+
+
+ TDisplayMode mode = S60->screenDevice()->DisplayMode();
+ S60->screenDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode);
+
+ RProcess me;
+ TSecureId securId = me.SecureId();
+ S60->uid = securId.operator TUid();
+
+/*
+ ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag
+ int argc = priv->argc;
+ char **argv = priv->argv;
+
+ // Get command line params
+ int j = argc ? 1 : 0;
+ for (int i=1; i<argc; i++) {
+ if (argv[i] && *argv[i] != '-') {
+ argv[j++] = argv[i];
+ continue;
+ }
+
+#if defined(QT_DEBUG)
+ if (qstrcmp(argv[i], "-nograb") == 0)
+ appNoGrab = !appNoGrab;
+ else
+#endif // QT_DEBUG
+ ;
+ }
+*/
+}
+
+/*****************************************************************************
+ qt_cleanup() - cleans up when the application is finished
+ *****************************************************************************/
+void qt_cleanup()
+{
+ QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles
+// S60 structure and window server session are freed in eventdispatcher destructor as they are needed there
+
+ // It's important that this happens here, before the event dispatcher gets
+ // deleted, because the input context needs the event loop one last time before
+ // it dies.
+ delete QApplicationPrivate::inputContext;
+ QApplicationPrivate::inputContext = 0;
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+ // TODO: Implement QApplicationPrivate::initializeWidgetPaletteHash()
+ // Possibly a task fot the S60Style guys
+}
+
+void QApplicationPrivate::createEventDispatcher()
+{
+ Q_Q(QApplication);
+ eventDispatcher = new QEventDispatcherS60(q);
+}
+
+QString QApplicationPrivate::appName() const
+{
+ return QCoreApplicationPrivate::appName();
+}
+
+bool QApplicationPrivate::modalState()
+{
+ return app_do_modal;
+}
+
+void QApplicationPrivate::enterModal_sys(QWidget *widget)
+{
+ if (!qt_modal_stack)
+ qt_modal_stack = new QWidgetList;
+ qt_modal_stack->insert(0, widget);
+ app_do_modal = true;
+}
+
+void QApplicationPrivate::leaveModal_sys(QWidget *widget)
+{
+ if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
+ if (qt_modal_stack->isEmpty()) {
+ delete qt_modal_stack;
+ qt_modal_stack = 0;
+ }
+ }
+ app_do_modal = qt_modal_stack != 0;
+}
+
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ if (!QApplicationPrivate::popupWidgets)
+ QApplicationPrivate::popupWidgets = new QWidgetList;
+ QApplicationPrivate::popupWidgets->append(popup);
+
+ if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()) {
+ Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
+ WId id = popup->effectiveWinId();
+ id->SetPointerCapture(true);
+ id->SetGloballyCapturing(true);
+ }
+
+ // popups are not focus-handled by the window system (the first
+ // popup grabbed the keyboard), so we have to do that manually: A
+ // new popup gets the focus
+ if (QApplication::focusWidget())
+ static_cast<QSymbianControl*>(QApplication::focusWidget()->effectiveWinId())->CancelLongTapTimer();
+ QWidget *fw = popup->focusWidget();
+ if (fw) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
+ fw = QApplication::focusWidget();
+ if (fw) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ q_func()->sendEvent(fw, &e);
+ }
+ }
+}
+
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ if (!QApplicationPrivate::popupWidgets)
+ return;
+ QApplicationPrivate::popupWidgets->removeAll(popup);
+
+ if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup
+ delete QApplicationPrivate::popupWidgets;
+ QApplicationPrivate::popupWidgets = 0;
+ if (!qt_nograb()) { // grabbing not disabled
+ Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
+ WId id = popup->effectiveWinId();
+ id->SetPointerCapture(false);
+ id->SetGloballyCapturing(false);
+ if (QWidgetPrivate::mouseGrabber != 0)
+ QWidgetPrivate::mouseGrabber->grabMouse();
+
+ if (QWidgetPrivate::keyboardGrabber != 0)
+ QWidgetPrivate::keyboardGrabber->grabKeyboard();
+
+ QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget()
+ : q_func()->focusWidget();
+ if (fw) {
+ if (fw != q_func()->focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ q_func()->sendEvent(fw, &e);
+ }
+ }
+ }
+ } else {
+ // popups are not focus-handled by the window system (the
+ // first popup grabbed the keyboard), so we have to do that
+ // manually: A popup was closed, so the previous popup gets
+ // the focus.
+ QWidget* aw = QApplicationPrivate::popupWidgets->last();
+ if (QWidget *fw = QApplication::focusWidget()) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ q_func()->sendEvent(fw, &e);
+ }
+ }
+}
+
+QWidget * QApplication::topLevelAt(QPoint const& point)
+{
+ QWidget *found = 0;
+ int lowestZ = INT_MAX;
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = 0; i < list.count(); ++i) {
+ QWidget *widget = list.at(i);
+ if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) {
+ Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
+ if (widget->geometry().adjusted(0,0,1,1).contains(point)) {
+ // At this point we know there is a Qt widget under the point.
+ // Now we need to make sure it is the top most in the z-order.
+ RDrawableWindow* rw = widget->d_func()->topData()->rwindow;
+ int z = rw->OrdinalPosition();
+ if (z < lowestZ) {
+ lowestZ = z;
+ found = widget;
+ }
+ }
+ }
+ }
+ return found;
+}
+
+void QApplication::alert(QWidget * /* widget */, int /* duration */)
+{
+ // TODO: Implement QApplication::alert(QWidget *widget, int duration)
+}
+
+int QApplication::doubleClickInterval()
+{
+ TTimeIntervalMicroSeconds32 us;
+ TInt distance;
+ S60->wsSession().GetDoubleClickSettings(us, distance);
+ return (us.Int() / 1000);
+}
+
+void QApplication::setDoubleClickInterval(int ms)
+{
+ TTimeIntervalMicroSeconds32 newUs( ms * 1000);
+ TTimeIntervalMicroSeconds32 us;
+ TInt distance;
+ S60->wsSession().GetDoubleClickSettings(us, distance);
+ if (us != newUs)
+ S60->wsSession().SetDoubleClick(newUs, distance);
+}
+
+int QApplication::keyboardInputInterval()
+{
+ return QApplicationPrivate::keyboard_input_time;
+}
+
+void QApplication::setKeyboardInputInterval(int ms)
+{
+ QApplicationPrivate::keyboard_input_time = ms;
+}
+
+int QApplication::cursorFlashTime()
+{
+ return QApplicationPrivate::cursor_flash_time;
+}
+
+void QApplication::setCursorFlashTime(int msecs)
+{
+ QApplicationPrivate::cursor_flash_time = msecs;
+}
+
+void QApplication::beep()
+{
+ TInt frequency=440;
+ TTimeIntervalMicroSeconds duration(500000);
+ QS60Beep* beep=NULL;
+ TRAPD(err, beep=QS60Beep::NewL(frequency, duration));
+ if(!err) {
+ beep->Play();
+ }
+ delete beep;
+ beep=NULL;
+}
+
+/*! \fn int QApplication::s60ProcessEvent(TWsEvent *event)
+ This function does the core processing of individual s60
+ \a{event}s. It returns 1 if the event was handled, 0 if
+ the \a event was not handled, and -1 if the event was
+ not handled because the event handle was not in the map.
+ */
+int QApplication::s60ProcessEvent(TWsEvent *event)
+{
+ bool handled = s60EventFilter(event);
+ if (handled)
+ return 1;
+
+ // Qt event handling. Handle some events regardless of if the handle is in our
+ // widget map or not.
+ CCoeControl* control = reinterpret_cast<CCoeControl*>(event->Handle());
+ const bool controlInMap = QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control);
+ switch (event->Type()) {
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+ case EEventKey:
+ case EEventKeyUp:
+ case EEventKeyDown:
+ {
+ // The control doesn't seem to be any of our widgets, so rely on the focused
+ // widget instead. If the user needs the control, it can be found inside the
+ // event structure.
+ QWidget *w = qApp ? qApp->focusWidget() : 0;
+ if (w) {
+ QInputContext *ic = w->inputContext();
+ if (ic && ic->s60FilterEvent(w, event)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ break;
+ }
+#endif
+ case EEventPointerEnter:
+ if (controlInMap)
+ return 1; // Qt::Enter will be generated in HandlePointerL
+ break;
+ case EEventPointerExit:
+ if (controlInMap) {
+ if (S60) {
+ // mouseEvent outside our window, send leave event to last focused widget
+ QMouseEvent mEvent(QEvent::Leave, S60->lastPointerEventPos, S60->lastCursorPos,
+ Qt::NoButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier);
+ if (S60->lastPointerEventTarget)
+ qt_sendSpontaneousEvent(S60->lastPointerEventTarget,&mEvent);
+ S60->lastPointerEventTarget = 0;
+ }
+ return 1;
+ }
+ break;
+ case EEventScreenDeviceChanged:
+ if (S60)
+ S60->updateScreenSize();
+ if (qt_desktopWidget) {
+ QSize oldSize = qt_desktopWidget->size();
+ qt_desktopWidget->data->crect.setWidth(S60->screenWidthInPixels);
+ qt_desktopWidget->data->crect.setHeight(S60->screenHeightInPixels);
+ QResizeEvent e(qt_desktopWidget->size(), oldSize);
+ QApplication::sendEvent(qt_desktopWidget, &e);
+ }
+ return 0; // Propagate to CONE
+ case EEventWindowVisibilityChanged:
+ if (controlInMap) {
+ const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged();
+ QWidget *w = QWidgetPrivate::mapper->value(control);
+ if (!w->d_func()->maybeTopData())
+ break;
+ if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) {
+ delete w->d_func()->topData()->backingStore;
+ w->d_func()->topData()->backingStore = 0;
+ } else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible)
+ && !w->d_func()->maybeBackingStore()) {
+ w->d_func()->topData()->backingStore = new QWidgetBackingStore(w);
+ w->update();
+ }
+ return 1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!controlInMap)
+ return -1;
+
+ return 0;
+}
+
+/*!
+ Returns false. Does nothing with the TWsEvent \a aEvent.
+ */
+bool QApplication::s60EventFilter(TWsEvent * /* aEvent */)
+{
+ return false;
+}
+
+/*!
+ Handles \a{command}s which are typically handled by
+ CAknAppUi::HandleCommandL(). Qts Ui integration into Symbian is
+ partially achieved by deriving from CAknAppUi. Currently, exit,
+ menu and softkey commands are handled.
+
+ \sa s60EventFilter(), s60ProcessEvent()
+*/
+void QApplication::symbianHandleCommand(int command)
+{
+ switch (command) {
+ case EEikCmdExit:
+#ifdef Q_WS_S60
+ case EAknSoftkeyExit:
+#endif
+ exit();
+ break;
+ default:
+ if (command >= SOFTKEYSTART && command <= SOFTKEYEND) {
+ int index= command-SOFTKEYSTART;
+ QWidget *focused = QApplication::focusWidget();
+ QWidget *softKeySource = focused ? focused : QApplication::activeWindow();
+ const QList<QAction*>& softKeys = softKeySource->softKeys();
+ Q_ASSERT(index < softKeys.count());
+ softKeys.at(index)->activate(QAction::Trigger);
+ }
+#ifdef Q_WS_S60
+ else
+ QMenuBarPrivate::symbianCommands(command);
+#endif
+ break;
+ }
+}
+
+/*!
+ Handles the resource change specified by \a type.
+ */
+void QApplication::symbianResourceChange(int type)
+{
+ switch (type) {
+#ifdef Q_WS_S60
+ case KEikDynamicLayoutVariantSwitch:
+ {
+ if (S60)
+ S60->updateScreenSize();
+
+#ifndef QT_NO_STYLE_S60
+ QS60Style *s60Style = 0;
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplication::style());
+ if (proxy)
+ s60Style = qobject_cast<QS60Style*>(proxy->baseStyle());
+ else
+#endif
+ s60Style = qobject_cast<QS60Style*>(QApplication::style());
+
+ if (s60Style)
+ s60Style->d_func()->handleDynamicLayoutVariantSwitch();
+#endif
+ }
+ break;
+
+#ifndef QT_NO_STYLE_S60
+ case KAknsMessageSkinChange:
+ if (QS60Style *s60Style = qobject_cast<QS60Style*>(QApplication::style()))
+ s60Style->d_func()->handleSkinChange();
+ break;
+#endif
+#endif // Q_WS_S60
+ default:
+ break;
+ }
+}
+
+#ifndef QT_NO_WHEELEVENT
+int QApplication::wheelScrollLines()
+{
+ return QApplicationPrivate::wheel_scroll_lines;
+}
+
+void QApplication::setWheelScrollLines(int n)
+{
+ QApplicationPrivate::wheel_scroll_lines = n;
+}
+#endif //QT_NO_WHEELEVENT
+
+bool QApplication::isEffectEnabled(Qt::UIEffect /* effect */)
+{
+ // TODO: Implement QApplication::isEffectEnabled(Qt::UIEffect effect)
+ return false;
+}
+
+void QApplication::setEffectEnabled(Qt::UIEffect /* effect */, bool /* enable */)
+{
+ // TODO: Implement QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+}
+
+TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym)
+{
+ if (keysym) {
+ // If keysym is specified, cache it.
+ scanCodeCache.insert(scanCode, keysym);
+ return keysym;
+ } else {
+ // If not, retrieve the cached version.
+ return scanCodeCache[scanCode];
+ }
+}
+
+
+void QApplicationPrivate::initializeMultitouch_sys()
+{ }
+void QApplicationPrivate::cleanupMultitouch_sys()
+{ }
+
+#ifndef QT_NO_SESSIONMANAGER
+QSessionManager::QSessionManager(QApplication * /* app */, QString & /* id */, QString& /* key */)
+{
+
+}
+
+QSessionManager::~QSessionManager()
+{
+
+}
+
+bool QSessionManager::allowsInteraction()
+{
+ return false;
+}
+
+void QSessionManager::cancel()
+{
+
+}
+#endif //QT_NO_SESSIONMANAGER
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 260db93..a3de120 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qguifunctions_wince.h"
#include "qmenubar.h"
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
@@ -48,9 +48,12 @@ extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.c
extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp
extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.cpp
#endif
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
#include <windowsm.h>
#include <tpcshell.h>
+#ifdef QT_WINCE_GESTURES
+#include <gesture.h>
+#endif
#endif
#include "qapplication.h"
@@ -88,6 +91,9 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
#include "qdebug.h"
#include <private/qkeymapper_p.h>
#include <private/qlocale_p.h>
+#include "qevent_p.h"
+#include "qstandardgestures.h"
+#include "qstandardgestures_p.h"
//#define ALIEN_DEBUG
@@ -104,32 +110,44 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
#endif
#endif // QT_NO_ACCESSIBILITY
-#include <winuser.h>
#if !defined(WINABLEAPI)
-# if defined(Q_OS_WINCE)
+# if defined(Q_WS_WINCE)
# include <bldver.h>
# endif
# include <winable.h>
#endif
+#ifndef WM_TOUCH
+# define WM_TOUCH 0x0240
+
+# define TOUCHEVENTF_MOVE 0x0001
+# define TOUCHEVENTF_DOWN 0x0002
+# define TOUCHEVENTF_UP 0x0004
+# define TOUCHEVENTF_INRANGE 0x0008
+# define TOUCHEVENTF_PRIMARY 0x0010
+# define TOUCHEVENTF_NOCOALESCE 0x0020
+# define TOUCHEVENTF_PEN 0x0040
+# define TOUCHEVENTF_PALM 0x0080
+
+# define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001
+# define TOUCHINPUTMASKF_EXTRAINFO 0x0002
+# define TOUCHINPUTMASKF_CONTACTAREA 0x0004
-#ifndef FLASHW_STOP
-typedef struct {
- UINT cbSize;
- HWND hwnd;
+typedef struct tagTOUCHINPUT
+{
+ LONG x;
+ LONG y;
+ HANDLE hSource;
+ DWORD dwID;
DWORD dwFlags;
- UINT uCount;
- DWORD dwTimeout;
-} FLASHWINFO, *PFLASHWINFO;
-#define FLASHW_STOP 0
-#define FLASHW_CAPTION 0x00000001
-#define FLASHW_TRAY 0x00000002
-#define FLASHW_ALL (FLASHW_CAPTION | FLASHW_TRAY)
-#define FLASHW_TIMER 0x00000004
-#define FLASHW_TIMERNOFG 0x0000000C
-#endif /* FLASHW_STOP */
-typedef BOOL (WINAPI *PtrFlashWindowEx)(PFLASHWINFO pfwi);
-static PtrFlashWindowEx pFlashWindowEx = 0;
+ DWORD dwMask;
+ DWORD dwTime;
+ ULONG_PTR dwExtraInfo;
+ DWORD cxContact;
+ DWORD cyContact;
+} TOUCHINPUT, *PTOUCHINPUT;
+
+#endif
#include <windowsx.h>
#include <limits.h>
@@ -153,9 +171,13 @@ static PtrFlashWindowEx pFlashWindowEx = 0;
#include <mywinsock.h>
#endif
+#ifndef IMR_CONFIRMRECONVERTSTRING
+#define IMR_CONFIRMRECONVERTSTRING 0x0005
+#endif
+
QT_BEGIN_NAMESPACE
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#ifndef SHRG_RETURNCMD
struct SHRGINFO {
DWORD cbSize;
@@ -240,10 +262,6 @@ QTabletDeviceData currentTabletPointer;
// from qregion_win.cpp
extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom);
-Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
- UINT wMsgFilterMax, UINT wRemoveMsg);
-Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
// support for on-the-fly changes of the XP theme engine
#ifndef WM_THEMECHANGED
#define WM_THEMECHANGED 0x031A
@@ -258,22 +276,24 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
#define WM_XBUTTONDOWN 0x020B
#define WM_XBUTTONUP 0x020C
#define WM_XBUTTONDBLCLK 0x020D
+#endif
+#ifndef GET_KEYSTATE_WPARAM
#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
#define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
#define XBUTTON1 0x0001
#define XBUTTON2 0x0002
+#endif
+#ifndef MK_XBUTTON1
#define MK_XBUTTON1 0x0020
#define MK_XBUTTON2 0x0040
#endif
-#ifdef Q_OS_WINCE
-#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
-#endif
-
-// support for multi-media-keys on ME/2000/XP
+// support for multi-media-keys
#ifndef WM_APPCOMMAND
#define WM_APPCOMMAND 0x0319
+#endif
+#ifndef FAPPCOMMAND_MOUSE
#define FAPPCOMMAND_MOUSE 0x8000
#define FAPPCOMMAND_KEY 0
#define FAPPCOMMAND_OEM 0x1000
@@ -307,6 +327,7 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
#define APPCOMMAND_BASS_UP 21
#define APPCOMMAND_TREBLE_DOWN 22
#define APPCOMMAND_TREBLE_UP 23
+#endif // FAPPCOMMAND_MOUSE
// New commands from Windows XP (some even Sp1)
#ifndef APPCOMMAND_MICROPHONE_VOLUME_MUTE
@@ -341,10 +362,6 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
#define APPCOMMAND_MEDIA_CHANNEL_DOWN 52
#endif // APPCOMMAND_MICROPHONE_VOLUME_MUTE
-#endif // WM_APPCOMMAND
-
-static UINT WM95_MOUSEWHEEL = 0;
-
#if (_WIN32_WINNT < 0x0400)
// This struct is defined in winuser.h if the _WIN32_WINNT >= 0x0400 -- in the
// other cases we have to define it on our own.
@@ -376,11 +393,6 @@ QRgb qt_colorref2qrgb(COLORREF col)
Internal variables and functions
*****************************************************************************/
-extern Q_CORE_EXPORT char theAppName[];
-extern Q_CORE_EXPORT char appFileName[];
-extern Q_CORE_EXPORT HINSTANCE appInst; // handle to app instance
-extern Q_CORE_EXPORT HINSTANCE appPrevInst; // handle to prev app instance
-extern Q_CORE_EXPORT int appCmdShow; // main window show command
static HWND curWin = 0; // current window
static HDC displayDC = 0; // display device context
@@ -422,11 +434,6 @@ extern QCursor *qt_grab_cursor();
#define __export
#endif
-QApplicationPrivate* getQApplicationPrivateInternal()
-{
- return qApp->d_func();
-}
-
extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
class QETWidget : public QWidget // event translator widget
@@ -448,6 +455,7 @@ public:
bool translateConfigEvent(const MSG &msg);
bool translateCloseEvent(const MSG &msg);
bool translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, int numPackets);
+ bool translateGestureEvent(const MSG &msg, const GESTUREINFO &gi);
void repolishStyle(QStyle &style);
inline void showChildren(bool spontaneous) { d_func()->showChildren(spontaneous); }
inline void hideChildren(bool spontaneous) { d_func()->hideChildren(spontaneous); }
@@ -497,7 +505,7 @@ static void qt_set_windows_color_resources()
pal.setColor(QPalette::HighlightedText,
QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHTTEXT))));
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
// ### hardcoded until I find out how to get it from the system settings.
pal.setColor(QPalette::LinkVisited, pal.highlight().color().dark(150));
pal.setColor(QPalette::Link, pal.highlight().color().light(130));
@@ -516,14 +524,13 @@ static void qt_set_windows_color_resources()
pal.setColor(QPalette::Inactive, QPalette::Light, pal.light().color());
pal.setColor(QPalette::Inactive, QPalette::Dark, pal.dark().color());
- if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95) {
- if (pal.midlight() == pal.button())
- pal.setColor(QPalette::Midlight, pal.button().color().lighter(110));
- if (pal.background() != pal.base()) {
- pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Inactive, QPalette::Window));
- pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Inactive, QPalette::Text));
- }
+ if (pal.midlight() == pal.button())
+ pal.setColor(QPalette::Midlight, pal.button().color().lighter(110));
+ if (pal.background() != pal.base()) {
+ pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Inactive, QPalette::Window));
+ pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Inactive, QPalette::Text));
}
+
const QColor bg = pal.background().color();
const QColor fg = pal.foreground().color(), btn = pal.button().color();
QColor disabled((fg.red()+btn.red())/2,(fg.green()+btn.green())/2,
@@ -573,36 +580,19 @@ static void qt_set_windows_color_resources()
static void qt_set_windows_font_resources()
{
-#ifndef Q_OS_WINCE
- QFont menuFont;
- QFont messageFont;
- QFont statusFont;
- QFont titleFont;
- QFont iconTitleFont;
- QT_WA({
- NONCLIENTMETRICS ncm;
- ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONTW);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
- menuFont = qt_LOGFONTtoQFont(ncm.lfMenuFont,true);
- messageFont = qt_LOGFONTtoQFont(ncm.lfMessageFont,true);
- statusFont = qt_LOGFONTtoQFont(ncm.lfStatusFont,true);
- titleFont = qt_LOGFONTtoQFont(ncm.lfCaptionFont,true);
- LOGFONTW lfIconTitleFont;
- SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
- iconTitleFont = qt_LOGFONTtoQFont(lfIconTitleFont,true);
- } , {
- // A version
- NONCLIENTMETRICSA ncm;
- ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, lfMessageFont) + sizeof(LOGFONTA);
- SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
- menuFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfMenuFont,true);
- messageFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfMessageFont,true);
- statusFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfStatusFont,true);
- titleFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfCaptionFont,true);
- LOGFONTA lfIconTitleFont;
- SystemParametersInfoA(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
- iconTitleFont = qt_LOGFONTtoQFont((LOGFONT&)lfIconTitleFont,true);
- });
+#ifndef Q_WS_WINCE
+ NONCLIENTMETRICS ncm;
+ ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
+
+ QFont menuFont = qt_LOGFONTtoQFont(ncm.lfMenuFont, true);
+ QFont messageFont = qt_LOGFONTtoQFont(ncm.lfMessageFont, true);
+ QFont statusFont = qt_LOGFONTtoQFont(ncm.lfStatusFont, true);
+ QFont titleFont = qt_LOGFONTtoQFont(ncm.lfCaptionFont, true);
+
+ LOGFONT lfIconTitleFont;
+ SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
+ QFont iconTitleFont = qt_LOGFONTtoQFont(lfIconTitleFont, true);
QApplication::setFont(menuFont, "QMenu");
QApplication::setFont(menuFont, "QMenuBar");
@@ -625,24 +615,19 @@ static void qt_set_windows_font_resources()
smallerFont.setPointSize(systemFont.pointSize()-1);
QApplication::setFont(smallerFont, "QTabBar");
}
-#endif// Q_OS_WINCE
+#endif// Q_WS_WINCE
}
static void qt_win_read_cleartype_settings()
{
- QT_WA({
- UINT result;
- BOOL ok;
- ok = SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0);
- if (ok)
- qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
- }, {
- UINT result;
- BOOL ok;
- ok = SystemParametersInfoA(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0);
- if (ok)
- qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
- });
+ UINT result = 0;
+#ifdef Q_OS_WINCE
+ if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &result, 0))
+ qt_cleartype_enabled = result;
+#else
+ if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0))
+ qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
+#endif
}
@@ -659,10 +644,10 @@ void QApplicationPrivate::initializeWidgetPaletteHash()
QPalette pal = *QApplicationPrivate::sys_pal;
QColor menuCol(qt_colorref2qrgb(GetSysColor(COLOR_MENU)));
QColor menuText(qt_colorref2qrgb(GetSysColor(COLOR_MENUTEXT)));
- BOOL isFlat = 0;
+ BOOL isFlat = false;
if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
&& QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
- SystemParametersInfo(0x1022 /*SPI_GETFLATMENU*/, 0, &isFlat, 0);
+ SystemParametersInfo(SPI_GETFLATMENU, 0, &isFlat, 0);
QPalette menu(pal);
// we might need a special color group for the menu.
menu.setColor(QPalette::Active, QPalette::Button, menuCol);
@@ -677,8 +662,7 @@ void QApplicationPrivate::initializeWidgetPaletteHash()
QColor(qt_colorref2qrgb(GetSysColor(
(QSysInfo::WindowsVersion >= QSysInfo::WV_XP
&& QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
- && isFlat ? COLOR_MENUHILIGHT
- : COLOR_HIGHLIGHT))));
+ && isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT))));
menu.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled);
menu.setColor(QPalette::Disabled, QPalette::Button,
menu.color(QPalette::Active, QPalette::Button));
@@ -694,10 +678,8 @@ void QApplicationPrivate::initializeWidgetPaletteHash()
menu.color(QPalette::Active, QPalette::Highlight));
menu.setColor(QPalette::Inactive, QPalette::HighlightedText,
menu.color(QPalette::Active, QPalette::HighlightedText));
-
- if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95)
- menu.setColor(QPalette::Inactive, QPalette::ButtonText,
- pal.color(QPalette::Inactive, QPalette::Dark));
+ menu.setColor(QPalette::Inactive, QPalette::ButtonText,
+ pal.color(QPalette::Inactive, QPalette::Dark));
QApplication::setPalette(menu, "QMenu");
if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
@@ -714,11 +696,10 @@ void QApplicationPrivate::initializeWidgetPaletteHash()
qt_init() - initializes Qt for Windows
*****************************************************************************/
-typedef BOOL (WINAPI *PtrUpdateLayeredWindow)(HWND hwnd, HDC hdcDst, const POINT *pptDst,
- const SIZE *psize, HDC hdcSrc, const POINT *pptSrc, COLORREF crKey,
- const Q_BLENDFUNCTION *pblend, DWORD dwflags);
-static PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0;
-
+typedef BOOL (WINAPI *PtrSetProcessDPIAware) (VOID);
+static PtrSetProcessDPIAware ptrSetProcessDPIAware = 0;
+PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0;
+PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect = 0;
static BOOL WINAPI qt_updateLayeredWindowIndirect(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *info)
{
return (*ptrUpdateLayeredWindow)(hwnd, info->hdcDst, info->pptDst, info->psize, info->hdcSrc,
@@ -745,9 +726,6 @@ void qt_init(QApplicationPrivate *priv, int)
appNoGrab = !appNoGrab;
else
#endif // QT_DEBUG
- if (qstrcmp(argv[i], "-direct3d") == 0)
- QApplication::setAttribute(Qt::AA_MSWindowsUseDirect3DByDefault);
- else
argv[j++] = argv[i];
}
if(j < priv->argc) {
@@ -755,21 +733,12 @@ void qt_init(QApplicationPrivate *priv, int)
priv->argc = j;
}
- // Get the application name/instance if qWinMain() was not invoked
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// No message boxes but important ones
SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
#endif
- if (appInst == 0) {
- QT_WA({
- appInst = GetModuleHandle(0);
- }, {
- appInst = GetModuleHandleA(0);
- });
- }
-
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// Initialize OLE/COM
// S_OK means success and S_FALSE means that it has already
// been initialized
@@ -781,7 +750,7 @@ void qt_init(QApplicationPrivate *priv, int)
#endif
// Misc. initialization
-#if defined(QT_DEBUG) && !defined(Q_OS_WINCE)
+#if defined(QT_DEBUG) && !defined(Q_WS_WINCE)
GdiSetBatchLimit(1);
#endif
@@ -793,48 +762,32 @@ void qt_init(QApplicationPrivate *priv, int)
#ifndef QT_NO_CURSOR
QCursorData::initialize();
#endif
- qApp->setObjectName(QLatin1String(theAppName));
+ qApp->setObjectName(priv->appName());
-#if !defined(Q_OS_WINCE)
// default font
- HFONT hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
- QFont f(QLatin1String("MS Sans Serif"),8);
- int result = 0;
- QT_WA({
- LOGFONT lf;
- if (result = GetObject(hfont, sizeof(lf), &lf))
- f = qt_LOGFONTtoQFont((LOGFONT&)lf,true);
- } , {
- LOGFONTA lf;
- if (result = GetObjectA(hfont, sizeof(lf), &lf))
- f = qt_LOGFONTtoQFont((LOGFONT&)lf,true);
- });
- if (result
- && QSysInfo::WindowsVersion >= QSysInfo::WV_2000
- && QSysInfo::WindowsVersion <= QSysInfo::WV_NT_based
- && f.family() == QLatin1String("MS Shell Dlg"))
- f.setFamily(QLatin1String("MS Shell Dlg 2"));
- QApplicationPrivate::setSystemFont(f);
-#else //Q_OS_WINCE
- LOGFONT lf;
- HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT);
- int result = 0;
- result = GetObject(stockFont, sizeof(lf), &lf);
- QFont font = qt_LOGFONTtoQFont(lf, true);
- if (result)
- QApplicationPrivate::setSystemFont(font);
-#endif //Q_OS_WINCE
+#ifndef Q_WS_WINCE
+ HGDIOBJ stockFont = GetStockObject(DEFAULT_GUI_FONT);
+#else
+ HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT);
+#endif
+
+ LOGFONT lf;
+ GetObject(stockFont, sizeof(lf), &lf);
+ QFont systemFont = qt_LOGFONTtoQFont(lf, true);
+
+#ifndef Q_WS_WINCE
+ if (systemFont.family() == QLatin1String("MS Shell Dlg")) {
+ systemFont.setFamily(QLatin1String("MS Shell Dlg 2"));
+ }
+#endif
+
+ QApplicationPrivate::setSystemFont(systemFont);
// QFont::locale_init(); ### Uncomment when it does something on Windows
if (QApplication::desktopSettingsAware())
qt_set_windows_resources();
- QT_WA({
- WM95_MOUSEWHEEL = RegisterWindowMessage(L"MSWHEEL_ROLLMSG");
- } , {
- WM95_MOUSEWHEEL = RegisterWindowMessageA("MSWHEEL_ROLLMSG");
- });
initWinTabFunctions();
QApplicationPrivate::inputContext = new QWinInputContext(0);
@@ -855,7 +808,50 @@ void qt_init(QApplicationPrivate *priv, int)
if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect)
ptrUpdateLayeredWindowIndirect = qt_updateLayeredWindowIndirect;
-#endif
+
+ // Notify Vista and Windows 7 that we support highter DPI settings
+ ptrSetProcessDPIAware = (PtrSetProcessDPIAware)
+ QLibrary::resolve(QLatin1String("user32"), "SetProcessDPIAware");
+ if (ptrSetProcessDPIAware)
+ ptrSetProcessDPIAware();
+#endif
+
+ priv->GetGestureInfo = 0;
+ priv->GetGestureExtraArgs = 0;
+
+#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES)
+ priv->GetGestureInfo = (PtrGetGestureInfo) &TKGetGestureInfo;
+ priv->GetGestureExtraArgs = (PtrGetGestureExtraArgs) &TKGetGestureExtraArguments;
+ priv->CloseGestureInfoHandle = (PtrCloseGestureInfoHandle) 0;
+ priv->SetGestureConfig = (PtrSetGestureConfig) 0;
+ priv->GetGestureConfig = (PtrGetGestureConfig) 0;
+#elif !defined(Q_WS_WINCE)
+ priv->GetGestureInfo =
+ (PtrGetGestureInfo)QLibrary::resolve(QLatin1String("user32"),
+ "GetGestureInfo");
+ priv->GetGestureExtraArgs =
+ (PtrGetGestureExtraArgs)QLibrary::resolve(QLatin1String("user32"),
+ "GetGestureExtraArgs");
+ priv->CloseGestureInfoHandle =
+ (PtrCloseGestureInfoHandle)QLibrary::resolve(QLatin1String("user32"),
+ "CloseGestureInfoHandle");
+ priv->SetGestureConfig =
+ (PtrSetGestureConfig)QLibrary::resolve(QLatin1String("user32"),
+ "SetGestureConfig");
+ priv->GetGestureConfig =
+ (PtrGetGestureConfig)QLibrary::resolve(QLatin1String("user32"),
+ "GetGestureConfig");
+ priv->BeginPanningFeedback =
+ (PtrBeginPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"),
+ "BeginPanningFeedback");
+ priv->UpdatePanningFeedback =
+ (PtrUpdatePanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"),
+ "UpdatePanningFeedback");
+ priv->EndPanningFeedback =
+ (PtrEndPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"),
+ "EndPanningFeedback");
+#endif
+ priv->gestureWidget = 0;
}
/*****************************************************************************
@@ -880,7 +876,7 @@ void qt_cleanup()
delete QApplicationPrivate::inputContext;
QApplicationPrivate::inputContext = 0;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// Deinitialize OLE/COM
OleUninitialize();
#endif
@@ -891,12 +887,6 @@ void qt_cleanup()
Platform specific global and internal functions
*****************************************************************************/
-Q_GUI_EXPORT int qWinAppCmdShow() // get main window show command
-{
- return appCmdShow;
-}
-
-
Q_GUI_EXPORT HDC qt_win_display_dc() // get display DC
{
Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
@@ -928,7 +918,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class
if (flags & Qt::MSWindowsOwnDC) {
cname = QLatin1String("QWidgetOwnDC");
style = CS_DBLCLKS;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
style |= CS_OWNDC;
#endif
icon = true;
@@ -937,25 +927,25 @@ const QString qt_reg_winclass(QWidget *w) // register window class
if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) {
if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
&& QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) {
- style |= 0x00020000; // CS_DROPSHADOW
+ style |= CS_DROPSHADOW;
}
cname = QLatin1String("QToolTip");
} else {
cname = QLatin1String("QTool");
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
style |= CS_SAVEBITS;
#endif
icon = false;
} else if (type == Qt::Popup) {
cname = QLatin1String("QPopup");
style = CS_DBLCLKS;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
style |= CS_SAVEBITS;
#endif
if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
&& QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
- style |= 0x00020000; // CS_DROPSHADOW
+ style |= CS_DROPSHADOW;
icon = false;
} else {
cname = QLatin1String("QWidget");
@@ -963,7 +953,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class
icon = true;
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// force CS_OWNDC when the GL graphics system is
// used as the default renderer
if (qt_win_owndc_required)
@@ -975,11 +965,11 @@ const QString qt_reg_winclass(QWidget *w) // register window class
// unique ID on WinCE to make sure we can
// move the windows to the front when starting
// a second instance.
- wchar_t uniqueAppID[256];
- GetModuleFileNameW(0, uniqueAppID, 255);
- cname = QString::number(RegisterWindowMessageW(
- (const wchar_t *) QString::fromUtf16((const ushort *)uniqueAppID).toLower().replace(QString(QString::fromLatin1("\\")),
- QString(QString::fromLatin1("_"))).utf16()));
+ wchar_t uniqueAppID[MAX_PATH];
+ GetModuleFileName(0, uniqueAppID, MAX_PATH);
+ cname = QString::number(RegisterWindowMessage(
+ (const wchar_t *) QString::fromWCharArray(uniqueAppID).toLower().replace(QLatin1Char('\\'),
+ QLatin1Char('_')).utf16()));
#endif
// since multiple Qt versions can be used in one process
@@ -990,15 +980,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class
static int classExists = -1;
if (classExists == -1) {
- QT_WA({
- WNDCLASS wcinfo;
- classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (TCHAR*)cname.utf16(), &wcinfo);
- classExists = classExists && wcinfo.lpfnWndProc != QtWndProc;
- }, {
- WNDCLASSA wcinfo;
- classExists = GetClassInfoA((HINSTANCE)qWinAppInst(), cname.toLatin1(), &wcinfo);
- classExists = classExists && wcinfo.lpfnWndProc != QtWndProc;
- });
+ WNDCLASS wcinfo;
+ classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (wchar_t*)cname.utf16(), &wcinfo);
+ classExists = classExists && wcinfo.lpfnWndProc != QtWndProc;
}
if (classExists)
@@ -1007,73 +991,37 @@ const QString qt_reg_winclass(QWidget *w) // register window class
if (winclassNames()->contains(cname)) // already registered in our list
return cname;
- ATOM atom;
-#ifndef Q_OS_WINCE
- HBRUSH bgBrush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
- QT_WA({
- WNDCLASS wc;
- wc.style = style;
- wc.lpfnWndProc = (WNDPROC)QtWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
- if (icon) {
- wc.hIcon = LoadIcon(appInst, L"IDI_ICON1");
- if (!wc.hIcon)
- wc.hIcon = LoadIcon(0, IDI_APPLICATION);
- } else {
- wc.hIcon = 0;
- }
- wc.hCursor = 0;
- wc.hbrBackground= bgBrush;
- wc.lpszMenuName = 0;
- wc.lpszClassName= (TCHAR*)cname.utf16();
- atom = RegisterClass(&wc);
- } , {
- WNDCLASSA wc;
- wc.style = style;
- wc.lpfnWndProc = (WNDPROC)QtWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
- if (icon) {
- wc.hIcon = LoadIconA(appInst, (char*)"IDI_ICON1");
- if (!wc.hIcon)
- wc.hIcon = LoadIconA(0, (char*)IDI_APPLICATION);
- } else {
- wc.hIcon = 0;
- }
- wc.hCursor = 0;
- wc.hbrBackground= bgBrush;
- wc.lpszMenuName = 0;
- QByteArray tempArray = cname.toLatin1();
- wc.lpszClassName= tempArray;
- atom = RegisterClassA(&wc);
- });
+ WNDCLASS wc;
+ wc.style = style;
+ wc.lpfnWndProc = (WNDPROC)QtWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = qWinAppInst();
+ if (icon) {
+ wc.hIcon = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
+#ifndef Q_WS_WINCE
+ if (!wc.hIcon)
+ wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+#endif
+ } else {
+ wc.hIcon = 0;
+ }
+ wc.hCursor = 0;
+#ifndef Q_WS_WINCE
+ wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
#else
- WNDCLASS wc;
- wc.style = style;
- wc.lpfnWndProc = (WNDPROC)QtWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
- if (icon) {
- wc.hIcon = LoadIcon(appInst, L"IDI_ICON1");
-// if (!wc.hIcon)
-// wc.hIcon = LoadIcon(0, IDI_APPLICATION);
- } else {
- wc.hIcon = 0;
- }
- wc.hCursor = 0;
- wc.hbrBackground= 0;
- wc.lpszMenuName = 0;
- wc.lpszClassName= (TCHAR*)cname.utf16();
- atom = RegisterClass(&wc);
+ wc.hbrBackground = 0;
#endif
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = (wchar_t*)cname.utf16();
+
+ ATOM atom = RegisterClass(&wc);
#ifndef QT_NO_DEBUG
if (!atom)
qErrnoWarning("QApplication::regClass: Registering window class failed.");
+#else
+ Q_UNUSED(atom);
#endif
winclassNames()->insert(cname, 1);
@@ -1091,11 +1039,7 @@ static void unregWinClasses()
WinClassNameHash *hash = winclassNames();
QHash<QString, int>::ConstIterator it = hash->constBegin();
while (it != hash->constEnd()) {
- QT_WA({
- UnregisterClass((TCHAR*)it.key().utf16(), (HINSTANCE)qWinAppInst());
- } , {
- UnregisterClassA(it.key().toLatin1(), (HINSTANCE)qWinAppInst());
- });
+ UnregisterClass((wchar_t*)it.key().utf16(), qWinAppInst());
++it;
}
hash->clear();
@@ -1129,7 +1073,7 @@ void qWinRequestConfig(WId id, int req, int x, int y, int w, int h)
configRequests->append(r); // store request in queue
}
-Q_GUI_EXPORT void qWinProcessConfigRequests() // perform requests in queue
+static void qWinProcessConfigRequests() // perform requests in queue
{
if (!configRequests)
return;
@@ -1312,16 +1256,13 @@ void QApplication::beep()
static void alert_widget(QWidget *widget, int duration)
{
+#ifdef Q_OS_WINCE
+ Q_UNUSED(widget);
+ Q_UNUSED(duration);
+#else
bool stopFlash = duration < 0;
- if (!pFlashWindowEx) {
-#ifndef Q_OS_WINCE
- QLibrary themeLib(QLatin1String("user32"));
- pFlashWindowEx = (PtrFlashWindowEx)themeLib.resolve("FlashWindowEx");
-#endif
- }
-
- if (pFlashWindowEx && widget && (!widget->isActiveWindow() || stopFlash)) {
+ if (widget && (!widget->isActiveWindow() || stopFlash)) {
DWORD timeOut = GetCaretBlinkTime();
if (timeOut <= 0)
timeOut = 250;
@@ -1339,8 +1280,9 @@ static void alert_widget(QWidget *widget, int duration)
info.dwTimeout = stopFlash ? 0 : timeOut;
info.uCount = stopFlash ? 0 : flashCount;
- pFlashWindowEx(&info);
+ FlashWindowEx(&info);
}
+#endif
}
void QApplication::alert(QWidget *widget, int duration)
@@ -1381,7 +1323,7 @@ void QApplication::winFocus(QWidget *widget, bool gotFocus)
&& (QApplicationPrivate::active_window->windowType() == Qt::Dialog)) {
// raise the entire application, not just the dialog
QWidget* mw = QApplicationPrivate::active_window;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
while(mw->parentWidget() && (mw->windowType() == Qt::Dialog))
mw = mw->parentWidget()->window();
if (mw->testAttribute(Qt::WA_WState_Created) && mw != QApplicationPrivate::active_window)
@@ -1428,12 +1370,13 @@ static int inputcharset = CP_ACP;
static bool qt_is_translatable_mouse_event(UINT message)
{
- return (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST ||
- message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK)
+ return (((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) ||
+ (message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK))
&& message != WM_MOUSEWHEEL
+ && message != WM_MOUSEHWHEEL)
-#ifndef Q_OS_WINCE
- || message >= WM_NCMOUSEMOVE && message <= WM_NCMBUTTONDBLCLK
+#ifndef Q_WS_WINCE
+ || (message >= WM_NCMOUSEMOVE && message <= WM_NCMBUTTONDBLCLK)
#endif
;
}
@@ -1472,7 +1415,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
msg.pt.y = GET_Y_LPARAM(lParam);
// If it's a non-client-area message the coords are screen coords, otherwise they are
// client coords.
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
if (message < WM_NCMOUSEMOVE || message > WM_NCMBUTTONDBLCLK)
#endif
ClientToScreen(msg.hwnd, &msg.pt);
@@ -1502,7 +1445,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
if (imeParentWnd && QApplication::activePopupWidget()
&& (message == WM_MBUTTONDOWN || message == WM_XBUTTONDOWN
|| message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
|| message == WM_NCMBUTTONDOWN || message == WM_NCLBUTTONDOWN
|| message == WM_NCRBUTTONDOWN)) {
#else
@@ -1512,7 +1455,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
switch (message) {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_QUERYENDSESSION: {
if (sm_smActive) // bogus message from windows
RETURN(true);
@@ -1534,19 +1477,19 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
// we receive the message for each toplevel window included internal hidden ones,
// but the aboutToQuit signal should be emitted only once.
- QApplicationPrivate *qAppPriv = getQApplicationPrivateInternal();
+ QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
if (endsession && !qAppPriv->aboutToQuitEmitted) {
qAppPriv->aboutToQuitEmitted = true;
int index = QApplication::staticMetaObject.indexOfSignal("aboutToQuit()");
qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0);
// since the process will be killed immediately quit() has no real effect
- qApp->quit();
+ QApplication::quit();
}
RETURN(0);
}
case WM_DISPLAYCHANGE:
- if (qApp->type() == QApplication::Tty)
+ if (QApplication::type() == QApplication::Tty)
break;
if (qt_desktopWidget) {
qt_desktopWidget->move(GetSystemMetrics(76), GetSystemMetrics(77));
@@ -1563,7 +1506,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
#endif
case WM_SETTINGCHANGE:
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
// CE SIP hide/show
if (wParam == SPI_SETSIPINFO) {
QResizeEvent re(QSize(0, 0), QSize(0, 0)); // Calculated by QDesktopWidget
@@ -1572,7 +1515,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
#endif
// ignore spurious XP message when user logs in again after locking
- if (qApp->type() == QApplication::Tty)
+ if (QApplication::type() == QApplication::Tty)
break;
if (QApplication::desktopSettingsAware() && wParam != SPI_SETWORKAREA) {
widget = (QETWidget*)QWidget::find(hwnd);
@@ -1595,7 +1538,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
if (wParam == SPI_SETFONTSMOOTHINGTYPE) {
qt_win_read_cleartype_settings();
- foreach (QWidget *w, qApp->topLevelWidgets()) {
+ foreach (QWidget *w, QApplication::topLevelWidgets()) {
if (!w->isVisible())
continue;
((QETWidget *) w)->forceUpdate();
@@ -1604,7 +1547,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
break;
case WM_SYSCOLORCHANGE:
- if (qApp->type() == QApplication::Tty)
+ if (QApplication::type() == QApplication::Tty)
break;
if (QApplication::desktopSettingsAware()) {
widget = (QETWidget*)QWidget::find(hwnd);
@@ -1656,7 +1599,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
RETURN(res);
if (qt_is_translatable_mouse_event(message)) {
- if (qApp->activePopupWidget() != 0) { // in popup mode
+ if (QApplication::activePopupWidget() != 0) { // in popup mode
POINT curPos = msg.pt;
QWidget* w = QApplication::widgetAt(curPos.x, curPos.y);
if (w)
@@ -1665,10 +1608,10 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
if (!qt_tabletChokeMouse) {
result = widget->translateMouseEvent(msg); // mouse event
-#if defined(Q_OS_WINCE) && !defined(QT_NO_CONTEXTMENU)
- if (message == WM_LBUTTONDOWN && widget != qApp->activePopupWidget()) {
+#if defined(Q_WS_WINCE) && !defined(QT_NO_CONTEXTMENU)
+ if (message == WM_LBUTTONDOWN && widget != QApplication::activePopupWidget()) {
QWidget* alienWidget = widget;
- if ((alienWidget != qApp->activePopupWidget()) && (alienWidget->contextMenuPolicy() != Qt::PreventContextMenu)) {
+ if ((alienWidget != QApplication::activePopupWidget()) && (alienWidget->contextMenuPolicy() != Qt::PreventContextMenu)) {
QPoint pos(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
QPoint globalPos(msg.pt.x, msg.pt.y);
// In case we are using Alien, then the widget to
@@ -1687,8 +1630,8 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
shrg.dwFlags = SHRG_RETURNCMD | SHRG_NOANIMATION;
resolveAygLibs();
if (ptrRecognizeGesture && (ptrRecognizeGesture(&shrg) == GN_CONTEXTMENU)) {
- if (qApp->activePopupWidget())
- qApp->activePopupWidget()->close();
+ if (QApplication::activePopupWidget())
+ QApplication::activePopupWidget()->close();
QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos);
result = qt_sendSpontaneousEvent(alienWidget, &e);
}
@@ -1700,7 +1643,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
// Sometimes we only get a WM_MOUSEMOVE message
// and sometimes we get both a WM_MOUSEMOVE and
// a WM_LBUTTONDOWN/UP, this creates a spurious mouse
- // press/release event, using the winPeekMessage
+ // press/release event, using the PeekMessage
// will help us fix this. This leaves us with a
// question:
// This effectively kills using the mouse AND the
@@ -1710,18 +1653,19 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
bool is_mouse_move = (message == WM_MOUSEMOVE);
if (is_mouse_move) {
MSG msg1;
- if (winPeekMessage(&msg1, msg.hwnd, WM_MOUSEFIRST,
- WM_MOUSELAST, PM_NOREMOVE))
+ if (PeekMessage(&msg1, msg.hwnd, WM_MOUSEFIRST,
+ WM_MOUSELAST, PM_NOREMOVE))
next_is_button = (msg1.message == WM_LBUTTONUP
|| msg1.message == WM_LBUTTONDOWN);
}
if (!is_mouse_move || (is_mouse_move && !next_is_button))
qt_tabletChokeMouse = false;
}
- } else if (message == WM95_MOUSEWHEEL) {
- result = widget->translateWheelEvent(msg);
} else {
switch (message) {
+ case WM_TOUCH:
+ result = QApplicationPrivate::instance()->translateTouchEvent(msg);
+ break;
case WM_KEYDOWN: // keyboard event
case WM_SYSKEYDOWN:
qt_keymapper_private()->updateKeyMap(msg);
@@ -1747,7 +1691,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_IME_KEYDOWN:
case WM_CHAR: {
MSG msg1;
- bool anyMsg = winPeekMessage(&msg1, msg.hwnd, 0, 0, PM_NOREMOVE);
+ bool anyMsg = PeekMessage(&msg1, msg.hwnd, 0, 0, PM_NOREMOVE);
if (anyMsg && msg1.message == WM_DEADCHAR) {
result = true; // consume event since there is a dead char next
break;
@@ -1766,7 +1710,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
widget = (QETWidget*)QApplication::activePopupWidget()->focusWidget()
? (QETWidget*)QApplication::activePopupWidget()->focusWidget()
: (QETWidget*)QApplication::activePopupWidget();
- else if (qApp->focusWidget())
+ else if (QApplication::focusWidget())
widget = (QETWidget*)QApplication::focusWidget();
else if (!widget || widget->internalWinId() == GetFocus()) // We faked the message to go to exactly that widget.
widget = (QETWidget*)widget->window();
@@ -1781,6 +1725,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
break;
case WM_MOUSEWHEEL:
+ case WM_MOUSEHWHEEL:
result = widget->translateWheelEvent(msg);
break;
@@ -1888,8 +1833,8 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
QWidget *g = QWidget::keyboardGrabber();
if (g)
widget = (QETWidget*)g;
- else if (qApp->focusWidget())
- widget = (QETWidget*)qApp->focusWidget();
+ else if (QApplication::focusWidget())
+ widget = (QETWidget*)QApplication::focusWidget();
else
widget = (QETWidget*)widget->window();
if (widget->isEnabled()) {
@@ -1911,17 +1856,21 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_NCHITTEST:
if (widget->isWindow()) {
QPoint pos = widget->mapFromGlobal(QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
// don't show resize-cursors for fixed-size widgets
QRect fs = widget->frameStrut();
if (!widget->isMinimized()) {
+ if (widget->minimumHeight() == widget->maximumHeight()) {
+ if (pos.y() < -(fs.top() - fs.left()))
+ return HTCAPTION;
+ if (pos.y() >= widget->height())
+ return HTBORDER;
+ }
if (widget->minimumWidth() == widget->maximumWidth() && (pos.x() < 0 || pos.x() >= widget->width()))
- break;
- if (widget->minimumHeight() == widget->maximumHeight() && (pos.y() < -(fs.top() - fs.left()) || pos.y() >= widget->height()))
- break;
+ return HTBORDER;
}
}
@@ -1930,7 +1879,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
#endif
case WM_SYSCOMMAND: {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
bool window_state_change = false;
Qt::WindowStates oldstate = Qt::WindowStates(widget->dataPtr()->window_state);
// MSDN:In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are
@@ -1942,11 +1891,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
#ifndef QT_NO_WHATSTHIS
QWhatsThis::enterWhatsThisMode();
#endif
- QT_WA({
- DefWindowProc(hwnd, WM_NCPAINT, 1, 0);
- } , {
- DefWindowProcA(hwnd, WM_NCPAINT, 1, 0);
- });
+ DefWindowProc(hwnd, WM_NCPAINT, 1, 0);
break;
#if defined(QT_NON_COMMERCIAL)
QT_NC_SYSCOMMAND
@@ -1958,7 +1903,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
QHideEvent e;
qt_sendSpontaneousEvent(widget, &e);
widget->hideChildren(true);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
const QString title = widget->windowIconText();
if (!title.isEmpty())
widget->setWindowTitle_helper(title);
@@ -1981,7 +1926,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
widget->showChildren(true);
QShowEvent e;
qt_sendSpontaneousEvent(widget, &e);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
const QString title = widget->windowTitle();
if (!title.isEmpty())
widget->setWindowTitle_helper(title);
@@ -2004,12 +1949,11 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
case WM_SETTINGCHANGE:
- if ( qApp->type() == QApplication::Tty )
+ if ( QApplication::type() == QApplication::Tty )
break;
if (!msg.wParam) {
- QString area = QT_WA_INLINE(QString::fromUtf16((unsigned short *)msg.lParam),
- QString::fromLocal8Bit((char*)msg.lParam));
+ QString area = QString::fromWCharArray((wchar_t*)msg.lParam);
if (area == QLatin1String("intl")) {
QLocalePrivate::updateSystemPrivate();
if (!widget->testAttribute(Qt::WA_SetLocale))
@@ -2017,7 +1961,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
}
else if (msg.wParam == SPI_SETICONTITLELOGFONT) {
- if (qApp->desktopSettingsAware()) {
+ if (QApplication::desktopSettingsAware()) {
widget = (QETWidget*)QWidget::find(hwnd);
if (widget && !widget->parentWidget()) {
qt_set_windows_font_resources();
@@ -2031,7 +1975,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
result = widget->translatePaintEvent(msg);
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_ENTERSIZEMOVE:
autoCaptureWnd = hwnd;
QApplicationPrivate::inSizeMove = true;
@@ -2060,7 +2004,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
break;
case WM_ACTIVATE:
- if ( qApp->type() == QApplication::Tty )
+ if ( QApplication::type() == QApplication::Tty )
break;
if (ptrWTOverlap && ptrWTEnable) {
@@ -2086,9 +2030,13 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
// WM_ACTIVATEAPP handles the "true" false case, as this is only when the application
// loses focus. Doing it here would result in the widget getting focus to not know
// where it got it from; it would simply get a 0 value as the old focus widget.
+#ifndef Q_WS_WINCE_WM
if (!(widget->windowState() & Qt::WindowMinimized)) {
// Ignore the activate message send by WindowsXP to a minimized window
-#ifdef Q_OS_WINCE_WM
+#else
+ {
+ if (widget->windowState() & Qt::WindowMinimized)
+ widget->dataPtr()->window_state &= ~Qt::WindowMinimized;
if (widget->windowState() & Qt::WindowFullScreen)
qt_wince_hide_taskbar(widget->winId());
#endif
@@ -2115,7 +2063,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_MOUSEACTIVATE:
if (widget->window()->windowType() == Qt::Tool) {
QWidget *w = widget;
@@ -2204,7 +2152,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
result = false;
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_WINDOWPOSCHANGING:
{
result = false;
@@ -2285,12 +2233,12 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
QWidget *fw = QWidget::keyboardGrabber();
if (!fw) {
- if (qApp->activePopupWidget())
- fw = (qApp->activePopupWidget()->focusWidget()
- ? qApp->activePopupWidget()->focusWidget()
- : qApp->activePopupWidget());
- else if (qApp->focusWidget())
- fw = qApp->focusWidget();
+ if (QApplication::activePopupWidget())
+ fw = (QApplication::activePopupWidget()->focusWidget()
+ ? QApplication::activePopupWidget()->focusWidget()
+ : QApplication::activePopupWidget());
+ else if (QApplication::focusWidget())
+ fw = QApplication::focusWidget();
else if (widget)
fw = widget->window();
}
@@ -2307,7 +2255,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_IME_STARTCOMPOSITION:
case WM_IME_ENDCOMPOSITION:
case WM_IME_COMPOSITION: {
- QWidget *fw = qApp->focusWidget();
+ QWidget *fw = QApplication::focusWidget();
QWinInputContext *im = fw ? qobject_cast<QWinInputContext *>(fw->inputContext()) : 0;
if (fw && im) {
if(message == WM_IME_STARTCOMPOSITION)
@@ -2319,8 +2267,27 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
break;
}
-
-#ifndef Q_OS_WINCE
+ case WM_IME_REQUEST: {
+ QWidget *fw = QApplication::focusWidget();
+ QWinInputContext *im = fw ? qobject_cast<QWinInputContext *>(fw->inputContext()) : 0;
+ if (fw && im) {
+ if(wParam == IMR_RECONVERTSTRING) {
+ int ret = im->reconvertString((RECONVERTSTRING *)lParam);
+ if (ret == -1) {
+ result = false;
+ } else {
+ return ret;
+ }
+ } else if (wParam == IMR_CONFIRMRECONVERTSTRING) {
+ RETURN(TRUE);
+ } else {
+ // in all other cases, call DefWindowProc()
+ result = false;
+ }
+ }
+ break;
+ }
+#ifndef Q_WS_WINCE
case WM_CHANGECBCHAIN:
case WM_DRAWCLIPBOARD:
#endif
@@ -2340,7 +2307,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_GETOBJECT:
{
// Ignoring all requests while starting up
- if (qApp->startingUp() || qApp->closingDown() || (DWORD)lParam != OBJID_CLIENT) {
+ if (QApplication::startingUp() || QApplication::closingDown() || (DWORD)lParam != OBJID_CLIENT) {
result = false;
break;
}
@@ -2383,11 +2350,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
text = widget->objectName();
ret = qMin<int>(wParam - 1, text.size());
text.resize(ret);
- QT_WA({
- memcpy((void *)lParam, text.utf16(), (text.size() + 1) * 2);
- }, {
- memcpy((void *)lParam, text.toLocal8Bit().data(), text.size() + 1);
- });
+ memcpy((void *)lParam, text.utf16(), (text.size() + 1) * sizeof(ushort));
delete acc;
}
if (!ret) {
@@ -2427,7 +2390,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
#endif // QT_NO_TABLETEVENT
}
break;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
case WM_SETFOCUS: {
HIMC hC;
hC = ImmGetContext(hwnd);
@@ -2440,7 +2403,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_KILLFOCUS:
if (!QWidget::find((HWND)wParam)) { // we don't get focus, so unset it now
if (!widget->hasFocus()) // work around Windows bug after minimizing/restoring
- widget = (QETWidget*)qApp->focusWidget();
+ widget = (QETWidget*)QApplication::focusWidget();
HWND focus = ::GetFocus();
//if there is a current widget and the new widget belongs to the same toplevel window
//or if the current widget was embedded into non-qt window (i.e. we won't get WM_ACTIVATEAPP)
@@ -2459,27 +2422,27 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
break;
case WM_THEMECHANGED:
- if ((widget->windowType() == Qt::Desktop) || !qApp || qApp->closingDown()
- || qApp->type() == QApplication::Tty)
+ if ((widget->windowType() == Qt::Desktop) || !qApp || QApplication::closingDown()
+ || QApplication::type() == QApplication::Tty)
break;
if (widget->testAttribute(Qt::WA_WState_Polished))
- qApp->style()->unpolish(widget);
+ QApplication::style()->unpolish(widget);
if (widget->testAttribute(Qt::WA_WState_Polished))
- qApp->style()->polish(widget);
- widget->repolishStyle(*qApp->style());
+ QApplication::style()->polish(widget);
+ widget->repolishStyle(*QApplication::style());
if (widget->isVisible())
widget->update();
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_INPUTLANGCHANGE: {
- char info[7];
- if (!GetLocaleInfoA(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) {
+ wchar_t info[7];
+ if (!GetLocaleInfo(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) {
inputcharset = CP_ACP;
} else {
- inputcharset = QString::fromLatin1(info).toInt();
+ inputcharset = QString::fromWCharArray(info).toInt();
}
QKeyMapper::changeKeyboard();
break;
@@ -2573,6 +2536,38 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
result = false;
break;
+ case WM_GESTURE: {
+ GESTUREINFO gi;
+ memset(&gi, 0, sizeof(GESTUREINFO));
+ gi.cbSize = sizeof(GESTUREINFO);
+
+ QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
+ BOOL bResult = false;
+ if (qAppPriv->GetGestureInfo)
+ bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi);
+ if (bResult) {
+ if (gi.dwID == GID_BEGIN) {
+ // find the alien widget for the gesture position.
+ // This might not be accurate as the position is the center
+ // point of two fingers for multi-finger gestures.
+ QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y);
+ QWidget *w = widget->childAt(widget->mapFromGlobal(pt));
+ qAppPriv->gestureWidget = w ? w : widget;
+ }
+ if (qAppPriv->gestureWidget)
+ static_cast<QETWidget*>(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi);
+ if (qAppPriv->CloseGestureInfoHandle)
+ qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam);
+ if (gi.dwID == GID_END)
+ qAppPriv->gestureWidget = 0;
+ } else {
+ DWORD dwErr = GetLastError();
+ if (dwErr > 0)
+ qWarning() << "translateGestureEvent: error = " << dwErr;
+ }
+ result = true;
+ break;
+ }
default:
result = false; // event was not processed
break;
@@ -2671,19 +2666,19 @@ bool qt_try_modal(QWidget *widget, MSG *msg, int& ret)
int type = msg->message;
bool block_event = false;
-#ifndef Q_OS_WINCE
- if (type != WM_NCHITTEST)
+#ifndef Q_WS_WINCE
+ if (type != WM_NCHITTEST) {
#endif
if ((type >= WM_MOUSEFIRST && type <= WM_MOUSELAST) ||
- type == WM_MOUSEWHEEL || type == (int)WM95_MOUSEWHEEL ||
+ type == WM_MOUSEWHEEL || type == WM_MOUSEHWHEEL ||
type == WM_MOUSELEAVE ||
(type >= WM_KEYFIRST && type <= WM_KEYLAST)
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
|| type == WM_NCMOUSEMOVE
#endif
) {
if (type == WM_MOUSEMOVE
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
|| type == WM_NCMOUSEMOVE
#endif
) {
@@ -2701,18 +2696,19 @@ bool qt_try_modal(QWidget *widget, MSG *msg, int& ret)
} else if (type == WM_CLOSE) {
block_event = true;
}
-#ifndef Q_OS_WINCE
- else if (type == WM_MOUSEACTIVATE || type == WM_NCLBUTTONDOWN){
- if (!top->isActiveWindow()) {
- top->activateWindow();
- } else {
- QApplication::beep();
- }
- block_event = true;
- ret = MA_NOACTIVATEANDEAT;
- } else if (type == WM_SYSCOMMAND) {
- if (!(msg->wParam == SC_RESTORE && widget->isMinimized()))
+#ifndef Q_WS_WINCE
+ else if (type == WM_MOUSEACTIVATE || type == WM_NCLBUTTONDOWN){
+ if (!top->isActiveWindow()) {
+ top->activateWindow();
+ } else {
+ QApplication::beep();
+ }
block_event = true;
+ ret = MA_NOACTIVATEANDEAT;
+ } else if (type == WM_SYSCOMMAND) {
+ if (!(msg->wParam == SC_RESTORE && widget->isMinimized()))
+ block_event = true;
+ }
}
#endif
@@ -2756,9 +2752,9 @@ void QApplicationPrivate::openPopup(QWidget *popup)
if (popup->focusWidget()) {
popup->focusWidget()->setFocus(Qt::PopupFocusReason);
} else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
- if (QWidget *fw = q_func()->focusWidget()) {
+ if (QWidget *fw = QApplication::focusWidget()) {
QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
- q_func()->sendEvent(fw, &e);
+ QApplication::sendEvent(fw, &e);
}
}
}
@@ -2785,13 +2781,13 @@ void QApplicationPrivate::closePopup(QWidget *popup)
if (!qt_nograb()) // grabbing not disabled
releaseAutoCapture();
QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget()
- : q_func()->focusWidget();
+ : QApplication::focusWidget();
if (fw) {
- if (fw != q_func()->focusWidget()) {
+ if (fw != QApplication::focusWidget()) {
fw->setFocus(Qt::PopupFocusReason);
} else {
QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
- q_func()->sendEvent(fw, &e);
+ QApplication::sendEvent(fw, &e);
}
}
} else {
@@ -2859,7 +2855,7 @@ static const ushort mouseTbl[] = {
WM_XBUTTONUP, QEvent::MouseButtonRelease, Qt::XButton1,
WM_XBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::XButton1,
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
WM_NCMOUSEMOVE, QEvent::NonClientAreaMouseMove, 0,
WM_NCLBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton,
WM_NCLBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton,
@@ -2914,20 +2910,11 @@ void qt_win_eatMouseMove()
// remove all those messages (usually 1) and post the last one with a
// reset button state
- MSG msg = {0, 0, 0, 0, 0, 0, 0};
- QT_WA( {
- while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
- ;
- if (msg.message == WM_MOUSEMOVE)
- PostMessage(msg.hwnd, msg.message, 0, msg.lParam);
- }, {
- MSG msg;
- msg.message = 0;
- while (PeekMessageA(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
- ;
- if (msg.message == WM_MOUSEMOVE)
- PostMessageA(msg.hwnd, msg.message, 0, msg.lParam);
- } );
+ MSG msg = {0, 0, 0, 0, 0, {0, 0} };
+ while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
+ ;
+ if (msg.message == WM_MOUSEMOVE)
+ PostMessage(msg.hwnd, msg.message, 0, msg.lParam);
}
// In DnD, the mouse release event never appears, so the
@@ -2962,8 +2949,8 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
// Compress mouse move events
if (msg.message == WM_MOUSEMOVE) {
MSG mouseMsg;
- while (winPeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEFIRST,
- WM_MOUSELAST, PM_NOREMOVE)) {
+ while (PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEFIRST,
+ WM_MOUSELAST, PM_NOREMOVE)) {
if (mouseMsg.message == WM_MOUSEMOVE) {
#define PEEKMESSAGE_IS_BROKEN 1
#ifdef PEEKMESSAGE_IS_BROKEN
@@ -2974,12 +2961,12 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
// key release events (kls 2003-05-13):
MSG keyMsg;
bool done = false;
- while (winPeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST,
- PM_NOREMOVE)) {
+ while (PeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST,
+ PM_NOREMOVE)) {
if (keyMsg.time < mouseMsg.time) {
if ((keyMsg.lParam & 0xC0000000) == 0x40000000) {
- winPeekMessage(&keyMsg, 0, keyMsg.message,
- keyMsg.message, PM_REMOVE);
+ PeekMessage(&keyMsg, 0, keyMsg.message,
+ keyMsg.message, PM_REMOVE);
} else {
done = true;
break;
@@ -3005,8 +2992,8 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
msgPtr->wParam = mouseMsg.wParam;
msgPtr->pt = mouseMsg.pt;
// Remove the mouse move message
- winPeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE,
- WM_MOUSEMOVE, PM_REMOVE);
+ PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE,
+ WM_MOUSEMOVE, PM_REMOVE);
} else {
break; // there was no more WM_MOUSEMOVE event
}
@@ -3035,7 +3022,9 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
if (alienWidget && alienWidget->internalWinId())
alienWidget = 0;
- if (type == QEvent::MouseMove || type == QEvent::NonClientAreaMouseMove) {
+ if (type == QEvent::MouseMove || type == QEvent::NonClientAreaMouseMove
+ || type == QEvent::TabletMove) {
+
if (!(state & Qt::MouseButtonMask))
qt_button_down = 0;
#ifndef QT_NO_CURSOR
@@ -3055,7 +3044,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
HWND id = effectiveWinId();
QWidget *mouseGrabber = QWidget::mouseGrabber();
- QWidget *activePopupWidget = qApp->activePopupWidget();
+ QWidget *activePopupWidget = QApplication::activePopupWidget();
if (mouseGrabber) {
if (!activePopupWidget || (activePopupWidget == this && !rect().contains(widgetPos)))
id = mouseGrabber->effectiveWinId();
@@ -3148,7 +3137,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
return false;
replayPopupMouseEvent = false;
- QWidget* activePopupWidget = qApp->activePopupWidget();
+ QWidget* activePopupWidget = QApplication::activePopupWidget();
QWidget *target = activePopupWidget;
const QPoint globalPos(gpos.x, gpos.y);
@@ -3166,6 +3155,8 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
popupButtonFocus = popupChild;
break;
case QEvent::MouseButtonRelease:
+ case QEvent::TabletRelease:
+
releaseAfter = true;
break;
default:
@@ -3176,10 +3167,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
if (popupButtonFocus) {
target = popupButtonFocus;
} else if (popupChild) {
- // forward mouse events to the popup child. mouse move events
- // are only forwarded to popup children that enable mouse tracking.
- if (type != QEvent::MouseMove || popupChild->hasMouseTracking())
- target = popupChild;
+ target = popupChild;
}
pos = target->mapFromGlobal(globalPos);
@@ -3209,7 +3197,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
}
if (type == QEvent::MouseButtonPress
- && qApp->activePopupWidget() != activePopupWidget
+ && QApplication::activePopupWidget() != activePopupWidget
&& replayPopupMouseEvent) {
// the popup dissappeared. Replay the event
QWidget* w = QApplication::widgetAt(gpos.x, gpos.y);
@@ -3223,10 +3211,10 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
POINT widgetpt = gpos;
ScreenToClient(hwndTarget, &widgetpt);
LPARAM lParam = MAKELPARAM(widgetpt.x, widgetpt.y);
- winPostMessage(hwndTarget, msg.message, msg.wParam, lParam);
+ PostMessage(hwndTarget, msg.message, msg.wParam, lParam);
}
} else if (type == QEvent::MouseButtonRelease && button == Qt::RightButton
- && qApp->activePopupWidget() == activePopupWidget) {
+ && QApplication::activePopupWidget() == activePopupWidget) {
// popup still alive and received right-button-release
#if !defined(QT_NO_CONTEXTMENU)
QContextMenuEvent e2(QContextMenuEvent::Mouse, pos, globalPos,
@@ -3290,12 +3278,12 @@ bool QETWidget::translateWheelEvent(const MSG &msg)
state = translateButtonState(GET_KEYSTATE_WPARAM(msg.wParam), 0, 0);
int delta;
- if (msg.message == WM_MOUSEWHEEL)
+ if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL)
delta = (short) HIWORD (msg.wParam);
else
delta = (int) msg.wParam;
- Qt::Orientation orient = (state&Qt::AltModifier
+ Qt::Orientation orient = (msg.message == WM_MOUSEHWHEEL || state&Qt::AltModifier
#if 0
// disabled for now - Trenton's one-wheel mouse makes trouble...
// "delta" for usual wheels is +-120. +-240 seems to indicate
@@ -3309,6 +3297,13 @@ bool QETWidget::translateWheelEvent(const MSG &msg)
#endif
) ? Qt::Horizontal : Qt::Vertical;
+ // according to the MSDN documentation on WM_MOUSEHWHEEL:
+ // a positive value indicates that the wheel was rotated to the right;
+ // a negative value indicates that the wheel was rotated to the left.
+ // Qt defines this value as the exact opposite, so we have to flip the value!
+ if (msg.message == WM_MOUSEHWHEEL)
+ delta = -delta;
+
QPoint globalPos;
globalPos.rx() = (short)LOWORD (msg.lParam);
@@ -3329,7 +3324,7 @@ bool QETWidget::translateWheelEvent(const MSG &msg)
// send the event to the widget or its ancestors
{
- QWidget* popup = qApp->activePopupWidget();
+ QWidget* popup = QApplication::activePopupWidget();
if (popup && w->window() != popup)
popup->close();
#ifndef QT_NO_WHEELEVENT
@@ -3345,8 +3340,8 @@ bool QETWidget::translateWheelEvent(const MSG &msg)
}
// send the event to the widget that has the focus or its ancestors, if different
- if (w != qApp->focusWidget() && (w = qApp->focusWidget())) {
- QWidget* popup = qApp->activePopupWidget();
+ if (w != QApplication::focusWidget() && (w = QApplication::focusWidget())) {
+ QWidget* popup = QApplication::activePopupWidget();
if (popup && w->window() != popup)
popup->close();
#ifndef QT_NO_WHEELEVENT
@@ -3399,17 +3394,19 @@ static void tabletInit(UINT wActiveCsr, HCTX hTab)
tdd.minTanPressure = int(np.axMin);
tdd.maxTanPressure = int(np.axMax);
- ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_X, &np);
- tdd.minX = int(np.axMin);
- tdd.maxX = int(np.axMax);
+ LOGCONTEXT lcMine;
- ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_Y, &np);
- tdd.minY = int(np.axMin);
- tdd.maxY = int(np.axMax);
+ /* get default region */
+ ptrWTInfo(WTI_DEFCONTEXT, 0, &lcMine);
- ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_Z, &np);
- tdd.minZ = int(np.axMin);
- tdd.maxZ = int(np.axMax);
+ tdd.minX = 0;
+ tdd.maxX = int(lcMine.lcInExtX) - int(lcMine.lcInOrgX);
+
+ tdd.minY = 0;
+ tdd.maxY = int(lcMine.lcInExtY) - int(lcMine.lcInOrgY);
+
+ tdd.minZ = 0;
+ tdd.maxZ = int(lcMine.lcInExtZ) - int(lcMine.lcInOrgZ);
int csr_type,
csr_physid;
@@ -3519,13 +3516,34 @@ bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf,
}
QPoint globalPos(qRound(hiResGlobal.x()), qRound(hiResGlobal.y()));
+ if (t == QEvent::TabletPress)
+ {
+ qt_button_down = QApplication::widgetAt(globalPos);
+ }
+
// make sure the tablet event get's sent to the proper widget...
- QWidget *w = QApplication::widgetAt(globalPos);
+ QWidget *w = 0;
+
if (qt_button_down)
w = qt_button_down; // Pass it to the thing that's grabbed it.
+ else
+ w = QApplication::widgetAt(globalPos);
if (!w)
w = this;
+
+ if (t == QEvent::TabletRelease)
+ {
+ if (qt_win_ignoreNextMouseReleaseEvent) {
+ qt_win_ignoreNextMouseReleaseEvent = false;
+ if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) {
+ releaseAutoCapture();
+ qt_button_down = 0;
+ }
+ }
+
+ }
+
QPoint localPos = w->mapFromGlobal(globalPos);
#ifndef QT_NO_TABLETEVENT
if (currentTabletPointer.currentDevice == QTabletEvent::Airbrush) {
@@ -3583,14 +3601,8 @@ static void initWinTabFunctions()
QLibrary library(QLatin1String("wintab32"));
if (library.load()) {
- QT_WA({
- ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
- ptrWTGet = (PtrWTGet)library.resolve("WTGetW");
- } , {
- ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoA");
- ptrWTGet = (PtrWTGet)library.resolve("WTGetA");
- });
-
+ ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
+ ptrWTGet = (PtrWTGet)library.resolve("WTGetW");
ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable");
ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap");
ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet");
@@ -3661,7 +3673,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
WORD b = HIWORD(msg.lParam);
QSize oldSize = size();
QSize newSize(a, b);
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
if (isFullScreen() && (oldSize.width() == newSize.height()) && (oldSize.height() == newSize.width()))
qt_wince_hide_taskbar(internalWinId());
#endif
@@ -3673,7 +3685,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
// Capture SIZE_MINIMIZED without preceding WM_SYSCOMMAND
// (like Windows+M)
if (msg.wParam == SIZE_MINIMIZED && !isMinimized()) {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
const QString title = windowIconText();
if (!title.isEmpty())
d_func()->setWindowTitle_helper(title);
@@ -3685,7 +3697,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
hideChildren(true);
}
} else if (msg.wParam != SIZE_MINIMIZED && isMinimized()) {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
const QString title = windowTitle();
if (!title.isEmpty())
d_func()->setWindowTitle_helper(title);
@@ -3731,7 +3743,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
QPoint oldPos = geometry().topLeft();
QPoint newCPos(a, b);
// Ignore silly Windows move event to wild pos after iconify.
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
if (!IsIconic(internalWinId()) && newCPos != oldPos) {
#endif
cr.moveTopLeft(newCPos);
@@ -3743,7 +3755,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
QMoveEvent * e = new QMoveEvent(newCPos, oldPos);
QApplication::postEvent(this, e);
}
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
}
#endif
}
@@ -3764,6 +3776,45 @@ bool QETWidget::translateCloseEvent(const MSG &)
return d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
}
+bool QETWidget::translateGestureEvent(const MSG &, const GESTUREINFO &gi)
+{
+ const QPoint widgetPos = QPoint(gi.ptsLocation.x, gi.ptsLocation.y);
+ QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos);
+ if (alienWidget && alienWidget->internalWinId())
+ alienWidget = 0;
+ QWidget *widget = alienWidget ? alienWidget : this;
+
+ QNativeGestureEvent event;
+ event.sequenceId = gi.dwSequenceID;
+ event.position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y);
+ event.argument = gi.ullArguments;
+
+ switch (gi.dwID) {
+ case GID_BEGIN:
+ event.gestureType = QNativeGestureEvent::GestureBegin;
+ break;
+ case GID_END:
+ event.gestureType = QNativeGestureEvent::GestureEnd;
+ break;
+ case GID_ZOOM:
+ event.gestureType = QNativeGestureEvent::Zoom;
+ break;
+ case GID_PAN:
+ event.gestureType = QNativeGestureEvent::Pan;
+ break;
+ case GID_ROTATE:
+ event.gestureType = QNativeGestureEvent::Rotate;
+ break;
+ case GID_TWOFINGERTAP:
+ case GID_ROLLOVER:
+ default:
+ break;
+ }
+ if (event.gestureType != QNativeGestureEvent::None)
+ qt_sendSpontaneousEvent(widget, &event);
+ return true;
+}
+
void QApplication::setCursorFlashTime(int msecs)
{
@@ -3785,7 +3836,7 @@ int QApplication::cursorFlashTime()
void QApplication::setDoubleClickInterval(int ms)
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
SetDoubleClickTime(ms);
#endif
QApplicationPrivate::mouse_double_click_time = ms;
@@ -3817,11 +3868,7 @@ void QApplication::setWheelScrollLines(int n)
#ifdef SPI_SETWHEELSCROLLLINES
if (n < 0)
n = 0;
- QT_WA({
- SystemParametersInfo(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0);
- } , {
- SystemParametersInfoA(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0);
- });
+ SystemParametersInfo(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0);
#else
QApplicationPrivate::wheel_scroll_lines = n;
#endif
@@ -3831,11 +3878,7 @@ int QApplication::wheelScrollLines()
{
#ifdef SPI_GETWHEELSCROLLLINES
uint i = 3;
- QT_WA({
- SystemParametersInfo(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0);
- } , {
- SystemParametersInfoA(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0);
- });
+ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0);
if (i > INT_MAX)
i = INT_MAX;
return i;
@@ -3880,8 +3923,7 @@ bool QApplication::isEffectEnabled(Qt::UIEffect effect)
if (QColormap::instance().depth() < 16)
return false;
- if (!effect_override && desktopSettingsAware()
- && !(QSysInfo::WindowsVersion == QSysInfo::WV_95 || QSysInfo::WindowsVersion == QSysInfo::WV_NT)) {
+ if (!effect_override && desktopSettingsAware()) {
// we know that they can be used when we are here
BOOL enabled = false;
UINT api;
@@ -3890,33 +3932,22 @@ bool QApplication::isEffectEnabled(Qt::UIEffect effect)
api = SPI_GETMENUANIMATION;
break;
case Qt::UI_FadeMenu:
- if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
- return false;
api = SPI_GETMENUFADE;
break;
case Qt::UI_AnimateCombo:
api = SPI_GETCOMBOBOXANIMATION;
break;
case Qt::UI_AnimateTooltip:
- if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
- api = SPI_GETMENUANIMATION;
- else
- api = SPI_GETTOOLTIPANIMATION;
+ api = SPI_GETTOOLTIPANIMATION;
break;
case Qt::UI_FadeTooltip:
- if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
- return false;
api = SPI_GETTOOLTIPFADE;
break;
default:
api = SPI_GETUIEFFECTS;
break;
}
- QT_WA({
- SystemParametersInfo(api, 0, &enabled, 0);
- } , {
- SystemParametersInfoA(api, 0, &enabled, 0);
- });
+ SystemParametersInfo(api, 0, &enabled, 0);
return enabled;
}
@@ -3965,4 +3996,90 @@ void QSessionManager::cancel()
#endif //QT_NO_SESSIONMANAGER
+
+PtrRegisterTouchWindow QApplicationPrivate::RegisterTouchWindow = 0;
+PtrGetTouchInputInfo QApplicationPrivate::GetTouchInputInfo = 0;
+PtrCloseTouchInputHandle QApplicationPrivate::CloseTouchInputHandle = 0;
+
+void QApplicationPrivate::initializeMultitouch_sys()
+{
+ QLibrary library(QLatin1String("user32"));
+ // MinGW (g++ 3.4.5) accepts only C casts.
+ RegisterTouchWindow = (PtrRegisterTouchWindow)(library.resolve("RegisterTouchWindow"));
+ GetTouchInputInfo = (PtrGetTouchInputInfo)(library.resolve("GetTouchInputInfo"));
+ CloseTouchInputHandle = (PtrCloseTouchInputHandle)(library.resolve("CloseTouchInputHandle"));
+
+ touchInputIDToTouchPointID.clear();
+}
+
+void QApplicationPrivate::cleanupMultitouch_sys()
+{
+ touchInputIDToTouchPointID.clear();
+}
+
+bool QApplicationPrivate::translateTouchEvent(const MSG &msg)
+{
+ QWidget *widgetForHwnd = QWidget::find(msg.hwnd);
+ if (!widgetForHwnd)
+ return false;
+
+ QRect screenGeometry = QApplication::desktop()->screenGeometry(widgetForHwnd);
+
+ QList<QTouchEvent::TouchPoint> touchPoints;
+
+ QVector<TOUCHINPUT> winTouchInputs(msg.wParam);
+ memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count());
+ Qt::TouchPointStates allStates = 0;
+ QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT));
+ for (int i = 0; i < winTouchInputs.count(); ++i) {
+ const TOUCHINPUT &touchInput = winTouchInputs.at(i);
+
+ int touchPointID = touchInputIDToTouchPointID.value(touchInput.dwID, -1);
+ if (touchPointID == -1) {
+ touchPointID = touchInputIDToTouchPointID.count();
+ touchInputIDToTouchPointID.insert(touchInput.dwID, touchPointID);
+ }
+
+ QTouchEvent::TouchPoint touchPoint(touchPointID);
+
+ // update state
+ QPointF screenPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.));
+ QRectF screenRect;
+ if (touchInput.dwMask & TOUCHINPUTMASKF_CONTACTAREA)
+ screenRect.setSize(QSizeF(qreal(touchInput.cxContact) / qreal(100.),
+ qreal(touchInput.cyContact) / qreal(100.)));
+ screenRect.moveCenter(screenPos);
+
+ Qt::TouchPointStates state;
+ if (touchInput.dwFlags & TOUCHEVENTF_DOWN) {
+ state = Qt::TouchPointPressed;
+ } else if (touchInput.dwFlags & TOUCHEVENTF_UP) {
+ state = Qt::TouchPointReleased;
+ } else {
+ state = (screenPos == touchPoint.screenPos()
+ ? Qt::TouchPointStationary
+ : Qt::TouchPointMoved);
+ }
+ if (touchInput.dwFlags & TOUCHEVENTF_PRIMARY)
+ state |= Qt::TouchPointPrimary;
+ touchPoint.setState(state);
+ touchPoint.setScreenRect(screenRect);
+ touchPoint.setNormalizedPos(QPointF(screenPos.x() / screenGeometry.width(),
+ screenPos.y() / screenGeometry.height()));
+
+ allStates |= state;
+
+ touchPoints.append(touchPoint);
+ }
+ QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam);
+
+ if ((allStates & Qt::TouchPointStateMask) == Qt::TouchPointReleased) {
+ // all touch points released, forget the ids we've seen, they may not be reused
+ touchInputIDToTouchPointID.clear();
+ }
+
+ translateRawTouchEvent(widgetForHwnd, QTouchEvent::TouchScreen, touchPoints);
+ return true;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index bf1251e..69dba40 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -78,11 +78,13 @@
#include <private/qcrashhandler_p.h>
#include <private/qcolor_p.h>
#include <private/qcursor_p.h>
+#include <private/qiconloader_p.h>
#include "qstyle.h"
#include "qmetaobject.h"
#include "qtimer.h"
#include "qlibrary.h"
#include <private/qgraphicssystemfactory_p.h>
+#include "qkde_p.h"
#if !defined (QT_NO_TABLET)
extern "C" {
@@ -130,6 +132,16 @@ extern "C" {
#include <private/qbackingstore_p.h>
+#ifdef QT_RX71_MULTITOUCH
+# include <qsocketnotifier.h>
+# include <linux/input.h>
+# include <errno.h>
+#endif
+
+#if _POSIX_VERSION+0 < 200112L && !defined(Q_OS_BSD4)
+# define QT_NO_UNSETENV
+#endif
+
QT_BEGIN_NAMESPACE
//#define X_NOT_BROKEN
@@ -159,6 +171,8 @@ static const char * x11_atomnames = {
"WM_TAKE_FOCUS\0"
"_NET_WM_PING\0"
"_NET_WM_CONTEXT_HELP\0"
+ "_NET_WM_SYNC_REQUEST\0"
+ "_NET_WM_SYNC_REQUEST_COUNTER\0"
// ICCCM window state
"WM_STATE\0"
@@ -296,6 +310,10 @@ static const char * x11_atomnames = {
// XEMBED
"_XEMBED\0"
"_XEMBED_INFO\0"
+
+ "Wacom Stylus\0"
+ "Wacom Cursor\0"
+ "Wacom Eraser\0"
};
Q_GUI_EXPORT QX11Data *qt_x11Data = 0;
@@ -506,6 +524,7 @@ static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg)
class QETWidget : public QWidget // event translator widget
{
public:
+ QWidgetPrivate* d_func() { return QWidget::d_func(); }
bool translateMouseEvent(const XEvent *);
void translatePaintEvent(const XEvent *);
bool translateConfigEvent(const XEvent *);
@@ -718,6 +737,44 @@ static int qt_xio_errhandler(Display *)
}
#endif
+#ifndef QT_NO_XSYNC
+struct qt_sync_request_event_data
+{
+ WId window;
+};
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg)
+{
+ qt_sync_request_event_data *data =
+ reinterpret_cast<qt_sync_request_event_data*>(arg);
+ if (event->type == ClientMessage &&
+ event->xany.window == data->window &&
+ event->xclient.message_type == ATOM(WM_PROTOCOLS) &&
+ (Atom)event->xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST)) {
+ QWidget *w = QWidget::find(event->xany.window);
+ if (QTLWExtra *tlw = ((QETWidget*)w)->d_func()->maybeTopData()) {
+ const ulong timestamp = (const ulong) event->xclient.data.l[1];
+ if (timestamp > X11->time)
+ X11->time = timestamp;
+ if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
+ tlw->syncRequestTimestamp = timestamp;
+ tlw->newCounterValueLo = event->xclient.data.l[2];
+ tlw->newCounterValueHi = event->xclient.data.l[3];
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+#endif // QT_NO_XSYNC
static void qt_x11_create_intern_atoms()
{
@@ -759,26 +816,6 @@ Q_GUI_EXPORT void qt_x11_apply_settings_in_all_apps()
}
/*! \internal
- Gets the current KDE 3 or 4 home path
-*/
-QString QApplicationPrivate::kdeHome()
-{
- static QString kdeHomePath;
- if (kdeHomePath.isEmpty()) {
- kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME"));
- if (kdeHomePath.isEmpty()) {
- int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
- QDir homeDir(QDir::homePath());
- QString kdeConfDir(QLatin1String("/.kde"));
- if (4 == kdeSessionVersion && homeDir.exists(QLatin1String(".kde4")))
- kdeConfDir = QLatin1String("/.kde4");
- kdeHomePath = QDir::homePath() + kdeConfDir;
- }
- }
- return kdeHomePath;
-}
-
-/*! \internal
apply the settings to the application
*/
bool QApplicationPrivate::x11_apply_settings()
@@ -834,30 +871,32 @@ bool QApplicationPrivate::x11_apply_settings()
}
// ### Fix properly for 4.6
- if (!(QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"))) {
+ bool usingGtkSettings = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle");
+ if (!usingGtkSettings) {
if (groupCount == QPalette::NColorGroups)
QApplicationPrivate::setSystemPalette(pal);
}
- int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
-
if (!appFont) {
- QFont font(QApplication::font());
- QString fontDescription;
- // Override Qt font if KDE4 settings can be used
- if (4 == kdeSessionVersion) {
- QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
- fontDescription = kdeSettings.value(QLatin1String("font")).toString();
- if (fontDescription.isEmpty()) {
- // KDE stores fonts without quotes
- fontDescription = kdeSettings.value(QLatin1String("font")).toStringList().join(QLatin1String(","));
+ // ### Fix properly for 4.6
+ if (!usingGtkSettings) {
+ QFont font(QApplication::font());
+ QString fontDescription;
+ // Override Qt font if KDE4 settings can be used
+ if (X11->desktopVersion == 4) {
+ QSettings kdeSettings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ fontDescription = kdeSettings.value(QLatin1String("font")).toString();
+ if (fontDescription.isEmpty()) {
+ // KDE stores fonts without quotes
+ fontDescription = kdeSettings.value(QLatin1String("font")).toStringList().join(QLatin1String(","));
+ }
+ }
+ if (fontDescription.isEmpty())
+ fontDescription = settings.value(QLatin1String("font")).toString();
+ if (!fontDescription .isEmpty()) {
+ font.fromString(fontDescription );
+ QApplicationPrivate::setSystemFont(font);
}
- }
- if (fontDescription.isEmpty())
- fontDescription = settings.value(QLatin1String("font")).toString();
- if (!fontDescription .isEmpty()) {
- font.fromString(fontDescription );
- QApplicationPrivate::setSystemFont(font);
}
}
@@ -875,29 +914,15 @@ bool QApplicationPrivate::x11_apply_settings()
// read new QStyle
QString stylename = settings.value(QLatin1String("style")).toString();
- if (stylename.isEmpty() && !QApplicationPrivate::styleOverride && X11->use_xrender) {
- QStringList availableStyles = QStyleFactory::keys();
- // Override Qt style if KDE4 settings can be used
- if (4 == kdeSessionVersion) {
- QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
- QString kde4Style = kdeSettings.value(QLatin1String("widgetStyle"),
- QLatin1String("Oxygen")).toString();
- foreach (const QString &style, availableStyles) {
- if (style.toLower() == kde4Style.toLower())
- stylename = kde4Style;
- }
- // Set QGtkStyle for GNOME
- } else if (X11->desktopEnvironment == DE_GNOME) {
- QString gtkStyleKey = QString::fromLatin1("GTK+");
- if (availableStyles.contains(gtkStyleKey))
- stylename = gtkStyleKey;
- }
+
+ if (stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull() && X11->use_xrender) {
+ stylename = x11_desktop_style();
}
static QString currentStyleName = stylename;
if (QCoreApplication::startingUp()) {
- if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride)
- QApplicationPrivate::styleOverride = new QString(stylename);
+ if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull())
+ QApplicationPrivate::styleOverride = stylename;
} else {
if (currentStyleName != stylename) {
currentStyleName = stylename;
@@ -1047,24 +1072,6 @@ static void qt_set_input_encoding()
XFree((char *)data);
}
-// Reads a KDE color setting
-static QColor kdeColor(const QString &key)
-{
- QSettings kdeSettings(QApplicationPrivate::kdeHome() +
- QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
- QVariant variant = kdeSettings.value(key);
- if (variant.isValid()) {
- QStringList values = variant.toStringList();
- if (values.size() == 3) {
- int r = values[0].toInt();
- int g = values[1].toInt();
- int b = values[2].toInt();
- return QColor(r, g, b);
- }
- }
- return QColor();
-}
-
// set font, foreground and background from x11 resources. The
// arguments may override the resource settings.
static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
@@ -1085,7 +1092,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
if (QApplication::desktopSettingsAware()) {
// first, read from settings
QApplicationPrivate::x11_apply_settings();
-
// the call to QApplication::style() below creates the system
// palette, which breaks the logic after the RESOURCE_MANAGER
// loop... so I have to save this value to be able to use it later
@@ -1231,9 +1237,10 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
QApplicationPrivate::setSystemFont(fnt);
}
+ // QGtkStyle sets it's own system palette
+ bool gtkStyle = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle");
bool kdeColors = (QApplication::desktopSettingsAware() && X11->desktopEnvironment == DE_KDE);
-
- if (kdeColors || (button || !resBG.isEmpty() || !resFG.isEmpty())) {// set app colors
+ if (!gtkStyle && (kdeColors || (button || !resBG.isEmpty() || !resFG.isEmpty()))) {// set app colors
bool allowX11ColorNames = QColor::allowX11ColorNames();
QColor::setAllowX11ColorNames(true);
@@ -1269,41 +1276,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
bright_mode = true;
}
- if (kdeColors) {
- // Setup KDE palette
- QColor color;
- color = kdeColor(QLatin1String("buttonBackground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal"));
- if (color.isValid())
- btn = color;
-
- color = kdeColor(QLatin1String("background"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal"));
- if (color.isValid())
- bg = color;
-
- color = kdeColor(QLatin1String("foreground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/ForegroundNormal"));
- if (color.isValid()) {
- fg = color;
- }
-
- color = kdeColor(QLatin1String("windowForeground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal"));
- if (color.isValid())
- wfg = color;
-
- color = kdeColor(QLatin1String("windowBackground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/BackgroundNormal"));
- if (color.isValid())
- base = color;
- }
-
QPalette pal(fg, btn, btn.lighter(125), btn.darker(130), btn.darker(120), wfg.isValid() ? wfg : fg, Qt::white, base, bg);
QColor disabled((fg.red() + btn.red()) / 2,
(fg.green() + btn.green())/ 2,
@@ -1316,34 +1288,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
highlight = QColor(selectBackground);
highlightText = QColor(selectForeground);
}
- // Use KDE3 or KDE4 color settings if present
- if (kdeColors) {
- QColor color = kdeColor(QLatin1String("selectBackground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal"));
- if (color.isValid())
- highlight = color;
-
- color = kdeColor(QLatin1String("selectForeground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal"));
- if (color.isValid())
- highlightText = color;
-
- color = kdeColor(QLatin1String("alternateBackground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate"));
- if (color.isValid())
- pal.setColor(QPalette::AlternateBase, color);
- else
- pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110));
-
- color = kdeColor(QLatin1String("buttonForeground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal"));
- if (color.isValid())
- pal.setColor(QPalette::ButtonText, color);
- }
if (highlight.isValid() && highlightText.isValid()) {
pal.setColor(QPalette::Highlight, highlight);
@@ -1366,10 +1310,9 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue);
}
- // QGtkStyle sets it's own system palette
- if (!(QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"))) {
- QApplicationPrivate::setSystemPalette(pal);
- }
+ if (kdeColors)
+ pal = QKde::kdePalette().resolve(pal);
+ QApplicationPrivate::setSystemPalette(pal);
QColor::setAllowX11ColorNames(allowX11ColorNames);
}
@@ -1389,6 +1332,8 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
effects.contains(QLatin1String("animatetoolbox")));
}
+
+ QIconLoader::instance()->updateSystemTheme();
}
@@ -1583,6 +1528,7 @@ static PtrWacomConfigOpenDevice ptrWacomConfigOpenDevice = 0;
static PtrWacomConfigGetRawParam ptrWacomConfigGetRawParam = 0;
static PtrWacomConfigCloseDevice ptrWacomConfigCloseDevice = 0;
static PtrWacomConfigTerm ptrWacomConfigTerm = 0;
+Q_GLOBAL_STATIC(QByteArray, wacomDeviceName)
#endif
#endif
@@ -1723,7 +1669,7 @@ void qt_init(QApplicationPrivate *priv, int,
X11->pattern_fills[i].screen = -1;
#endif
- X11->startupId = X11->originalStartupId = 0;
+ X11->startupId = 0;
int argc = priv->argc;
char **argv = priv->argv;
@@ -1905,10 +1851,20 @@ void qt_init(QApplicationPrivate *priv, int,
QX11InfoData *screen = X11->screens + s;
screen->ref = 1; // ensures it doesn't get deleted
screen->screen = s;
- screen->dpiX = (DisplayWidth(X11->display, s) * 254 + DisplayWidthMM(X11->display, s)*5)
- / (DisplayWidthMM(X11->display, s)*10);
- screen->dpiY = (DisplayHeight(X11->display, s) * 254 + DisplayHeightMM(X11->display, s)*5)
- / (DisplayHeightMM(X11->display, s)*10);
+
+ int widthMM = DisplayWidthMM(X11->display, s);
+ if (widthMM != 0) {
+ screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10);
+ } else {
+ screen->dpiX = 72;
+ }
+
+ int heightMM = DisplayHeightMM(X11->display, s);
+ if (heightMM != 0) {
+ screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10);
+ } else {
+ screen->dpiY = 72;
+ }
X11->argbVisuals[s] = 0;
X11->argbColormaps[s] = 0;
@@ -2084,6 +2040,13 @@ void qt_init(QApplicationPrivate *priv, int,
#endif // QT_RUNTIME_XCURSOR
#endif // QT_NO_XCURSOR
+#ifndef QT_NO_XSYNC
+ int xsync_evbase, xsync_errbase;
+ int major, minor;
+ if (XSyncQueryExtension(X11->display, &xsync_evbase, &xsync_errbase))
+ XSyncInitialize(X11->display, &major, &minor);
+#endif // QT_NO_XSYNC
+
#ifndef QT_NO_XINERAMA
#ifdef QT_RUNTIME_XINERAMA
X11->ptrXineramaQueryExtension = 0;
@@ -2245,6 +2208,7 @@ void qt_init(QApplicationPrivate *priv, int,
X11->compositingManagerRunning = XGetSelectionOwner(X11->display,
ATOM(_NET_WM_CM_S0));
X11->desktopEnvironment = DE_UNKNOWN;
+ X11->desktopVersion = 0;
// See if the current window manager is using the freedesktop.org spec to give its name
Window windowManagerWindow = XNone;
@@ -2320,6 +2284,9 @@ void qt_init(QApplicationPrivate *priv, int,
XFree((char *)data);
}
+ if (X11->desktopEnvironment == DE_KDE)
+ X11->desktopVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
+
qt_set_input_encoding();
qt_set_x11_resources(appFont, appFGCol, appBGCol, appBTNCol);
@@ -2355,13 +2322,6 @@ void qt_init(QApplicationPrivate *priv, int,
XAxisInfoPtr a;
XDevice *dev = 0;
-#if !defined(Q_OS_IRIX)
- // XFree86 divides a stylus and eraser into 2 devices, so we must do for both...
- const QString XFREENAMESTYLUS = QLatin1String("stylus");
- const QString XFREENAMEPEN = QLatin1String("pen");
- const QString XFREENAMEERASER = QLatin1String("eraser");
-#endif
-
if (X11->ptrXListInputDevices) {
devices = X11->ptrXListInputDevices(X11->display, &ndev);
if (!devices)
@@ -2376,18 +2336,19 @@ void qt_init(QApplicationPrivate *priv, int,
gotStylus = false;
gotEraser = false;
- QString devName = QString::fromLocal8Bit(devs->name).toLower();
#if defined(Q_OS_IRIX)
+ QString devName = QString::fromLocal8Bit(devs->name).toLower();
if (devName == QLatin1String(WACOM_NAME)) {
deviceType = QTabletEvent::Stylus;
gotStylus = true;
}
#else
- if (devName.startsWith(XFREENAMEPEN)
- || devName.startsWith(XFREENAMESTYLUS)) {
+ if (devs->type == ATOM(XWacomStylus)) {
deviceType = QTabletEvent::Stylus;
+ if (wacomDeviceName()->isEmpty())
+ wacomDeviceName()->append(devs->name);
gotStylus = true;
- } else if (devName.startsWith(XFREENAMEERASER)) {
+ } else if (devs->type == ATOM(XWacomEraser)) {
deviceType = QTabletEvent::XFreeEraser;
gotEraser = true;
}
@@ -2523,10 +2484,15 @@ void qt_init(QApplicationPrivate *priv, int,
#endif // QT_NO_TABLET
X11->startupId = getenv("DESKTOP_STARTUP_ID");
- X11->originalStartupId = X11->startupId;
- static char desktop_startup_id[] = "DESKTOP_STARTUP_ID=";
- putenv(desktop_startup_id);
-
+ if (X11->startupId) {
+#ifndef QT_NO_UNSETENV
+ unsetenv("DESKTOP_STARTUP_ID");
+#else
+ // it's a small memory leak, however we won't crash if Qt is
+ // unloaded and someones tries to use the envoriment.
+ putenv(strdup("DESKTOP_STARTUP_ID="));
+#endif
+ }
} else {
// read some non-GUI settings when not using the X server...
@@ -2585,31 +2551,35 @@ void qt_init(QApplicationPrivate *priv, int,
/*!
\internal
*/
-void QApplicationPrivate::x11_initialize_style()
+QString QApplicationPrivate::x11_desktop_style()
{
- if (QApplicationPrivate::app_style)
- return;
-
+ QString stylename;
switch(X11->desktopEnvironment) {
- case DE_KDE:
- if (X11->use_xrender)
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("plastique"));
- else
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows"));
- break;
- case DE_GNOME:
- if (X11->use_xrender)
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cleanlooks"));
- else
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows"));
- break;
- case DE_CDE:
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cde"));
- break;
- default:
- // Don't do anything
+ case DE_KDE:
+ stylename = QKde::kdeStyle();
+ break;
+ case DE_GNOME: {
+ QStringList availableStyles = QStyleFactory::keys();
+ // Set QGtkStyle for GNOME if available
+ QString gtkStyleKey = QString::fromLatin1("GTK+");
+ if (availableStyles.contains(gtkStyleKey)) {
+ stylename = gtkStyleKey;
break;
+ }
+ if (X11->use_xrender)
+ stylename = QLatin1String("cleanlooks");
+ else
+ stylename = QLatin1String("windows");
+ break;
+ }
+ case DE_CDE:
+ stylename = QLatin1String("cde");
+ break;
+ default:
+ // Don't do anything
+ break;
}
+ return stylename;
}
void QApplicationPrivate::initializeWidgetPaletteHash()
@@ -2640,10 +2610,6 @@ void qt_cleanup()
#endif
}
- // restore original value back. This is also done in QWidgetPrivate::show_sys.
- if (X11->originalStartupId)
- putenv(X11->originalStartupId);
-
#ifndef QT_NO_XRENDER
for (int i = 0; i < X11->solid_fill_count; ++i) {
if (X11->solid_fills[i].picture)
@@ -2978,7 +2944,7 @@ QWidget *QApplication::topLevelAt(const QPoint &p)
void QApplication::syncX()
{
if (X11->display)
- XSync(X11->display, False); // don't discard events
+ XSync(X11->display, False); // don't discard events
}
@@ -3116,6 +3082,19 @@ int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
XSendEvent(event->xclient.display, event->xclient.window,
False, SubstructureNotifyMask|SubstructureRedirectMask, event);
}
+#ifndef QT_NO_XSYNC
+ } else if (a == ATOM(_NET_WM_SYNC_REQUEST)) {
+ const ulong timestamp = (const ulong) event->xclient.data.l[1];
+ if (timestamp > X11->time)
+ X11->time = timestamp;
+ if (QTLWExtra *tlw = w->d_func()->maybeTopData()) {
+ if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
+ tlw->syncRequestTimestamp = timestamp;
+ tlw->newCounterValueLo = event->xclient.data.l[2];
+ tlw->newCounterValueHi = event->xclient.data.l[3];
+ }
+ }
+#endif
}
} else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
widget->translateScrollDoneEvent(event);
@@ -3146,6 +3125,7 @@ int QApplication::x11ProcessEvent(XEvent* event)
{
Q_D(QApplication);
QScopedLoopLevelCounter loopLevelCounter(d->threadData);
+
#ifdef ALIEN_DEBUG
//qDebug() << "QApplication::x11ProcessEvent:" << event->type;
#endif
@@ -3351,19 +3331,10 @@ int QApplication::x11ProcessEvent(XEvent* event)
QSize oldSize(w->size());
w->data->crect.setWidth(DisplayWidth(X11->display, scr));
w->data->crect.setHeight(DisplayHeight(X11->display, scr));
- QVarLengthArray<QRect> oldSizes(desktop->numScreens());
- for (int i = 0; i < desktop->numScreens(); ++i)
- oldSizes[i] = desktop->screenGeometry(i);
QResizeEvent e(w->size(), oldSize);
QApplication::sendEvent(w, &e);
- for (int i = 0; i < qMin(oldSizes.count(), desktop->numScreens()); ++i) {
- if (oldSizes[i] != desktop->screenGeometry(i))
- emit desktop->resized(i);
- }
- for (int i = oldSizes.count(); i < desktop->numScreens(); ++i)
- emit desktop->resized(i); // added
- for (int i = desktop->numScreens(); i < oldSizes.count(); ++i)
- emit desktop->resized(i); // removed
+ if (w != desktop)
+ QApplication::sendEvent(desktop, &e);
}
#endif // QT_NO_XRANDR
@@ -4139,7 +4110,9 @@ bool QETWidget::translateMouseEvent(const XEvent *event)
|| ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify)
&& qt_button_down == this)
|| (nextEvent.type == ClientMessage
- && nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE))) {
+ && (nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE) ||
+ (nextEvent.xclient.message_type == ATOM(WM_PROTOCOLS) &&
+ (Atom)nextEvent.xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST))))) {
qApp->x11ProcessEvent(&nextEvent);
continue;
} else if (nextEvent.type != MotionNotify ||
@@ -4409,7 +4382,6 @@ bool QETWidget::translateMouseEvent(const XEvent *event)
QMouseEvent e(type, pos, globalPos, button, buttons, modifiers);
QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down,
qt_last_mouse_receiver);
-
if (type == QEvent::MouseButtonPress
&& button == Qt::RightButton
&& (openPopupCount == oldOpenPopupCount)) {
@@ -4478,8 +4450,7 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId)
WACOMCONFIG *config = ptrWacomConfigInit(X11->display, 0);
if (config == 0)
return;
- const char *name = "stylus"; // TODO get this from the X config instead (users may have called it differently)
- WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, name);
+ WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, wacomDeviceName()->constData());
if (device == 0)
return;
unsigned keys[1];
@@ -4537,6 +4508,46 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId)
}
#endif
+struct qt_tablet_motion_data
+{
+ Time timestamp;
+ int tabletMotionType;
+ bool error; // found a reason to stop searching
+};
+
+static Bool qt_mouseMotion_scanner(Display *, XEvent *event, XPointer arg)
+{
+ qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg;
+ if (data->error)
+ return false;
+
+ if (event->type == MotionNotify)
+ return true;
+
+ data->error = event->type != data->tabletMotionType; // we stop compression when another event gets in between.
+ return false;
+}
+
+static Bool qt_tabletMotion_scanner(Display *, XEvent *event, XPointer arg)
+{
+ qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg;
+ if (data->error)
+ return false;
+
+ if (event->type == data->tabletMotionType) {
+ if (data->timestamp > 0) {
+ if ((reinterpret_cast<const XDeviceMotionEvent*>(event))->time > data->timestamp) {
+ data->error = true;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ data->error = event->type != MotionNotify; // we stop compression when another event gets in between.
+ return false;
+}
+
bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet)
{
#if defined (Q_OS_IRIX)
@@ -4563,16 +4574,14 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet
qreal rotation = 0;
int deviceType = QTabletEvent::NoDevice;
int pointerType = QTabletEvent::UnknownPointer;
- XEvent xinputMotionEvent;
XEvent mouseMotionEvent;
+ XEvent dummy;
const XDeviceMotionEvent *motion = 0;
XDeviceButtonEvent *button = 0;
const XProximityNotifyEvent *proximity = 0;
QEvent::Type t;
Qt::KeyboardModifiers modifiers = 0;
bool reinsertMouseEvent = false;
- bool neverFoundMouseEvent = true;
- XEvent xinputMotionEventNext;
XEvent mouseMotionEventSave;
#if !defined (Q_OS_IRIX)
XID device_id;
@@ -4580,72 +4589,40 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet
if (ev->type == tablet->xinput_motion) {
motion = reinterpret_cast<const XDeviceMotionEvent*>(ev);
- for (;;) {
- // get the corresponding mouseMotionEvent for motion
- if (XCheckTypedWindowEvent(X11->display, internalWinId(), MotionNotify, &mouseMotionEvent)) {
+
+ // Do event compression. Skip over tablet+mouse move events if there are newer ones.
+ qt_tablet_motion_data tabletMotionData;
+ tabletMotionData.tabletMotionType = tablet->xinput_motion;
+ while (true) {
+ // Find first mouse event since we expect them in pairs inside Qt
+ tabletMotionData.error =false;
+ tabletMotionData.timestamp = 0;
+ if (XCheckIfEvent(X11->display, &mouseMotionEvent, &qt_mouseMotion_scanner, (XPointer) &tabletMotionData)) {
mouseMotionEventSave = mouseMotionEvent;
reinsertMouseEvent = true;
- neverFoundMouseEvent = false;
-
- if (mouseMotionEvent.xmotion.time > motion->time) {
- XEvent xinputMotionEventLoop = *ev;
-
- // xinput event is older than the mouse event --> search for the corresponding xinput event for the given mouse event
- while (mouseMotionEvent.xmotion.time > (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEventLoop))->time) {
- if (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) {
- xinputMotionEvent = xinputMotionEventLoop;
- }
- else {
- break;
- }
- }
- motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent);
- }
-
- // get the next xinputMotionEvent, for the next loop run
- if (!XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventNext)) {
- XPutBackEvent(X11->display, &mouseMotionEvent);
- reinsertMouseEvent = false;
- break;
- }
-
- if (mouseMotionEvent.xmotion.time != motion->time) {
- // reinsert in order
- if (mouseMotionEvent.xmotion.time >= motion->time) {
- XPutBackEvent(X11->display, &mouseMotionEvent);
- XPutBackEvent(X11->display, &xinputMotionEventNext);
- // next entry in queue is xinputMotionEventNext
- }
- else {
- XPutBackEvent(X11->display, &xinputMotionEventNext);
- XPutBackEvent(X11->display, &mouseMotionEvent);
- // next entry in queue is mouseMotionEvent
- }
- reinsertMouseEvent = false;
- break;
- }
- }
- else {
+ } else {
break;
}
- xinputMotionEvent = xinputMotionEventNext;
- motion = (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent));
- }
+ // Now discard any duplicate tablet events.
+ tabletMotionData.error = false;
+ tabletMotionData.timestamp = mouseMotionEvent.xmotion.time;
+ while (XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) {
+ motion = reinterpret_cast<const XDeviceMotionEvent*>(&dummy);
+ }
- if (reinsertMouseEvent) {
- XPutBackEvent(X11->display, &mouseMotionEventSave);
+ // now check if there are more recent tablet motion events since we'll compress the current one with
+ // newer ones in that case
+ tabletMotionData.error = false;
+ tabletMotionData.timestamp = 0;
+ if (! XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) {
+ break; // done with compression
+ }
+ motion = reinterpret_cast<const XDeviceMotionEvent*>(&dummy);
}
- if (neverFoundMouseEvent) {
- XEvent xinputMotionEventLoop;
- bool eventFound = false;
- // xinput event without mouseMotionEvent --> search the newest xinputMotionEvent
- while (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) {
- xinputMotionEvent = xinputMotionEventLoop;
- eventFound = true;
- }
- if (eventFound) motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent);
+ if (reinsertMouseEvent) {
+ XPutBackEvent(X11->display, &mouseMotionEventSave);
}
t = QEvent::TabletMove;
@@ -5018,6 +4995,7 @@ bool QETWidget::translatePropertyEvent(const XEvent *event)
return true;
}
+
//
// Paint event translation
//
@@ -5196,6 +5174,14 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
otherEvent.xconfigure.border_width;
}
}
+#ifndef QT_NO_XSYNC
+ qt_sync_request_event_data sync_event;
+ sync_event.window = internalWinId();
+ for (XEvent ev;;) {
+ if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event))
+ break;
+ }
+#endif // QT_NO_XSYNC
}
QRect cr (geometry());
@@ -5281,6 +5267,20 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
if (d->extra && d->extra->topextra)
d->extra->topextra->inTopLevelResize = false;
}
+#ifndef QT_NO_XSYNC
+ if (QTLWExtra *tlwExtra = d->maybeTopData()) {
+ if (tlwExtra->newCounterValueLo != 0 || tlwExtra->newCounterValueHi != 0) {
+ XSyncValue value;
+ XSyncIntsToValue(&value,
+ tlwExtra->newCounterValueLo,
+ tlwExtra->newCounterValueHi);
+
+ XSyncSetCounter(X11->display, tlwExtra->syncUpdateCounter, value);
+ tlwExtra->newCounterValueHi = 0;
+ tlwExtra->newCounterValueLo = 0;
+ }
+ }
+#endif
return true;
}
@@ -5898,4 +5898,225 @@ void QSessionManager::requestPhase2()
#endif // QT_NO_SESSIONMANAGER
+#if defined(QT_RX71_MULTITOUCH)
+
+static inline int testBit(const char *array, int bit)
+{
+ return (array[bit/8] & (1<<(bit%8)));
+}
+
+static int openRX71Device(const QByteArray &deviceName)
+{
+ int fd = open(deviceName, O_RDONLY | O_NONBLOCK);
+ if (fd == -1) {
+ fd = -errno;
+ return fd;
+ }
+
+ // fetch the event type mask and check that the device reports absolute coordinates
+ char eventTypeMask[(EV_MAX + sizeof(char) - 1) * sizeof(char) + 1];
+ memset(eventTypeMask, 0, sizeof(eventTypeMask));
+ if (ioctl(fd, EVIOCGBIT(0, sizeof(eventTypeMask)), eventTypeMask) < 0) {
+ close(fd);
+ return -1;
+ }
+ if (!testBit(eventTypeMask, EV_ABS)) {
+ close(fd);
+ return -1;
+ }
+
+ // make sure that we can get the absolute X and Y positions from the device
+ char absMask[(ABS_MAX + sizeof(char) - 1) * sizeof(char) + 1];
+ memset(absMask, 0, sizeof(absMask));
+ if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absMask)), absMask) < 0) {
+ close(fd);
+ return -1;
+ }
+ if (!testBit(absMask, ABS_X) || !testBit(absMask, ABS_Y)) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+void QApplicationPrivate::initializeMultitouch_sys()
+{
+ Q_Q(QApplication);
+
+ QByteArray deviceName = QByteArray("/dev/input/event");
+ int currentDeviceNumber = 0;
+ for (;;) {
+ int fd = openRX71Device(QByteArray(deviceName + QByteArray::number(currentDeviceNumber++)));
+ if (fd == -ENOENT) {
+ // no more devices
+ break;
+ }
+ if (fd < 0) {
+ // not a touch device
+ continue;
+ }
+
+ struct input_absinfo abs_x, abs_y, abs_z;
+ ioctl(fd, EVIOCGABS(ABS_X), &abs_x);
+ ioctl(fd, EVIOCGABS(ABS_Y), &abs_y);
+ ioctl(fd, EVIOCGABS(ABS_Z), &abs_z);
+
+ int deviceNumber = allRX71TouchPoints.count();
+
+ QSocketNotifier *socketNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q);
+ QObject::connect(socketNotifier, SIGNAL(activated(int)), q, SLOT(_q_readRX71MultiTouchEvents()));
+
+ RX71TouchPointState touchPointState = {
+ socketNotifier,
+ QTouchEvent::TouchPoint(deviceNumber),
+
+ abs_x.minimum, abs_x.maximum, q->desktop()->screenGeometry().width(),
+ abs_y.minimum, abs_y.maximum, q->desktop()->screenGeometry().height(),
+ abs_z.minimum, abs_z.maximum
+ };
+ allRX71TouchPoints.append(touchPointState);
+ }
+
+ hasRX71MultiTouch = allRX71TouchPoints.count() > 1;
+ if (!hasRX71MultiTouch) {
+ for (int i = 0; i < allRX71TouchPoints.count(); ++i) {
+ QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier;
+ close(socketNotifier->socket());
+ delete socketNotifier;
+ }
+ allRX71TouchPoints.clear();
+ }
+}
+
+void QApplicationPrivate::cleanupMultitouch_sys()
+{
+ hasRX71MultiTouch = false;
+ for (int i = 0; i < allRX71TouchPoints.count(); ++i) {
+ QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier;
+ close(socketNotifier->socket());
+ delete socketNotifier;
+ }
+ allRX71TouchPoints.clear();
+}
+
+bool QApplicationPrivate::readRX71MultiTouchEvents(int deviceNumber)
+{
+ RX71TouchPointState &touchPointState = allRX71TouchPoints[deviceNumber];
+ QSocketNotifier *socketNotifier = touchPointState.socketNotifier;
+ int fd = socketNotifier->socket();
+
+ QTouchEvent::TouchPoint &touchPoint = touchPointState.touchPoint;
+
+ bool down = touchPoint.state() != Qt::TouchPointReleased;
+ if (down)
+ touchPoint.setState(Qt::TouchPointStationary);
+
+ bool changed = false;
+ for (;;) {
+ struct input_event inputEvent;
+ int bytesRead = read(fd, &inputEvent, sizeof(inputEvent));
+ if (bytesRead <= 0)
+ break;
+ if (bytesRead != sizeof(inputEvent)) {
+ qWarning("Qt: INTERNAL ERROR: short read in readRX71MultiTouchEvents()");
+ return false;
+ }
+
+ switch (inputEvent.type) {
+ case EV_SYN:
+ changed = true;
+ switch (touchPoint.state()) {
+ case Qt::TouchPointPressed:
+ case Qt::TouchPointReleased:
+ // make sure we don't compress pressed and releases with any other events
+ return changed;
+ default:
+ break;
+ }
+ continue;
+ case EV_KEY:
+ case EV_ABS:
+ break;
+ default:
+ qWarning("Qt: WARNING: unknown event type %d on multitouch device", inputEvent.type);
+ continue;
+ }
+
+ QPointF screenPos = touchPoint.screenPos();
+ switch (inputEvent.code) {
+ case BTN_TOUCH:
+ if (!down && inputEvent.value != 0)
+ touchPoint.setState(Qt::TouchPointPressed);
+ else if (down && inputEvent.value == 0)
+ touchPoint.setState(Qt::TouchPointReleased);
+ break;
+ case ABS_TOOL_WIDTH:
+ case ABS_VOLUME:
+ case ABS_PRESSURE:
+ // ignore for now
+ break;
+ case ABS_X:
+ {
+ qreal newValue = ((qreal(inputEvent.value - touchPointState.minX)
+ / qreal(touchPointState.maxX - touchPointState.minX))
+ * touchPointState.scaleX);
+ screenPos.rx() = newValue;
+ touchPoint.setScreenPos(screenPos);
+ break;
+ }
+ case ABS_Y:
+ {
+ qreal newValue = ((qreal(inputEvent.value - touchPointState.minY)
+ / qreal(touchPointState.maxY - touchPointState.minY))
+ * touchPointState.scaleY);
+ screenPos.ry() = newValue;
+ touchPoint.setScreenPos(screenPos);
+ break;
+ }
+ case ABS_Z:
+ {
+ // map Z (signal strength) to pressure for now
+ qreal newValue = (qreal(inputEvent.value - touchPointState.minZ)
+ / qreal(touchPointState.maxZ - touchPointState.minZ));
+ touchPoint.setPressure(newValue);
+ break;
+ }
+ default:
+ qWarning("Qt: WARNING: unknown event code %d on multitouch device", inputEvent.code);
+ continue;
+ }
+ }
+
+ if (down && touchPoint.state() != Qt::TouchPointReleased)
+ touchPoint.setState(changed ? Qt::TouchPointMoved : Qt::TouchPointStationary);
+
+ return changed;
+}
+
+void QApplicationPrivate::_q_readRX71MultiTouchEvents()
+{
+ // read touch events from all devices
+ bool changed = false;
+ for (int i = 0; i < allRX71TouchPoints.count(); ++i)
+ changed = readRX71MultiTouchEvents(i) || changed;
+ if (!changed)
+ return;
+
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ for (int i = 0; i < allRX71TouchPoints.count(); ++i)
+ touchPoints.append(allRX71TouchPoints.at(i).touchPoint);
+
+ translateRawTouchEvent(0, QTouchEvent::TouchScreen, touchPoints);
+}
+
+#else // !QT_RX71_MULTITOUCH
+
+void QApplicationPrivate::initializeMultitouch_sys()
+{ }
+void QApplicationPrivate::cleanupMultitouch_sys()
+{ }
+
+#endif // QT_RX71_MULTITOUCH
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qboxlayout.cpp b/src/gui/kernel/qboxlayout.cpp
index 0eb7ff1..273df31 100644
--- a/src/gui/kernel/qboxlayout.cpp
+++ b/src/gui/kernel/qboxlayout.cpp
@@ -452,7 +452,6 @@ void QBoxLayoutPrivate::calcHfw(int w)
vertically.
\ingroup geomanagement
- \ingroup appearance
QBoxLayout takes the space it gets (from its parent layout or from
the parentWidget()), divides it up into a row of boxes, and makes
@@ -527,7 +526,7 @@ void QBoxLayoutPrivate::calcHfw(int w)
You will almost always want to use QVBoxLayout and QHBoxLayout
rather than QBoxLayout because of their convenient constructors.
- \sa QGridLayout, QStackedLayout, {Layout Classes}
+ \sa QGridLayout, QStackedLayout, {Layout Management}
*/
/*!
@@ -925,9 +924,15 @@ void QBoxLayout::insertSpacing(int index, int size)
else
b = QLayoutPrivate::createSpacerItem(this, 0, size, QSizePolicy::Minimum, QSizePolicy::Fixed);
- QBoxLayoutItem *it = new QBoxLayoutItem(b);
- it->magic = true;
- d->list.insert(index, it);
+ QT_TRY {
+ QBoxLayoutItem *it = new QBoxLayoutItem(b);
+ it->magic = true;
+ d->list.insert(index, it);
+
+ } QT_CATCH(...) {
+ delete b;
+ QT_RETHROW;
+ }
invalidate();
}
@@ -1027,8 +1032,21 @@ void QBoxLayout::insertWidget(int index, QWidget *widget, int stretch,
index = d->list.count();
QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
b->setAlignment(alignment);
- QBoxLayoutItem *it = new QBoxLayoutItem(b, stretch);
- d->list.insert(index, it);
+
+ QBoxLayoutItem *it;
+ QT_TRY{
+ it = new QBoxLayoutItem(b, stretch);
+ } QT_CATCH(...) {
+ delete b;
+ QT_RETHROW;
+ }
+
+ QT_TRY{
+ d->list.insert(index, it);
+ } QT_CATCH(...) {
+ delete it;
+ QT_RETHROW;
+ }
invalidate();
}
@@ -1271,8 +1289,6 @@ QBoxLayout::Direction QBoxLayout::direction() const
\brief The QHBoxLayout class lines up widgets horizontally.
\ingroup geomanagement
- \ingroup appearance
- \mainclass
This class is used to construct horizontal box layout objects. See
QBoxLayout for details.
@@ -1295,7 +1311,7 @@ QBoxLayout::Direction QBoxLayout::direction() const
\image qhboxlayout-with-5-children.png Horizontal box layout with five child widgets
- \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
+ \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example}
*/
@@ -1389,8 +1405,6 @@ QHBoxLayout::~QHBoxLayout()
\brief The QVBoxLayout class lines up widgets vertically.
\ingroup geomanagement
- \ingroup appearance
- \mainclass
This class is used to construct vertical box layout objects. See
QBoxLayout for details.
@@ -1413,7 +1427,7 @@ QHBoxLayout::~QHBoxLayout()
\image qvboxlayout-with-5-children.png Horizontal box layout with five child widgets
- \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
+ \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example}
*/
/*!
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index 0ace9d3..dd39aa3 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -50,6 +50,7 @@
#include "qvariant.h"
#include "qbuffer.h"
#include "qimage.h"
+#include "qtextcodec.h"
QT_BEGIN_NAMESPACE
@@ -57,10 +58,6 @@ QT_BEGIN_NAMESPACE
\class QClipboard
\brief The QClipboard class provides access to the window system clipboard.
- \ingroup io
- \ingroup environment
- \mainclass
-
The clipboard offers a simple mechanism to copy and paste data
between applications.
@@ -276,11 +273,12 @@ QClipboard::~QClipboard()
*/
QString QClipboard::text(QString &subtype, Mode mode) const
{
- const QMimeData *data = mimeData(mode);
+ const QMimeData *const data = mimeData(mode);
if (!data)
return QString();
+
+ const QStringList formats = data->formats();
if (subtype.isEmpty()) {
- QStringList formats = data->formats();
if (formats.contains(QLatin1String("text/plain")))
subtype = QLatin1String("plain");
else {
@@ -289,13 +287,21 @@ QString QClipboard::text(QString &subtype, Mode mode) const
subtype = formats.at(i).mid(5);
break;
}
+ if (subtype.isEmpty())
+ return QString();
}
- }
- if (subtype.isEmpty())
+ } else if (!formats.contains(QLatin1String("text/") + subtype)) {
return QString();
- if (subtype == QLatin1String("plain"))
- return data->text();
- return QString::fromUtf8(data->data(QLatin1String("text/") + subtype));
+ }
+
+ const QByteArray rawData = data->data(QLatin1String("text/") + subtype);
+
+ QTextCodec* codec = QTextCodec::codecForMib(106); // utf-8 is default
+ if (subtype == QLatin1String("html"))
+ codec = QTextCodec::codecForHtml(rawData, codec);
+ else
+ codec = QTextCodec::codecForUtfText(rawData, codec);
+ return codec->toUnicode(rawData);
}
/*!
diff --git a/src/gui/kernel/qclipboard_mac.cpp b/src/gui/kernel/qclipboard_mac.cpp
index b800973..af24bd5 100644
--- a/src/gui/kernel/qclipboard_mac.cpp
+++ b/src/gui/kernel/qclipboard_mac.cpp
@@ -50,6 +50,7 @@
#include "qurl.h"
#include <stdlib.h>
#include <string.h>
+#include "qt_cocoa_helpers_mac_p.h"
QT_BEGIN_NAMESPACE
@@ -525,8 +526,17 @@ QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const
QString c_flavor = c->flavorFor(format);
if(!c_flavor.isEmpty()) {
// Handle text/plain a little differently. Try handling Unicode first.
- if((c_flavor == QLatin1String("com.apple.traditional-mac-plain-text") || c_flavor == QLatin1String("public.utf8-plain-text")) &&
- hasFlavor(QLatin1String("public.utf16-plain-text")))
+ bool checkForUtf16 = (c_flavor == QLatin1String("com.apple.traditional-mac-plain-text")
+ || c_flavor == QLatin1String("public.utf8-plain-text"));
+ if (checkForUtf16 || c_flavor == QLatin1String("public.utf16-plain-text")) {
+ // Try to get the NSStringPboardType from NSPasteboard, newlines are mapped
+ // correctly (as '\n') in this data. The 'public.utf16-plain-text' type
+ // usually maps newlines to '\r' instead.
+ QString str = qt_mac_get_pasteboardString();
+ if (!str.isEmpty())
+ return str;
+ }
+ if (checkForUtf16 && hasFlavor(QLatin1String("public.utf16-plain-text")))
c_flavor = QLatin1String("public.utf16-plain-text");
QVariant ret;
diff --git a/src/gui/kernel/qclipboard_s60.cpp b/src/gui/kernel/qclipboard_s60.cpp
new file mode 100644
index 0000000..9a2629c
--- /dev/null
+++ b/src/gui/kernel/qclipboard_s60.cpp
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qclipboard.h"
+
+#ifndef QT_NO_CLIPBOARD
+
+#include "qapplication.h"
+#include "qbitmap.h"
+#include "qdatetime.h"
+#include "qbuffer.h"
+#include "qwidget.h"
+#include "qevent.h"
+#include "private/qcore_symbian_p.h"
+#include <QtDebug>
+
+// Symbian's clipboard
+#include <baclipb.h>
+QT_BEGIN_NAMESPACE
+
+//### Mime Type mapping to UIDs
+
+const TUid KQtCbDataStream = {0x2001B2DD};
+
+
+class QClipboardData
+{
+public:
+ QClipboardData();
+ ~QClipboardData();
+
+ void setSource(QMimeData* s)
+ {
+ if (s == src)
+ return;
+ delete src;
+ src = s;
+ }
+ QMimeData* source()
+ { return src; }
+ bool connected()
+ { return connection; }
+ void clear();
+
+private:
+ QMimeData* src;
+ bool connection;
+};
+
+QClipboardData::QClipboardData():src(0),connection(true)
+{
+ clear();
+}
+
+QClipboardData::~QClipboardData()
+{
+ connection = false;
+ delete src;
+}
+
+void QClipboardData::clear()
+{
+ QMimeData* newSrc = new QMimeData;
+ delete src;
+ src = newSrc;
+}
+
+static QClipboardData *internalCbData = 0;
+
+static void cleanupClipboardData()
+{
+ delete internalCbData;
+ internalCbData = 0;
+}
+
+static QClipboardData *clipboardData()
+{
+ if (internalCbData == 0) {
+ internalCbData = new QClipboardData;
+ if (internalCbData)
+ {
+ if (!internalCbData->connected())
+ {
+ delete internalCbData;
+ internalCbData = 0;
+ }
+ else
+ {
+ qAddPostRoutine(cleanupClipboardData);
+ }
+ }
+ }
+ return internalCbData;
+}
+
+void writeToStreamLX(const QMimeData* aData, RWriteStream& aStream)
+{
+ // This function both leaves and throws exceptions. There must be no destructor
+ // dependencies between cleanup styles, and no cleanup stack dependencies on stacked objects.
+ QStringList headers = aData->formats();
+ aStream << TCardinality(headers.count());
+ for (QStringList::const_iterator iter= headers.constBegin();iter != headers.constEnd();iter++)
+ {
+ HBufC* stringData = TPtrC(reinterpret_cast<const TUint16*>((*iter).utf16())).AllocLC();
+ QByteArray ba = aData->data((*iter));
+ qDebug() << "copy to clipboard mime: " << *iter << " data: " << ba;
+ // mime type
+ aStream << TCardinality(stringData->Size());
+ aStream << *(stringData);
+ // mime data
+ aStream << TCardinality(ba.size());
+ aStream.WriteL(reinterpret_cast<const uchar*>(ba.constData()),ba.size());
+ CleanupStack::PopAndDestroy(stringData);
+ }
+}
+
+void readFromStreamLX(QMimeData* aData,RReadStream& aStream)
+{
+ // This function both leaves and throws exceptions. There must be no destructor
+ // dependencies between cleanup styles, and no cleanup stack dependencies on stacked objects.
+ TCardinality mimeTypeCount;
+ aStream >> mimeTypeCount;
+ for (int i = 0; i< mimeTypeCount;i++)
+ {
+ // mime type
+ TCardinality mimeTypeSize;
+ aStream >> mimeTypeSize;
+ HBufC* mimeTypeBuf = HBufC::NewLC(aStream,mimeTypeSize);
+ QString mimeType = QString::fromUtf16(mimeTypeBuf->Des().Ptr(),mimeTypeBuf->Length());
+ CleanupStack::PopAndDestroy(mimeTypeBuf);
+ // mime data
+ TCardinality dataSize;
+ aStream >> dataSize;
+ QByteArray ba;
+ ba.reserve(dataSize);
+ aStream.ReadL(reinterpret_cast<uchar*>(ba.data_ptr()->data),dataSize);
+ ba.data_ptr()->size = dataSize;
+ qDebug() << "paste from clipboard mime: " << mimeType << " data: " << ba;
+ aData->setData(mimeType,ba);
+ }
+}
+
+
+/*****************************************************************************
+ QClipboard member functions
+ *****************************************************************************/
+
+void QClipboard::clear(Mode mode)
+{
+ setText(QString(), mode);
+}
+const QMimeData* QClipboard::mimeData(Mode mode) const
+{
+ if (mode != Clipboard) return 0;
+ QClipboardData *d = clipboardData();
+ if (d)
+ {
+ TRAPD(err,{
+ RFs fs = qt_s60GetRFs();
+ CClipboard* cb = CClipboard::NewForReadingLC(fs);
+ Q_ASSERT(cb);
+ RStoreReadStream stream;
+ TStreamId stid = (cb->StreamDictionary()).At(KQtCbDataStream);
+ stream.OpenLC(cb->Store(),stid);
+ QT_TRYCATCH_LEAVING(readFromStreamLX(d->source(),stream));
+ CleanupStack::PopAndDestroy(2,cb);
+ return d->source();
+ });
+ if (err != KErrNone){
+ qDebug()<< "clipboard is empty/err: " << err;
+ }
+
+ }
+ return 0;
+}
+
+
+void QClipboard::setMimeData(QMimeData* src, Mode mode)
+{
+ if (mode != Clipboard) return;
+ QClipboardData *d = clipboardData();
+ if (d)
+ {
+ TRAPD(err,{
+ RFs fs = qt_s60GetRFs();
+ CClipboard* cb = CClipboard::NewForWritingLC(fs);
+ RStoreWriteStream stream;
+ TStreamId stid = stream.CreateLC(cb->Store());
+ QT_TRYCATCH_LEAVING(writeToStreamLX(src,stream));
+ d->setSource(src);
+ stream.CommitL();
+ (cb->StreamDictionary()).AssignL(KQtCbDataStream,stid);
+ cb->CommitL();
+ CleanupStack::PopAndDestroy(2,cb);
+ });
+ if (err != KErrNone){
+ qDebug()<< "clipboard write err :" << err;
+ }
+ }
+ emitChanged(QClipboard::Clipboard);
+}
+
+bool QClipboard::supportsMode(Mode mode) const
+{
+ return (mode == Clipboard);
+}
+
+bool QClipboard::ownsMode(Mode mode) const
+{
+ if (mode == Clipboard)
+ qWarning("QClipboard::ownsClipboard: UNIMPLEMENTED!");
+ return false;
+}
+
+bool QClipboard::event(QEvent * /* e */)
+{
+ return true;
+}
+
+void QClipboard::connectNotify( const char * )
+{
+}
+
+void QClipboard::ownerDestroyed()
+{
+}
+QT_END_NAMESPACE
+#endif // QT_NO_CLIPBOARD
diff --git a/src/gui/kernel/qclipboard_win.cpp b/src/gui/kernel/qclipboard_win.cpp
index 7154571..ea7db2f 100644
--- a/src/gui/kernel/qclipboard_win.cpp
+++ b/src/gui/kernel/qclipboard_win.cpp
@@ -200,7 +200,7 @@ HRESULT QtCeGetClipboard(IDataObject** obj)
if (clipData == 0) {
clipData = GetClipboardData(CF_UNICODETEXT);
if (clipData != 0)
- clipText = QString::fromUtf16((unsigned short *)clipData);
+ clipText = QString::fromWCharArray((wchar_t *)clipData);
} else {
clipText = QString::fromLatin1((const char*)clipData);
}
@@ -325,13 +325,7 @@ bool QClipboard::event(QEvent *e)
}
if (propagate && d->nextClipboardViewer) {
- QT_WA({
- SendMessage(d->nextClipboardViewer, m->message,
- m->wParam, m->lParam);
- } , {
- SendMessageA(d->nextClipboardViewer, m->message,
- m->wParam, m->lParam);
- });
+ SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam);
}
return true;
diff --git a/src/gui/kernel/qclipboard_x11.cpp b/src/gui/kernel/qclipboard_x11.cpp
index d37781f..12950ea 100644
--- a/src/gui/kernel/qclipboard_x11.cpp
+++ b/src/gui/kernel/qclipboard_x11.cpp
@@ -800,7 +800,7 @@ static Atom send_selection(QClipboardData *d, Atom target, Window window, Atom p
QByteArray data;
QByteArray fmt = X11->xdndAtomToString(target);
- if (fmt.isEmpty() || !QInternalMimeData::hasFormatHelper(QString::fromAscii(fmt), d->source())) { // Not a MIME type we have
+ if (fmt.isEmpty()) { // Not a MIME type we have
DEBUG("QClipboard: send_selection(): converting to type '%s' is not supported", fmt.data());
return XNone;
}
diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
index ac66d40..cbf5cb6 100644
--- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
+++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
@@ -197,11 +197,19 @@ static void cleanupCocoaApplicationDelegate()
}
}
- // Prevent Cocoa from terminating the application, since this simply
- // exits the program whithout allowing QApplication::exec() to return.
- // The call to QApplication::quit() above will instead quit the
- // application from the Qt side.
- return NSTerminateCancel;
+ if (qtPrivate->threadData->eventLoops.size() == 0) {
+ // INVARIANT: No event loop is executing. This probably
+ // means that Qt is used as a plugin, or as a part of a native
+ // Cocoa application. In any case it should be fine to
+ // terminate now:
+ return NSTerminateNow;
+ } else {
+ // Prevent Cocoa from terminating the application, since this simply
+ // exits the program whithout allowing QApplication::exec() to return.
+ // The call to QApplication::quit() above will instead quit the
+ // application from the Qt side.
+ return NSTerminateCancel;
+ }
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm
index 201f374..a2be9eb 100644
--- a/src/gui/kernel/qcocoapanel_mac.mm
+++ b/src/gui/kernel/qcocoapanel_mac.mm
@@ -85,6 +85,12 @@ QT_USE_NAMESPACE
last resort (i.e., this is code that can potentially be removed).
*/
+- (void)toggleToolbarShown:(id)sender
+{
+ macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]);
+ [super toggleToolbarShown:sender];
+}
+
- (void)keyDown:(NSEvent *)theEvent
{
bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index 1389b44..bc32078 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -49,6 +49,8 @@
#include <private/qt_cocoa_helpers_mac_p.h>
#include <private/qdnd_p.h>
#include <private/qmacinputcontext_p.h>
+#include <private/qmultitouch_mac_p.h>
+#include <private/qevent_p.h>
#include <qscrollarea.h>
#include <qhash.h>
@@ -100,7 +102,7 @@ static dndenum_mapper dnd_enums[] = {
{ NSDragOperationCopy, Qt::CopyAction, true },
{ NSDragOperationGeneric, Qt::CopyAction, false },
{ NSDragOperationEvery, Qt::ActionMask, false },
- { NSDragOperationNone, Qt::IgnoreAction, false }
+ { NSDragOperationNone, Qt::IgnoreAction, false }
};
static NSDragOperation qt_mac_mapDropAction(Qt::DropAction action)
@@ -196,8 +198,10 @@ extern "C" {
if (self) {
[self finishInitWithQWidget:widget widgetPrivate:widgetprivate];
}
+ composingText = new QString();
composing = false;
sendKeyEvents = true;
+ inKeyDown = false;
currentCustomTypes = 0;
[self setHidden:YES];
return self;
@@ -224,14 +228,14 @@ extern "C" {
currentCustomTypes = new QStringList();
*currentCustomTypes = customTypes;
const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName";
- NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType,
- NSFilenamesPboardType, NSStringPboardType,
- NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
- NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
- NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
- NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType,
+ NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType,
+ NSFilenamesPboardType, NSStringPboardType,
+ NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
+ NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
+ NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
+ NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType,
NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
- NSFilesPromisePboardType, NSInkTextPboardType,
+ NSFilesPromisePboardType, NSInkTextPboardType,
NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
// Add custom types supported by the application.
for (int i = 0; i < customTypes.size(); i++) {
@@ -276,16 +280,16 @@ extern "C" {
dropData = 0;
}
}
-
-- (void)addDropData:(id <NSDraggingInfo>)sender
+
+- (void)addDropData:(id <NSDraggingInfo>)sender
{
[self removeDropData];
- CFStringRef dropPasteboard = (CFStringRef) [[sender draggingPasteboard] name];
+ CFStringRef dropPasteboard = (CFStringRef) [[sender draggingPasteboard] name];
dropData = new QCocoaDropData(dropPasteboard);
-}
+}
-- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
-{
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
if (qwidget->testAttribute(Qt::WA_DropSiteRegistered) == false)
return NSDragOperationNone;
NSPoint windowPoint = [sender draggingLocation];
@@ -303,7 +307,7 @@ extern "C" {
NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
QPoint posDrag(localPoint.x, localPoint.y);
- NSDragOperation nsActions = [sender draggingSourceOperationMask];
+ NSDragOperation nsActions = [sender draggingSourceOperationMask];
Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions);
QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) = nsActions;
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
@@ -332,8 +336,8 @@ extern "C" {
qDMEvent.accept(); // accept by default, since enter event was accepted.
QApplication::sendEvent(qwidget, &qDMEvent);
if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) {
- // since we accepted the drag enter event, the widget expects
- // future drage move events.
+ // since we accepted the drag enter event, the widget expects
+ // future drage move events.
// ### check if we need to treat this like the drag enter event.
nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDEEvent.dropAction());
} else {
@@ -341,7 +345,7 @@ extern "C" {
}
QT_PREPEND_NAMESPACE(qt_mac_copy_answer_rect)(qDMEvent);
return nsActions;
- }
+ }
}
- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender
@@ -369,7 +373,7 @@ extern "C" {
if (qt_mac_mouse_inside_answer_rect(posDrag)
&& QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) == nsActions)
return QT_PREPEND_NAMESPACE(qt_mac_mapDropActions)(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastAction));
- // send drag move event to the widget
+ // send drag move event to the widget
QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) = nsActions;
Qt::DropActions qtAllowed = QT_PREPEND_NAMESPACE(qt_mac_mapNSDragOperations)(nsActions);
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
@@ -432,7 +436,7 @@ extern "C" {
NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
QPoint posDrop(localPoint.x, localPoint.y);
- NSDragOperation nsActions = [sender draggingSourceOperationMask];
+ NSDragOperation nsActions = [sender draggingSourceOperationMask];
Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions);
QMimeData *mimeData = dropData;
if (QDragManager::self()->source())
@@ -453,6 +457,7 @@ extern "C" {
- (void)dealloc
{
+ delete composingText;
[[NSNotificationCenter defaultCenter] removeObserver:self];
delete currentCustomTypes;
[self unregisterDraggedTypes];
@@ -547,15 +552,7 @@ extern "C" {
qwidget->objectName().local8Bit().data());
#endif
QPainter p(qwidget);
- QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(qwidget->parent());
- QPoint scrollAreaOffset;
- if (scrollArea && scrollArea->viewport() == qwidget) {
- QAbstractScrollAreaPrivate *priv
- = static_cast<QAbstractScrollAreaPrivate *>(qt_widget_private(scrollArea));
- scrollAreaOffset = priv->contentsOffset();
- p.translate(-scrollAreaOffset);
- }
- qwidgetprivate->paintBackground(&p, qrgn, scrollAreaOffset,
+ qwidgetprivate->paintBackground(&p, qrgn,
qwidget->isWindow() ? QWidgetPrivate::DrawAsRoot : 0);
p.end();
}
@@ -566,11 +563,6 @@ extern "C" {
qt_sendSpontaneousEvent(qwidget, &e);
if (!redirectionOffset.isNull())
QPainter::restoreRedirected(qwidget);
-#ifdef QT_RASTER_PAINTENGINE
- if(engine && engine->type() == QPaintEngine::Raster)
- static_cast<QRasterPaintEngine*>(engine)->flush(qwidget,
- qrgn.boundingRect().topLeft());
-#endif
if (engine)
engine->setSystemClip(QRegion());
qwidget->setAttribute(Qt::WA_WState_InPaintEvent, false);
@@ -641,7 +633,7 @@ extern "C" {
QHoverEvent he(QEvent::HoverEnter, QPoint(viewPoint.x, viewPoint.y), QPoint(-1, -1));
QApplicationPrivate::instance()->notify_helper(qwidget, &he);
}
- }
+ }
}
- (void)mouseExited:(NSEvent *)event
@@ -650,7 +642,7 @@ extern "C" {
NSPoint globalPoint = [[event window] convertBaseToScreen:[event locationInWindow]];
if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) {
QApplication::sendEvent(qwidget, &leaveEvent);
-
+
// ### Think about if it is necessary to update the cursor, should only be for a few cases.
qt_mac_update_cursor_at_global_pos(flipPoint(globalPoint).toPoint());
if (qwidget->testAttribute(Qt::WA_Hover)
@@ -675,14 +667,22 @@ extern "C" {
- (void)mouseMoved:(NSEvent *)theEvent
{
- qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton);
+ // We always enable mouse tracking for all QCocoaView-s. In cases where we have
+ // child views, we will receive mouseMoved for both parent & the child (if
+ // mouse is over the child). We need to ignore the parent mouseMoved in such
+ // cases.
+ NSPoint windowPoint = [theEvent locationInWindow];
+ NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
+ if (candidateView && candidateView == self) {
+ qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton);
+ }
}
- (void)mouseDown:(NSEvent *)theEvent
{
qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::LeftButton);
// Don't call super here. This prevents us from getting the mouseUp event,
- // which we need to send even if the mouseDown event was not accepted.
+ // which we need to send even if the mouseDown event was not accepted.
// (this is standard Qt behavior.)
}
@@ -696,7 +696,7 @@ extern "C" {
}
- (void)rightMouseDown:(NSEvent *)theEvent
-{
+{
bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::RightButton);
if (!mouseOK)
@@ -845,6 +845,102 @@ extern "C" {
[super tabletPoint:tabletEvent];
}
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+- (void)touchesBeganWithEvent:(NSEvent *)event;
+{
+ bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
+ qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
+}
+
+- (void)touchesMovedWithEvent:(NSEvent *)event;
+{
+ bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
+ qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
+}
+
+- (void)touchesEndedWithEvent:(NSEvent *)event;
+{
+ bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
+ qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
+}
+
+- (void)touchesCancelledWithEvent:(NSEvent *)event;
+{
+ bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
+ qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
+}
+
+- (void)magnifyWithEvent:(NSEvent *)event;
+{
+ if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
+ return;
+
+ QNativeGestureEvent qNGEvent;
+ qNGEvent.gestureType = QNativeGestureEvent::Zoom;
+ NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
+ qNGEvent.position = flipPoint(p).toPoint();
+ qNGEvent.percentage = [event magnification];
+ qt_sendSpontaneousEvent(qwidget, &qNGEvent);
+}
+
+- (void)rotateWithEvent:(NSEvent *)event;
+{
+ if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
+ return;
+
+ QNativeGestureEvent qNGEvent;
+ qNGEvent.gestureType = QNativeGestureEvent::Rotate;
+ NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
+ qNGEvent.position = flipPoint(p).toPoint();
+ qNGEvent.percentage = -[event rotation];
+ qt_sendSpontaneousEvent(qwidget, &qNGEvent);
+}
+
+- (void)swipeWithEvent:(NSEvent *)event;
+{
+ if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
+ return;
+
+ QNativeGestureEvent qNGEvent;
+ qNGEvent.gestureType = QNativeGestureEvent::Swipe;
+ NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
+ qNGEvent.position = flipPoint(p).toPoint();
+ if ([event deltaX] == 1)
+ qNGEvent.angle = 180.0f;
+ else if ([event deltaX] == -1)
+ qNGEvent.angle = 0.0f;
+ else if ([event deltaY] == 1)
+ qNGEvent.angle = 90.0f;
+ else if ([event deltaY] == -1)
+ qNGEvent.angle = 270.0f;
+ qt_sendSpontaneousEvent(qwidget, &qNGEvent);
+}
+
+- (void)beginGestureWithEvent:(NSEvent *)event;
+{
+ if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
+ return;
+
+ QNativeGestureEvent qNGEvent;
+ qNGEvent.gestureType = QNativeGestureEvent::GestureBegin;
+ NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
+ qNGEvent.position = flipPoint(p).toPoint();
+ qt_sendSpontaneousEvent(qwidget, &qNGEvent);
+}
+
+- (void)endGestureWithEvent:(NSEvent *)event;
+{
+ if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
+ return;
+
+ QNativeGestureEvent qNGEvent;
+ qNGEvent.gestureType = QNativeGestureEvent::GestureEnd;
+ NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]];
+ qNGEvent.position = flipPoint(p).toPoint();
+ qt_sendSpontaneousEvent(qwidget, &qNGEvent);
+}
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+
- (void)frameDidChange:(NSNotification *)note
{
Q_UNUSED(note);
@@ -887,6 +983,15 @@ extern "C" {
return qwidget->focusPolicy() != Qt::NoFocus;
}
+- (BOOL)resignFirstResponder
+{
+ // Seems like the following test only triggers if this
+ // view is inside a QMacNativeWidget:
+ if (qwidget == QApplication::focusWidget())
+ QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason);
+ return YES;
+}
+
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
{
Q_UNUSED(isLocal);
@@ -932,6 +1037,7 @@ extern "C" {
- (void)keyDown:(NSEvent *)theEvent
{
+ inKeyDown = true;
sendKeyEvents = true;
QWidget *widgetToGetKey = qwidget;
@@ -951,6 +1057,7 @@ extern "C" {
if (!keyOK && !sendToPopup)
[super keyDown:theEvent];
}
+ inKeyDown = false;
}
@@ -988,20 +1095,37 @@ extern "C" {
- (void) insertText:(id)aString
{
- if (composing) {
- // Send the commit string to the widget.
- QString commitText;
+ QString commitText;
+ if ([aString length]) {
if ([aString isKindOfClass:[NSAttributedString class]]) {
- commitText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string]));
+ commitText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string]));
} else {
commitText = QCFString::toQString(reinterpret_cast<CFStringRef>(aString));
};
+ }
+
+ if ([aString length] && !inKeyDown) {
+ // Handle the case where insertText is called from somewhere else than the keyDown
+ // implementation, for example when inserting text from the character palette.
+ QInputMethodEvent e;
+ e.setCommitString(commitText);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ } else if ([aString length] && composing) {
+ // Send the commit string to the widget.
composing = false;
sendKeyEvents = false;
QInputMethodEvent e;
e.setCommitString(commitText);
qt_sendSpontaneousEvent(qwidget, &e);
+ } else {
+ // The key sequence "`q" on a French Keyboard will generate two calls to insertText before
+ // it returns from interpretKeyEvents. The first call will turn off 'composing' and accept
+ // the "`" key. The last keyDown event needs to be processed by the widget to get the
+ // character "q". The string parameter is ignored for the second call.
+ sendKeyEvents = true;
}
+
+ composingText->clear();
}
- (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange
@@ -1023,7 +1147,7 @@ extern "C" {
while (index < composingLength) {
NSRange effectiveRange;
NSRange range = NSMakeRange(index, composingLength-index);
- NSDictionary *attributes = [aString attributesAtIndex:index
+ NSDictionary *attributes = [aString attributesAtIndex:index
longestEffectiveRange:&effectiveRange
inRange:range];
NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName];
@@ -1032,7 +1156,7 @@ extern "C" {
NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName];
if (color) {
clr = colorFrom(color);
- }
+ }
QTextCharFormat format;
format.setFontUnderline(true);
format.setUnderlineColor(clr);
@@ -1055,12 +1179,21 @@ extern "C" {
attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
0, composingLength, format);
}
+ *composingText = qtText;
QInputMethodEvent e(qtText, attrs);
qt_sendSpontaneousEvent(qwidget, &e);
+ if (!composingLength)
+ composing = false;
}
- (void) unmarkText
{
+ if (composing) {
+ QInputMethodEvent e;
+ e.setCommitString(*composingText);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ }
+ composingText->clear();
composing = false;
}
@@ -1099,7 +1232,7 @@ extern "C" {
- (NSRange) markedRange
{
- NSRange range;
+ NSRange range;
if (composing) {
range.location = 0;
range.length = composingLength;
@@ -1124,13 +1257,13 @@ extern "C" {
selRange.length = 0;
}
return selRange;
-
+
}
- (NSRect) firstRectForCharacterRange:(NSRange)theRange
{
Q_UNUSED(theRange);
- // The returned rect is always based on the internal cursor.
+ // The returned rect is always based on the internal cursor.
QRect mr(qwidget->inputMethodQuery(Qt::ImMicroFocus).toRect());
QPoint mp(qwidget->mapToGlobal(QPoint(mr.bottomLeft())));
NSRect rect ;
@@ -1278,7 +1411,7 @@ Qt::DropAction QDragManager::drag(QDrag *o)
NSImage *image = (NSImage *)qt_mac_create_nsimage(pix);
[image retain];
DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent];
- // save supported actions
+ // save supported actions
[dndParams->view setSupportedActions: qt_mac_mapDropActions(dragPrivate()->possible_actions)];
NSPoint imageLoc = {dndParams->localPoint.x - hotspot.x(),
dndParams->localPoint.y + pix.height() - hotspot.y()};
@@ -1302,7 +1435,7 @@ Qt::DropAction QDragManager::drag(QDrag *o)
Qt::DropAction performedAction(qt_mac_mapNSDragOperation(dndParams->performedAction));
// do post drag processing, if required.
if(performedAction != Qt::IgnoreAction) {
- // check if the receiver points us to a file location.
+ // check if the receiver points us to a file location.
// if so, we need to do the file copy/move ourselves.
QCFType<CFURLRef> pasteLocation = 0;
PasteboardCopyPasteLocation(dragBoard.pasteBoard(), &pasteLocation);
diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h
index 6e00400..9d4e3d0 100644
--- a/src/gui/kernel/qcocoaview_mac_p.h
+++ b/src/gui/kernel/qcocoaview_mac_p.h
@@ -59,6 +59,7 @@ QT_FORWARD_DECLARE_CLASS(QWidgetPrivate);
QT_FORWARD_DECLARE_CLASS(QWidget);
QT_FORWARD_DECLARE_CLASS(QEvent);
QT_FORWARD_DECLARE_CLASS(QCocoaDropData);
+QT_FORWARD_DECLARE_CLASS(QString);
QT_FORWARD_DECLARE_CLASS(QStringList);
QT_BEGIN_NAMESPACE
@@ -85,6 +86,8 @@ Q_GUI_EXPORT
bool composing;
int composingLength;
bool sendKeyEvents;
+ bool inKeyDown;
+ QString *composingText;
QStringList *currentCustomTypes;
NSInteger dragEnterSequence;
}
diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm
index 7674e60..59e8254 100644
--- a/src/gui/kernel/qcocoawindow_mac.mm
+++ b/src/gui/kernel/qcocoawindow_mac.mm
@@ -104,6 +104,12 @@ QT_USE_NAMESPACE
last resort (i.e., this is code that can potentially be removed).
*/
+- (void)toggleToolbarShown:(id)sender
+{
+ macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]);
+ [super toggleToolbarShown:sender];
+}
+
- (void)keyDown:(NSEvent *)theEvent
{
bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index fbbc6bf..e26a592 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
\ingroup appearance
\ingroup shared
- \mainclass
+
This class is mainly used to create mouse cursors that are
associated with particular widgets and to get and set the position
@@ -403,7 +403,7 @@ void QCursorData::initialize()
QCursor::QCursor()
{
if (!QCursorData::initialized) {
- if (qApp->startingUp()) {
+ if (QApplication::startingUp()) {
d = 0;
return;
}
@@ -561,7 +561,6 @@ QCursor::operator QVariant() const
{
return QVariant(QVariant::Cursor, this);
}
-
+QT_END_NAMESPACE
#endif // QT_NO_CURSOR
-QT_END_NAMESPACE
diff --git a/src/gui/kernel/qcursor_qws.cpp b/src/gui/kernel/qcursor_qws.cpp
index b6fd149..fb44df8 100644
--- a/src/gui/kernel/qcursor_qws.cpp
+++ b/src/gui/kernel/qcursor_qws.cpp
@@ -66,7 +66,11 @@ QCursorData::~QCursorData()
{
delete bm;
delete bmm;
- QPaintDevice::qwsDisplay()->destroyCursor(id);
+ QT_TRY {
+ QPaintDevice::qwsDisplay()->destroyCursor(id);
+ } QT_CATCH(const std::bad_alloc &) {
+ // do nothing.
+ }
}
diff --git a/src/gui/kernel/qcursor_s60.cpp b/src/gui/kernel/qcursor_s60.cpp
new file mode 100644
index 0000000..1f89430
--- /dev/null
+++ b/src/gui/kernel/qcursor_s60.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qcursor_p.h>
+#include <qcursor.h>
+#include <qt_s60_p.h>
+
+#ifdef QT_NO_CURSOR
+QT_BEGIN_NAMESPACE
+
+QPoint QCursor::pos()
+{
+ return S60->lastCursorPos;
+}
+
+void QCursor::setPos(int x, int y)
+{
+ S60->lastCursorPos = QPoint(x, y);
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_CURSOR
diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp
index a4a94c1..2867e62 100644
--- a/src/gui/kernel/qcursor_win.cpp
+++ b/src/gui/kernel/qcursor_win.cpp
@@ -66,7 +66,7 @@ QCursorData::~QCursorData()
{
delete bm;
delete bmm;
-#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
+#if !defined(Q_WS_WINCE) || defined(GWES_ICONCURS)
if (hcurs)
DestroyCursor(hcurs);
#endif
@@ -129,7 +129,7 @@ extern HBITMAP qt_createIconMask(const QBitmap &bitmap);
static HCURSOR create32BitCursor(const QPixmap &pixmap, int hx, int hy)
{
HCURSOR cur = 0;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
QBitmap mask = pixmap.mask();
if (mask.isNull()) {
mask = QBitmap(pixmap.size());
@@ -317,54 +317,50 @@ void QCursorData::update()
phand_bits, phandm_bits
};
- unsigned short *sh;
+ wchar_t *sh = 0;
switch (cshape) { // map to windows cursor
case Qt::ArrowCursor:
- sh = (unsigned short*)IDC_ARROW;
+ sh = IDC_ARROW;
break;
case Qt::UpArrowCursor:
- sh = (unsigned short*)IDC_UPARROW;
+ sh = IDC_UPARROW;
break;
case Qt::CrossCursor:
- sh = (unsigned short*)IDC_CROSS;
+ sh = IDC_CROSS;
break;
case Qt::WaitCursor:
- sh = (unsigned short*)IDC_WAIT;
+ sh = IDC_WAIT;
break;
case Qt::IBeamCursor:
- sh = (unsigned short*)IDC_IBEAM;
+ sh = IDC_IBEAM;
break;
case Qt::SizeVerCursor:
- sh = (unsigned short*)IDC_SIZENS;
+ sh = IDC_SIZENS;
break;
case Qt::SizeHorCursor:
- sh = (unsigned short*)IDC_SIZEWE;
+ sh = IDC_SIZEWE;
break;
case Qt::SizeBDiagCursor:
- sh = (unsigned short*)IDC_SIZENESW;
+ sh = IDC_SIZENESW;
break;
case Qt::SizeFDiagCursor:
- sh = (unsigned short*)IDC_SIZENWSE;
+ sh = IDC_SIZENWSE;
break;
case Qt::SizeAllCursor:
- sh = (unsigned short*)IDC_SIZEALL;
+ sh = IDC_SIZEALL;
break;
case Qt::ForbiddenCursor:
- sh = (unsigned short*)IDC_NO;
+ sh = IDC_NO;
break;
case Qt::WhatsThisCursor:
- sh = (unsigned short*)IDC_HELP;
+ sh = IDC_HELP;
break;
case Qt::BusyCursor:
- sh = (unsigned short*)IDC_APPSTARTING;
+ sh = IDC_APPSTARTING;
break;
case Qt::PointingHandCursor:
- if ((QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) > QSysInfo::WV_95 ||
- (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) > QSysInfo::WV_NT) {
- sh = (unsigned short*)IDC_HAND;
- break;
- }
- // fall through
+ sh = IDC_HAND;
+ break;
case Qt::BlankCursor:
case Qt::SplitVCursor:
case Qt::SplitHCursor:
@@ -407,7 +403,7 @@ void QCursorData::update()
}
int n = qMax(1, bbits.width() / 8);
int h = bbits.height();
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
uchar* xBits = new uchar[h * n];
uchar* xMask = new uchar[h * n];
int x = 0;
@@ -430,7 +426,7 @@ void QCursorData::update()
xBits, xMask);
delete [] xBits;
delete [] xMask;
-#elif defined(GWES_ICONCURS) // Q_OS_WINCE
+#elif defined(GWES_ICONCURS) // Q_WS_WINCE
// Windows CE only supports fixed cursor size.
int sysW = GetSystemMetrics(SM_CXCURSOR);
int sysH = GetSystemMetrics(SM_CYCURSOR);
@@ -480,13 +476,11 @@ void QCursorData::update()
qWarning("QCursor::update: Invalid cursor shape %d", cshape);
return;
}
- // ### From MSDN:
- // ### LoadCursor has been superseded by the LoadImage function.
- QT_WA({
- hcurs = LoadCursorW(0, reinterpret_cast<const TCHAR *>(sh));
- } , {
- hcurs = LoadCursorA(0, reinterpret_cast<const char*>(sh));
- });
+#ifdef Q_WS_WINCE
+ hcurs = LoadCursor(0, sh);
+#else
+ hcurs = (HCURSOR)LoadImage(0, sh, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+#endif
}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget.h b/src/gui/kernel/qdesktopwidget.h
index 38f88b8..cc95795 100644
--- a/src/gui/kernel/qdesktopwidget.h
+++ b/src/gui/kernel/qdesktopwidget.h
@@ -56,6 +56,9 @@ class QDesktopWidgetPrivate;
class Q_GUI_EXPORT QDesktopWidget : public QWidget
{
Q_OBJECT
+ Q_PROPERTY(bool virtualDesktop READ isVirtualDesktop)
+ Q_PROPERTY(int screenCount READ screenCount NOTIFY screenCountChanged)
+ Q_PROPERTY(int primaryScreen READ primaryScreen)
public:
QDesktopWidget();
~QDesktopWidget();
@@ -63,6 +66,7 @@ public:
bool isVirtualDesktop() const;
int numScreens() const;
+ int screenCount() const;
int primaryScreen() const;
int screenNumber(const QWidget *widget = 0) const;
@@ -85,6 +89,7 @@ public:
Q_SIGNALS:
void resized(int);
void workAreaResized(int);
+ void screenCountChanged(int);
protected:
void resizeEvent(QResizeEvent *e);
@@ -97,6 +102,9 @@ private:
friend class QApplicationPrivate;
};
+inline int QDesktopWidget::screenCount() const
+{ return numScreens(); }
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/kernel/qdesktopwidget.qdoc b/src/gui/kernel/qdesktopwidget.qdoc
new file mode 100644
index 0000000..0c2c8a5
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget.qdoc
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QDesktopWidget
+ \brief The QDesktopWidget class provides access to screen information on multi-head systems.
+
+ \ingroup advanced
+ \ingroup desktop
+
+ QApplication::desktop() function should be used to get an instance
+ of the QDesktopWidget.
+
+ Systems with more than one graphics card and monitor can manage the
+ physical screen space available either as multiple desktops, or as a
+ large virtual desktop, which usually has the size of the bounding
+ rectangle of all the screens (see virtualDesktop). For an
+ application, one of the available screens is the primary screen, i.e.
+ the screen where the main widget resides (see primaryScreen). All
+ windows opened in the context of the application should be
+ constrained to the boundaries of the primary screen; for example,
+ it would be inconvenient if a dialog box popped up on a different
+ screen, or split over two screens.
+
+ The QDesktopWidget provides information about the geometry of the
+ available screens with screenGeometry(). The number of screens
+ available is returned by screenCount, and the screenCountChanged
+ signal is emitted when screens are added or removed during runtime.
+ The screen number that a particular point or widget is located in
+ is returned by screenNumber().
+
+ Widgets provided by Qt use this class, for example, to place
+ tooltips, menus and dialog boxes according to the parent or
+ application widget. Applications can use this class to save window
+ positions, or to place child widgets and dialogs on one particular
+ screen.
+
+ \img qdesktopwidget.png Managing Multiple Screens
+
+ In the illustration above, Application One's primary screen is
+ screen 0, and App Two's primary screen is screen 1.
+
+ \target multiple screens note
+ \note QDesktopWidget inherits the QWidget properties, width() and
+ height(), which specify the size of the desktop. However, for
+ desktops with multiple screens, the size of the desktop is the union
+ of all the screen sizes, so width() and height() should \e not be
+ used for computing the size of a widget to be placed on one of the
+ screens. The correct width and height values are obtained using
+ availableGeometry() or screenGeometry() for a particular screen.
+
+ \sa QApplication, QApplication::desktop(), QX11Info::appRootWindow()
+*/
+
+/*!
+ \fn QDesktopWidget::QDesktopWidget()
+
+ \internal
+
+ Creates the desktop widget.
+
+ If the system supports a virtual desktop, this widget will have
+ the size of the virtual desktop; otherwise this widget will have
+ the size of the primary screen.
+
+ Instead of using QDesktopWidget directly, use QApplication::desktop().
+*/
+
+/*!
+ \fn QDesktopWidget::~QDesktopWidget()
+
+ \internal
+
+ Destroys the desktop widget and frees any allocated resources.
+*/
+
+/*!
+ \fn int QDesktopWidget::numScreens() const
+
+ Returns the number of available screens.
+
+ \obsolete
+
+ This function is deprecated. Use screenCount instead.
+
+ \sa primaryScreen
+*/
+
+/*!
+ \fn QWidget *QDesktopWidget::screen(int screen)
+
+ Returns a widget that represents the screen with index \a screen
+ (a value of -1 means the default screen).
+
+ If the system uses a virtual desktop, the returned widget will
+ have the geometry of the entire virtual desktop; i.e., bounding
+ every \a screen.
+
+ \sa primaryScreen, screenCount, virtualDesktop
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::availableGeometry(int screen) const
+
+ Returns the available geometry of the screen with index \a screen. What
+ is available will be subrect of screenGeometry() based on what the
+ platform decides is available (for example excludes the dock and menu bar
+ on Mac OS X, or the task bar on Windows). The default screen is used if
+ \a screen is -1.
+
+ \sa screenNumber(), screenGeometry()
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const
+ \overload
+
+ Returns the available geometry of the screen which contains \a widget.
+
+ \sa screenGeometry()
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::availableGeometry(const QPoint &p) const
+ \overload
+
+ Returns the available geometry of the screen which contains \a p.
+
+ \sa screenGeometry()
+*/
+
+
+/*!
+ \fn const QRect QDesktopWidget::screenGeometry(int screen) const
+
+ Returns the geometry of the screen with index \a screen. The default
+ screen is used if \a screen is -1.
+
+ \sa screenNumber()
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const
+ \overload
+
+ Returns the geometry of the screen which contains \a widget.
+*/
+
+/*!
+ \fn const QRect QDesktopWidget::screenGeometry(const QPoint &p) const
+ \overload
+
+ Returns the geometry of the screen which contains \a p.
+*/
+
+
+/*!
+ \fn int QDesktopWidget::screenNumber(const QWidget *widget) const
+
+ Returns the index of the screen that contains the largest
+ part of \a widget, or -1 if the widget not on a screen.
+
+ \sa primaryScreen
+*/
+
+/*!
+ \fn int QDesktopWidget::screenNumber(const QPoint &point) const
+
+ \overload
+ Returns the index of the screen that contains the \a point, or the
+ screen which is the shortest distance from the \a point.
+
+ \sa primaryScreen
+*/
+
+/*!
+ \fn void QDesktopWidget::resizeEvent(QResizeEvent *event)
+ \reimp
+*/
+
+/*!
+ \fn void QDesktopWidget::resized(int screen)
+
+ This signal is emitted when the size of \a screen changes.
+*/
+
+/*!
+ \fn void QDesktopWidget::workAreaResized(int screen)
+
+ This signal is emitted when the work area available on \a screen changes.
+*/
+
+/*!
+ \property QDesktopWidget::screenCount
+ \brief the number of screens currently available on the system.
+
+ \since 4.6
+
+ \sa screenCountChanged()
+*/
+
+/*!
+ \property QDesktopWidget::primaryScreen
+ \brief the index of the screen that is configured to be the primary screen
+ on the system.
+*/
+
+/*!
+ \property QDesktopWidget::virtualDesktop
+
+ \brief if the system manages the available screens in a virtual desktop.
+
+ For virtual desktops, screen() will always return the same widget.
+ The size of the virtual desktop is the size of this desktop
+ widget.
+*/
+
+/*!
+ \fn void QDesktopWidget::screenCountChanged(int newCount)
+
+ \since 4.6
+
+ This signal is emitted when the number of screens changes to \a newCount.
+
+ \sa screenCount
+*/
diff --git a/src/gui/kernel/qdesktopwidget_mac.mm b/src/gui/kernel/qdesktopwidget_mac.mm
index 1ada345..da8a1d1 100644
--- a/src/gui/kernel/qdesktopwidget_mac.mm
+++ b/src/gui/kernel/qdesktopwidget_mac.mm
@@ -97,15 +97,13 @@ QT_USE_NAMESPACE
Q_GLOBAL_STATIC(QDesktopWidgetImplementation, qdesktopWidgetImplementation)
QDesktopWidgetImplementation::QDesktopWidgetImplementation()
- : appScreen(0), displays(0)
+ : appScreen(0)
{
onResize();
}
QDesktopWidgetImplementation::~QDesktopWidgetImplementation()
{
- if (displays)
- [displays release];
}
QDesktopWidgetImplementation *QDesktopWidgetImplementation::instance()
@@ -118,13 +116,7 @@ QRect QDesktopWidgetImplementation::availableRect(int screenIndex) const
if (screenIndex < 0 || screenIndex >= screenCount)
screenIndex = appScreen;
- NSRect r = [[displays objectAtIndex:screenIndex] visibleFrame];
- NSRect primaryRect = [[displays objectAtIndex:0] frame];
-
- const int flippedY = - r.origin.y + // account for position offset and
- primaryRect.size.height - r.size.height; // height difference.
- return QRectF(r.origin.x, flippedY,
- r.size.width, r.size.height).toRect();
+ return availableRects[screenIndex].toRect();
}
QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const
@@ -132,22 +124,28 @@ QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const
if (screenIndex < 0 || screenIndex >= screenCount)
screenIndex = appScreen;
- NSRect r = [[displays objectAtIndex:screenIndex] frame];
- NSRect primaryRect = [[displays objectAtIndex:0] frame];
-
- const int flippedY = - r.origin.y + // account for position offset and
- primaryRect.size.height - r.size.height; // height difference.
- return QRectF(r.origin.x, flippedY,
- r.size.width, r.size.height).toRect();
+ return screenRects[screenIndex].toRect();
}
void QDesktopWidgetImplementation::onResize()
{
- if (displays)
- [displays release];
-
- displays = [[NSScreen screens] retain];
- screenCount = [displays count];
+ QMacCocoaAutoReleasePool pool;
+ NSArray *displays = [NSScreen screens];
+ screenCount = [displays count];
+
+ screenRects.clear();
+ availableRects.clear();
+ NSRect primaryRect = [[displays objectAtIndex:0] frame];
+ for (int i = 0; i<screenCount; i++) {
+ NSRect r = [[displays objectAtIndex:i] frame];
+ const int flippedY = - r.origin.y + // account for position offset and
+ primaryRect.size.height - r.size.height; // height difference.
+ screenRects.append(QRectF(r.origin.x, flippedY,
+ r.size.width, r.size.height));
+ r = [[displays objectAtIndex:i] visibleFrame];
+ availableRects.append(QRectF(r.origin.x, flippedY,
+ r.size.width, r.size.height));
+ }
}
@@ -195,7 +193,7 @@ const QRect QDesktopWidget::screenGeometry(int screen) const
int QDesktopWidget::screenNumber(const QWidget *widget) const
{
- QDesktopWidgetImplementation *d = qdesktopWidgetImplementation();
+ QDesktopWidgetImplementation *d = qdesktopWidgetImplementation();
if (!widget)
return d->appScreen;
QRect frame = widget->frameGeometry();
@@ -216,7 +214,7 @@ int QDesktopWidget::screenNumber(const QWidget *widget) const
int QDesktopWidget::screenNumber(const QPoint &point) const
{
- QDesktopWidgetImplementation *d = qdesktopWidgetImplementation();
+ QDesktopWidgetImplementation *d = qdesktopWidgetImplementation();
int closestScreen = -1;
int shortestDistance = INT_MAX;
for (int i = 0; i < d->screenCount; ++i) {
@@ -232,13 +230,25 @@ int QDesktopWidget::screenNumber(const QPoint &point) const
void QDesktopWidget::resizeEvent(QResizeEvent *)
{
- QDesktopWidgetImplementation *d = qdesktopWidgetImplementation();
+ QDesktopWidgetImplementation *d = qdesktopWidgetImplementation();
+
+ const int oldScreenCount = d->screenCount;
+ const QVector<QRectF> oldRects(d->screenRects);
+ const QVector<QRectF> oldWorks(d->availableRects);
d->onResize();
- for (int i = 0; i < d->screenCount; ++i) {
- emit resized(i);
+ for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) {
+ if (oldRects.at(i) != d->screenRects.at(i))
+ emit resized(i);
+ }
+ for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) {
+ if (oldWorks.at(i) != d->availableRects.at(i))
+ emit workAreaResized(i);
}
+
+ if (oldScreenCount != d->screenCount)
+ emit screenCountChanged(d->screenCount);
}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget_mac_p.h b/src/gui/kernel/qdesktopwidget_mac_p.h
index 77af8f7..91d970e 100644
--- a/src/gui/kernel/qdesktopwidget_mac_p.h
+++ b/src/gui/kernel/qdesktopwidget_mac_p.h
@@ -64,7 +64,8 @@ public:
int appScreen;
int screenCount;
- NSArray *displays;
+ QVector<QRectF> availableRects;
+ QVector<QRectF> screenRects;
QRect availableRect(int screenIndex) const;
QRect screenRect(int screenIndex) const;
diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp
new file mode 100644
index 0000000..4127302
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget_s60.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesktopwidget.h"
+#include "qapplication_p.h"
+#include "qwidget_p.h"
+#include "qt_s60_p.h"
+#include <w32std.h>
+
+#include "hal.h"
+#include "hal_data.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesktopWidgetPrivate : public QWidgetPrivate
+{
+
+public:
+ QDesktopWidgetPrivate();
+ ~QDesktopWidgetPrivate();
+
+ static void init(QDesktopWidget *that);
+ static void cleanup();
+
+ static int screenCount;
+ static int primaryScreen;
+
+ static QVector<QRect> *rects;
+ static QVector<QRect> *workrects;
+
+ static int refcount;
+};
+
+int QDesktopWidgetPrivate::screenCount = 1;
+int QDesktopWidgetPrivate::primaryScreen = 0;
+QVector<QRect> *QDesktopWidgetPrivate::rects = 0;
+QVector<QRect> *QDesktopWidgetPrivate::workrects = 0;
+int QDesktopWidgetPrivate::refcount = 0;
+
+QDesktopWidgetPrivate::QDesktopWidgetPrivate()
+{
+ ++refcount;
+}
+
+QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
+{
+ if (!--refcount)
+ cleanup();
+}
+
+void QDesktopWidgetPrivate::init(QDesktopWidget *that)
+{
+ int screenCount=0;
+
+ if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone)
+ QDesktopWidgetPrivate::screenCount = screenCount;
+ else
+ QDesktopWidgetPrivate::screenCount = 0;
+
+ rects = new QVector<QRect>();
+ workrects = new QVector<QRect>();
+
+ rects->resize(QDesktopWidgetPrivate::screenCount);
+ workrects->resize(QDesktopWidgetPrivate::screenCount);
+
+ // ### TODO: Implement proper multi-display support
+ rects->resize(1);
+ rects->replace(0, that->rect());
+ workrects->resize(1);
+ workrects->replace(0, that->rect());
+}
+
+void QDesktopWidgetPrivate::cleanup()
+{
+ delete rects;
+ rects = 0;
+ delete workrects;
+ workrects = 0;
+}
+
+
+QDesktopWidget::QDesktopWidget()
+ : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
+{
+ setObjectName(QLatin1String("desktop"));
+ QDesktopWidgetPrivate::init(this);
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return true;
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return QDesktopWidgetPrivate::primaryScreen;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ Q_D(const QDesktopWidget);
+ return QDesktopWidgetPrivate::screenCount;
+}
+
+QWidget *QDesktopWidget::screen(int /* screen */)
+{
+ return this;
+}
+
+const QRect QDesktopWidget::availableGeometry(int /* screen */) const
+{
+ TRect clientRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ return qt_TRect2QRect(clientRect);
+}
+
+const QRect QDesktopWidget::screenGeometry(int /* screen */) const
+{
+ Q_D(const QDesktopWidget);
+ return QRect(0, 0, S60->screenWidthInPixels, S60->screenHeightInPixels);
+ }
+
+int QDesktopWidget::screenNumber(const QWidget * /* widget */) const
+{
+ return QDesktopWidgetPrivate::primaryScreen;
+}
+
+int QDesktopWidget::screenNumber(const QPoint & /* point */) const
+{
+ return QDesktopWidgetPrivate::primaryScreen;
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *)
+{
+ Q_D(QDesktopWidget);
+ QVector<QRect> oldrects;
+ oldrects = *d->rects;
+ QVector<QRect> oldworkrects;
+ oldworkrects = *d->workrects;
+ int oldscreencount = d->screenCount;
+
+ QDesktopWidgetPrivate::cleanup();
+ QDesktopWidgetPrivate::init(this);
+
+ for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) {
+ QRect oldrect = oldrects[i];
+ QRect newrect = d->rects->at(i);
+ if (oldrect != newrect)
+ emit resized(i);
+ }
+
+ for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) {
+ QRect oldrect = oldworkrects[j];
+ QRect newrect = d->workrects->at(j);
+ if (oldrect != newrect)
+ emit workAreaResized(j);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp
index 68cfa91..0caf473 100644
--- a/src/gui/kernel/qdesktopwidget_win.cpp
+++ b/src/gui/kernel/qdesktopwidget_win.cpp
@@ -45,7 +45,7 @@
#include "qlibrary.h"
#include <qvector.h>
#include <limits.h>
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include <sipapi.h>
#endif
#include "qwidget_p.h"
@@ -92,7 +92,7 @@ QVector<QRect> *QDesktopWidgetPrivate::rects = 0;
QVector<QRect> *QDesktopWidgetPrivate::workrects = 0;
static int screen_number = 0;
int QDesktopWidgetPrivate::refcount = 0;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
// Use SIP information, if available
// SipGetInfo is not supported by SSDK (no definition!).
static inline void qt_get_sip_info(QRect &rect)
@@ -152,41 +152,27 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that)
rects = new QVector<QRect>();
workrects = new QVector<QRect>();
+ screenCount = 0;
#ifndef Q_OS_WINCE
- if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
- screenCount = 0;
- // Trying to get the function pointers to Win98/2000 only functions
- QLibrary user32Lib(QLatin1String("user32"));
- if (!user32Lib.load())
- return;
+ QLibrary user32Lib(QLatin1String("user32"));
+ if (user32Lib.load()) {
enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors");
- QT_WA({
- getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW");
- } , {
- getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoA");
- });
-
- if (!enumDisplayMonitors || !getMonitorInfo) {
- screenCount = GetSystemMetrics(80); // SM_CMONITORS
- rects->resize(screenCount);
- for (int i = 0; i < screenCount; ++i)
- rects->replace(i, that->rect());
- return;
- }
- // Calls enumCallback
- enumDisplayMonitors(0, 0, enumCallback, 0);
- enumDisplayMonitors = 0;
- getMonitorInfo = 0;
- } else {
- rects->resize(1);
- rects->replace(0, that->rect());
- workrects->resize(1);
- workrects->replace(0, that->rect());
+ getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW");
}
-#else
- screenCount = 0;
+ if (!enumDisplayMonitors || !getMonitorInfo) {
+ screenCount = GetSystemMetrics(80); // SM_CMONITORS
+ rects->resize(screenCount);
+ for (int i = 0; i < screenCount; ++i)
+ rects->replace(i, that->rect());
+ return;
+ }
+ // Calls enumCallback
+ enumDisplayMonitors(0, 0, enumCallback, 0);
+ enumDisplayMonitors = 0;
+ getMonitorInfo = 0;
+#else
QLibrary coreLib(QLatin1String("coredll"));
if (coreLib.load()) {
// CE >= 4.0 case
@@ -208,7 +194,7 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that)
SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
QRect qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
-#if defined(Q_OS_WINCE_WM)
+#if defined(Q_WS_WINCE_WM)
qt_get_sip_info(qr);
#endif
@@ -222,7 +208,7 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that)
enumDisplayMonitors(0, 0, enumCallback, 0);
enumDisplayMonitors = 0;
getMonitorInfo = 0;
-#endif // Q_OS_WINCE
+#endif // Q_WS_WINCE
}
QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
@@ -303,106 +289,99 @@ QWidget *QDesktopWidget::screen(int /* screen */)
const QRect QDesktopWidget::availableGeometry(int screen) const
{
Q_D(const QDesktopWidget);
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
for(int i=0; i < d->workrects->size(); ++i)
qt_get_sip_info((*d->workrects)[i]);
#endif
- if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
- if (screen < 0 || screen >= d->screenCount)
- screen = d->primaryScreen;
+ if (screen < 0 || screen >= d->screenCount)
+ screen = d->primaryScreen;
- return d->workrects->at(screen);
- } else {
- return d->workrects->at(d->primaryScreen);
- }
+ return d->workrects->at(screen);
}
const QRect QDesktopWidget::screenGeometry(int screen) const
{
const QDesktopWidgetPrivate *d = d_func();
- if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
- if (screen < 0 || screen >= d->screenCount)
- screen = d->primaryScreen;
+ if (screen < 0 || screen >= d->screenCount)
+ screen = d->primaryScreen;
- return d->rects->at(screen);
- } else {
- return d->rects->at(d->primaryScreen);
- }
+ return d->rects->at(screen);
}
int QDesktopWidget::screenNumber(const QWidget *widget) const
{
Q_D(const QDesktopWidget);
- if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
- if (!widget)
- return d->primaryScreen;
- QRect frame = widget->frameGeometry();
- if (!widget->isWindow())
- frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0)));
-
- int maxSize = -1;
- int maxScreen = -1;
-
- for (int i = 0; i < d->screenCount; ++i) {
- QRect sect = d->rects->at(i).intersected(frame);
- int size = sect.width() * sect.height();
- if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
- maxSize = size;
- maxScreen = i;
- }
- }
- return maxScreen;
- } else {
+ if (!widget)
return d->primaryScreen;
+
+ QRect frame = widget->frameGeometry();
+ if (!widget->isWindow())
+ frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0)));
+
+ int maxSize = -1;
+ int maxScreen = -1;
+
+ for (int i = 0; i < d->screenCount; ++i) {
+ QRect sect = d->rects->at(i).intersected(frame);
+ int size = sect.width() * sect.height();
+ if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
+ maxSize = size;
+ maxScreen = i;
+ }
}
+
+ return maxScreen;
}
int QDesktopWidget::screenNumber(const QPoint &point) const
{
Q_D(const QDesktopWidget);
+
int closestScreen = -1;
- if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
- int shortestDistance = INT_MAX;
- for (int i = 0; i < d->screenCount; ++i) {
- int thisDistance = d->pointToRect(point, d->rects->at(i));
- if (thisDistance < shortestDistance) {
- shortestDistance = thisDistance;
- closestScreen = i;
- }
+ int shortestDistance = INT_MAX;
+
+ for (int i = 0; i < d->screenCount; ++i) {
+ int thisDistance = d->pointToRect(point, d->rects->at(i));
+ if (thisDistance < shortestDistance) {
+ shortestDistance = thisDistance;
+ closestScreen = i;
}
}
+
return closestScreen;
}
void QDesktopWidget::resizeEvent(QResizeEvent *)
{
Q_D(QDesktopWidget);
- QVector<QRect> oldrects;
- oldrects = *d->rects;
- QVector<QRect> oldworkrects;
- oldworkrects = *d->workrects;
+ const QVector<QRect> oldrects(*d->rects);
+ const QVector<QRect> oldworkrects(*d->workrects);
int oldscreencount = d->screenCount;
QDesktopWidgetPrivate::cleanup();
QDesktopWidgetPrivate::init(this);
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
for(int i=0; i < d->workrects->size(); ++i)
qt_get_sip_info((*d->workrects)[i]);
#endif
for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) {
- QRect oldrect = oldrects[i];
- QRect newrect = d->rects->at(i);
+ const QRect oldrect = oldrects[i];
+ const QRect newrect = d->rects->at(i);
if (oldrect != newrect)
emit resized(i);
}
for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) {
- QRect oldrect = oldworkrects[j];
- QRect newrect = d->workrects->at(j);
+ const QRect oldrect = oldworkrects[j];
+ const QRect newrect = d->workrects->at(j);
if (oldrect != newrect)
emit workAreaResized(j);
}
+
+ if (oldscreencount != d->screenCount) {
+ emit screenCountChanged(d->screenCount);
+ }
}
#ifdef Q_CC_MSVC
diff --git a/src/gui/kernel/qdesktopwidget_x11.cpp b/src/gui/kernel/qdesktopwidget_x11.cpp
index 2fc322d..b4ad31d 100644
--- a/src/gui/kernel/qdesktopwidget_x11.cpp
+++ b/src/gui/kernel/qdesktopwidget_x11.cpp
@@ -197,7 +197,7 @@ void QDesktopWidgetPrivate::init()
if (screens) {
// leaks QWidget* pointers on purpose, can't delete them as pointer escapes
- screens = (QWidget**) realloc(screens, j * sizeof(QWidget*));
+ screens = q_check_ptr((QWidget**) realloc(screens, j * sizeof(QWidget*)));
if (j > screenCount)
memset(&screens[screenCount], 0, (j-screenCount) * sizeof(QWidget*));
}
@@ -285,26 +285,36 @@ const QRect QDesktopWidget::availableGeometry(int screen) const
if (d->workareas[screen].isValid())
return d->workareas[screen];
- if ((d->screenCount == 1 || !isVirtualDesktop())
- && X11->isSupportedByWM(ATOM(_NET_WORKAREA))) {
+ if (X11->isSupportedByWM(ATOM(_NET_WORKAREA))) {
+ int x11Screen = isVirtualDesktop() ? DefaultScreen(X11->display) : screen;
+
Atom ret;
int format, e;
unsigned char *data = 0;
unsigned long nitems, after;
e = XGetWindowProperty(X11->display,
- QX11Info::appRootWindow(screen),
- ATOM(_NET_WORKAREA), 0, 4, False, XA_CARDINAL,
- &ret, &format, &nitems, &after, &data);
+ QX11Info::appRootWindow(x11Screen),
+ ATOM(_NET_WORKAREA), 0, 4, False, XA_CARDINAL,
+ &ret, &format, &nitems, &after, &data);
+ QRect workArea;
if (e == Success && ret == XA_CARDINAL &&
format == 32 && nitems == 4) {
long *workarea = (long *) data;
- d->workareas[screen].setRect(workarea[0], workarea[1],
- workarea[2], workarea[3]);
+ workArea = QRect(workarea[0], workarea[1], workarea[2], workarea[3]);
} else {
- d->workareas[screen] = screenGeometry(screen);
+ workArea = screenGeometry(screen);
+ }
+
+ if (isVirtualDesktop()) {
+ // intersect the workarea (which spawns all Xinerama screens) with the rect for the
+ // requested screen
+ workArea &= screenGeometry(screen);
}
+
+ d->workareas[screen] = workArea;
+
if (data)
XFree(data);
} else {
@@ -372,7 +382,32 @@ int QDesktopWidget::screenNumber(const QPoint &point) const
void QDesktopWidget::resizeEvent(QResizeEvent *event)
{
Q_D(QDesktopWidget);
+ int oldScreenCount = d->screenCount;
+ QVector<QRect> oldRects(oldScreenCount);
+ QVector<QRect> oldWorks(oldScreenCount);
+ for (int i = 0; i < oldScreenCount; ++i) {
+ oldRects[i] = d->rects[i];
+ oldWorks[i] = d->workareas[i];
+ }
+
d->init();
+
+ for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) {
+ if (oldRects.at(i) != d->rects[i])
+ emit resized(i);
+ }
+
+ // ### workareas are just reset by init, not filled with new values
+ // ### so this will not work correctly
+ for (int j = 0; j < qMin(oldScreenCount, d->screenCount); ++j) {
+ if (oldWorks.at(j) != d->workareas[j])
+ emit workAreaResized(j);
+ }
+
+ if (oldScreenCount != d->screenCount) {
+ emit screenCountChanged(d->screenCount);
+ }
+
qt_desktopwidget_workarea_dirty = true;
QWidget::resizeEvent(event);
}
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
index b6ed979..fcf140e 100644
--- a/src/gui/kernel/qdnd.cpp
+++ b/src/gui/kernel/qdnd.cpp
@@ -368,7 +368,7 @@ QDragManager::~QDragManager()
QDragManager *QDragManager::self()
{
- if (!instance && qApp && !qApp->closingDown())
+ if (!instance && !QApplication::closingDown())
instance = new QDragManager;
return instance;
}
diff --git a/src/gui/kernel/qdnd_mac.mm b/src/gui/kernel/qdnd_mac.mm
index 911983a..507ff18 100644
--- a/src/gui/kernel/qdnd_mac.mm
+++ b/src/gui/kernel/qdnd_mac.mm
@@ -405,12 +405,12 @@ bool QWidgetPrivate::qt_mac_dnd_event(uint kind, DragRef dragRef)
SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDEEvent.dropAction()));
if (!qDEEvent.isAccepted())
- // The widget is simply not interrested in this
+ // The widget is simply not interested in this
// drag. So tell carbon this by returning 'false'. We will then
// not receive any further move, drop or leave events for this widget.
return false;
else {
- // Documentation states that a drag move event is sendt immidiatly after
+ // Documentation states that a drag move event is sent immediately after
// a drag enter event. So we do that. This will honor widgets overriding
// 'dragMoveEvent' only, and not 'dragEnterEvent'
QDragMoveEvent qDMEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata,
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index 43e884a..1f64015 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -65,7 +65,7 @@
#endif
#if defined(Q_WS_WIN)
-# include <windows.h>
+# include <qt_windows.h>
# include <objidl.h>
#endif
@@ -202,7 +202,7 @@ public:
#endif
};
-class Q_GUI_EXPORT QDragManager: public QObject {
+class QDragManager: public QObject {
Q_OBJECT
QDragManager();
diff --git a/src/gui/kernel/qdnd_s60.cpp b/src/gui/kernel/qdnd_s60.cpp
new file mode 100644
index 0000000..e014940
--- /dev/null
+++ b/src/gui/kernel/qdnd_s60.cpp
@@ -0,0 +1,395 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+
+#ifndef QT_NO_DRAGANDDROP
+
+#include "qwidget.h"
+#include "qdatetime.h"
+#include "qbitmap.h"
+#include "qcursor.h"
+#include "qevent.h"
+#include "qpainter.h"
+#include "qdnd_p.h"
+
+#include <COECNTRL.H>
+// pointer cursor
+#include <w32std.h>
+#include <gdi.h>
+QT_BEGIN_NAMESPACE
+//### artistic impression of Symbians default DnD cursor ?
+
+static QPixmap *defaultPm = 0;
+static const int default_pm_hotx = -50;
+static const int default_pm_hoty = -50;
+static const char *const default_pm[] = {
+"13 9 3 1",
+". c None",
+" c #000000",
+"X c #FFFFFF",
+"X X X X X X X",
+" X X X X X X ",
+"X ......... X",
+" X.........X ",
+"X ......... X",
+" X.........X ",
+"X ......... X",
+" X X X X X X ",
+"X X X X X X X",
+};
+//### actions need to be redefined for S60
+// Shift/Ctrl handling, and final drop status
+static Qt::DropAction global_accepted_action = Qt::MoveAction;
+static Qt::DropActions possible_actions = Qt::IgnoreAction;
+
+
+// static variables in place of a proper cross-process solution
+static QDrag *drag_object;
+static bool qt_symbian_dnd_dragging = false;
+
+
+static Qt::KeyboardModifiers oldstate;
+
+class QShapedPixmapWidget
+{
+public:
+ QShapedPixmapWidget(RWsSession aWsSession,RWindowTreeNode* aNode)
+ {
+ sprite = RWsSprite(aWsSession);
+ cursorSprite.iBitmap = 0;
+ cursorSprite.iMaskBitmap = 0;
+ cursorSprite.iInvertMask = EFalse;
+ cursorSprite.iOffset = TPoint(0,0);
+ cursorSprite.iInterval = TTimeIntervalMicroSeconds32(0);
+ cursorSprite.iDrawMode = CGraphicsContext::EDrawModePEN;
+ sprite.Construct(*aNode,TPoint(0,0), ESpriteNoShadows | ESpriteNoChildClip);
+ sprite.AppendMember(cursorSprite);
+ sprite.Activate();
+ }
+ ~QShapedPixmapWidget()
+ {
+ sprite.Close();
+ cursorSprite.iBitmap = 0;
+ delete cursorBitmap;
+ cursorBitmap = 0; //redundant...
+ }
+ void disableCursor()
+ {
+ cursorSprite.iBitmap = 0;
+ sprite.UpdateMember(0,cursorSprite);
+ }
+ void enableCursor()
+ {
+ cursorSprite.iBitmap = cursorBitmap;
+ sprite.UpdateMember(0,cursorSprite);
+ }
+ void setPixmap(QPixmap pm)
+ {
+ //### heaplock centralized.
+ QImage temp = pm.toImage();
+ QSize size = pm.size();
+ temp.bits();
+ CFbsBitmap *curbm = q_check_ptr(new CFbsBitmap()); // CBase derived object needs check on new
+ curbm->Create(TSize(size.width(),size.height()),EColor16MA);
+ curbm->LockHeap(ETrue);
+ memcpy((uchar*)curbm->DataAddress(),temp.bits(),temp.numBytes());
+ curbm->UnlockHeap(ETrue);
+ delete cursorSprite.iBitmap;
+ cursorSprite.iBitmap = curbm;
+ cursorBitmap = curbm;
+ sprite.UpdateMember(0,cursorSprite);
+ }
+ CFbsBitmap *cursorBitmap;
+ RWsPointerCursor pointerCursor;
+ RWsSprite sprite;
+ TSpriteMember cursorSprite;
+
+};
+
+
+static QShapedPixmapWidget *qt_symbian_dnd_deco = 0;
+
+void QDragManager::updatePixmap()
+{
+ if (qt_symbian_dnd_deco) {
+ QPixmap pm;
+ QPoint pm_hot(default_pm_hotx,default_pm_hoty);
+ if (drag_object) {
+ pm = drag_object->pixmap();
+ if (!pm.isNull())
+ pm_hot = drag_object->hotSpot();
+ }
+ if (pm.isNull()) {
+ if (!defaultPm)
+ defaultPm = new QPixmap(default_pm);
+ pm = *defaultPm;
+ }
+ qt_symbian_dnd_deco->setPixmap(pm);
+ }
+}
+
+void QDragManager::timerEvent(QTimerEvent *) { }
+
+void QDragManager::move(const QPoint&) {
+}
+
+void QDragManager::updateCursor()
+{
+}
+
+
+bool QDragManager::eventFilter(QObject *o, QEvent *e)
+{
+ if (beingCancelled) {
+ return false;
+ }
+ if (!o->isWidgetType())
+ return false;
+
+ switch(e->type()) {
+ case QEvent::MouseButtonPress:
+ {
+ }
+ case QEvent::MouseMove:
+ {
+ if (!object) { //#### this should not happen
+ qWarning("QDragManager::eventFilter: No object");
+ return true;
+ }
+ QDragManager *manager = QDragManager::self();
+ QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
+ if (manager->object)
+ possible_actions = manager->dragPrivate()->possible_actions;
+ else
+ possible_actions = Qt::IgnoreAction;
+
+ QMouseEvent *me = (QMouseEvent *)e;
+
+ if (me->buttons()) {
+ Qt::DropAction prevAction = global_accepted_action;
+ QWidget *cw = QApplication::widgetAt(me->globalPos());
+ // map the Coords relative to the window.
+ if (!cw)
+ return true;
+ TPoint windowPos = cw->effectiveWinId()->PositionRelativeToScreen();
+ qt_symbian_dnd_deco->sprite.SetPosition(TPoint(me->globalX()- windowPos.iX,me->globalY()- windowPos.iY));
+
+ while (cw && !cw->acceptDrops() && !cw->isWindow())
+ cw = cw->parentWidget();
+
+ if (object->target() != cw) {
+ if (object->target()) {
+ QDragLeaveEvent dle;
+ QApplication::sendEvent(object->target(), &dle);
+ willDrop = false;
+ global_accepted_action = Qt::IgnoreAction;
+ updateCursor();
+ restoreCursor = true;
+ object->d_func()->target = 0;
+ }
+ if (cw && cw->acceptDrops()) {
+ object->d_func()->target = cw;
+ QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ QApplication::sendEvent(object->target(), &dee);
+ willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction;
+ global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction;
+ updateCursor();
+ restoreCursor = true;
+ }
+ } else if (cw) {
+ QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ if (global_accepted_action != Qt::IgnoreAction) {
+ dme.setDropAction(global_accepted_action);
+ dme.accept();
+ }
+ QApplication::sendEvent(cw, &dme);
+ willDrop = dme.isAccepted();
+ global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction;
+ updatePixmap();
+ updateCursor();
+ }
+ if (global_accepted_action != prevAction)
+ emitActionChanged(global_accepted_action);
+ }
+ return true; // Eat all mouse events
+ }
+
+ case QEvent::MouseButtonRelease:
+ {
+ qApp->removeEventFilter(this);
+ if (restoreCursor) {
+ qt_symbian_dnd_deco->disableCursor();
+ willDrop = false;
+ restoreCursor = false;
+ }
+ if (object && object->target()) {
+
+ QMouseEvent *me = (QMouseEvent *)e;
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
+
+ QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ QApplication::sendEvent(object->target(), &de);
+ if (de.isAccepted())
+ global_accepted_action = de.dropAction();
+ else
+ global_accepted_action = Qt::IgnoreAction;
+
+ if (object)
+ object->deleteLater();
+ drag_object = object = 0;
+ }
+ eventLoop->exit();
+ return true; // Eat all mouse events
+ }
+
+ default:
+ break;
+ }
+ return false;
+}
+
+Qt::DropAction QDragManager::drag(QDrag *o)
+{
+ Q_ASSERT(!qt_symbian_dnd_dragging);
+ if (object == o || !o || !o->source())
+ return Qt::IgnoreAction;
+
+ if (object) {
+ cancel();
+ qApp->removeEventFilter(this);
+ beingCancelled = false;
+ }
+
+ object = drag_object = o;
+ RWsSession winSession = o->source()->effectiveWinId()->ControlEnv()->WsSession();
+ Q_ASSERT(!qt_symbian_dnd_deco);
+ qt_symbian_dnd_deco = new QShapedPixmapWidget(winSession, o->source()->effectiveWinId()->DrawableWindow());
+
+ oldstate = Qt::NoModifier; // #### Should use state that caused the drag
+ willDrop = false;
+ updatePixmap();
+ updateCursor();
+ restoreCursor = true;
+
+ object->d_func()->target = 0;
+ TPoint windowPos = source()->effectiveWinId()->PositionRelativeToScreen();
+ qt_symbian_dnd_deco->sprite.SetPosition(TPoint(QCursor::pos().x()- windowPos.iX ,QCursor::pos().y() - windowPos.iY));
+
+ QPoint hotspot = drag_object->hotSpot();
+ qt_symbian_dnd_deco->cursorSprite.iOffset = TPoint(- hotspot.x(),- hotspot.y());
+ qt_symbian_dnd_deco->sprite.UpdateMember(0,qt_symbian_dnd_deco->cursorSprite);
+
+ qApp->installEventFilter(this);
+
+ global_accepted_action = Qt::MoveAction;
+ qt_symbian_dnd_dragging = true;
+
+ eventLoop = new QEventLoop;
+ // block
+ (void) eventLoop->exec(QEventLoop::AllEvents);
+ delete eventLoop;
+ eventLoop = 0;
+
+ delete qt_symbian_dnd_deco;
+ qt_symbian_dnd_deco = 0;
+ qt_symbian_dnd_dragging = false;
+
+
+ return global_accepted_action;
+}
+
+
+void QDragManager::cancel(bool deleteSource)
+{
+ beingCancelled = true;
+
+ if (object->target()) {
+ QDragLeaveEvent dle;
+ QApplication::sendEvent(object->target(), &dle);
+ }
+
+ if (drag_object) {
+ if (deleteSource)
+ object->deleteLater();
+ drag_object = object = 0;
+ }
+
+ delete qt_symbian_dnd_deco;
+ qt_symbian_dnd_deco = 0;
+
+ global_accepted_action = Qt::IgnoreAction;
+}
+
+
+void QDragManager::drop()
+{
+}
+
+QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const
+{
+ if (!drag_object)
+ return QVariant();
+ QByteArray data = drag_object->mimeData()->data(mimetype);
+ if (type == QVariant::String)
+ return QString::fromUtf8(data);
+ return data;
+}
+
+bool QDropData::hasFormat_sys(const QString &format) const
+{
+ return formats().contains(format);
+}
+
+QStringList QDropData::formats_sys() const
+{
+ if (drag_object)
+ return drag_object->mimeData()->formats();
+ return QStringList();
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_DRAGANDDROP
diff --git a/src/gui/kernel/qdnd_win.cpp b/src/gui/kernel/qdnd_win.cpp
index 547476e..53392b5 100644
--- a/src/gui/kernel/qdnd_win.cpp
+++ b/src/gui/kernel/qdnd_win.cpp
@@ -154,9 +154,9 @@ QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
#ifdef QDND_DEBUG
qDebug("QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)");
#ifndef Q_OS_WINCE
- char buf[256] = {0};
- GetClipboardFormatNameA(pformatetc->cfFormat, buf, 255);
- qDebug("CF = %d : %s", pformatetc->cfFormat, buf);
+ wchar_t buf[256] = {0};
+ GetClipboardFormatName(pformatetc->cfFormat, buf, 255);
+ qDebug("CF = %d : %s", pformatetc->cfFormat, QString::fromWCharArray(buf));
#endif
#endif
@@ -398,52 +398,47 @@ void QOleDropSource::createCursors()
int h = cpm.height();
if (!pm.isNull()) {
- int x1 = qMin(-hotSpot.x(),0);
- int x2 = qMax(pm.width()-hotSpot.x(),cpm.width());
- int y1 = qMin(-hotSpot.y(),0);
- int y2 = qMax(pm.height()-hotSpot.y(),cpm.height());
+ int x1 = qMin(-hotSpot.x(), 0);
+ int x2 = qMax(pm.width() - hotSpot.x(), cpm.width());
+ int y1 = qMin(-hotSpot.y(), 0);
+ int y2 = qMax(pm.height() - hotSpot.y(), cpm.height());
- w = x2-x1+1;
- h = y2-y1+1;
+ w = x2 - x1 + 1;
+ h = y2 - y1 + 1;
}
QRect srcRect = pm.rect();
QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y()));
QPoint newHotSpot = hotSpot;
-#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
- bool limitedCursorSize = (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)
- || (QSysInfo::WindowsVersion == QSysInfo::WV_NT)
- || (QSysInfo::WindowsVersion == QSysInfo::WV_CE);
-
- if (limitedCursorSize) {
- // Limited cursor size
- int reqw = GetSystemMetrics(SM_CXCURSOR);
- int reqh = GetSystemMetrics(SM_CYCURSOR);
-
- QPoint hotspotInPM = newHotSpot - pmDest;
- if (reqw < w) {
- // Not wide enough - move objectpm right
- qreal r = qreal(newHotSpot.x()) / w;
- newHotSpot = QPoint(int(r * reqw), newHotSpot.y());
- if (newHotSpot.x() + cpm.width() > reqw)
- newHotSpot.setX(reqw - cpm.width());
-
- srcRect = QRect(QPoint(hotspotInPM.x() - newHotSpot.x(), srcRect.top()), QSize(reqw, srcRect.height()));
- }
- if (reqh < h) {
- qreal r = qreal(newHotSpot.y()) / h;
- newHotSpot = QPoint(newHotSpot.x(), int(r * reqh));
- if (newHotSpot.y() + cpm.height() > reqh)
- newHotSpot.setY(reqh - cpm.height());
-
- srcRect = QRect(QPoint(srcRect.left(), hotspotInPM.y() - newHotSpot.y()), QSize(srcRect.width(), reqh));
- }
- // Always use system cursor size
- w = reqw;
- h = reqh;
+#if defined(Q_OS_WINCE)
+ // Limited cursor size
+ int reqw = GetSystemMetrics(SM_CXCURSOR);
+ int reqh = GetSystemMetrics(SM_CYCURSOR);
+
+ QPoint hotspotInPM = newHotSpot - pmDest;
+ if (reqw < w) {
+ // Not wide enough - move objectpm right
+ qreal r = qreal(newHotSpot.x()) / w;
+ newHotSpot = QPoint(int(r * reqw), newHotSpot.y());
+ if (newHotSpot.x() + cpm.width() > reqw)
+ newHotSpot.setX(reqw - cpm.width());
+
+ srcRect = QRect(QPoint(hotspotInPM.x() - newHotSpot.x(), srcRect.top()), QSize(reqw, srcRect.height()));
}
+ if (reqh < h) {
+ qreal r = qreal(newHotSpot.y()) / h;
+ newHotSpot = QPoint(newHotSpot.x(), int(r * reqh));
+ if (newHotSpot.y() + cpm.height() > reqh)
+ newHotSpot.setY(reqh - cpm.height());
+
+ srcRect = QRect(QPoint(srcRect.left(), hotspotInPM.y() - newHotSpot.y()), QSize(srcRect.width(), reqh));
+ }
+ // Always use system cursor size
+ w = reqw;
+ h = reqh;
#endif
+
QPixmap newCursor(w, h);
if (!pm.isNull()) {
newCursor.fill(QColor(0, 0, 0, 0));
@@ -549,7 +544,7 @@ QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
return ResultFromScode(DRAGDROP_S_DROP);
}
#endif
- qApp->processEvents();
+ QApplication::processEvents();
return NOERROR;
}
}
diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp
index 9babfdc..bb586c2 100644
--- a/src/gui/kernel/qdnd_x11.cpp
+++ b/src/gui/kernel/qdnd_x11.cpp
@@ -542,6 +542,8 @@ bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data
dm->xdndMimeTransferedPixmapIndex =
(dm->xdndMimeTransferedPixmapIndex + 1) % 2;
}
+ } else {
+ DEBUG("QClipboard: xdndMimeDataForAtom(): converting to type '%s' is not supported", qPrintable(atomName));
}
}
return data;
@@ -622,28 +624,12 @@ QVariant QX11Data::xdndMimeConvertToFormat(Atom a, const QByteArray &data, const
if (format == QLatin1String("image/ppm")) {
if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) {
Pixmap xpm = *((Pixmap*)data.data());
- Display *dpy = display;
- Window r;
- int x,y;
- uint w,h,bw,d;
if (!xpm)
return QByteArray();
- XGetGeometry(dpy,xpm, &r,&x,&y,&w,&h,&bw,&d);
+ QPixmap qpm = QPixmap::fromX11Pixmap(xpm);
QImageWriter imageWriter;
- GC gc = XCreateGC(dpy, xpm, 0, 0);
- QImage imageToWrite;
- if (d == 1) {
- QBitmap qbm(w,h);
- XCopyArea(dpy,xpm,qbm.handle(),gc,0,0,w,h,0,0);
- imageWriter.setFormat("PBMRAW");
- imageToWrite = qbm.toImage();
- } else {
- QPixmap qpm(w,h);
- XCopyArea(dpy,xpm,qpm.handle(),gc,0,0,w,h,0,0);
- imageWriter.setFormat("PPMRAW");
- imageToWrite = qpm.toImage();
- }
- XFreeGC(dpy,gc);
+ imageWriter.setFormat("PPMRAW");
+ QImage imageToWrite = qpm.toImage();
QBuffer buf;
buf.open(QIODevice::WriteOnly);
imageWriter.setDevice(&buf);
@@ -1087,12 +1073,14 @@ void qt_xdnd_send_leave()
if (!qt_xdnd_current_target)
return;
+ QDragManager *manager = QDragManager::self();
+
XClientMessageEvent leave;
leave.type = ClientMessage;
leave.window = qt_xdnd_current_target;
leave.format = 32;
leave.message_type = ATOM(XdndLeave);
- leave.data.l[0] = qt_xdnd_dragsource_xid;
+ leave.data.l[0] = manager->dragPrivate()->source->effectiveWinId();
leave.data.l[1] = 0; // flags
leave.data.l[2] = 0; // x, y
leave.data.l[3] = 0; // w, h
@@ -1108,8 +1096,8 @@ void qt_xdnd_send_leave()
else
XSendEvent(X11->display, qt_xdnd_current_proxy_target, False,
NoEventMask, (XEvent*)&leave);
+
// reset the drag manager state
- QDragManager *manager = QDragManager::self();
manager->willDrop = false;
if (global_accepted_action != Qt::IgnoreAction)
manager->emitActionChanged(Qt::IgnoreAction);
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index b19d791..a61b6fa 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -83,6 +83,13 @@ QInputEvent::~QInputEvent()
\sa QApplication::keyboardModifiers()
*/
+/*! \fn void QInputEvent::setModifiers(Qt::KeyboardModifiers modifiers)
+
+ \internal
+
+ Sets the keyboard modifiers flags for this event.
+*/
+
/*!
\class QMouseEvent
\ingroup events
@@ -106,8 +113,12 @@ QInputEvent::~QInputEvent()
propagated up the parent widget chain until a widget accepts it
with accept(), or an event filter consumes it.
+ \note If a mouse event is propagated to a \l{QWidget}{widget} for
+ which Qt::WA_NoMousePropagation has been set, that mouse event
+ will not be propagated further up the parent widget chain.
+
The state of the keyboard modifier keys can be found by calling the
- \l{QInputEvent::modifiers()}{modifiers()} function, inhertied from
+ \l{QInputEvent::modifiers()}{modifiers()} function, inherited from
QInputEvent.
The functions pos(), x(), and y() give the cursor position
@@ -663,8 +674,9 @@ QWheelEvent::QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta,
The QWidget::setEnable() function can be used to enable or disable
mouse and keyboard events for a widget.
- The event handlers QWidget::keyPressEvent() and
- QWidget::keyReleaseEvent() receive key events.
+ The event handlers QWidget::keyPressEvent(), QWidget::keyReleaseEvent(),
+ QGraphicsItem::keyPressEvent() and QGraphicsItem::keyReleaseEvent()
+ receive key events.
\sa QFocusEvent, QWidget::grabKeyboard()
*/
@@ -861,6 +873,17 @@ bool QKeyEvent::matches(QKeySequence::StandardKey matchKey) const
uint searchkey = (modifiers() | key()) & ~(Qt::KeypadModifier); //The keypad modifier should not make a difference
uint platform = QApplicationPrivate::currentPlatform();
+#ifdef Q_WS_MAC
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ uint oldSearchKey = searchkey;
+ searchkey &= ~(Qt::ControlModifier | Qt::MetaModifier);
+ if (oldSearchKey & Qt::ControlModifier)
+ searchkey |= Qt::MetaModifier;
+ if (oldSearchKey & Qt::MetaModifier)
+ searchkey |= Qt::ControlModifier;
+ }
+#endif
+
uint N = QKeySequencePrivate::numberOfKeyBindings;
int first = 0;
int last = N - 1;
@@ -969,8 +992,9 @@ bool QKeyEvent::matches(QKeySequence::StandardKey matchKey) const
The reason for a particular focus event is returned by reason()
in the appropriate event handler.
- The event handlers QWidget::focusInEvent() and
- QWidget::focusOutEvent() receive focus events.
+ The event handlers QWidget::focusInEvent(),
+ QWidget::focusOutEvent(), QGraphicsItem::focusInEvent and
+ QGraphicsItem::focusOutEvent() receive focus events.
\sa QWidget::setFocus(), QWidget::setFocusPolicy(), {Keyboard Focus}
*/
@@ -1056,8 +1080,17 @@ Qt::FocusReason QFocusEvent::reason() const
rect() that is the bounding rectangle of that region. Both are
provided because many widgets can't make much use of region(),
and rect() can be much faster than region().boundingRect().
+
+ \section1 Automatic Clipping
+
Painting is clipped to region() during the processing of a paint
- event.
+ event. This clipping is performed by Qt's paint system and is
+ independent of any clipping that may be applied to a QPainter used to
+ draw on the paint device.
+
+ As a result, the value returned by QPainter::clipRegion() on
+ a newly-constructed QPainter will not reflect the clip region that is
+ used by the paint system.
\sa QPainter, QWidget::update(), QWidget::repaint(),
QWidget::paintEvent()
@@ -1588,12 +1621,14 @@ Qt::ButtonState QContextMenuEvent::state() const
string is controlled by the widget only). The AttributeType enum
describes the different attributes that can be set.
- A class implementing QWidget::inputMethodEvent() should at least
- understand and honor the \l TextFormat and \l Cursor attributes.
+ A class implementing QWidget::inputMethodEvent() or
+ QGraphicsItem::inputMethodEvent() should at least understand and
+ honor the \l TextFormat and \l Cursor attributes.
Since input methods need to be able to query certain properties
- from the widget, the widget must also implement
- QWidget::inputMethodQuery().
+ from the widget or graphics item, subclasses must also implement
+ QWidget::inputMethodQuery() and QGraphicsItem::inputMethodQuery(),
+ respectively.
When receiving an input method event, the text widget has to performs the
following steps:
@@ -1665,6 +1700,17 @@ Qt::ButtonState QContextMenuEvent::state() const
several are specified for any character in the string the behaviour
is undefined.
+ \value Selection
+ If set, the edit cursor should be moved to the specified position
+ in the editor text contents. In contrast with \c Cursor, this
+ attribute does not work on the preedit text, but on the surrounding
+ text. The cursor will be moved after the commit string has been
+ committed, and the preedit string will be located at the new edit
+ position.
+ The start position specifies the new position and the length
+ variable can be used to set a selection starting from that point.
+ The value is unused.
+
\sa Attribute
*/
@@ -3070,7 +3116,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
<< ", " << me->button()
<< ", " << hex << (int)me->buttons()
<< ", " << hex << (int)me->modifiers()
- << ")";
+ << ')';
}
return dbg.space();
@@ -3091,7 +3137,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
dbg.nospace() << "QWheelEvent(" << static_cast<const QWheelEvent *>(e)->delta()
- << ")";
+ << ')';
return dbg.space();
#endif
case QEvent::KeyPress:
@@ -3117,7 +3163,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
<< ", \"" << ke->text()
<< "\", " << ke->isAutoRepeat()
<< ", " << ke->count()
- << ")";
+ << ')';
}
return dbg.space();
case QEvent::FocusIn:
@@ -3507,4 +3553,637 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar)
#endif
+/*!
+ \class QTouchEvent
+ \brief The QTouchEvent class contains parameters that describe a touch event.
+ \since 4.6
+ \ingroup events
+
+ \section1 Enabling Touch Events
+
+ Touch events occur when pressing, releasing, or moving one or more touch points on a touch
+ device (such as a touch-screen or track-pad). To receive touch events, widgets have to have the
+ Qt::WA_AcceptTouchEvents attribute set and graphics items need to have the
+ \l{QGraphicsItem::setAcceptTouchEvents()}{acceptTouchEvents} attribute set to true.
+
+ When using QAbstractScrollArea based widgets, you should enabled the Qt::WA_AcceptTouchEvents
+ attribute on the scroll area's \l{QAbstractScrollArea::viewport()}{viewport}.
+
+ Similarly to QMouseEvent, Qt automatically grabs each touch point on the first press inside a
+ widget, and the widget will receive all updates for the touch point until it is released.
+ Note that it is possible for a widget to receive events for multiple touch points, and that
+ multiple widgets may be receiving touch events at the same time.
+
+ \section1 Event Handling
+
+ All touch events are of type QEvent::TouchBegin, QEvent::TouchUpdate, or QEvent::TouchEnd.
+ Reimplement QWidget::event() or QAbstractScrollArea::viewportEvent() for widgets and
+ QGraphicsItem::sceneEvent() for items in a graphics view to receive touch events.
+
+ The QEvent::TouchUpdate and QEvent::TouchEnd events are sent to the widget or item that
+ accepted the QEvent::TouchBegin event. If the QEvent::TouchBegin event is not accepted and not
+ filtered by an event filter, then no further touch events are sent until the next
+ QEvent::TouchBegin.
+
+ The touchPoints() function returns a list of all touch points contained in the event.
+ Information about each touch point can be retrieved using the QTouchEvent::TouchPoint class.
+ The Qt::TouchPointState enum describes the different states that a touch point may have.
+
+ \section1 Event Delivery and Propagation
+
+ By default, QWidget::event() translates the first non-primary touch point in a QTouchEvent into
+ a QMouseEvent. This makes it possible to enable touch events on existing widgets that do not
+ normally handle QTouchEvent. See below for information on some special considerations needed
+ when doing this.
+
+ QEvent::TouchBegin is the first touch event sent to a widget. The QEvent::TouchBegin event
+ contains a special accept flag that indicates whether the receiver wants the event. By default,
+ the event is accepted. You should call ignore() if the touch event is not handled by your
+ widget. The QEvent::TouchBegin event is propagated up the parent widget chain until a widget
+ accepts it with accept(), or an event filter consumes it. For QGraphicsItems, the
+ QEvent::TouchBegin event is propagated to items under the mouse (similar to mouse event
+ propagation for QGraphicsItems).
+
+ \section1 Touch Point Grouping
+
+ As mentioned above, it is possible that several widgets can be receiving QTouchEvents at the
+ same time. However, Qt makes sure to never send duplicate QEvent::TouchBegin events to the same
+ widget, which could theoretically happen during propagation if, for example, the user touched 2
+ separate widgets in a QGroupBox and both widgets ignored the QEvent::TouchBegin event.
+
+ To avoid this, Qt will group new touch points together using the following rules:
+
+ \list
+
+ \i When the first touch point is detected, the destination widget is determined firstly by the
+ location on screen and secondly by the propagation rules.
+
+ \i When additional touch points are detected, Qt first looks to see if there are any active
+ touch points on any ancestor or descendent of the widget under the new touch point. If there
+ are, the new touch point is grouped with the first, and the new touch point will be sent in a
+ single QTouchEvent to the widget that handled the first touch point. (The widget under the new
+ touch point will not receive an event).
+
+ \endlist
+
+ This makes it possible for sibling widgets to handle touch events independently while making
+ sure that the sequence of QTouchEvents is always correct.
+
+ \section1 Mouse Events and the Primary Touch Point
+
+ QTouchEvent delivery is independent from that of QMouseEvent. On some windowing systems, mouse
+ events are also sent for the \l{QTouchEvent::TouchPoint::isPrimary()}{primary touch point}.
+ This means it is possible for your widget to receive both QTouchEvent and QMouseEvent for the
+ same user interaction point. You can use the QTouchEvent::TouchPoint::isPrimary() function to
+ identify the primary touch point.
+
+ Note that on some systems, it is possible to receive touch events without a primary touch
+ point. All this means is that there will be no mouse event generated for the touch points in
+ the QTouchEvent.
+
+ \section1 Caveats
+
+ \list
+
+ \i As mentioned above, enabling touch events means multiple widgets can be receiving touch
+ events simultaneously. Combined with the default QWidget::event() handling for QTouchEvents,
+ this gives you great flexibility in designing multi-touch user interfaces. Be aware of the
+ implications. For example, is is possible that the user is moving a QSlider with one finger and
+ pressing a QPushButton with another. The signals emitted by these widgets will be
+ interleaved.
+
+ \i Recursion into the event loop using one of the exec() methods (e.g., QDialog::exec() or
+ QMenu::exec()) in a QTouchEvent event handler is not supported. Since there are multiple event
+ recipients, unexpected recursion may cause problems, including but not limited to lost events
+ and unexpected infinite recursion.
+
+ \i QTouchEvents are not affected by a \l{QWidget::grabMouse()}{mouse grab} or an
+ \l{QApplication::activePopupWidget()}{active pop-up widget}. The behavior of QTouchEvents is
+ undefined when opening a pop-up or grabbing the mouse while there are multiple active touch
+ points.
+
+ \endlist
+
+ \sa QTouchEvent::TouchPoint, Qt::TouchPointState, Qt::WA_AcceptTouchEvents,
+ QGraphicsItem::acceptTouchEvents()
+*/
+
+/*! \enum Qt::TouchPointState
+ \since 4.6
+
+ This enum represents the state of a touch point at the time the
+ QTouchEvent occurred.
+
+ \value TouchPointPressed The touch point is now pressed.
+ \value TouchPointMoved The touch point moved.
+ \value TouchPointStationary The touch point did not move.
+ \value TouchPointReleased The touch point was released.
+
+ \omitvalue TouchPointStateMask
+ \omitvalue TouchPointPrimary
+*/
+
+/*! \enum QTouchEvent::DeviceType
+
+ This enum represents the type of device that generated a QTouchEvent.
+
+ \value TouchScreen In this type of device, the touch surface and display are integrated. This
+ means the surface and display typically have the same size, such that there
+ is a direct relationship between the touch points' physical positions and the
+ coordinate reported by QTouchEvent::TouchPoint. As a result, Qt allows the
+ user to interact directly with multiple QWidgets and QGraphicsItems at the
+ same time.
+
+ \value TouchPad In this type of device, the touch surface is separate from the display. There
+ is not a direct relationship between the physical touch location and the
+ on-screen coordinates. Instead, they are calculated relative to the current
+ mouse position, and the user must use the touch-pad to move this reference
+ point. Unlike touch-screens, Qt allows users to only interact with a single
+ QWidget or QGraphicsItem at a time.
+*/
+
+/*!
+ Constructs a QTouchEvent with the given \a eventType, \a deviceType, and \a touchPoints.
+ The \a touchPointStates and \a modifiers are the current touch point states and keyboard
+ modifiers at the time of the event.
+*/
+QTouchEvent::QTouchEvent(QEvent::Type eventType,
+ QTouchEvent::DeviceType deviceType,
+ Qt::KeyboardModifiers modifiers,
+ Qt::TouchPointStates touchPointStates,
+ const QList<QTouchEvent::TouchPoint> &touchPoints)
+ : QInputEvent(eventType, modifiers),
+ _widget(0),
+ _deviceType(deviceType),
+ _touchPointStates(touchPointStates),
+ _touchPoints(touchPoints)
+{ }
+
+/*!
+ Destroys the QTouchEvent.
+*/
+QTouchEvent::~QTouchEvent()
+{ }
+
+/*! \fn QWidget *QTouchEvent::widget() const
+
+ Returns the widget on which the event occurred.
+*/
+
+
+/*! \fn Qt::TouchPointStates QTouchEvent::touchPointStates() const
+
+ Returns a bitwise OR of all the touch point states for this event.
+*/
+
+/*! \fn const QList<QTouchEvent::TouchPoint> &QTouchEvent::touchPoints() const
+
+ Returns the list of touch points contained in the touch event.
+*/
+
+/*! \fn QTouchEvent::DeviceType QTouchEvent::deviceType() const
+
+ Returns the touch device Type, which is of type \l {QTouchEvent::DeviceType} {DeviceType}.
+*/
+
+/*! \fn void QTouchEvent::setWidget(QWidget *widget)
+
+ \internal
+
+ Sets the widget for this event.
+*/
+
+/*! \fn void QTouchEvent::setTouchPointStates(Qt::TouchPointStates touchPointStates)
+
+ \internal
+
+ Sets a bitwise OR of all the touch point states for this event.
+*/
+
+/*! \fn void QTouchEvent::setTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints)
+
+ \internal
+
+ Sets the list of touch points for this event.
+*/
+
+/*! \fn void QTouchEvent::setDeviceType(DeviceType deviceType)
+
+ \internal
+
+ Sets the device type to \a deviceType, which is of type \l {QTouchEvent::DeviceType}
+ {DeviceType}.
+*/
+
+/*! \class QTouchEvent::TouchPoint
+ \brief The QTouchEvent::TouchPoint class provides information about a touch point in a QTouchEvent.
+ \since 4.6
+*/
+
+/*! \internal
+
+ Constructs a QTouchEvent::TouchPoint for use in a QTouchEvent.
+*/
+QTouchEvent::TouchPoint::TouchPoint(int id)
+ : d(new QTouchEventTouchPointPrivate(id))
+{ }
+
+/*! \internal
+
+ Constructs a copy of \a other.
+*/
+QTouchEvent::TouchPoint::TouchPoint(const QTouchEvent::TouchPoint &other)
+ : d(other.d)
+{
+ d->ref.ref();
+}
+
+/*! \internal
+
+ Destroys the QTouchEvent::TouchPoint.
+*/
+QTouchEvent::TouchPoint::~TouchPoint()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+/*!
+ Returns the id number of this touch point.
+
+ Id numbers are globally sequential, starting at zero, meaning the
+ first touch point in the application has id 0, the second has id 1,
+ and so on.
+*/
+int QTouchEvent::TouchPoint::id() const
+{
+ return d->id;
+}
+
+/*!
+ Returns the current state of this touch point.
+*/
+Qt::TouchPointState QTouchEvent::TouchPoint::state() const
+{
+ return Qt::TouchPointState(int(d->state) & Qt::TouchPointStateMask);
+}
+
+/*!
+ Returns true if this touch point is the primary touch point. The primary touch point is the
+ point for which the windowing system generates mouse events.
+*/
+bool QTouchEvent::TouchPoint::isPrimary() const
+{
+ return (d->state & Qt::TouchPointPrimary) != 0;
+}
+
+/*!
+ Returns the position of this touch point, relative to the widget
+ or QGraphicsItem that received the event.
+
+ \sa startPos(), lastPos(), screenPos(), scenePos(), normalizedPos()
+*/
+QPointF QTouchEvent::TouchPoint::pos() const
+{
+ return d->rect.center();
+}
+
+/*!
+ Returns the scene position of this touch point.
+
+ The scene position is the position in QGraphicsScene coordinates
+ if the QTouchEvent is handled by a QGraphicsItem::touchEvent()
+ reimplementation, and identical to the screen position for
+ widgets.
+
+ \sa startScenePos(), lastScenePos(), pos()
+*/
+QPointF QTouchEvent::TouchPoint::scenePos() const
+{
+ return d->sceneRect.center();
+}
+
+/*!
+ Returns the screen position of this touch point.
+
+ \sa startScreenPos(), lastScreenPos(), pos()
+*/
+QPointF QTouchEvent::TouchPoint::screenPos() const
+{
+ return d->screenRect.center();
+}
+
+/*!
+ Returns the normalized position of this touch point.
+
+ The coordinates are normalized to the size of the touch device,
+ i.e. (0,0) is the top-left corner and (1,1) is the bottom-right corner.
+
+ \sa startNormalizedPos(), lastNormalizedPos(), pos()
+*/
+QPointF QTouchEvent::TouchPoint::normalizedPos() const
+{
+ return d->normalizedPos;
+}
+
+/*!
+ Returns the starting position of this touch point, relative to the
+ widget or QGraphicsItem that received the event.
+
+ \sa pos(), lastPos()
+*/
+QPointF QTouchEvent::TouchPoint::startPos() const
+{
+ return d->startPos;
+}
+
+/*!
+ Returns the starting scene position of this touch point.
+
+ The scene position is the position in QGraphicsScene coordinates
+ if the QTouchEvent is handled by a QGraphicsItem::touchEvent()
+ reimplementation, and identical to the screen position for
+ widgets.
+
+ \sa scenePos(), lastScenePos()
+*/
+QPointF QTouchEvent::TouchPoint::startScenePos() const
+{
+ return d->startScenePos;
+}
+
+/*!
+ Returns the starting screen position of this touch point.
+
+ \sa screenPos(), lastScreenPos()
+*/
+QPointF QTouchEvent::TouchPoint::startScreenPos() const
+{
+ return d->startScreenPos;
+}
+
+/*!
+ Returns the normalized starting position of this touch point.
+
+ The coordinates are normalized to the size of the touch device,
+ i.e. (0,0) is the top-left corner and (1,1) is the bottom-right corner.
+
+ \sa normalizedPos(), lastNormalizedPos()
+*/
+QPointF QTouchEvent::TouchPoint::startNormalizedPos() const
+{
+ return d->startNormalizedPos;
+}
+
+/*!
+ Returns the position of this touch point from the previous touch
+ event, relative to the widget or QGraphicsItem that received the event.
+
+ \sa pos(), startPos()
+*/
+QPointF QTouchEvent::TouchPoint::lastPos() const
+{
+ return d->lastPos;
+}
+
+/*!
+ Returns the scene position of this touch point from the previous
+ touch event.
+
+ The scene position is the position in QGraphicsScene coordinates
+ if the QTouchEvent is handled by a QGraphicsItem::touchEvent()
+ reimplementation, and identical to the screen position for
+ widgets.
+
+ \sa scenePos(), startScenePos()
+*/
+QPointF QTouchEvent::TouchPoint::lastScenePos() const
+{
+ return d->lastScenePos;
+}
+
+/*!
+ Returns the screen position of this touch point from the previous
+ touch event.
+
+ \sa screenPos(), startScreenPos()
+*/
+QPointF QTouchEvent::TouchPoint::lastScreenPos() const
+{
+ return d->lastScreenPos;
+}
+
+/*!
+ Returns the normalized position of this touch point from the
+ previous touch event.
+
+ The coordinates are normalized to the size of the touch device,
+ i.e. (0,0) is the top-left corner and (1,1) is the bottom-right corner.
+
+ \sa normalizedPos(), startNormalizedPos()
+*/
+QPointF QTouchEvent::TouchPoint::lastNormalizedPos() const
+{
+ return d->lastNormalizedPos;
+}
+
+/*!
+ Returns the rect for this touch point, relative to the widget
+ or QGraphicsItem that received the event. The rect is centered
+ around the point returned by pos().
+
+ \note This function returns an empty rect if the device does not report touch point sizes.
+*/
+QRectF QTouchEvent::TouchPoint::rect() const
+{
+ return d->rect;
+}
+
+/*!
+ Returns the rect for this touch point in scene coordinates.
+
+ \note This function returns an empty rect if the device does not report touch point sizes.
+
+ \sa scenePos(), rect()
+*/
+QRectF QTouchEvent::TouchPoint::sceneRect() const
+{
+ return d->sceneRect;
+}
+
+/*!
+ Returns the rect for this touch point in screen coordinates.
+
+ \note This function returns an empty rect if the device does not report touch point sizes.
+
+ \sa screenPos(), rect()
+*/
+QRectF QTouchEvent::TouchPoint::screenRect() const
+{
+ return d->screenRect;
+}
+
+/*!
+ Returns the pressure of this touch point. The return value is in
+ the range 0.0 to 1.0.
+*/
+qreal QTouchEvent::TouchPoint::pressure() const
+{
+ return d->pressure;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setId(int id)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->id = id;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setState(Qt::TouchPointStates state)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->state = state;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setPos(const QPointF &pos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->rect.moveCenter(pos);
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->sceneRect.moveCenter(scenePos);
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->screenRect.moveCenter(screenPos);
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setNormalizedPos(const QPointF &normalizedPos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->normalizedPos = normalizedPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setStartPos(const QPointF &startPos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->startPos = startPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setStartScenePos(const QPointF &startScenePos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->startScenePos = startScenePos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setStartScreenPos(const QPointF &startScreenPos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->startScreenPos = startScreenPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setStartNormalizedPos(const QPointF &startNormalizedPos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->startNormalizedPos = startNormalizedPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setLastPos(const QPointF &lastPos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->lastPos = lastPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setLastScenePos(const QPointF &lastScenePos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->lastScenePos = lastScenePos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setLastScreenPos(const QPointF &lastScreenPos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->lastScreenPos = lastScreenPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setLastNormalizedPos(const QPointF &lastNormalizedPos)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->lastNormalizedPos = lastNormalizedPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setRect(const QRectF &rect)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->rect = rect;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setSceneRect(const QRectF &sceneRect)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->sceneRect = sceneRect;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setScreenRect(const QRectF &screenRect)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->screenRect = screenRect;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setPressure(qreal pressure)
+{
+ if (d->ref != 1)
+ d = d->detach();
+ d->pressure = pressure;
+}
+
+/*! \internal */
+QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::TouchPoint &other)
+{
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ delete d;
+ d = other.d;
+ return *this;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 7dc14cc..5f3b29b 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -52,6 +52,8 @@
#include <QtGui/qmime.h>
#include <QtGui/qdrag.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qset.h>
QT_BEGIN_HEADER
@@ -60,6 +62,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
class QAction;
+class QGesture;
class Q_GUI_EXPORT QInputEvent : public QEvent
{
@@ -67,6 +70,7 @@ public:
QInputEvent(Type type, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
~QInputEvent();
inline Qt::KeyboardModifiers modifiers() const { return modState; }
+ inline void setModifiers(Qt::KeyboardModifiers modifiers) { modState = modifiers; }
protected:
Qt::KeyboardModifiers modState;
};
@@ -241,7 +245,7 @@ public:
inline QT3_SUPPORT_CONSTRUCTOR QKeyEvent(Type type, int key, int /*ascii*/,
int modifiers, const QString& text = QString(),
bool autorep = false, ushort count = 1)
- : QInputEvent(type, (Qt::KeyboardModifiers)(modifiers & (int)Qt::KeyButtonMask)), txt(text), k(key),
+ : QInputEvent(type, Qt::KeyboardModifiers(modifiers & (int)Qt::KeyButtonMask)), txt(text), k(key),
c(count), autor(autorep)
{
if (key >= Qt::Key_Back && key <= Qt::Key_MediaLast)
@@ -424,7 +428,8 @@ public:
TextFormat,
Cursor,
Language,
- Ruby
+ Ruby,
+ Selection
};
class Attribute {
public:
@@ -719,6 +724,101 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ?
inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);}
#endif // QT_NO_SHORTCUT
+class QTouchEventTouchPointPrivate;
+class Q_GUI_EXPORT QTouchEvent : public QInputEvent
+{
+public:
+ class Q_GUI_EXPORT TouchPoint
+ {
+ public:
+ TouchPoint(int id = -1);
+ TouchPoint(const QTouchEvent::TouchPoint &other);
+ ~TouchPoint();
+
+ int id() const;
+
+ Qt::TouchPointState state() const;
+ bool isPrimary() const;
+
+ QPointF pos() const;
+ QPointF startPos() const;
+ QPointF lastPos() const;
+
+ QPointF scenePos() const;
+ QPointF startScenePos() const;
+ QPointF lastScenePos() const;
+
+ QPointF screenPos() const;
+ QPointF startScreenPos() const;
+ QPointF lastScreenPos() const;
+
+ QPointF normalizedPos() const;
+ QPointF startNormalizedPos() const;
+ QPointF lastNormalizedPos() const;
+
+ QRectF rect() const;
+ QRectF sceneRect() const;
+ QRectF screenRect() const;
+
+ qreal pressure() const;
+
+ // internal
+ void setId(int id);
+ void setState(Qt::TouchPointStates state);
+ void setPos(const QPointF &pos);
+ void setScenePos(const QPointF &scenePos);
+ void setScreenPos(const QPointF &screenPos);
+ void setNormalizedPos(const QPointF &normalizedPos);
+ void setStartPos(const QPointF &startPos);
+ void setStartScenePos(const QPointF &startScenePos);
+ void setStartScreenPos(const QPointF &startScreenPos);
+ void setStartNormalizedPos(const QPointF &startNormalizedPos);
+ void setLastPos(const QPointF &lastPos);
+ void setLastScenePos(const QPointF &lastScenePos);
+ void setLastScreenPos(const QPointF &lastScreenPos);
+ void setLastNormalizedPos(const QPointF &lastNormalizedPos);
+ void setRect(const QRectF &rect);
+ void setSceneRect(const QRectF &sceneRect);
+ void setScreenRect(const QRectF &screenRect);
+ void setPressure(qreal pressure);
+ QTouchEvent::TouchPoint &operator=(const QTouchEvent::TouchPoint &other);
+
+ private:
+ QTouchEventTouchPointPrivate *d;
+ };
+
+ enum DeviceType {
+ TouchScreen,
+ TouchPad
+ };
+
+ QTouchEvent(QEvent::Type eventType,
+ QTouchEvent::DeviceType deviceType = TouchScreen,
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier,
+ Qt::TouchPointStates touchPointStates = 0,
+ const QList<QTouchEvent::TouchPoint> &touchPoints = QList<QTouchEvent::TouchPoint>());
+ ~QTouchEvent();
+
+ inline QWidget *widget() const { return _widget; }
+ inline QTouchEvent::DeviceType deviceType() const { return _deviceType; }
+ inline Qt::TouchPointStates touchPointStates() const { return _touchPointStates; }
+ inline const QList<QTouchEvent::TouchPoint> &touchPoints() const { return _touchPoints; }
+
+ // internal
+ inline void setWidget(QWidget *widget) { _widget = widget; }
+ inline void setDeviceType(DeviceType deviceType) { _deviceType = deviceType; }
+ inline void setTouchPointStates(Qt::TouchPointStates touchPointStates) { _touchPointStates = touchPointStates; }
+ inline void setTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints) { _touchPoints = touchPoints; }
+
+protected:
+ QWidget *_widget;
+ QTouchEvent::DeviceType _deviceType;
+ Qt::TouchPointStates _touchPointStates;
+ QList<QTouchEvent::TouchPoint> _touchPoints;
+
+ friend class QApplicationPrivate;
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index fe5ebdd..7cfa36e 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -43,6 +43,7 @@
#define QEVENT_P_H
#include <QtCore/qglobal.h>
+#include <QtGui/qevent.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +59,7 @@ QT_BEGIN_NAMESPACE
//
// ### Qt 5: remove
-class Q_GUI_EXPORT QKeyEventEx : public QKeyEvent
+class QKeyEventEx : public QKeyEvent
{
public:
QKeyEventEx(Type type, int key, Qt::KeyboardModifiers modifiers,
@@ -76,7 +77,7 @@ protected:
};
// ### Qt 5: remove
-class Q_GUI_EXPORT QMouseEventEx : public QMouseEvent
+class QMouseEventEx : public QMouseEvent
{
public:
QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
@@ -89,6 +90,66 @@ protected:
friend class QMouseEvent;
};
+class QTouchEventTouchPointPrivate
+{
+public:
+ inline QTouchEventTouchPointPrivate(int id)
+ : ref(1),
+ id(id),
+ state(Qt::TouchPointReleased),
+ pressure(qreal(-1.))
+ { }
+
+ inline QTouchEventTouchPointPrivate *detach()
+ {
+ QTouchEventTouchPointPrivate *d = new QTouchEventTouchPointPrivate(*this);
+ d->ref = 1;
+ if (!this->ref.deref())
+ delete this;
+ return d;
+ }
+
+ QAtomicInt ref;
+ int id;
+ Qt::TouchPointStates state;
+ QRectF rect, sceneRect, screenRect;
+ QPointF normalizedPos,
+ startPos, startScenePos, startScreenPos, startNormalizedPos,
+ lastPos, lastScenePos, lastScreenPos, lastNormalizedPos;
+ qreal pressure;
+};
+
+class QNativeGestureEvent : public QEvent
+{
+public:
+ enum Type {
+ None,
+ GestureBegin,
+ GestureEnd,
+ Pan,
+ Zoom,
+ Rotate,
+ Swipe
+ };
+
+ QNativeGestureEvent()
+ : QEvent(QEvent::NativeGesture), gestureType(None), percentage(0)
+#ifdef Q_WS_WIN
+ , sequenceId(0), argument(0)
+#endif
+ {
+ }
+
+ Type gestureType;
+ float percentage;
+ QPoint position;
+ float angle;
+#ifdef Q_WS_WIN
+ ulong sequenceId;
+ quint64 argument;
+#endif
+};
+
QT_END_NAMESPACE
#endif // QEVENT_P_H
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
index 25bcb32..1667da8 100644
--- a/src/gui/kernel/qeventdispatcher_mac.mm
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -497,6 +497,40 @@ static bool IsMouseOrKeyEvent( NSEvent* event )
}
#endif
+static inline void qt_mac_waitForMoreEvents()
+{
+#ifndef QT_MAC_USE_COCOA
+ while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e20, true) == kCFRunLoopRunTimedOut) ;
+#else
+ // If no event exist in the cocoa event que, wait
+ // (and free up cpu time) until at least one event occur.
+ // This implementation is a bit on the edge, but seems to
+ // work fine:
+ NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantFuture]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (event)
+ [NSApp postEvent:event atStart:YES];
+#endif
+}
+
+#ifdef QT_MAC_USE_COCOA
+static inline void qt_mac_waitForMoreModalSessionEvents()
+{
+ // If no event exist in the cocoa event que, wait
+ // (and free up cpu time) until at least one event occur.
+ // This implementation is a bit on the edge, but seems to
+ // work fine:
+ NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantFuture]
+ inMode:NSModalPanelRunLoopMode
+ dequeue:YES];
+ if (event)
+ [NSApp postEvent:event atStart:YES];
+}
+#endif
+
bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherMac);
@@ -506,16 +540,6 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
wakeUp();
emit awake();
-#ifndef QT_MAC_NO_QUICKDRAW
- if(!qt_mac_safe_pdev) { //create an empty widget and this can be used for a port anytime
- QWidget *tlw = new QWidget;
- tlw->setAttribute(Qt::WA_DeleteOnClose);
- tlw->setObjectName(QLatin1String("empty_widget"));
- tlw->hide();
- qt_mac_safe_pdev = tlw;
- }
-#endif
-
bool retVal = false;
forever {
if (d->interrupt)
@@ -525,55 +549,42 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
QMacCocoaAutoReleasePool pool;
NSEvent* event = 0;
- if (flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec) {
- // The point of the CocoaRequestModal event is to make sure that a
- // non-execed app modal window recurses into it's own dialog exec
- // once cocoa is spinning the event loop for us (e.g on top of [NSApp run]).
- // We expect only one event to notify us about this, regardless of how many
- // widgets that are waiting to be modal. So we remove all other pending
- // events, if any. And since cocoa will now take over event processing for us,
- // we allow new app modal widgets to recurse on top of us, hence the release of
- // the block:
- QBoolBlocker block(d->blockCocoaRequestModal, false);
- QCoreApplication::removePostedEvents(qApp, QEvent::CocoaRequestModal);
-
- if (NSModalSession session = d->activeModalSession())
- while ([NSApp runModalSession:session] == NSRunContinuesResponse) {
- // runModalSession will not wait for events, so we do it
- // ourselves (otherwise we would spend 100% CPU inside this loop):
- event = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:[NSDate distantFuture] inMode:NSModalPanelRunLoopMode dequeue:YES];
- if (event)
- [NSApp postEvent:event atStart:YES];
- }
- else
+ // If Qt is used as a plugin, or just added into a native cocoa
+ // application, we should not run or stop NSApplication;
+ // This will be done from outside Qt.
+ // And if processEvents is called manually (rather than from QEventLoop), we
+ // cannot enter a tight loop and block the call, but instead return after one flush:
+ bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning];
+ bool canExec_Qt = flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec;
+
+ if (canExec_Qt && canExec_3rdParty) {
+ // We can use exec-mode, meaning that we can stay in a tight loop until
+ // interrupted. This is mostly an optimization, but it also allow us
+ // to use [NSApp run], which is the recommended way of running applications
+ // in cocoa. [NSApp run] should be called at least once for any cocoa app.
+ if (NSModalSession session = d->currentModalSession()) {
+ QBoolBlocker execGuard(d->currentExecIsNSAppRun, false);
+ while (!d->interrupt && [NSApp runModalSession:session] == NSRunContinuesResponse)
+ qt_mac_waitForMoreModalSessionEvents();
+ } else {
+ d->nsAppRunCalledByQt = true;
+ QBoolBlocker execGuard(d->currentExecIsNSAppRun, true);
[NSApp run];
-
- d->rebuildModalSessionStack(false);
+ }
retVal = true;
} else do {
- // Since we now are going to spin the event loop just _one_ round
- // we need to block all incoming CocoaRequestModal events to ensure
- // that we don't recurse into a new exec-ing event loop while doing
- // so (and as such, 'hang' the thread inside the recursion):
- QBoolBlocker block(d->blockCocoaRequestModal, true);
+ // INVARIANT: We cannot block the thread (and run in a tight loop).
+ // Instead we will process all current pending events and return.
bool mustRelease = false;
if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
- // process a pending user input event
+ // Process a pending user input event
mustRelease = true;
event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
} else {
- if (NSModalSession session = d->activeModalSession()) {
- // There's s a modal widget showing, run it's session:
- if (flags & QEventLoop::WaitForMoreEvents) {
- // Wait for at least one event
- // before spinning the session:
- event = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:[NSDate distantFuture] inMode:NSModalPanelRunLoopMode dequeue:YES];
- if (event)
- [NSApp postEvent:event atStart:YES];
- }
+ if (NSModalSession session = d->currentModalSession()) {
+ if (flags & QEventLoop::WaitForMoreEvents)
+ qt_mac_waitForMoreModalSessionEvents();
[NSApp runModalSession:session];
retVal = true;
break;
@@ -644,41 +655,35 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
&& (flags & QEventLoop::WaitForMoreEvents));
if (canWait) {
// INVARIANT: We haven't processed any events yet. And we're told
- // to stay inside this function until at least one event is processed
- // (WaitForMoreEvents). So we wait on the window server:
-#ifndef QT_MAC_USE_COCOA
- while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e20, true) == kCFRunLoopRunTimedOut);
-#else
- QMacCocoaAutoReleasePool pool;
- NSEvent *manualEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode
- dequeue:YES];
- if (manualEvent)
- [NSApp sendEvent:manualEvent];
-#endif
+ // to stay inside this function until at least one event is processed.
+ qt_mac_waitForMoreEvents();
flags &= ~QEventLoop::WaitForMoreEvents;
} else {
- // Done with event processing for now. Leave the function:
+ // Done with event processing for now.
+ // Leave the function:
break;
}
}
- // Because pending deffered-delete events are only sendt after
- // returning from the loop level they were posted in, we schedule
- // an extra wakup to force the _current_ run loop to process them (in
- // case the application stands idle waiting for the delete event):
- wakeUp();
+#ifdef QT_MAC_USE_COCOA
+ // In case we _now_ process events using [NSApp run], we need to stop it to
+ // ensure that:
+ // 1. the QEventLoop that called us is still executing, or
+ // 2. we have a modal session that needs to be spun instead.
+ // In case this is a plain call to processEvents (perhaps from a loop)
+ // from the application (rather than from a QEventLoop), we delay the
+ // interrupting until we/ actually enter a lower loop level (hence the
+ // deffered delete of the object below):
+ QtMacInterruptDispatcherHelp::interruptLater();
+#endif
- if (d->interrupt){
- // We restart NSApplication by first stopping it, and then call 'run'
- // again (NSApplication is actually already stopped, hence the need
- // for a restart, but calling stop again will also make the call
- // return from the current recursion). When the call returns to
- // QEventLoop (mind, not from this recursion, but from the one we're
- // about to stop), it will just call QEventDispatcherMac::processEvents()
- // again.
+ if (d->interrupt) {
+ // We should continue to leave all recursion to processEvents until
+ // processEvents is called again (e.g. from a QEventLoop that
+ // was not yet told to quit:
interrupt();
}
+
return retVal;
}
@@ -710,104 +715,169 @@ bool QEventDispatcherMacPrivate::blockSendPostedEvents = false;
#ifdef QT_MAC_USE_COCOA
QStack<QCocoaModalSessionInfo> QEventDispatcherMacPrivate::cocoaModalSessionStack;
-bool QEventDispatcherMacPrivate::blockCocoaRequestModal = false;
+bool QEventDispatcherMacPrivate::currentExecIsNSAppRun = false;
+bool QEventDispatcherMacPrivate::nsAppRunCalledByQt = false;
+NSModalSession QEventDispatcherMacPrivate::currentModalSessionCached = 0;
-static void qt_mac_setChildDialogsResponsive(QWidget *widget, bool responsive)
+int QEventDispatcherMacPrivate::activeModalSessionCount()
{
+ // Returns the number of modal sessions created
+ // (and not just pushed onto the stack, pending to be created)
+ int count = 0;
+ for (int i=cocoaModalSessionStack.size()-1; i>=0; --i) {
+ QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
+ if (info.session)
+ ++count;
+ }
+ return count;
+}
+
+void QEventDispatcherMacPrivate::temporarilyStopAllModalSessions()
+{
+ // Stop all created modal session, and as such, make then
+ // pending again. The next call to currentModalSession will
+ // recreate the session on top again:
+ int stackSize = cocoaModalSessionStack.size();
+ for (int i=stackSize-1; i>=0; --i) {
+ QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
+ if (info.session) {
+ [NSApp endModalSession:info.session];
+ info.session = 0;
+ }
+ }
+ currentModalSessionCached = 0;
+}
+
+NSModalSession QEventDispatcherMacPrivate::currentModalSession()
+{
+ // If we have one or more modal windows, this function will create
+ // a session for each of those, and return the one for the top.
+ if (currentModalSessionCached)
+ return currentModalSessionCached;
+
+ if (cocoaModalSessionStack.isEmpty())
+ return 0;
+
+ // Since this code will end up calling our Qt event handler
+ // (also from beginModalSessionForWindow), we need to block
+ // that to avoid side effects of events beeing delivered:
+ QBoolBlocker block(blockSendPostedEvents, true);
+
+ if (![NSApp isRunning]) {
+ // Sadly, we need to introduce this little event flush
+ // to stop dialogs from blinking/poping in front if a
+ // modal session restart was needed:
+ while (NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:nil
+ inMode:NSDefaultRunLoopMode
+ dequeue: YES]) {
+ qt_mac_send_event(0, event, 0);
+ }
+ }
+
+ int sessionCount = cocoaModalSessionStack.size();
+ for (int i=0; i<sessionCount; ++i) {
+ QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
+ if (!info.widget)
+ continue;
+ if (info.widget->testAttribute(Qt::WA_DontShowOnScreen))
+ continue;
+ if (!info.session) {
+ QMacCocoaAutoReleasePool pool;
+ NSWindow *window = qt_mac_window_for(info.widget);
+ if (!window)
+ continue;
+ info.session = [NSApp beginModalSessionForWindow:window];
+ }
+ currentModalSessionCached = info.session;
+ }
+
+ return currentModalSessionCached;
+}
+
+static void setChildrenWorksWhenModal(QWidget *widget, bool worksWhenModal)
+{
+ // For NSPanels (but not NSWindows, sadly), we can set the flag
+ // worksWhenModal, so that they are active even when they are not modal.
QList<QDialog *> dialogs = widget->findChildren<QDialog *>();
for (int i=0; i<dialogs.size(); ++i){
NSWindow *window = qt_mac_window_for(dialogs[i]);
if (window && [window isKindOfClass:[NSPanel class]]) {
- [static_cast<NSPanel *>(window) setWorksWhenModal:responsive];
- if (responsive && dialogs[i]->isVisible()){
+ [static_cast<NSPanel *>(window) setWorksWhenModal:worksWhenModal];
+ if (worksWhenModal && dialogs[i]->isVisible()){
[window orderFront:window];
}
}
}
}
-NSModalSession QEventDispatcherMacPrivate::activeModalSession()
+void QEventDispatcherMacPrivate::updateChildrenWorksWhenModal()
{
- // Create (if needed) and return the modal session
- // for the top-most modal dialog, if any:
- if (cocoaModalSessionStack.isEmpty())
- return 0;
- QCocoaModalSessionInfo &info = cocoaModalSessionStack.last();
- if (!info.widget)
- return 0;
- if (info.widget->testAttribute(Qt::WA_DontShowOnScreen)){
- // INVARIANT: We have a modal widget, but it's not visible on screen.
- // This will e.g. be true for native dialogs. Make the dialog children
- // of the previous modal dialog unresponsive, so that the current dialog
- // (native or not) is the only reponsive dialog on screen:
- int size = cocoaModalSessionStack.size();
+ // Make the dialog children of the widget
+ // active. And make the dialog children of
+ // the previous modal dialog unactive again:
+ int size = cocoaModalSessionStack.size();
+ if (size > 0){
+ if (QWidget *prevModal = cocoaModalSessionStack[size-1].widget)
+ setChildrenWorksWhenModal(prevModal, true);
if (size > 1){
if (QWidget *prevModal = cocoaModalSessionStack[size-2].widget)
- qt_mac_setChildDialogsResponsive(prevModal, false);
+ setChildrenWorksWhenModal(prevModal, false);
}
- return 0;
}
+}
- if (!info.session) {
- QMacCocoaAutoReleasePool pool;
- NSWindow *window = qt_mac_window_for(info.widget);
- if (!window)
- return 0;
- // 'beginModalSessionForWindow' will give the event loop a spin, and as
- // such, deliver Qt events. This might lead to inconsistent behaviour
- // (especially if CocoaRequestModal is delivered), so we need to block:
- QBoolBlocker block(blockSendPostedEvents, true);
- info.session = [NSApp beginModalSessionForWindow:window];
- // Make the dialog children of the current modal dialog
- // responsive. And make the dialog children of
- // the previous modal dialog unresponsive again:
- qt_mac_setChildDialogsResponsive(info.widget, true);
- int size = cocoaModalSessionStack.size();
- if (size > 1){
- if (QWidget *prevModal = cocoaModalSessionStack[size-2].widget)
- qt_mac_setChildDialogsResponsive(prevModal, false);
- }
- }
- return info.session;
+void QEventDispatcherMacPrivate::beginModalSession(QWidget *widget)
+{
+ // Add a new, empty (null), NSModalSession to the stack.
+ // It will become active the next time QEventDispatcher::processEvents is called.
+ // A QCocoaModalSessionInfo is considered pending to become active if the widget pointer
+ // is non-zero, and the session pointer is zero (it will become active upon a call to
+ // currentModalSession). A QCocoaModalSessionInfo is considered pending to be stopped if
+ // the widget pointer is zero, and the session pointer is non-zero (it will be fully
+ // stopped in endModalSession().
+ QCocoaModalSessionInfo info = {widget, 0};
+ cocoaModalSessionStack.push(info);
+ updateChildrenWorksWhenModal();
+ currentModalSessionCached = 0;
}
-void QEventDispatcherMacPrivate::rebuildModalSessionStack(bool pop)
+void QEventDispatcherMacPrivate::endModalSession(QWidget *widget)
{
- // Calling [NSApp stopModal], or [NSApp stop], will stop all modal dialogs
- // in one go. So to to not confuse cocoa, we need to stop all our modal
- // sessions as well. QMacEventDispatcher will make them modal again
- // in the correct order as long as they are left on the cocoaModalSessionStack
- // and a CocoaRequestModal is posted:
- if (cocoaModalSessionStack.isEmpty())
- return;
+ // Mark all sessions attached to widget as pending to be stopped. We do this
+ // by setting the widget pointer to zero, but leave the session pointer.
+ // We don't tell cocoa to stop any sessions just yet, because cocoa only understands
+ // when we stop the _current_ modal session (which is the session on top of
+ // the stack, and might not belong to 'widget').
+ int stackSize = cocoaModalSessionStack.size();
+ for (int i=stackSize-1; i>=0; --i) {
+ QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
+ if (info.widget == widget)
+ info.widget = 0;
+ }
- QMacCocoaAutoReleasePool pool;
- [NSApp stopModal];
- [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
- modifierFlags:0 timestamp:0. windowNumber:0 context:0
- subtype:SHRT_MAX data1:0 data2:0] atStart:NO];
+ // Now we stop, and remove, all sessions marked as pending
+ // to be stopped on _top_ of the stack, if any:
+ bool needToInterruptEventDispatcher = false;
+ bool needToUpdateChildrenWorksWhenModal = false;
- for (int i=0; i<cocoaModalSessionStack.size(); ++i){
+ for (int i=stackSize-1; i>=0; --i) {
QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
+ if (info.widget)
+ break;
+ cocoaModalSessionStack.remove(i);
+ needToUpdateChildrenWorksWhenModal = true;
+ currentModalSessionCached = 0;
if (info.session) {
[NSApp endModalSession:info.session];
- info.session = 0;
+ needToInterruptEventDispatcher = true;
}
}
- if (pop) {
- QCocoaModalSessionInfo info = cocoaModalSessionStack.pop();
- if (info.widget)
- qt_mac_setChildDialogsResponsive(info.widget, false);
- }
-
- if (!cocoaModalSessionStack.isEmpty()) {
- // Since we now have pending modal sessions again, make
- // sure that we enter modal for the one on the top later:
- qApp->postEvent(qApp, new QEvent(QEvent::CocoaRequestModal));
- } else {
- QCoreApplication::removePostedEvents(qApp, QEvent::CocoaRequestModal);
- }
+ if (needToUpdateChildrenWorksWhenModal)
+ updateChildrenWorksWhenModal();
+ if (needToInterruptEventDispatcher)
+ QEventDispatcherMac::instance()->interrupt();
}
#endif
@@ -868,27 +938,29 @@ void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info)
}
}
-#ifdef QT_MAC_USE_COCOA
-static void stopNSApp()
-{
- QMacCocoaAutoReleasePool pool;
- static const short NSAppShouldStopForQt = SHRT_MAX;
- [NSApp stop:NSApp];
- [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
- modifierFlags:0 timestamp:0. windowNumber:0 context:0
- subtype:NSAppShouldStopForQt data1:0 data2:0] atStart:NO];
-}
-#endif
-
void QEventDispatcherMac::interrupt()
{
Q_D(QEventDispatcherMac);
d->interrupt = true;
wakeUp();
+
#ifndef QT_MAC_USE_COCOA
CFRunLoopStop(mainRunLoop());
#else
- stopNSApp();
+ QMacCocoaAutoReleasePool pool;
+ // In case we wait for more events inside
+ // processEvents (or NSApp run), post a dummy to wake it up:
+ static const short NSAppShouldStopForQt = SHRT_MAX;
+ [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
+ modifierFlags:0 timestamp:0. windowNumber:0 context:0
+ subtype:NSAppShouldStopForQt data1:0 data2:0] atStart:NO];
+
+ if (d->activeModalSessionCount() == 0) {
+ // We should only stop NSApp if we actually started it (and
+ // not some 3rd party application, e.g. if we are a plugin).
+ if (d->nsAppRunCalledByQt)
+ [NSApp stop:NSApp];
+ }
#endif
}
@@ -926,5 +998,52 @@ QEventDispatcherMac::~QEventDispatcherMac()
CFRelease(d->waitingObserver);
}
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef QT_MAC_USE_COCOA
+
+QtMacInterruptDispatcherHelp* QtMacInterruptDispatcherHelp::instance = 0;
+
+QtMacInterruptDispatcherHelp::QtMacInterruptDispatcherHelp() : cancelled(false)
+{
+ // This is the whole point of encapsulation this code
+ // inside a class; we can make the code (inside destructor)
+ // execute on lower loop level:
+ deleteLater();
+}
+
+QtMacInterruptDispatcherHelp::~QtMacInterruptDispatcherHelp()
+{
+ if (cancelled)
+ return;
+
+ instance = 0;
+
+ if (QEventDispatcherMacPrivate::currentExecIsNSAppRun) {
+ int activeCount = QEventDispatcherMacPrivate::activeModalSessionCount();
+ if (activeCount > 0) {
+ // The problem we now have hit: [NSApp stop] will not stop NSApp
+ // if a session is active; it will stop the session instead.
+ // So to stop NSApp, we need to temporarily stop all the
+ // sessions, then stop NSApp, then restart the session on top again.
+ // We need to do this to ensure that we're not stuck inside
+ // [NSApp run] when we really should be running a modal session:
+ QEventDispatcherMacPrivate::temporarilyStopAllModalSessions();
+ }
+ }
+ // Always interrupt once more in case the modal session stack changed
+ // while processEvents was called manually from within the application:
+ QEventDispatcherMac::instance()->interrupt();
+}
+
+void QtMacInterruptDispatcherHelp::interruptLater() {
+ if (instance) {
+ instance->cancelled = true;
+ delete instance;
+ }
+ instance = new QtMacInterruptDispatcherHelp;
+}
+
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qeventdispatcher_mac_p.h b/src/gui/kernel/qeventdispatcher_mac_p.h
index 48a33ec..41f539f 100644
--- a/src/gui/kernel/qeventdispatcher_mac_p.h
+++ b/src/gui/kernel/qeventdispatcher_mac_p.h
@@ -172,9 +172,15 @@ public:
#ifdef QT_MAC_USE_COCOA
// The following variables help organizing modal sessions:
static QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
- static bool blockCocoaRequestModal;
- static NSModalSession activeModalSession();
- static void rebuildModalSessionStack(bool pop);
+ static bool currentExecIsNSAppRun;
+ static bool nsAppRunCalledByQt;
+ static NSModalSession currentModalSessionCached;
+ static void updateChildrenWorksWhenModal();
+ static NSModalSession currentModalSession();
+ static int activeModalSessionCount();
+ static void temporarilyStopAllModalSessions();
+ static void beginModalSession(QWidget *widget);
+ static void endModalSession(QWidget *widget);
#endif
MacSocketHash macSockets;
@@ -192,6 +198,20 @@ private:
CFRunLoopActivity activity, void *info);
};
+#ifdef QT_MAC_USE_COCOA
+class QtMacInterruptDispatcherHelp : public QObject
+{
+ static QtMacInterruptDispatcherHelp *instance;
+ bool cancelled;
+
+ QtMacInterruptDispatcherHelp();
+ ~QtMacInterruptDispatcherHelp();
+
+ public:
+ static void interruptLater();
+};
+#endif
+
QT_END_NAMESPACE
#endif // QEVENTDISPATCHER_MAC_P_H
diff --git a/src/gui/kernel/qeventdispatcher_s60.cpp b/src/gui/kernel/qeventdispatcher_s60.cpp
new file mode 100644
index 0000000..8dc063e
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_s60.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qwidget.h>
+
+#include "qeventdispatcher_s60_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QEventDispatcherS60::QEventDispatcherS60(QObject *parent)
+ : QEventDispatcherSymbian(parent),
+ m_noInputEvents(false)
+{
+}
+
+QEventDispatcherS60::~QEventDispatcherS60()
+{
+ for (int c = 0; c < m_deferredInputEvents.size(); ++c) {
+ delete m_deferredInputEvents[c].event;
+ }
+}
+
+bool QEventDispatcherS60::processEvents ( QEventLoop::ProcessEventsFlags flags )
+{
+ bool ret = false;
+
+ QT_TRY {
+ bool oldNoInputEventsValue = m_noInputEvents;
+ if (flags & QEventLoop::ExcludeUserInputEvents) {
+ m_noInputEvents = true;
+ } else {
+ m_noInputEvents = false;
+ ret = sendDeferredInputEvents() || ret;
+ }
+
+ ret = QEventDispatcherSymbian::processEvents(flags) || ret;
+
+ m_noInputEvents = oldNoInputEventsValue;
+ } QT_CATCH (const std::exception& ex) {
+#ifndef QT_NO_EXCEPTIONS
+ CActiveScheduler::Current()->Error(qt_symbian_exception2Error(ex));
+#endif
+ }
+
+ return ret;
+}
+
+bool QEventDispatcherS60::hasPendingEvents()
+{
+ return !m_deferredInputEvents.isEmpty() || QEventDispatcherSymbian::hasPendingEvents();
+}
+
+void QEventDispatcherS60::saveInputEvent(QSymbianControl *control, QWidget *widget, QInputEvent *event)
+{
+ DeferredInputEvent inputEvent = {control, widget, event};
+ m_deferredInputEvents.append(inputEvent);
+ connect(widget, SIGNAL(destroyed(QObject *)), SLOT(removeInputEventsForWidget(QObject *)));
+}
+
+bool QEventDispatcherS60::sendDeferredInputEvents()
+{
+ bool eventsSent = false;
+ while (!m_deferredInputEvents.isEmpty()) {
+ DeferredInputEvent inputEvent = m_deferredInputEvents.takeFirst();
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ inputEvent.control->sendInputEvent(inputEvent.widget, inputEvent.event);
+#ifndef QT_NO_EXCEPTIONS
+ } catch (...) {
+ delete inputEvent.event;
+ throw;
+ }
+#endif
+ delete inputEvent.event;
+ eventsSent = true;
+ }
+
+ return eventsSent;
+}
+
+void QEventDispatcherS60::removeInputEventsForWidget(QObject *object)
+{
+ for (int c = 0; c < m_deferredInputEvents.size(); ++c) {
+ if (m_deferredInputEvents[c].widget == object) {
+ delete m_deferredInputEvents[c].event;
+ m_deferredInputEvents.removeAt(c--);
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qmousevr41xx_qws.h b/src/gui/kernel/qeventdispatcher_s60_p.h
index 2ab5e27..6179a51 100644
--- a/src/gui/embedded/qmousevr41xx_qws.h
+++ b/src/gui/kernel/qeventdispatcher_s60_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtGui module of the Qt Toolkit.
+** This file is part of the QtGui of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,42 +39,58 @@
**
****************************************************************************/
-#ifndef QMOUSEVR41XX_QWS_H
-#define QMOUSEVR41XX_QWS_H
+#ifndef QEVENTDISPATCHER_S60_P_H
+#define QEVENTDISPATCHER_S60_P_H
-#include <QtGui/qmouse_qws.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.
+//
-QT_BEGIN_HEADER
+#include <private/qeventdispatcher_symbian_p.h>
+#include "qt_s60_p.h"
QT_BEGIN_NAMESPACE
-QT_MODULE(Gui)
+class Q_GUI_EXPORT QEventDispatcherS60 : public QEventDispatcherSymbian
+{
+ Q_OBJECT
-#ifndef QT_NO_QWS_MOUSE_VR41XX
+public:
+ QEventDispatcherS60(QObject *parent = 0);
+ ~QEventDispatcherS60();
-class QWSVr41xxMouseHandlerPrivate;
+ bool processEvents ( QEventLoop::ProcessEventsFlags flags );
+ bool hasPendingEvents();
-class QWSVr41xxMouseHandler : public QWSCalibratedMouseHandler
-{
-public:
- explicit QWSVr41xxMouseHandler(const QString & = QString(),
- const QString & = QString());
- ~QWSVr41xxMouseHandler();
+ bool excludeUserInputEvents() { return m_noInputEvents; }
- void resume();
- void suspend();
+ void saveInputEvent(QSymbianControl *control, QWidget *widget, QInputEvent *event);
-protected:
- QWSVr41xxMouseHandlerPrivate *d;
+private:
+ bool sendDeferredInputEvents();
+
+private Q_SLOTS:
+ void removeInputEventsForWidget(QObject *object);
private:
- friend class QWSVr41xxMouseHandlerPrivate;
-};
+ bool m_noInputEvents;
-#endif // QT_NO_QWS_MOUSE_VR41XX
+ struct DeferredInputEvent
+ {
+ QSymbianControl *control;
+ QWidget *widget;
+ QInputEvent *event;
+ };
+ QList<DeferredInputEvent> m_deferredInputEvents;
+};
QT_END_NAMESPACE
-QT_END_HEADER
-
-#endif // QMOUSEVR41XX_QWS_H
+#endif // QEVENTDISPATCHER_S60_P_H
diff --git a/src/gui/kernel/qformlayout.cpp b/src/gui/kernel/qformlayout.cpp
index f77f001..2c53145 100644
--- a/src/gui/kernel/qformlayout.cpp
+++ b/src/gui/kernel/qformlayout.cpp
@@ -1006,10 +1006,8 @@ QStyle* QFormLayoutPrivate::getStyle() const
\since 4.4
\brief The QFormLayout class manages forms of input widgets and their associated labels.
- \ingroup appearance
\ingroup geomanagement
- \mainclass
QFormLayout is a convenience layout class that lays out its
children in a two-column form. The left column consists of labels
diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp
new file mode 100644
index 0000000..eeb6528
--- /dev/null
+++ b/src/gui/kernel/qgesture.cpp
@@ -0,0 +1,308 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgesture.h"
+#include <private/qgesture_p.h>
+#include "qgraphicsitem.h"
+
+QT_BEGIN_NAMESPACE
+
+
+class QEventFilterProxyGraphicsItem : public QGraphicsItem
+{
+public:
+ QEventFilterProxyGraphicsItem(QGesture *g)
+ : gesture(g)
+ {
+ }
+ bool sceneEventFilter(QGraphicsItem *, QEvent *event)
+ {
+ return gesture ? gesture->filterEvent(event) : false;
+ }
+ QRectF boundingRect() const { return QRectF(); }
+ void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) { }
+
+private:
+ QGesture *gesture;
+};
+
+/*!
+ \class QGesture
+ \since 4.6
+
+ \brief The QGesture class is the base class for implementing custom
+ gestures.
+
+ This class represents both an object that recognizes a gesture out of a set
+ of input events (a gesture recognizer), and a gesture object itself that
+ can be used to get extended information about the triggered gesture.
+
+ The class has a list of properties that can be queried by the user to get
+ some gesture-specific parameters (for example, an offset of a Pan gesture).
+
+ Usually gesture recognizer implements a state machine, storing its state
+ internally in the recognizer object. The recognizer receives input events
+ through the \l{QGesture::}{filterEvent()} virtual function and decides
+ whether the event should change the state of the recognizer by emitting an
+ appropriate signal.
+
+ Input events should be either fed to the recognizer one by one with a
+ filterEvent() function, or the gesture recognizer should be attached to an
+ object it filters events for by specifying it as a parent object. The
+ QGesture object installs itself as an event filter to the parent object
+ automatically, the unsetObject() function should be used to remove an event
+ filter from the parent object. To make a
+ gesture that operates on a QGraphicsItem, both the appropriate QGraphicsView
+ should be passed as a parent object and setGraphicsItem() functions should
+ be used to attach a gesture to a graphics item.
+
+ This is a base class, to create a custom gesture type, you should subclass
+ it and implement its pure virtual functions.
+
+ \sa QPanGesture
+*/
+
+/*! \fn bool QGesture::filterEvent(QEvent *event)
+
+ Parses input \a event and emits a signal when detects a gesture.
+
+ In your reimplementation of this function, if you want to filter the \a
+ event out, i.e. stop it being handled further, return true; otherwise
+ return false;
+
+ This is a pure virtual function that needs to be implemented in subclasses.
+*/
+
+/*! \fn void QGesture::started()
+
+ The signal is emitted when the gesture is started. Extended information
+ about the gesture is contained in the signal sender object.
+
+ In addition to started(), a triggered() signal should also be emitted.
+*/
+
+/*! \fn void QGesture::triggered()
+
+ The signal is emitted when the gesture is detected. Extended information
+ about the gesture is contained in the signal sender object.
+*/
+
+/*! \fn void QGesture::finished()
+
+ The signal is emitted when the gesture is finished. Extended information
+ about the gesture is contained in the signal sender object.
+*/
+
+/*! \fn void QGesture::cancelled()
+
+ The signal is emitted when the gesture is cancelled, for example the reset()
+ function is called while the gesture was in the process of emitting a
+ triggered() signal. Extended information about the gesture is contained in
+ the sender object.
+*/
+
+
+/*!
+ Creates a new gesture handler object and marks it as a child of \a parent.
+
+ The \a parent object is also the default event source for the gesture,
+ meaning that the gesture installs itself as an event filter for the \a
+ parent.
+
+ \sa setGraphicsItem()
+*/
+QGesture::QGesture(QObject *gestureTarget, QObject *parent)
+ : QObject(*new QGesturePrivate, parent)
+{
+ setGestureTarget(gestureTarget);
+}
+
+/*! \internal
+ */
+QGesture::QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent)
+ : QObject(dd, parent)
+{
+ setGestureTarget(gestureTarget);
+}
+
+/*!
+ Destroys the gesture object.
+*/
+QGesture::~QGesture()
+{
+}
+
+/*!
+ \property QGesture::gestureTarget
+
+ Gesture target is the object that the gesture will observe for events.
+ Typically this means that the gesture installs an event filter on the
+ target object.
+*/
+void QGesture::setGestureTarget(QObject *object)
+{
+ d_func()->setupGestureTarget(object);
+}
+
+QObject* QGesture::gestureTarget() const
+{
+ return d_func()->gestureTarget;
+}
+
+void QGesturePrivate::setupGestureTarget(QObject *object)
+{
+ Q_Q(QGesture);
+ if (gestureTarget)
+ gestureTarget->removeEventFilter(q);
+ if (object)
+ object->installEventFilter(q);
+ gestureTarget = object;
+}
+
+/*! \internal
+ */
+bool QGesture::eventFilter(QObject *receiver, QEvent *event)
+{
+ Q_D(QGesture);
+ if (d->graphicsItem && receiver == parent())
+ return false;
+ return filterEvent(event);
+}
+
+/*!
+ \property QGesture::state
+
+ \brief The current state of the gesture.
+*/
+
+/*!
+ Returns the gesture recognition state.
+ */
+Qt::GestureState QGesture::state() const
+{
+ return d_func()->state;
+}
+
+/*!
+ Sets this gesture's recognition state to \a state and emits appropriate
+ signals.
+
+ This functions emits the signals according to the old state and the new
+ \a state, and it should be called after all the internal properties have been
+ initialized.
+
+ \sa started(), triggered(), finished(), cancelled()
+ */
+void QGesture::updateState(Qt::GestureState state)
+{
+ Q_D(QGesture);
+ if (d->state == state) {
+ if (state == Qt::GestureUpdated)
+ emit triggered();
+ return;
+ }
+ const Qt::GestureState oldState = d->state;
+ d->state = state;
+ if (state != Qt::NoGesture && oldState > state) {
+ // comparing the state as ints: state should only be changed from
+ // started to (optionally) updated and to finished.
+ qWarning("QGesture::updateState: incorrect new state");
+ return;
+ }
+ if (oldState == Qt::NoGesture)
+ emit started();
+ if (state == Qt::GestureUpdated)
+ emit triggered();
+ else if (state == Qt::GestureFinished)
+ emit finished();
+ else if (state == Qt::NoGesture)
+ emit cancelled();
+
+ if (state == Qt::GestureFinished) {
+ // gesture is finished, so we reset the internal state.
+ d->state = Qt::NoGesture;
+ }
+}
+
+/*!
+ Sets the \a graphicsItem the gesture is filtering events for.
+
+ The gesture will install an event filter to the \a graphicsItem and
+ redirect them to the filterEvent() function.
+
+ \sa graphicsItem()
+*/
+void QGesture::setGraphicsItem(QGraphicsItem *graphicsItem)
+{
+ Q_D(QGesture);
+ if (d->graphicsItem && d->eventFilterProxyGraphicsItem)
+ d->graphicsItem->removeSceneEventFilter(d->eventFilterProxyGraphicsItem);
+ d->graphicsItem = graphicsItem;
+ if (!d->eventFilterProxyGraphicsItem)
+ d->eventFilterProxyGraphicsItem = new QEventFilterProxyGraphicsItem(this);
+ if (graphicsItem)
+ graphicsItem->installSceneEventFilter(d->eventFilterProxyGraphicsItem);
+}
+
+/*!
+ Returns the graphics item the gesture is filtering events for.
+
+ \sa setGraphicsItem()
+*/
+QGraphicsItem* QGesture::graphicsItem() const
+{
+ return d_func()->graphicsItem;
+}
+
+/*! \fn void QGesture::reset()
+
+ Resets the internal state of the gesture. This function might be called by
+ the filterEvent() implementation in a derived class, or by the user to
+ cancel a gesture. The base class implementation calls
+ updateState(Qt::NoGesture) which emits the cancelled()
+ signal if the state() of the gesture indicated it was active.
+*/
+void QGesture::reset()
+{
+ updateState(Qt::NoGesture);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h
new file mode 100644
index 0000000..1d2fa6d
--- /dev/null
+++ b/src/gui/kernel/qgesture.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURE_H
+#define QGESTURE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGraphicsItem;
+class QGesturePrivate;
+class Q_GUI_EXPORT QGesture : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QGesture)
+
+ Q_PROPERTY(Qt::GestureState state READ state)
+ Q_PROPERTY(QObject* gestureTarget READ gestureTarget WRITE setGestureTarget)
+
+public:
+ explicit QGesture(QObject *gestureTarget = 0, QObject *parent = 0);
+ ~QGesture();
+
+ virtual bool filterEvent(QEvent *event) = 0;
+
+ void setGestureTarget(QObject *object);
+ QObject* gestureTarget() const;
+
+ void setGraphicsItem(QGraphicsItem *);
+ QGraphicsItem *graphicsItem() const;
+
+ Qt::GestureState state() const;
+
+protected:
+ QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent);
+ bool eventFilter(QObject*, QEvent*);
+
+ virtual void reset();
+ void updateState(Qt::GestureState state);
+
+Q_SIGNALS:
+ void started();
+ void triggered();
+ void finished();
+ void cancelled();
+
+private:
+ friend class QWidget;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGESTURE_H
diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h
new file mode 100644
index 0000000..f584713
--- /dev/null
+++ b/src/gui/kernel/qgesture_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURE_P_H
+#define QGESTURE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrect.h"
+#include "qpoint.h"
+#include "qdatetime.h"
+#include "qgesture.h"
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QGraphicsItem;
+class QGesturePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QGesture)
+
+public:
+ QGesturePrivate()
+ : gestureTarget(0), graphicsItem(0), eventFilterProxyGraphicsItem(0),
+ state(Qt::NoGesture)
+ {
+ }
+
+ virtual void setupGestureTarget(QObject *o);
+
+ QPointer<QObject> gestureTarget;
+ QGraphicsItem *graphicsItem;
+ QGraphicsItem *eventFilterProxyGraphicsItem;
+
+ Qt::GestureState state;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGESTURE_P_H
diff --git a/src/gui/kernel/qgridlayout.cpp b/src/gui/kernel/qgridlayout.cpp
index 6cded5a..0cf850e 100644
--- a/src/gui/kernel/qgridlayout.cpp
+++ b/src/gui/kernel/qgridlayout.cpp
@@ -980,8 +980,7 @@ QRect QGridLayoutPrivate::cellRect(int row, int col) const
\brief The QGridLayout class lays out widgets in a grid.
\ingroup geomanagement
- \ingroup appearance
- \mainclass
+
QGridLayout takes the space made available to it (by its parent
layout or by the parentWidget()), divides it up into rows and
@@ -1034,18 +1033,19 @@ QRect QGridLayoutPrivate::cellRect(int row, int col) const
other layouts into the cells of your grid layout using
addWidget(), addItem(), and addLayout().
- QGridLayout also includes two margin widths: the margin() and the
- spacing(). The margin is the width of the reserved space along
- each of the QGridLayout's four sides. The spacing is the width of
- the automatically allocated spacing between neighboring boxes.
+ QGridLayout also includes two margin widths:
+ the \l{getContentsMargins()}{contents margin} and the spacing().
+ The contents margin is the width of the reserved space along each
+ of the QGridLayout's four sides. The spacing() is the width of the
+ automatically allocated spacing between neighboring boxes.
- The default margin() and spacing() values are provided by the
- style. The default margin Qt styles specify is 9 for child
- widgets and 11 for windows. The spacing defaults to the same as
+ The default contents margin values are provided by the
+ \l{QStyle::pixelMetric()}{style}. The default value Qt styles specify
+ is 9 for child widgets and 11 for windows. The spacing defaults to the same as
the margin width for a top-level layout, or to the same as the
parent layout.
- \sa QBoxLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
+ \sa QBoxLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example}
*/
@@ -1078,7 +1078,7 @@ QGridLayout::QGridLayout()
#ifdef QT3_SUPPORT
/*!
- \obsolete
+ \obsolete
Constructs a new QGridLayout with \a nRows rows, \a nCols columns
and parent widget, \a parent. \a parent may not be 0. The grid
layout is called \a name.
diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp
index e4be9a3..c96919a 100644
--- a/src/gui/kernel/qguifunctions_wince.cpp
+++ b/src/gui/kernel/qguifunctions_wince.cpp
@@ -215,13 +215,7 @@ int qt_wince_GetDIBits(HDC /*hdc*/ , HBITMAP hSourceBitmap, uint, uint, LPVOID l
return ret;
}
-bool qt_wince_TextOutW(HDC hdc, int x, int y, LPWSTR lpString, UINT c)
-{
- return ExtTextOutW(hdc, x, y, 0, NULL, lpString, c, NULL);
-}
-
-
-HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCTSTR, LPCTSTR file, LPCTSTR params, LPCTSTR dir, int showCmd)
+HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCWSTR, LPCWSTR file, LPCWSTR params, LPCWSTR dir, int showCmd)
{
SHELLEXECUTEINFO info;
info.hwnd = hwnd;
@@ -253,21 +247,40 @@ COLORREF qt_wince_PALETTEINDEX( WORD /*wPaletteIndex*/)
return 0;
}
-BOOL qt_wince_TextOut( HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString )
-{
- return ExtTextOut( hdc, nXStart, nYStart - 16, 0, NULL, lpString, cbString, NULL );
-}
-
// Internal Qt -----------------------------------------------------
bool qt_wince_is_platform(const QString &platformString) {
- TCHAR tszPlatform[64];
- if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
- sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
- if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
+ wchar_t tszPlatform[64];
+ if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform) / sizeof(wchar_t), tszPlatform, 0))
+ if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
return true;
return false;
}
+int qt_wince_get_build()
+{
+ OSVERSIONINFO osvi;
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ if (GetVersionEx(&osvi)) {
+ return osvi.dwBuildNumber;
+ }
+ return 0;
+}
+
+int qt_wince_get_version()
+{
+ OSVERSIONINFO osvi;
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ if (GetVersionEx(&osvi)) {
+ return (osvi.dwMajorVersion * 10 + osvi.dwMinorVersion);
+ }
+ return 0;
+}
+
+bool qt_wince_is_windows_mobile_65()
+{
+ return ((qt_wince_get_version() == 52) && (qt_wince_get_build() > 2000));
+}
+
bool qt_wince_is_pocket_pc() {
return qt_wince_is_platform(QString::fromLatin1("PocketPC"));
}
@@ -316,8 +329,8 @@ void qt_wince_maximize(QWidget *widget)
void qt_wince_minimize(HWND hwnd) {
- uint exstyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
- uint style = GetWindowLongW(hwnd, GWL_STYLE);
+ uint exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ uint style = GetWindowLong(hwnd, GWL_STYLE);
RECT rect;
RECT crect = {0,0,0,0};
GetWindowRect(hwnd, &rect);
diff --git a/src/gui/kernel/qguifunctions_wince.h b/src/gui/kernel/qguifunctions_wince.h
index 043f1b6..5d57af5 100644
--- a/src/gui/kernel/qguifunctions_wince.h
+++ b/src/gui/kernel/qguifunctions_wince.h
@@ -73,10 +73,6 @@ int qt_wince_GetDIBits(HDC, HBITMAP, uint, uint, void*, LPBITMAPINFO, uint);
// QWidget
#define SW_SHOWMINIMIZED SW_MINIMIZE
-// QPaintEngine
-bool qt_wince_TextOutW(HDC, int, int, LPWSTR, UINT);
-#define TextOutW(a,b,c,d,e) qt_wince_TextOutW(a,b,c,d,e)
-
// QRegion
#define ALTERNATE 0
#define WINDING 1
@@ -128,7 +124,7 @@ typedef struct tagTTPOLYCURVE
#define TT_PRIM_CSPLINE 3
#define ANSI_VAR_FONT 12
-HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCTSTR operation, LPCTSTR file, LPCTSTR params, LPCTSTR dir, int showCmd);
+HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCWSTR operation, LPCWSTR file, LPCWSTR params, LPCWSTR dir, int showCmd);
#define ShellExecute(a,b,c,d,e,f) qt_wince_ShellExecute(a,b,c,d,e,f)
@@ -150,8 +146,6 @@ HWND qt_wince_SetClipboardViewer(
// Graphics ---------------------------------------------------------
COLORREF qt_wince_PALETTEINDEX( WORD wPaletteIndex );
#define PALETTEINDEX(a) qt_wince_PALETTEINDEX(a)
-BOOL qt_wince_TextOut( HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString );
-#define TextOut(a,b,c,d,e) qt_wince_TextOut(a,b,c,d,e)
#endif // Q_OS_WINCE
#endif // QGUIFUNCTIONS_WCE_H
diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp
index 62c9117..a515a58 100644
--- a/src/gui/kernel/qguivariant.cpp
+++ b/src/gui/kernel/qguivariant.cpp
@@ -60,6 +60,11 @@
#include "qregion.h"
#include "qsizepolicy.h"
#include "qtextformat.h"
+#include "qmatrix4x4.h"
+#include "qvector2d.h"
+#include "qvector3d.h"
+#include "qvector4d.h"
+#include "qquaternion.h"
#include "private/qvariant_p.h"
@@ -148,6 +153,31 @@ static void construct(QVariant::Private *x, const void *copy)
v_construct<QColor>(x, &color);
break;
}
+#ifndef QT_NO_MATRIX4X4
+ case QVariant::Matrix4x4:
+ v_construct<QMatrix4x4>(x, copy);
+ break;
+#endif
+#ifndef QT_NO_VECTOR2D
+ case QVariant::Vector2D:
+ v_construct<QVector2D>(x, copy);
+ break;
+#endif
+#ifndef QT_NO_VECTOR3D
+ case QVariant::Vector3D:
+ v_construct<QVector3D>(x, copy);
+ break;
+#endif
+#ifndef QT_NO_VECTOR4D
+ case QVariant::Vector4D:
+ v_construct<QVector4D>(x, copy);
+ break;
+#endif
+#ifndef QT_NO_QUATERNION
+ case QVariant::Quaternion:
+ v_construct<QQuaternion>(x, copy);
+ break;
+#endif
default:
qcoreVariantHandler()->construct(x, copy);
return;
@@ -221,6 +251,31 @@ static void clear(QVariant::Private *d)
case QVariant::Pen:
v_clear<QPen>(d);
break;
+#ifndef QT_NO_MATRIX4X4
+ case QVariant::Matrix4x4:
+ v_clear<QMatrix4x4>(d);
+ break;
+#endif
+#ifndef QT_NO_VECTOR2D
+ case QVariant::Vector2D:
+ v_clear<QVector2D>(d);
+ break;
+#endif
+#ifndef QT_NO_VECTOR3D
+ case QVariant::Vector3D:
+ v_clear<QVector3D>(d);
+ break;
+#endif
+#ifndef QT_NO_VECTOR4D
+ case QVariant::Vector4D:
+ v_clear<QVector4D>(d);
+ break;
+#endif
+#ifndef QT_NO_QUATERNION
+ case QVariant::Quaternion:
+ v_clear<QVector4D>(d);
+ break;
+#endif
default:
qcoreVariantHandler()->clear(d);
return;
@@ -266,7 +321,26 @@ static bool isNull(const QVariant::Private *d)
case QVariant::KeySequence:
#endif
case QVariant::Pen:
+#ifndef QT_NO_MATRIX4X4
+ case QVariant::Matrix4x4:
+#endif
break;
+#ifndef QT_NO_VECTOR2D
+ case QVariant::Vector2D:
+ return v_cast<QVector2D>(d)->isNull();
+#endif
+#ifndef QT_NO_VECTOR3D
+ case QVariant::Vector3D:
+ return v_cast<QVector3D>(d)->isNull();
+#endif
+#ifndef QT_NO_VECTOR4D
+ case QVariant::Vector4D:
+ return v_cast<QVector4D>(d)->isNull();
+#endif
+#ifndef QT_NO_QUATERNION
+ case QVariant::Quaternion:
+ return v_cast<QQuaternion>(d)->isNull();
+#endif
default:
return qcoreVariantHandler()->isNull(d);
}
@@ -326,6 +400,26 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b)
#endif
case QVariant::Pen:
return *v_cast<QPen>(a) == *v_cast<QPen>(b);
+#ifndef QT_NO_MATRIX4X4
+ case QVariant::Matrix4x4:
+ return *v_cast<QMatrix4x4>(a) == *v_cast<QMatrix4x4>(b);
+#endif
+#ifndef QT_NO_VECTOR2D
+ case QVariant::Vector2D:
+ return *v_cast<QVector2D>(a) == *v_cast<QVector2D>(b);
+#endif
+#ifndef QT_NO_VECTOR3D
+ case QVariant::Vector3D:
+ return *v_cast<QVector3D>(a) == *v_cast<QVector3D>(b);
+#endif
+#ifndef QT_NO_VECTOR4D
+ case QVariant::Vector4D:
+ return *v_cast<QVector4D>(a) == *v_cast<QVector4D>(b);
+#endif
+#ifndef QT_NO_QUATERNION
+ case QVariant::Quaternion:
+ return *v_cast<QQuaternion>(a) == *v_cast<QQuaternion>(b);
+#endif
default:
break;
}
@@ -513,6 +607,31 @@ static void streamDebug(QDebug dbg, const QVariant &v)
case QVariant::Pen:
dbg.nospace() << qvariant_cast<QPen>(v);
break;
+#ifndef QT_NO_MATRIX4X4
+ case QVariant::Matrix4x4:
+ dbg.nospace() << qvariant_cast<QMatrix4x4>(v);
+ break;
+#endif
+#ifndef QT_NO_VECTOR2D
+ case QVariant::Vector2D:
+ dbg.nospace() << qvariant_cast<QVector2D>(v);
+ break;
+#endif
+#ifndef QT_NO_VECTOR3D
+ case QVariant::Vector3D:
+ dbg.nospace() << qvariant_cast<QVector3D>(v);
+ break;
+#endif
+#ifndef QT_NO_VECTOR4D
+ case QVariant::Vector4D:
+ dbg.nospace() << qvariant_cast<QVector4D>(v);
+ break;
+#endif
+#ifndef QT_NO_QUATERNION
+ case QVariant::Quaternion:
+ dbg.nospace() << qvariant_cast<QQuaternion>(v);
+ break;
+#endif
default:
qcoreVariantHandler()->debugStream(dbg, v);
break;
@@ -596,6 +715,21 @@ Q_DECL_METATYPE_HELPER(QTextLength)
Q_DECL_METATYPE_HELPER(QTextFormat)
Q_DECL_METATYPE_HELPER(QMatrix)
Q_DECL_METATYPE_HELPER(QTransform)
+#ifndef QT_NO_MATRIX4X4
+Q_DECL_METATYPE_HELPER(QMatrix4x4)
+#endif
+#ifndef QT_NO_VECTOR2D
+Q_DECL_METATYPE_HELPER(QVector2D)
+#endif
+#ifndef QT_NO_VECTOR3D
+Q_DECL_METATYPE_HELPER(QVector3D)
+#endif
+#ifndef QT_NO_VECTOR4D
+Q_DECL_METATYPE_HELPER(QVector4D)
+#endif
+#ifndef QT_NO_QUATERNION
+Q_DECL_METATYPE_HELPER(QQuaternion)
+#endif
#ifdef QT_NO_DATASTREAM
# define Q_IMPL_METATYPE_HELPER(TYPE) \
@@ -645,7 +779,32 @@ static const QMetaTypeGuiHelper qVariantGuiHelper[] = {
Q_IMPL_METATYPE_HELPER(QTextLength),
Q_IMPL_METATYPE_HELPER(QTextFormat),
Q_IMPL_METATYPE_HELPER(QMatrix),
- Q_IMPL_METATYPE_HELPER(QTransform)
+ Q_IMPL_METATYPE_HELPER(QTransform),
+#ifndef QT_NO_MATRIX4X4
+ Q_IMPL_METATYPE_HELPER(QMatrix4x4),
+#else
+ {0, 0, 0, 0},
+#endif
+#ifndef QT_NO_VECTOR2D
+ Q_IMPL_METATYPE_HELPER(QVector2D),
+#else
+ {0, 0, 0, 0},
+#endif
+#ifndef QT_NO_VECTOR3D
+ Q_IMPL_METATYPE_HELPER(QVector3D),
+#else
+ {0, 0, 0, 0},
+#endif
+#ifndef QT_NO_VECTOR4D
+ Q_IMPL_METATYPE_HELPER(QVector4D),
+#else
+ {0, 0, 0, 0},
+#endif
+#ifndef QT_NO_QUATERNION
+ Q_IMPL_METATYPE_HELPER(QQuaternion)
+#else
+ {0, 0, 0, 0}
+#endif
};
static const QVariant::Handler *qt_guivariant_last_handler = 0;
diff --git a/src/gui/kernel/qkde.cpp b/src/gui/kernel/qkde.cpp
new file mode 100644
index 0000000..98bf0a0
--- /dev/null
+++ b/src/gui/kernel/qkde.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qkde_p.h"
+#include <QtCore/QLibrary>
+#include <QtCore/QDir>
+#include <QtCore/qdebug.h>
+#include <QtCore/QSettings>
+#include "QtGui/qstylefactory.h"
+#include "qt_x11_p.h"
+
+#if defined(Q_WS_X11)
+
+QT_BEGIN_NAMESPACE
+
+/*! \internal
+Gets the current KDE home path
+like "/home/troll/.kde"
+*/
+QString QKde::kdeHome()
+{
+ static QString kdeHomePath;
+ if (kdeHomePath.isEmpty()) {
+ kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME"));
+ if (kdeHomePath.isEmpty()) {
+ QDir homeDir(QDir::homePath());
+ QString kdeConfDir(QLatin1String("/.kde"));
+ if (4 == X11->desktopVersion && homeDir.exists(QLatin1String(".kde4")))
+ kdeConfDir = QLatin1String("/.kde4");
+ kdeHomePath = QDir::homePath() + kdeConfDir;
+ }
+ }
+ return kdeHomePath;
+}
+
+/*!\internal
+ Reads the color from the config, and store it in the palette with the given color role if found
+ */
+static bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QSettings &kdeSettings, const QString &kde4Key, const QString &kde3Key = QString())
+{
+ QVariant variant = kdeSettings.value(kde4Key);
+ if (!variant.isValid())
+ QVariant variant = kdeSettings.value(kde3Key);
+ if (variant.isValid()) {
+ QStringList values = variant.toStringList();
+ if (values.size() == 3) {
+ int r = values[0].toInt();
+ int g = values[1].toInt();
+ int b = values[2].toInt();
+ pal->setBrush(role, QColor(r, g, b));
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/*!\internal
+ Returns the KDE palette
+*/
+QPalette QKde::kdePalette()
+{
+ const QSettings theKdeSettings(QKde::kdeHome() +
+ QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ QPalette pal;
+
+ // Setup KDE palette
+ kdeColor(&pal, QPalette::Button, theKdeSettings, QLatin1String("Colors:Button/BackgroundNormal"), QLatin1String("buttonBackground"));
+ kdeColor(&pal, QPalette::Window, theKdeSettings, QLatin1String("Colors:Window/BackgroundNormal"), QLatin1String("background"));
+ kdeColor(&pal, QPalette::Text, theKdeSettings, QLatin1String("Colors:View/ForegroundNormal"), QLatin1String("foreground"));
+ kdeColor(&pal, QPalette::WindowText, theKdeSettings, QLatin1String("Colors:Window/ForegroundNormal"), QLatin1String("windowForeground"));
+ kdeColor(&pal, QPalette::Base, theKdeSettings, QLatin1String("Colors:View/BackgroundNormal"), QLatin1String("windowBackground"));
+ kdeColor(&pal, QPalette::Highlight, theKdeSettings, QLatin1String("Colors:Selection/BackgroundNormal"), QLatin1String("selectBackground"));
+ kdeColor(&pal, QPalette::HighlightedText, theKdeSettings, QLatin1String("Colors:Selection/ForegroundNormal"), QLatin1String("selectForeground"));
+ kdeColor(&pal, QPalette::AlternateBase, theKdeSettings, QLatin1String("Colors:View/BackgroundAlternate"), QLatin1String("alternateBackground"));
+ kdeColor(&pal, QPalette::ButtonText, theKdeSettings, QLatin1String("Colors:Button/ForegroundNormal"), QLatin1String("buttonForeground"));
+ kdeColor(&pal, QPalette::Link, theKdeSettings, QLatin1String("Colors:View/ForegroundLink"), QLatin1String("linkColor"));
+ kdeColor(&pal, QPalette::LinkVisited, theKdeSettings, QLatin1String("Colors:View/ForegroundVisited"), QLatin1String("visitedLinkColor"));
+ //## TODO tooltip color
+
+ return pal;
+}
+
+/*!\internal
+ Returns the name of the QStyle to use.
+ (read from the kde config if needed)
+*/
+QString QKde::kdeStyle()
+{
+ if (X11->desktopVersion >= 4) {
+ QSettings kdeSettings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ QString style = kdeSettings.value(QLatin1String("widgetStyle"), QLatin1String("Oxygen")).toString();
+
+ QStringList availableStyles = QStyleFactory::keys();
+ if(availableStyles.contains(style, Qt::CaseInsensitive))
+ return style;
+ }
+
+ if (X11->use_xrender)
+ return QLatin1String("plastique");
+ else
+ return QLatin1String("windows");
+}
+
+/*!\internal
+ placeholder to load icon from kde.
+ to be implemented
+ */
+QIcon QKde::kdeIcon(const QString &name)
+{
+ //###todo
+ return QIcon();
+}
+
+QT_END_NAMESPACE
+
+#endif //Q_WS_X11
+
diff --git a/src/gui/kernel/qkde_p.h b/src/gui/kernel/qkde_p.h
new file mode 100644
index 0000000..c794bad
--- /dev/null
+++ b/src/gui/kernel/qkde_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKDE_H
+#define QKDE_H
+
+#include <QtCore/qglobal.h>
+#include <QtGui/QPalette>
+#include <QtGui/QIcon>
+
+//
+// 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.
+//
+#if defined(Q_WS_X11)
+
+
+QT_BEGIN_NAMESPACE
+
+// This namespace contains helper function to help KDE integration
+namespace QKde {
+ QString kdeHome();
+ QString kdeStyle();
+ QPalette kdePalette();
+ QIcon kdeIcon(const QString &name);
+}
+
+
+QT_END_NAMESPACE
+
+#endif // Q_WS_X11
+#endif // QKDE_H
diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp
index 456f4a4..a4afa09 100644
--- a/src/gui/kernel/qkeymapper.cpp
+++ b/src/gui/kernel/qkeymapper.cpp
@@ -51,7 +51,6 @@ QT_BEGIN_NAMESPACE
/*!
\class QKeyMapper
\since 4.2
- \ingroup application
\internal
\sa QObject
@@ -116,6 +115,4 @@ QKeyMapperPrivate *qt_keymapper_private()
return QKeyMapper::instance()->d_func();
}
-Q_GUI_EXPORT QList<int> qt_keymapper_possibleKeys(QKeyEvent *e) { return QKeyMapper::instance()->possibleKeys(e); }
-
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp
index 04a9081..b163c7b 100644
--- a/src/gui/kernel/qkeymapper_mac.cpp
+++ b/src/gui/kernel/qkeymapper_mac.cpp
@@ -48,6 +48,7 @@
#include <qinputcontext.h>
#include <private/qkeymapper_p.h>
#include <private/qapplication_p.h>
+#include <private/qmacinputcontext_p.h>
QT_BEGIN_NAMESPACE
@@ -160,6 +161,14 @@ Qt::KeyboardModifiers qt_mac_get_modifiers(int keys)
ret |= Qt::KeyboardModifier(qt_mac_modifier_symbols[i].qt_code);
}
}
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ Qt::KeyboardModifiers oldModifiers = ret;
+ ret &= ~(Qt::MetaModifier | Qt::ControlModifier);
+ if (oldModifiers & Qt::ControlModifier)
+ ret |= Qt::MetaModifier;
+ if (oldModifiers & Qt::MetaModifier)
+ ret |= Qt::ControlModifier;
+ }
return ret;
}
static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys)
@@ -176,6 +185,15 @@ static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys)
ret |= qt_mac_modifier_symbols[i].mac_code;
}
}
+
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ int oldModifiers = ret;
+ ret &= ~(controlKeyBit | cmdKeyBit);
+ if (oldModifiers & controlKeyBit)
+ ret |= cmdKeyBit;
+ if (oldModifiers & cmdKeyBit)
+ ret |= controlKeyBit;
+ }
return ret;
}
void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object)
@@ -480,7 +498,8 @@ static bool translateKeyEventInternal(EventHandlerCallRef er, EventRef keyEvent,
#ifdef QT_MAC_USE_COCOA
if (outHandled) {
qt_mac_eat_unicode_key = false;
- CallNextEventHandler(er, keyEvent);
+ if (er)
+ CallNextEventHandler(er, keyEvent);
*outHandled = qt_mac_eat_unicode_key;
}
#endif
@@ -544,7 +563,7 @@ QKeyMapperPrivate::QKeyMapperPrivate()
QKeyMapperPrivate::~QKeyMapperPrivate()
{
- clearMappings();
+ deleteLayouts();
}
bool
@@ -639,7 +658,7 @@ QKeyMapperPrivate::updateKeyboard()
}
void
-QKeyMapperPrivate::clearMappings()
+QKeyMapperPrivate::deleteLayouts()
{
keyboard_mode = NullMode;
for (int i = 0; i < 255; ++i) {
@@ -648,6 +667,12 @@ QKeyMapperPrivate::clearMappings()
keyLayout[i] = 0;
}
}
+}
+
+void
+QKeyMapperPrivate::clearMappings()
+{
+ deleteLayouts();
updateKeyboard();
}
@@ -692,8 +717,14 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e
return true;
}
- if (qApp->inputContext() && qApp->inputContext()->isComposing())
+ if (qApp->inputContext() && qApp->inputContext()->isComposing()) {
+ if (ekind == kEventRawKeyDown) {
+ QMacInputContext *context = qobject_cast<QMacInputContext*>(qApp->inputContext());
+ if (context)
+ context->setLastKeydownEvent(event);
+ }
return false;
+ }
//get modifiers
Qt::KeyboardModifiers modifiers;
int qtKey;
@@ -704,8 +735,10 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e
QString text(ourChar);
/* This is actually wrong - but unfortunatly it is the best that can be
done for now because of the Control/Meta mapping problems */
- if (modifiers & (Qt::ControlModifier | Qt::MetaModifier))
+ if (modifiers & (Qt::ControlModifier | Qt::MetaModifier)
+ && !qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
text = QString();
+ }
if (widget) {
@@ -721,7 +754,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e
//is it of use to text services? If so we won't bother
//with a QKeyEvent.
qt_mac_eat_unicode_key = false;
- CallNextEventHandler(er, event);
+ if (er)
+ CallNextEventHandler(er, event);
extern bool qt_mac_menubar_is_open();
if (qt_mac_eat_unicode_key || qt_mac_menubar_is_open()) {
return true;
diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h
index e411731..aa55d82 100644
--- a/src/gui/kernel/qkeymapper_p.h
+++ b/src/gui/kernel/qkeymapper_p.h
@@ -58,6 +58,7 @@
#include <qlist.h>
#include <qlocale.h>
#include <qevent.h>
+#include <qhash.h>
#if defined (Q_WS_MAC64)
# include <private/qt_mac_p.h>
@@ -160,6 +161,7 @@ public:
bool translateKeyEvent(QWidget *receiver, const MSG &msg, bool grab);
void updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode, quint32 vk_key);
bool isADeadKey(unsigned int vk_key, unsigned int modifiers);
+ void deleteLayouts();
KeyboardLayoutItem *keyLayout[256];
@@ -188,6 +190,7 @@ public:
bool updateKeyboard();
void updateKeyMap(EventHandlerCallRef, EventRef, void *);
bool translateKeyEvent(QWidget *, EventHandlerCallRef, EventRef, void *, bool);
+ void deleteLayouts();
enum { NullMode, UnicodeMode, OtherMode } keyboard_mode;
union {
@@ -203,6 +206,13 @@ public:
UInt32 keyboard_dead;
KeyboardLayoutItem *keyLayout[256];
#elif defined(Q_WS_QWS)
+#elif defined(Q_OS_SYMBIAN)
+private:
+ QHash<TUint, int> s60ToQtKeyMap;
+ void fillKeyMap();
+public:
+ QString translateKeyEvent(int keySym, Qt::KeyboardModifiers modifiers);
+ int mapS60KeyToQt(TUint s60key);
#endif
};
diff --git a/src/gui/kernel/qkeymapper_s60.cpp b/src/gui/kernel/qkeymapper_s60.cpp
new file mode 100644
index 0000000..6063ee4
--- /dev/null
+++ b/src/gui/kernel/qkeymapper_s60.cpp
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qkeymapper_p.h"
+#include <e32keys.h>
+
+QT_BEGIN_NAMESPACE
+
+QKeyMapperPrivate::QKeyMapperPrivate()
+{
+ fillKeyMap();
+}
+
+QKeyMapperPrivate::~QKeyMapperPrivate()
+{
+}
+
+QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent * /* e */)
+{
+ QList<int> result;
+ return result;
+}
+
+void QKeyMapperPrivate::clearMappings()
+{
+ // stub
+}
+
+QString QKeyMapperPrivate::translateKeyEvent(int keySym, Qt::KeyboardModifiers /* modifiers */)
+{
+ if (keySym >= Qt::Key_Escape)
+ return QString();
+
+ // Symbian doesn't actually use modifiers, but gives us the character code directly.
+
+ return QString(QChar(keySym));
+}
+
+void QKeyMapperPrivate::fillKeyMap()
+{
+ using namespace Qt;
+ static const struct {
+ TUint s60Key;
+ int qtKey;
+ } map[] = {
+ {EKeyBell, Key_unknown},
+ {EKeyBackspace, Key_Backspace},
+ {EKeyTab, Key_Tab},
+ {EKeyLineFeed, Key_unknown},
+ {EKeyVerticalTab, Key_unknown},
+ {EKeyFormFeed, Key_unknown},
+ {EKeyEnter, Key_Enter},
+ {EKeyEscape, Key_Escape},
+ {EKeySpace, Key_Space},
+ {EKeyDelete, Key_Delete},
+ {EKeyPrintScreen, Key_SysReq},
+ {EKeyPause, Key_Pause},
+ {EKeyHome, Key_Home},
+ {EKeyEnd, Key_End},
+ {EKeyPageUp, Key_PageUp},
+ {EKeyPageDown, Key_PageDown},
+ {EKeyInsert, Key_Insert},
+ {EKeyLeftArrow, Key_Left},
+ {EKeyRightArrow, Key_Right},
+ {EKeyUpArrow, Key_Up},
+ {EKeyDownArrow, Key_Down},
+ {EKeyLeftShift, Key_Shift},
+ {EKeyRightShift, Key_Shift},
+ {EKeyLeftAlt, Key_Alt},
+ {EKeyRightAlt, Key_AltGr},
+ {EKeyLeftCtrl, Key_Control},
+ {EKeyRightCtrl, Key_Control},
+ {EKeyLeftFunc, Key_Super_L},
+ {EKeyRightFunc, Key_Super_R},
+ {EKeyCapsLock, Key_CapsLock},
+ {EKeyNumLock, Key_NumLock},
+ {EKeyScrollLock, Key_ScrollLock},
+ {EKeyF1, Key_F1},
+ {EKeyF2, Key_F2},
+ {EKeyF3, Key_F3},
+ {EKeyF4, Key_F4},
+ {EKeyF5, Key_F5},
+ {EKeyF6, Key_F6},
+ {EKeyF7, Key_F7},
+ {EKeyF8, Key_F8},
+ {EKeyF9, Key_F9},
+ {EKeyF10, Key_F10},
+ {EKeyF11, Key_F11},
+ {EKeyF12, Key_F12},
+ {EKeyF13, Key_F13},
+ {EKeyF14, Key_F14},
+ {EKeyF15, Key_F15},
+ {EKeyF16, Key_F16},
+ {EKeyF17, Key_F17},
+ {EKeyF18, Key_F18},
+ {EKeyF19, Key_F19},
+ {EKeyF20, Key_F20},
+ {EKeyF21, Key_F21},
+ {EKeyF22, Key_F22},
+ {EKeyF23, Key_F23},
+ {EKeyF24, Key_F24},
+ {EKeyOff, Key_unknown},
+ {EKeyIncContrast, Key_unknown},
+ {EKeyDecContrast, Key_unknown},
+ {EKeyBacklightOn, Key_unknown},
+ {EKeyBacklightOff, Key_unknown},
+ {EKeyBacklightToggle, Key_unknown},
+ {EKeySliderDown, Key_unknown},
+ {EKeySliderUp, Key_unknown},
+ {EKeyMenu, Key_Menu},
+ {EKeyDictaphonePlay, Key_unknown},
+ {EKeyDictaphoneStop, Key_unknown},
+ {EKeyDictaphoneRecord, Key_unknown},
+ {EKeyHelp, Key_unknown},
+ {EKeyDial, Key_Call},
+ {EKeyScreenDimension0, Key_unknown},
+ {EKeyScreenDimension1, Key_unknown},
+ {EKeyScreenDimension2, Key_unknown},
+ {EKeyScreenDimension3, Key_unknown},
+ {EKeyIncVolume, Key_unknown},
+ {EKeyDecVolume, Key_unknown},
+ {EKeyDevice0, Key_Context1}, // Found by manual testing, left softkey.
+ {EKeyDevice1, Key_Context2}, // Found by manual testing.
+ {EKeyDevice2, Key_unknown},
+ {EKeyDevice3, Key_Select}, // Found by manual testing.
+ {EKeyDevice4, Key_unknown},
+ {EKeyDevice5, Key_unknown},
+ {EKeyDevice6, Key_unknown},
+ {EKeyDevice7, Key_unknown},
+ {EKeyDevice8, Key_unknown},
+ {EKeyDevice9, Key_unknown},
+ {EKeyDeviceA, Key_unknown},
+ {EKeyDeviceB, Key_unknown},
+ {EKeyDeviceC, Key_unknown},
+ {EKeyDeviceD, Key_unknown},
+ {EKeyDeviceE, Key_unknown},
+ {EKeyDeviceF, Key_unknown},
+ {EKeyApplication0, Key_Launch0},
+ {EKeyApplication1, Key_Launch1},
+ {EKeyApplication2, Key_Launch2},
+ {EKeyApplication3, Key_Launch3},
+ {EKeyApplication4, Key_Launch4},
+ {EKeyApplication5, Key_Launch5},
+ {EKeyApplication6, Key_Launch6},
+ {EKeyApplication7, Key_Launch7},
+ {EKeyApplication8, Key_Launch8},
+ {EKeyApplication9, Key_Launch9},
+ {EKeyApplicationA, Key_LaunchA},
+ {EKeyApplicationB, Key_LaunchB},
+ {EKeyApplicationC, Key_LaunchC},
+ {EKeyApplicationD, Key_LaunchD},
+ {EKeyApplicationE, Key_LaunchE},
+ {EKeyApplicationF, Key_LaunchF},
+ {EKeyYes, Key_Yes},
+ {EKeyNo, Key_No},
+ {EKeyIncBrightness, Key_unknown},
+ {EKeyDecBrightness, Key_unknown},
+ {EKeyKeyboardExtend, Key_unknown},
+ {EKeyDevice10, Key_unknown},
+ {EKeyDevice11, Key_unknown},
+ {EKeyDevice12, Key_unknown},
+ {EKeyDevice13, Key_unknown},
+ {EKeyDevice14, Key_unknown},
+ {EKeyDevice15, Key_unknown},
+ {EKeyDevice16, Key_unknown},
+ {EKeyDevice17, Key_unknown},
+ {EKeyDevice18, Key_unknown},
+ {EKeyDevice19, Key_unknown},
+ {EKeyDevice1A, Key_unknown},
+ {EKeyDevice1B, Key_unknown},
+ {EKeyDevice1C, Key_unknown},
+ {EKeyDevice1D, Key_unknown},
+ {EKeyDevice1E, Key_unknown},
+ {EKeyDevice1F, Key_unknown},
+ {EKeyApplication10, Key_unknown},
+ {EKeyApplication11, Key_unknown},
+ {EKeyApplication12, Key_unknown},
+ {EKeyApplication13, Key_unknown},
+ {EKeyApplication14, Key_unknown},
+ {EKeyApplication15, Key_unknown},
+ {EKeyApplication16, Key_unknown},
+ {EKeyApplication17, Key_unknown},
+ {EKeyApplication18, Key_unknown},
+ {EKeyApplication19, Key_unknown},
+ {EKeyApplication1A, Key_unknown},
+ {EKeyApplication1B, Key_unknown},
+ {EKeyApplication1C, Key_unknown},
+ {EKeyApplication1D, Key_unknown},
+ {EKeyApplication1E, Key_unknown},
+ {EKeyApplication1F, Key_unknown}
+ };
+ const int mapSize = int(sizeof(map)/sizeof(map[0]));
+ s60ToQtKeyMap.reserve(mapSize + 5); // +5? docs: Ideally, slightly more than number of items
+ for (int i = 0; i < mapSize; ++i)
+ s60ToQtKeyMap.insert(map[i].s60Key, map[i].qtKey);
+}
+
+int QKeyMapperPrivate::mapS60KeyToQt(TUint s60key)
+{
+ QHash<TUint, int>::const_iterator mapping;
+ mapping = s60ToQtKeyMap.find(s60key);
+ if (mapping != s60ToQtKeyMap.end()) {
+ return *mapping;
+ } else {
+ return Qt::Key_unknown;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_win.cpp b/src/gui/kernel/qkeymapper_win.cpp
index a51444f..2ac3f70 100644
--- a/src/gui/kernel/qkeymapper_win.cpp
+++ b/src/gui/kernel/qkeymapper_win.cpp
@@ -41,7 +41,7 @@
#include "qkeymapper_p.h"
-#include <windows.h>
+#include <qt_windows.h>
#include <qdebug.h>
#include <private/qevent_p.h>
#include <private/qlocale_p.h>
@@ -57,9 +57,7 @@ QT_BEGIN_NAMESPACE
// Implemented elsewhere
extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
-Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
- UINT wRemoveMsg);
+
extern Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id);
#ifndef LANG_PASHTO
#define LANG_PASHTO 0x63
@@ -467,12 +465,7 @@ static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer,
Q_ASSERT(vk > 0 && vk < 256);
int code = 0;
QChar unicodeBuffer[5];
- int res = 0;
- if (QSysInfo::WindowsVersion < QSysInfo::WV_NT)
- res = ToAscii(vk, scancode, kbdBuffer, reinterpret_cast<LPWORD>(unicodeBuffer), 0);
- else
- res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);
-
+ int res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);
if (res)
code = unicodeBuffer[0].toUpper().unicode();
@@ -504,38 +497,6 @@ static inline int asciiToKeycode(char a, int state)
return a & 0xff;
}
-static int inputcharset = CP_ACP;
-static inline QChar wmchar_to_unicode(DWORD c)
-{
- // qt_winMB2QString is the generalization of this function.
- QT_WA({
- return QChar((ushort)c);
- } , {
- char mb[2];
- mb[0] = c & 0xff;
- mb[1] = 0;
- WCHAR wc[1];
- MultiByteToWideChar(inputcharset, MB_PRECOMPOSED, mb, -1, wc, 1);
- return QChar(wc[0]);
- });
-}
-
-static inline QChar imechar_to_unicode(DWORD c)
-{
- // qt_winMB2QString is the generalization of this function.
- QT_WA({
- return QChar((ushort)c);
- } , {
- char mb[3];
- mb[0] = (c >> 8) & 0xff;
- mb[1] = c & 0xff;
- mb[2] = 0;
- WCHAR wc[1];
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, -1, wc, 1);
- return QChar(wc[0]);
- });
-}
-
static inline bool isModifierKey(int code)
{
return (code >= Qt::Key_Shift) && (code <= Qt::Key_ScrollLock);
@@ -621,10 +582,10 @@ QKeyMapperPrivate::QKeyMapperPrivate()
QKeyMapperPrivate::~QKeyMapperPrivate()
{
- clearMappings();
+ deleteLayouts();
}
-void QKeyMapperPrivate::clearMappings()
+void QKeyMapperPrivate::deleteLayouts()
{
for (int i = 0; i < 255; ++i) {
if (keyLayout[i]) {
@@ -632,46 +593,23 @@ void QKeyMapperPrivate::clearMappings()
keyLayout[i] = 0;
}
}
+}
+
+void QKeyMapperPrivate::clearMappings()
+{
+ deleteLayouts();
/* MAKELCID()'s first argument is a WORD, and GetKeyboardLayout()
* returns a DWORD. */
-// LCID newLCID = MAKELCID(DWORD(GetKeyboardLayout(0)), SORT_DEFAULT);
+
+ LCID newLCID = MAKELCID((DWORD)GetKeyboardLayout(0), SORT_DEFAULT);
// keyboardInputLocale = qt_localeFromLCID(newLCID);
- LCID newLCID = MAKELCID(
- reinterpret_cast<long>(GetKeyboardLayout(0)),
- SORT_DEFAULT
- );
- keyboardInputLocale = qt_localeFromLCID(newLCID);
+
bool bidi = false;
-#ifdef UNICODE
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_2000) {
- WCHAR wchLCIDFontSig[16];
- if (GetLocaleInfoW(newLCID,
- LOCALE_FONTSIGNATURE,
- &wchLCIDFontSig[0],
- (sizeof(wchLCIDFontSig)/sizeof(WCHAR)))
- && (wchLCIDFontSig[7] & (WCHAR)0x0800))
+ wchar_t LCIDFontSig[16];
+ if (GetLocaleInfo(newLCID, LOCALE_FONTSIGNATURE, LCIDFontSig, sizeof(LCIDFontSig) / sizeof(wchar_t))
+ && (LCIDFontSig[7] & (wchar_t)0x0800))
bidi = true;
- } else
-#endif //UNICODE
- {
- if (newLCID == 0x0859 || //Sindhi (Arabic script)
- newLCID == 0x0460) //Kashmiri (Arabic script)
- bidi = true;;
-
- switch (PRIMARYLANGID(newLCID))
- {
- case LANG_ARABIC:
- case LANG_HEBREW:
- case LANG_URDU:
- case LANG_FARSI:
- case LANG_PASHTO:
- //case LANG_UIGHUR:
- case LANG_SYRIAC:
- case LANG_DIVEHI:
- bidi = true;
- }
- }
keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight;
}
@@ -760,7 +698,7 @@ void QKeyMapperPrivate::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32
keyLayout[vk_key]->qtKey[8] = fallbackKey;
// If this vk_key a Dead Key
- if (MapVirtualKey(vk_key, 2) & 0x80008000) { // (High-order dead key on Win 95 is 0x8000)
+ if (MapVirtualKey(vk_key, 2) & 0x80000000) {
// Push a Space, then the original key through the low-level ToAscii functions.
// We do this because these functions (ToAscii / ToUnicode) will alter the internal state of
// the keyboard driver By doing the following, we set the keyboard driver state back to what
@@ -837,13 +775,13 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool
bool isNumpad = (msg.wParam >= VK_NUMPAD0 && msg.wParam <= VK_NUMPAD9);
quint32 nModifiers = 0;
- if (QSysInfo::WindowsVersion < QSysInfo::WV_NT || QSysInfo::WindowsVersion & QSysInfo::WV_CE_based) {
+#if defined(Q_OS_WINCE)
nModifiers |= (GetKeyState(VK_SHIFT ) < 0 ? ShiftAny : 0);
nModifiers |= (GetKeyState(VK_CONTROL) < 0 ? ControlAny : 0);
nModifiers |= (GetKeyState(VK_MENU ) < 0 ? AltAny : 0);
nModifiers |= (GetKeyState(VK_LWIN ) < 0 ? MetaLeft : 0);
nModifiers |= (GetKeyState(VK_RWIN ) < 0 ? MetaRight : 0);
- } else {
+#else
// Map native modifiers to some bit representation
nModifiers |= (GetKeyState(VK_LSHIFT ) & 0x80 ? ShiftLeft : 0);
nModifiers |= (GetKeyState(VK_RSHIFT ) & 0x80 ? ShiftRight : 0);
@@ -857,7 +795,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool
nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0);
nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0);
nModifiers |= (GetKeyState(VK_SCROLL ) & 0x01 ? ScrollLock : 0);
- }
+#endif // Q_OS_WINCE
+
if (msg.lParam & ExtendedKey)
nModifiers |= msg.lParam & ExtendedKey;
@@ -870,12 +809,12 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool
// Now we know enough to either have MapVirtualKey or our own keymap tell us if it's a deadkey
bool isDeadKey = isADeadKey(msg.wParam, state)
- || MapVirtualKey(msg.wParam, 2) & 0x80008000; // High-order on 95 is 0x8000
+ || MapVirtualKey(msg.wParam, 2) & 0x80000000;
// A multi-character key not found by our look-ahead
if (msgType == WM_CHAR) {
QString s;
- QChar ch = wmchar_to_unicode(msg.wParam);
+ QChar ch = QChar((ushort)msg.wParam);
if (!ch.isNull())
s += ch;
@@ -886,7 +825,7 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool
// Input method characters not found by our look-ahead
else if (msgType == WM_IME_CHAR) {
QString s;
- QChar ch = imechar_to_unicode(msg.wParam);
+ QChar ch = QChar((ushort)msg.wParam);
if (!ch.isNull())
s += ch;
@@ -917,8 +856,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool
}
} else if (msgType == WM_KEYUP) {
if (dirStatus == VK_LSHIFT
- && (msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL)
- || msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT))) {
+ && ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL))
+ || (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) {
k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, Qt::Key_Direction_L, 0,
QString(), false, 0,
scancode, msg.wParam, nModifiers);
@@ -927,8 +866,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool
scancode, msg.wParam, nModifiers);
dirStatus = 0;
} else if (dirStatus == VK_RSHIFT
- && (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL)
- || msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT))) {
+ && ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL))
+ || (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) {
k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, Qt::Key_Direction_R,
0, QString(), false, 0,
scancode, msg.wParam, nModifiers);
@@ -1050,11 +989,9 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool
: msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR);
QChar uch;
- if (winPeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) {
+ if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) {
// Found a ?_CHAR
- uch = charType == WM_IME_CHAR
- ? imechar_to_unicode(wm_char.wParam)
- : wmchar_to_unicode(wm_char.wParam);
+ uch = QChar((ushort)wm_char.wParam);
if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN))
uch = uch.toLower(); // (See doc of WM_SYSCHAR) Alt-letter
if (!code && !uch.row())
@@ -1067,7 +1004,7 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool
// to find the correct key using the current message parameters & keyboard state.
if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
BYTE keyState[256];
- WCHAR newKey[3] = {0};
+ wchar_t newKey[3] = {0};
GetKeyboardState(keyState);
int val = ToUnicode(vk_key, scancode, keyState, newKey, 2, 0);
if (val == 1) {
@@ -1085,18 +1022,10 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool
uch = QChar(QLatin1Char(0x7f)); // Windows doesn't know this one.
} else {
if (msgType != WM_SYSKEYDOWN || !code) {
- UINT map;
- QT_WA({
- map = MapVirtualKey(msg.wParam, 2);
- } , {
- map = MapVirtualKeyA(msg.wParam, 2);
- // High-order bit is 0x8000 on '95
- if (map & 0x8000)
- map = (map^0x8000)|0x80000000;
- });
+ UINT map = MapVirtualKey(msg.wParam, 2);
// If the high bit of the return value is set, it's a deadkey
if (!(map & 0x80000000))
- uch = wmchar_to_unicode((DWORD)map);
+ uch = QChar((ushort)map);
}
}
if (!code && !uch.row())
@@ -1237,6 +1166,8 @@ bool QKeyMapper::sendKeyEvent(QWidget *widget, bool grab,
if (QApplicationPrivate::instance()->qt_tryAccelEvent(widget, &a))
return true;
}
+#else
+ Q_UNUSED(grab);
#endif
if (!widget->isEnabled())
return false;
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 6293087..2e82ab5 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -105,20 +105,39 @@ static bool operator<(int key, const MacSpecialKey &entry)
static const MacSpecialKey * const MacSpecialKeyEntriesEnd = entries + NumEntries;
-static QChar macSymbolForQtKey(int key)
+QChar qt_macSymbolForQtKey(int key)
{
const MacSpecialKey *i = qBinaryFind(entries, MacSpecialKeyEntriesEnd, key);
if (i == MacSpecialKeyEntriesEnd)
return QChar();
- return QChar(i->macSymbol);
+ ushort macSymbol = i->macSymbol;
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)
+ && (macSymbol == kControlUnicode || macSymbol == kCommandUnicode)) {
+ if (macSymbol == kControlUnicode)
+ macSymbol = kCommandUnicode;
+ else
+ macSymbol = kControlUnicode;
+ }
+
+ return QChar(macSymbol);
}
static int qtkeyForMacSymbol(const QChar ch)
{
+ const ushort unicode = ch.unicode();
for (int i = 0; i < NumEntries; ++i) {
const MacSpecialKey &entry = entries[i];
- if (entry.macSymbol == ch.unicode())
- return entry.key;
+ if (entry.macSymbol == unicode) {
+ int key = entry.key;
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)
+ && (unicode == kControlUnicode || unicode == kCommandUnicode)) {
+ if (unicode == kControlUnicode)
+ key = Qt::Key_Control;
+ else
+ key = Qt::Key_Meta;
+ }
+ return key;
+ }
}
return -1;
}
@@ -126,16 +145,15 @@ static int qtkeyForMacSymbol(const QChar ch)
#else
static bool qt_sequence_no_mnemonics = false;
#endif
-void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemonics = !b; }
+void Q_AUTOTEST_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemonics = !b; }
/*!
\class QKeySequence
\brief The QKeySequence class encapsulates a key sequence as used
by shortcuts.
- \ingroup misc
\ingroup shared
- \mainclass
+
In its most common form, a key sequence describes a combination of
keys that must be used together to perform some action. Key sequences
@@ -207,70 +225,72 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
corresponds to the \key Control keys.
\table
- \header \i StandardKey \i Windows \i Mac OS X \i KDE \i GNOME
- \row \i HelpContents \i F1 \i Ctrl+? \i F1 \i F1
- \row \i WhatsThis \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1
- \row \i Open \i Ctrl+O \i Ctrl+O \i Ctrl+O \i Ctrl+O
- \row \i Close \i Ctrl+F4, Ctrl+W \i Ctrl+W, Ctrl+F4 \i Ctrl+W \i Ctrl+W
- \row \i Save \i Ctrl+S \i Ctrl+S \i Ctrl+S \i Ctrl+S
- \row \i SaveAs \i \i Ctrl+Shift+S \i \i Ctrl+Shift+S
- \row \i New \i Ctrl+N \i Ctrl+N \i Ctrl+N \i Ctrl+N
- \row \i Delete \i Del \i Del, Meta+D \i Del, Ctrl+D \i Del, Ctrl+D
- \row \i Cut \i Ctrl+X, Shift+Del \i Ctrl+X \i Ctrl+X, F20, Shift+Del \i Ctrl+X, F20, Shift+Del
- \row \i Copy \i Ctrl+C, Ctrl+Ins \i Ctrl+C \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C, F16, Ctrl+Ins
- \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins
- \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14
- \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z
- \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left
- \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right
- \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5
- \row \i ZoomIn \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus
- \row \i ZoomOut \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus
- \row \i Print \i Ctrl+P \i Ctrl+P \i Ctrl+P \i Ctrl+P
- \row \i AddTab \i Ctrl+T \i Ctrl+T \i Ctrl+Shift+N, Ctrl+T \i Ctrl+T
- \row \i NextChild \i Ctrl+Tab, Forward, Ctrl+F6 \i Ctrl+}, Forward, Ctrl+Tab \i Ctrl+Tab, Forward, Ctrl+Comma \i Ctrl+Tab, Forward
- \row \i PreviousChild \i Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \i Ctrl+{, Back, Ctrl+Shift+Tab \i Ctrl+Shift+Tab, Back, Ctrl+Period \i Ctrl+Shift+Tab, Back
- \row \i Find \i Ctrl+F \i Ctrl+F \i Ctrl+F \i Ctrl+F
- \row \i FindNext \i F3, Ctrl+G \i Ctrl+G \i F3 \i Ctrl+G, F3
- \row \i FindPrevious \i Shift+F3, Ctrl+Shift+G \i Ctrl+Shift+G \i Shift+F3 \i Ctrl+Shift+G, Shift+F3
- \row \i Replace \i Ctrl+H \i (none) \i Ctrl+R \i Ctrl+H
- \row \i SelectAll \i Ctrl+A \i Ctrl+A \i Ctrl+A \i Ctrl+A
- \row \i Bold \i Ctrl+B \i Ctrl+B \i Ctrl+B \i Ctrl+B
- \row \i Italic \i Ctrl+I \i Ctrl+I \i Ctrl+I \i Ctrl+I
- \row \i Underline \i Ctrl+U \i Ctrl+U \i Ctrl+U \i Ctrl+U
- \row \i MoveToNextChar \i Right \i Right \i Right \i Right
- \row \i MoveToPreviousChar \i Left \i Left \i Left \i Left
- \row \i MoveToNextWord \i Ctrl+Right \i Alt+Right \i Ctrl+Right \i Ctrl+Right
- \row \i MoveToPreviousWord \i Ctrl+Left \i Alt+Left \i Ctrl+Left \i Ctrl+Left
- \row \i MoveToNextLine \i Down \i Down \i Down \i Down
- \row \i MoveToPreviousLine \i Up \i Up \i Up \i Up
- \row \i MoveToNextPage \i PgDown \i PgDown, Alt+PgDown, Meta+Down, Meta+PgDown\i PgDown \i PgDown
- \row \i MoveToPreviousPage \i PgUp \i PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \i PgUp \i PgUp
- \row \i MoveToStartOfLine \i Home \i Ctrl+Left, Meta+Left \i Home \i Home
- \row \i MoveToEndOfLine \i End \i Ctrl+Right, Meta+Right \i End \i End
- \row \i MoveToStartOfBlock \i (none) \i Alt+Up, Meta+A \i (none) \i (none)
- \row \i MoveToEndOfBlock \i (none) \i Alt+Down, Meta+E \i (none) \i (none)
- \row \i MoveToStartOfDocument\i Ctrl+Home \i Ctrl+Up, Home \i Ctrl+Home \i Ctrl+Home
- \row \i MoveToEndOfDocument \i Ctrl+End \i Ctrl+Down, End \i Ctrl+End \i Ctrl+End
- \row \i SelectNextChar \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right
- \row \i SelectPreviousChar \i Shift+Left \i Shift+Left \i Shift+Left \i Shift?left
- \row \i SelectNextWord \i Ctrl+Shift+Right \i Alt+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right
- \row \i SelectPreviousWord \i Ctrl+Shift+Left \i Alt+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left
- \row \i SelectNextLine \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down
- \row \i SelectPreviousLine \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up
- \row \i SelectNextPage \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown
- \row \i SelectPreviousPage \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp
- \row \i SelectStartOfLine \i Shift+Home \i Ctrl+Shift+Left \i Shift+Home \i Shift+Home
- \row \i SelectEndOfLine \i Shift+End \i Ctrl+Shift+Right \i Shift+End \i Shift+End
- \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up \i (none) \i (none)
- \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down \i (none) \i (none)
- \row \i SelectStartOfDocument\i Ctrl+Shift+Home \i Ctrl+Shift+Up, Shift+Home \i Ctrl+Shift+Home\i Ctrl+Shift+Home
- \row \i SelectEndOfDocument \i Ctrl+Shift+End \i Ctrl+Shift+Down, Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End
- \row \i DeleteStartOfWord \i Ctrl+Backspace \i Alt+Backspace \i Ctrl+Backspace \i Ctrl+Backspace
- \row \i DeleteEndOfWord \i Ctrl+Del \i (none) \i Ctrl+Del \i Ctrl+Del
- \row \i DeleteEndOfLine \i (none) \i (none) \i Ctrl+K \i Ctrl+K
- \row \i InsertParagraphSeparator \i Enter \i Enter \i Enter \i Enter
- \row \i InsertLineSeparator \i Shift+Enter \i Meta+Enter \i Shift+Enter \i Shift+Enter
+ \header \i StandardKey \i Windows \i Mac OS X \i KDE \i GNOME \i S60
+ \row \i HelpContents \i F1 \i Ctrl+? \i F1 \i F1 \i F2
+ \row \i WhatsThis \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1
+ \row \i Open \i Ctrl+O \i Ctrl+O \i Ctrl+O \i Ctrl+O \i (none)
+ \row \i Close \i Ctrl+F4, Ctrl+W \i Ctrl+W, Ctrl+F4 \i Ctrl+W \i Ctrl+W \i (none)
+ \row \i Save \i Ctrl+S \i Ctrl+S \i Ctrl+S \i Ctrl+S \i (none)
+ \row \i Quit \i \i Ctrl+Q \i Qtrl+Q \i Qtrl+Q \i (none)
+ \row \i SaveAs \i \i Ctrl+Shift+S \i \i Ctrl+Shift+S \i (none)
+ \row \i New \i Ctrl+N \i Ctrl+N \i Ctrl+N \i Ctrl+N \i (none)
+ \row \i Delete \i Del \i Del, Meta+D \i Del, Ctrl+D \i Del, Ctrl+D \i Del
+ \row \i Cut \i Ctrl+X, Shift+Del \i Ctrl+X \i Ctrl+X, F20, Shift+Del \i Ctrl+X, F20, Shift+Del \i Ctrl+X
+ \row \i Copy \i Ctrl+C, Ctrl+Ins \i Ctrl+C \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C
+ \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins \i Ctrl+V
+ \row \i Preferences \i \i Ctrl+, \i \i \i (none)
+ \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14 \i Ctrl+Z
+ \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none)
+ \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left \i (none)
+ \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right \i (none)
+ \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5 \i (none)
+ \row \i ZoomIn \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i (none)
+ \row \i ZoomOut \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i (none)
+ \row \i Print \i Ctrl+P \i Ctrl+P \i Ctrl+P \i Ctrl+P \i (none)
+ \row \i AddTab \i Ctrl+T \i Ctrl+T \i Ctrl+Shift+N, Ctrl+T \i Ctrl+T \i (none)
+ \row \i NextChild \i Ctrl+Tab, Forward, Ctrl+F6 \i Ctrl+}, Forward, Ctrl+Tab \i Ctrl+Tab, Forward, Ctrl+Comma \i Ctrl+Tab, Forward \i (none)
+ \row \i PreviousChild \i Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \i Ctrl+{, Back, Ctrl+Shift+Tab \i Ctrl+Shift+Tab, Back, Ctrl+Period \i Ctrl+Shift+Tab, Back \i (none)
+ \row \i Find \i Ctrl+F \i Ctrl+F \i Ctrl+F \i Ctrl+F \i (none)
+ \row \i FindNext \i F3, Ctrl+G \i Ctrl+G \i F3 \i Ctrl+G, F3 \i (none)
+ \row \i FindPrevious \i Shift+F3, Ctrl+Shift+G \i Ctrl+Shift+G \i Shift+F3 \i Ctrl+Shift+G, Shift+F3 \i (none)
+ \row \i Replace \i Ctrl+H \i (none) \i Ctrl+R \i Ctrl+H \i (none)
+ \row \i SelectAll \i Ctrl+A \i Ctrl+A \i Ctrl+A \i Ctrl+A \i (none)
+ \row \i Bold \i Ctrl+B \i Ctrl+B \i Ctrl+B \i Ctrl+B \i (none)
+ \row \i Italic \i Ctrl+I \i Ctrl+I \i Ctrl+I \i Ctrl+I \i (none)
+ \row \i Underline \i Ctrl+U \i Ctrl+U \i Ctrl+U \i Ctrl+U \i (none)
+ \row \i MoveToNextChar \i Right \i Right \i Right \i Right \i Right
+ \row \i MoveToPreviousChar \i Left \i Left \i Left \i Left \i Left
+ \row \i MoveToNextWord \i Ctrl+Right \i Alt+Right \i Ctrl+Right \i Ctrl+Right \i Ctrl+Right
+ \row \i MoveToPreviousWord \i Ctrl+Left \i Alt+Left \i Ctrl+Left \i Ctrl+Left \i Ctrl+Left
+ \row \i MoveToNextLine \i Down \i Down \i Down \i Down \i Down
+ \row \i MoveToPreviousLine \i Up \i Up \i Up \i Up \i Up
+ \row \i MoveToNextPage \i PgDown \i PgDown, Alt+PgDown, Meta+Down, Meta+PgDown\i PgDown \i PgDown \i PgDown
+ \row \i MoveToPreviousPage \i PgUp \i PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \i PgUp \i PgUp \i PgUp
+ \row \i MoveToStartOfLine \i Home \i Ctrl+Left, Meta+Left \i Home \i Home \i Home
+ \row \i MoveToEndOfLine \i End \i Ctrl+Right, Meta+Right \i End \i End \i End
+ \row \i MoveToStartOfBlock \i (none) \i Alt+Up, Meta+A \i (none) \i (none) \i (none)
+ \row \i MoveToEndOfBlock \i (none) \i Alt+Down, Meta+E \i (none) \i (none) \i (none)
+ \row \i MoveToStartOfDocument\i Ctrl+Home \i Ctrl+Up, Home \i Ctrl+Home \i Ctrl+Home \i Ctrl+Home
+ \row \i MoveToEndOfDocument \i Ctrl+End \i Ctrl+Down, End \i Ctrl+End \i Ctrl+End \i Ctrl+End
+ \row \i SelectNextChar \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right
+ \row \i SelectPreviousChar \i Shift+Left \i Shift+Left \i Shift+Left \i Shift+Left \i Shift+Left
+ \row \i SelectNextWord \i Ctrl+Shift+Right \i Alt+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right
+ \row \i SelectPreviousWord \i Ctrl+Shift+Left \i Alt+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left
+ \row \i SelectNextLine \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down
+ \row \i SelectPreviousLine \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up
+ \row \i SelectNextPage \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown
+ \row \i SelectPreviousPage \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp
+ \row \i SelectStartOfLine \i Shift+Home \i Ctrl+Shift+Left \i Shift+Home \i Shift+Home \i Shift+Home
+ \row \i SelectEndOfLine \i Shift+End \i Ctrl+Shift+Right \i Shift+End \i Shift+End \i Shift+End
+ \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up \i (none) \i (none) \i (none)
+ \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down \i (none) \i (none) \i (none)
+ \row \i SelectStartOfDocument\i Ctrl+Shift+Home \i Ctrl+Shift+Up, Shift+Home \i Ctrl+Shift+Home\i Ctrl+Shift+Home \i Ctrl+Shift+Home
+ \row \i SelectEndOfDocument \i Ctrl+Shift+End \i Ctrl+Shift+Down, Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End
+ \row \i DeleteStartOfWord \i Ctrl+Backspace \i Alt+Backspace \i Ctrl+Backspace \i Ctrl+Backspace \i (none)
+ \row \i DeleteEndOfWord \i Ctrl+Del \i (none) \i Ctrl+Del \i Ctrl+Del \i (none)
+ \row \i DeleteEndOfLine \i (none) \i (none) \i Ctrl+K \i Ctrl+K \i (none)
+ \row \i InsertParagraphSeparator \i Enter \i Enter \i Enter \i Enter \i (none)
+ \row \i InsertLineSeparator \i Shift+Enter \i Meta+Enter \i Shift+Enter \i Shift+Enter \i (none)
\endtable
Note that, since the key sequences used for the standard shortcuts differ
@@ -481,9 +501,9 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::InsertParagraphSeparator,0, Qt::Key_Return, QApplicationPrivate::KB_All},
{QKeySequence::InsertParagraphSeparator,0, Qt::Key_Enter, QApplicationPrivate::KB_All},
{QKeySequence::Delete, 1, Qt::Key_Delete, QApplicationPrivate::KB_All},
- {QKeySequence::MoveToStartOfLine, 0, Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToStartOfLine, 0, Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::MoveToStartOfDocument, 0, Qt::Key_Home, QApplicationPrivate::KB_Mac},
- {QKeySequence::MoveToEndOfLine, 0, Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToEndOfLine, 0, Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::MoveToEndOfDocument, 0, Qt::Key_End, QApplicationPrivate::KB_Mac},
{QKeySequence::MoveToPreviousChar, 0, Qt::Key_Left, QApplicationPrivate::KB_All},
{QKeySequence::MoveToPreviousLine, 0, Qt::Key_Up, QApplicationPrivate::KB_All},
@@ -492,6 +512,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::MoveToPreviousPage, 1, Qt::Key_PageUp, QApplicationPrivate::KB_All},
{QKeySequence::MoveToNextPage, 1, Qt::Key_PageDown, QApplicationPrivate::KB_All},
{QKeySequence::HelpContents, 0, Qt::Key_F1, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::HelpContents, 0, Qt::Key_F2, QApplicationPrivate::KB_S60},
{QKeySequence::FindNext, 0, Qt::Key_F3, QApplicationPrivate::KB_X11},
{QKeySequence::FindNext, 1, Qt::Key_F3, QApplicationPrivate::KB_Win},
{QKeySequence::Refresh, 0, Qt::Key_F5, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
@@ -502,13 +523,14 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::PreviousChild, 0, Qt::Key_Back, QApplicationPrivate::KB_All},
{QKeySequence::NextChild, 0, Qt::Key_Forward, QApplicationPrivate::KB_All},
{QKeySequence::Forward, 0, Qt::SHIFT | Qt::Key_Backspace, QApplicationPrivate::KB_Win},
+ {QKeySequence::Delete, 0, Qt::SHIFT | Qt::Key_Backspace, QApplicationPrivate::KB_S60},
{QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Return, QApplicationPrivate::KB_All},
{QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Enter, QApplicationPrivate::KB_All},
{QKeySequence::Paste, 0, Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
{QKeySequence::Cut, 0, Qt::SHIFT | Qt::Key_Delete, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, //## Check if this should work on mac
- {QKeySequence::SelectStartOfLine, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectStartOfLine, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectStartOfDocument, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Mac},
- {QKeySequence::SelectEndOfLine, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectEndOfLine, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectEndOfDocument, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Mac},
{QKeySequence::SelectPreviousChar, 0, Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_All},
{QKeySequence::SelectPreviousLine, 0, Qt::SHIFT | Qt::Key_Up, QApplicationPrivate::KB_All},
@@ -521,6 +543,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::FindPrevious, 1, Qt::SHIFT | Qt::Key_F3, QApplicationPrivate::KB_Win},
{QKeySequence::ZoomIn, 1, Qt::CTRL | Qt::Key_Plus, QApplicationPrivate::KB_All},
{QKeySequence::NextChild, 0, Qt::CTRL | Qt::Key_Comma, QApplicationPrivate::KB_KDE},
+ {QKeySequence::Preferences, 0, Qt::CTRL | Qt::Key_Comma, QApplicationPrivate::KB_Mac},
{QKeySequence::ZoomOut, 1, Qt::CTRL | Qt::Key_Minus, QApplicationPrivate::KB_All},
{QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::Key_Period, QApplicationPrivate::KB_KDE},
{QKeySequence::HelpContents, 1, Qt::CTRL | Qt::Key_Question, QApplicationPrivate::KB_Mac},
@@ -538,6 +561,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::New, 1, Qt::CTRL | Qt::Key_N, QApplicationPrivate::KB_All},
{QKeySequence::Open, 1, Qt::CTRL | Qt::Key_O, QApplicationPrivate::KB_All},
{QKeySequence::Print, 1, Qt::CTRL | Qt::Key_P, QApplicationPrivate::KB_All},
+ {QKeySequence::Quit, 0, Qt::CTRL | Qt::Key_Q, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_KDE | QApplicationPrivate::KB_Mac},
{QKeySequence::Refresh, 1, Qt::CTRL | Qt::Key_R, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac},
{QKeySequence::Replace, 0, Qt::CTRL | Qt::Key_R, QApplicationPrivate::KB_KDE},
{QKeySequence::Save, 1, Qt::CTRL | Qt::Key_S, QApplicationPrivate::KB_All},
@@ -559,15 +583,15 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::DeleteStartOfWord, 0, Qt::CTRL | Qt::Key_Backspace, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win},
{QKeySequence::Copy, 0, Qt::CTRL | Qt::Key_Insert, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win},
{QKeySequence::DeleteEndOfWord, 0, Qt::CTRL | Qt::Key_Delete, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win},
- {QKeySequence::MoveToStartOfDocument, 0, Qt::CTRL | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
- {QKeySequence::MoveToEndOfDocument, 0, Qt::CTRL | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToStartOfDocument, 0, Qt::CTRL | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
+ {QKeySequence::MoveToEndOfDocument, 0, Qt::CTRL | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::Back, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Mac},
- {QKeySequence::MoveToPreviousWord, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToPreviousWord, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::MoveToStartOfLine, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Mac },
{QKeySequence::MoveToStartOfDocument, 1, Qt::CTRL | Qt::Key_Up, QApplicationPrivate::KB_Mac},
{QKeySequence::Forward, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Mac},
{QKeySequence::MoveToEndOfLine, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Mac },
- {QKeySequence::MoveToNextWord, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToNextWord, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::MoveToEndOfDocument, 1, Qt::CTRL | Qt::Key_Down, QApplicationPrivate::KB_Mac},
{QKeySequence::Close, 1, Qt::CTRL | Qt::Key_F4, QApplicationPrivate::KB_Win},
{QKeySequence::Close, 0, Qt::CTRL | Qt::Key_F4, QApplicationPrivate::KB_Mac},
@@ -580,12 +604,12 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above
{QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
{QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above
- {QKeySequence::SelectStartOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
- {QKeySequence::SelectEndOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
- {QKeySequence::SelectPreviousWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectStartOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
+ {QKeySequence::SelectEndOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
+ {QKeySequence::SelectPreviousWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectStartOfLine, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Mac },
{QKeySequence::SelectStartOfDocument, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Up, QApplicationPrivate::KB_Mac},
- {QKeySequence::SelectNextWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectNextWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectEndOfLine, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Mac },
{QKeySequence::SelectEndOfDocument, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Down, QApplicationPrivate::KB_Mac},
{QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_F6, QApplicationPrivate::KB_Win},
@@ -669,12 +693,14 @@ const uint QKeySequencePrivate::numberOfKeyBindings = sizeof(QKeySequencePrivate
\value NextChild Navigate to next tab or child window.
\value Open Open document.
\value Paste Paste.
+ \value Preferences Open the preferences dialog.
\value PreviousChild Navigate to previous tab or child window.
\value Print Print document.
+ \value Quit Quit the application.
\value Redo Redo.
\value Refresh Refresh or reload current document.
\value Replace Find and replace.
- \value SaveAs Save document after prompting the user for a file name.
+ \value SaveAs Save document after prompting the user for a file name.
\value Save Save document.
\value SelectAll Select all text.
\value SelectEndOfBlock Extend selection to the end of a text block. This shortcut is only used on OS X.
@@ -726,7 +752,9 @@ QKeySequence::QKeySequence(StandardKey key)
*/
QKeySequence::QKeySequence()
{
- d = new QKeySequencePrivate();
+ static QKeySequencePrivate shared_empty;
+ d = &shared_empty;
+ d->ref.ref();
}
/*!
@@ -780,6 +808,21 @@ QKeySequence::QKeySequence(const QKeySequence& keysequence)
d->ref.ref();
}
+#ifdef Q_WS_MAC
+static inline int maybeSwapShortcut(int shortcut)
+{
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ uint oldshortcut = shortcut;
+ shortcut &= ~(Qt::CTRL | Qt::META);
+ if (oldshortcut & Qt::CTRL)
+ shortcut |= Qt::META;
+ if (oldshortcut & Qt::META)
+ shortcut |= Qt::CTRL;
+ }
+ return shortcut;
+}
+#endif
+
/*!
\since 4.2
@@ -796,10 +839,16 @@ QList<QKeySequence> QKeySequence::keyBindings(StandardKey key)
for (uint i = 0; i < QKeySequencePrivate::numberOfKeyBindings ; ++i) {
QKeyBinding keyBinding = QKeySequencePrivate::keyBindings[i];
if (keyBinding.standardKey == key && (keyBinding.platform & platform)) {
- if (keyBinding.priority > 0)
- list.prepend(QKeySequence(QKeySequencePrivate::keyBindings[i].shortcut));
- else
- list.append(QKeySequence(QKeySequencePrivate::keyBindings[i].shortcut));
+ uint shortcut =
+#ifdef Q_WS_MAC
+ maybeSwapShortcut(QKeySequencePrivate::keyBindings[i].shortcut);
+#else
+ QKeySequencePrivate::keyBindings[i].shortcut;
+#endif
+ if (keyBinding.priority > 0)
+ list.prepend(QKeySequence(shortcut));
+ else
+ list.append(QKeySequence(shortcut));
}
}
return list;
@@ -967,9 +1016,16 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence
gmodifs = globalModifs();
if (gmodifs->isEmpty()) {
#ifdef Q_WS_MAC
- *gmodifs << QModifKeyName(Qt::CTRL, QChar(kCommandUnicode));
+ const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
+ if (dontSwap)
+ *gmodifs << QModifKeyName(Qt::META, QChar(kCommandUnicode));
+ else
+ *gmodifs << QModifKeyName(Qt::CTRL, QChar(kCommandUnicode));
*gmodifs << QModifKeyName(Qt::ALT, QChar(kOptionUnicode));
- *gmodifs << QModifKeyName(Qt::META, QChar(kControlUnicode));
+ if (dontSwap)
+ *gmodifs << QModifKeyName(Qt::CTRL, QChar(kControlUnicode));
+ else
+ *gmodifs << QModifKeyName(Qt::META, QChar(kControlUnicode));
*gmodifs << QModifKeyName(Qt::SHIFT, QChar(kShiftUnicode));
#endif
*gmodifs << QModifKeyName(Qt::CTRL, QLatin1String("ctrl+"))
@@ -1067,8 +1123,6 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence
if (found)
break;
}
-#ifdef Q_WS_MAC
-#endif
}
return ret;
}
@@ -1097,15 +1151,30 @@ QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat
QString s;
#if defined(Q_WS_MAC)
if (nativeText) {
- // On MAC the order is Meta, Alt, Shift, Control.
- if ((key & Qt::META) == Qt::META)
- s += macSymbolForQtKey(Qt::Key_Meta);
- if ((key & Qt::ALT) == Qt::ALT)
- s += macSymbolForQtKey(Qt::Key_Alt);
- if ((key & Qt::SHIFT) == Qt::SHIFT)
- s += macSymbolForQtKey(Qt::Key_Shift);
- if ((key & Qt::CTRL) == Qt::CTRL)
- s += macSymbolForQtKey(Qt::Key_Control);
+ // On Mac OS X the order (by default) is Meta, Alt, Shift, Control.
+ // If the AA_MacDontSwapCtrlAndMeta is enabled, then the order
+ // is Ctrl, Alt, Shift, Meta. The macSymbolForQtKey does this swap
+ // for us, which means that we have to adjust our order here.
+ // The upshot is a lot more infrastructure to keep the number of
+ // if tests down and the code relatively clean.
+ static const int ModifierOrder[] = { Qt::META, Qt::ALT, Qt::SHIFT, Qt::CTRL, 0 };
+ static const int QtKeyOrder[] = { Qt::Key_Meta, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Control, 0 };
+ static const int DontSwapModifierOrder[] = { Qt::CTRL, Qt::ALT, Qt::SHIFT, Qt::META, 0 };
+ static const int DontSwapQtKeyOrder[] = { Qt::Key_Control, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Meta, 0 };
+ const int *modifierOrder;
+ const int *qtkeyOrder;
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ modifierOrder = DontSwapModifierOrder;
+ qtkeyOrder = DontSwapQtKeyOrder;
+ } else {
+ modifierOrder = ModifierOrder;
+ qtkeyOrder = QtKeyOrder;
+ }
+
+ for (int i = 0; modifierOrder[i] != 0; ++i) {
+ if (key & modifierOrder[i])
+ s += qt_macSymbolForQtKey(qtkeyOrder[i]);
+ }
} else
#endif
{
@@ -1138,7 +1207,7 @@ QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat
int i=0;
#if defined(Q_WS_MAC)
if (nativeText) {
- QChar ch = macSymbolForQtKey(key);
+ QChar ch = qt_macSymbolForQtKey(key);
if (!ch.isNull())
p = ch;
else
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index b9a326c..157249c 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -136,7 +136,9 @@ public:
DeleteEndOfLine,
InsertParagraphSeparator,
InsertLineSeparator,
- SaveAs
+ SaveAs,
+ Preferences,
+ Quit
};
QKeySequence();
diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp
index ee16d1c..e58a995 100644
--- a/src/gui/kernel/qlayout.cpp
+++ b/src/gui/kernel/qlayout.cpp
@@ -61,7 +61,10 @@ static int menuBarHeightForWidth(QWidget *menubar, int w)
int result = menubar->heightForWidth(qMax(w, menubar->minimumWidth()));
if (result != -1)
return result;
- result = menubar->sizeHint().height();
+ result = menubar->sizeHint()
+ .expandedTo(menubar->minimumSize())
+ .expandedTo(menubar->minimumSizeHint())
+ .boundedTo(menubar->maximumSize()).height();
if (result != -1)
return result;
}
@@ -72,7 +75,6 @@ static int menuBarHeightForWidth(QWidget *menubar, int w)
\class QLayout
\brief The QLayout class is the base class of geometry managers.
- \ingroup appearance
\ingroup geomanagement
This is an abstract base class inherited by the concrete classes
@@ -80,7 +82,7 @@ static int menuBarHeightForWidth(QWidget *menubar, int w)
For users of QLayout subclasses or of QMainWindow there is seldom
any need to use the basic functions provided by QLayout, such as
- setSizeConstraint() or setMenuBar(). See \l{Layout Classes}
+ setSizeConstraint() or setMenuBar(). See \l{Layout Management}
for more information.
To make your own layout manager, implement the functions
@@ -95,7 +97,7 @@ static int menuBarHeightForWidth(QWidget *menubar, int w)
Geometry management stops when the layout manager is deleted.
- \sa QLayoutItem, {Layout Classes}, {Basic Layouts Example},
+ \sa QLayoutItem, {Layout Management}, {Basic Layouts Example},
{Border Layout Example}, {Flow Layout Example}
*/
@@ -145,7 +147,12 @@ QLayout::QLayout(QLayoutPrivate &dd, QLayout *lay, QWidget *w)
} else {
d->topLevel = true;
w->d_func()->layout = this;
- invalidate();
+ QT_TRY {
+ invalidate();
+ } QT_CATCH(...) {
+ w->d_func()->layout = 0;
+ QT_RETHROW;
+ }
}
}
}
@@ -230,7 +237,12 @@ QLayout::QLayout(QWidget *parent, int margin, int spacing, const char *name)
} else {
d->topLevel = true;
parent->d_func()->layout = this;
- invalidate();
+ QT_TRY {
+ invalidate();
+ } QT_CATCH(...) {
+ parent->d_func()->layout = 0;
+ QT_RETHROW;
+ }
}
}
}
@@ -1583,8 +1595,6 @@ QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy)
{
return stream >> policy.data;
}
-
-#endif
-
+#endif // QT_NO_DATASTREAM
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qlayoutengine.cpp b/src/gui/kernel/qlayoutengine.cpp
index ed50263..aaac965 100644
--- a/src/gui/kernel/qlayoutengine.cpp
+++ b/src/gui/kernel/qlayoutengine.cpp
@@ -329,7 +329,7 @@ void qGeomCalc(QVector<QLayoutStruct> &chain, int start, int count,
qDebug() << "qGeomCalc" << "start" << start << "count" << count << "pos" << pos
<< "space" << space << "spacer" << spacer;
for (i = start; i < start + count; ++i) {
- qDebug() << i << ":" << chain[i].minimumSize << chain[i].smartSizeHint()
+ qDebug() << i << ':' << chain[i].minimumSize << chain[i].smartSizeHint()
<< chain[i].maximumSize << "stretch" << chain[i].stretch
<< "empty" << chain[i].empty << "expansive" << chain[i].expansive
<< "spacing" << chain[i].spacing;
diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp
index 43758a6..2774d83 100644
--- a/src/gui/kernel/qlayoutitem.cpp
+++ b/src/gui/kernel/qlayoutitem.cpp
@@ -54,7 +54,8 @@ QT_BEGIN_NAMESPACE
inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
{
- return priv->fromOrToLayoutItemRect(rect, -1);
+ return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin,
+ -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin);
}
inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
@@ -64,7 +65,8 @@ inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
{
- return priv->fromOrToLayoutItemRect(rect, +1);
+ return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin,
+ priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin);
}
inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
@@ -85,7 +87,6 @@ QSizePolicy::operator QVariant() const
\brief The QLayoutItem class provides an abstract item that a
QLayout manipulates.
- \ingroup appearance
\ingroup geomanagement
This is used by custom layouts.
@@ -114,7 +115,6 @@ QSizePolicy::operator QVariant() const
/*!
\class QSpacerItem
- \ingroup appearance
\ingroup geomanagement
\brief The QSpacerItem class provides blank space in a layout.
@@ -142,7 +142,6 @@ QSizePolicy::operator QVariant() const
/*!
\class QWidgetItem
- \ingroup appearance
\ingroup geomanagement
\brief The QWidgetItem class is a layout item that represents a widget.
diff --git a/src/gui/kernel/qmime_mac.cpp b/src/gui/kernel/qmime_mac.cpp
index dcc04af..e86564f 100644
--- a/src/gui/kernel/qmime_mac.cpp
+++ b/src/gui/kernel/qmime_mac.cpp
@@ -68,9 +68,10 @@
#include "qmap.h"
#include <private/qt_mac_p.h>
+
#ifdef Q_WS_MAC32
#include <QuickTime/QuickTime.h>
-#include "qlibrary.h"
+#include <qlibrary.h>
#endif
QT_BEGIN_NAMESPACE
@@ -127,32 +128,43 @@ CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker");
/*!
\class QMacPasteboardMime
- \brief The QMacPasteboardMime class maps open-standard MIME to Mac flavors.
+ \brief The QMacPasteboardMime class converts between a MIME type and a
+ \l{http://developer.apple.com/macosx/uniformtypeidentifiers.html}{Uniform
+ Type Identifier (UTI)} format.
\since 4.2
- \ingroup io
+
\ingroup draganddrop
- \ingroup misc
- Qt's drag and drop support and clipboard facilities use the MIME
- standard. On X11, this maps trivially to the Xdnd protocol, but on
- Mac although some applications use MIME types to describe clipboard
- formats, others use arbitrary non-standardized naming conventions,
- or unnamed built-in Mac formats.
+ Qt's drag and drop and clipboard facilities use the MIME
+ standard. On X11, this maps trivially to the Xdnd protocol. On
+ Mac, although some applications use MIME to describe clipboard
+ contents, it is more common to use Apple's UTI format.
+
+ QMacPasteboardMime's role is to bridge the gap between MIME and UTI;
+ By subclasses this class, one can extend Qt's drag and drop
+ and clipboard handling to convert to and from unsupported, or proprietary, UTI formats.
- By instantiating subclasses of QMacPasteboardMime that provide conversions
- between Mac flavors and MIME formats, you can convert proprietary
- clipboard formats to MIME formats.
+ A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation.
- Qt has predefined support for the following Mac flavors:
+ Qt has predefined support for the following UTIs:
\list
- \i kScrapFlavorTypeUnicode - converted to "text/plain;charset=ISO-10646-UCS-2"
- \i kScrapFlavorTypeText - converted to "text/plain;charset=system" or "text/plain"
- \i kScrapFlavorTypePicture - converted to "application/x-qt-image"
- \i typeFileURL - converted to "text/uri-list"
+ \i public.utf8-plain-text - converts to "text/plain"
+ \i public.utf16-plain-text - converts to "text/plain"
+ \i public.html - converts to "text/html"
+ \i public.url - converts to "text/uri-list"
+ \i public.file-url - converts to "text/uri-list"
+ \i public.tiff - converts to "application/x-qt-image"
+ \i com.apple.traditional-mac-plain-text - converts to "text/plain"
+ \i com.apple.pict - converts to "application/x-qt-image"
\endlist
- You can check if a MIME type is convertible using canConvert() and
- can perform conversions with convertToMime() and convertFromMime().
+ When working with MIME data, Qt will interate through all instances of QMacPasteboardMime to
+ find an instance that can convert to, or from, a specific MIME type. It will do this by calling
+ canConvert() on each instance, starting with (and choosing) the last created instance first.
+ The actual conversions will be done by using convertToMime() and convertFromMime().
+
+ \note The API uses the term "flavor" in some cases. This is for backwards
+ compatibility reasons, and should now be understood as UTIs.
*/
/*! \enum QMacPasteboardMime::QMacPasteboardMimeType
@@ -206,7 +218,7 @@ QString QMacPasteboardMimeAny::flavorFor(const QString &mime)
if(mime == QLatin1String("application/x-qt-mime-type-name"))
return QString();
QString ret = QLatin1String("com.trolltech.anymime.") + mime;
- return ret.replace(QLatin1String("/"), QLatin1String("--"));
+ return ret.replace(QLatin1Char('/'), QLatin1String("--"));
}
QString QMacPasteboardMimeAny::mimeFor(QString flav)
@@ -382,7 +394,7 @@ QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime)
int i = mime.indexOf(QLatin1String("charset="));
if (i >= 0) {
QString cs(mime.mid(i+8).toLower());
- i = cs.indexOf(QLatin1String(";"));
+ i = cs.indexOf(QLatin1Char(';'));
if (i>=0)
cs = cs.left(i);
if (cs == QLatin1String("system"))
@@ -495,6 +507,8 @@ QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mim
#ifdef Q_WS_MAC32
+// This can be removed once 10.6 is the minimum (or we have to require 64-bit) whichever comes first.
+
typedef ComponentResult (*PtrGraphicsImportSetDataHandle)(GraphicsImportComponent, Handle);
typedef ComponentResult (*PtrGraphicsImportCreateCGImage)(GraphicsImportComponent, CGImageRef*, UInt32);
typedef ComponentResult (*PtrGraphicsExportSetInputCGImage)(GraphicsExportComponent, CGImageRef);
@@ -625,7 +639,9 @@ QList<QByteArray> QMacPasteboardMimePict::convertFromMime(const QString &mime, Q
DisposeHandle(pic);
return ret;
}
-#endif
+
+
+#endif //Q_WS_MAC32
class QMacPasteboardMimeTiff : public QMacPasteboardMime {
public:
@@ -672,33 +688,11 @@ QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteA
return ret;
const QByteArray &a = data.first();
QCFType<CGImageRef> image;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- QCFType<CFDataRef> data = CFDataCreateWithBytesNoCopy(0,
- reinterpret_cast<const UInt8 *>(a.constData()),
- a.size(), kCFAllocatorNull);
- QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(data, 0);
- image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
- } else
-#endif
- {
-#ifdef Q_WS_MAC32
- if (resolveMimeQuickTimeSymbols()) {
- Handle tiff = NewHandle(a.size());
- memcpy(*tiff, a.constData(), a.size());
- GraphicsImportComponent graphicsImporter;
- ComponentResult result = OpenADefaultComponent(GraphicsImporterComponentType,
- kQTFileTypeTIFF, &graphicsImporter);
- if (!result)
- result = ptrGraphicsImportSetDataHandle(graphicsImporter, tiff);
- if (!result)
- result = ptrGraphicsImportCreateCGImage(graphicsImporter, &image,
- kGraphicsImportCreateCGImageUsingCurrentSettings);
- CloseComponent(graphicsImporter);
- DisposeHandle(tiff);
- }
-#endif
- }
+ QCFType<CFDataRef> tiffData = CFDataCreateWithBytesNoCopy(0,
+ reinterpret_cast<const UInt8 *>(a.constData()),
+ a.size(), kCFAllocatorNull);
+ QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
+ image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
if (image != 0)
ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage());
@@ -841,6 +835,80 @@ QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime
return ret;
}
+class QMacPasteboardMimeUrl : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeUrl() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeUrl::convertorName()
+{
+ return QLatin1String("URL");
+}
+
+QString QMacPasteboardMimeUrl::flavorFor(const QString &mime)
+{
+ if(mime.startsWith(QLatin1String("text/uri-list")))
+ return QLatin1String("public.url");
+ return QString();
+}
+
+QString QMacPasteboardMimeUrl::mimeFor(QString flav)
+{
+ if(flav == QLatin1String("public.url"))
+ return QLatin1String("text/uri-list");
+ return QString();
+}
+
+bool QMacPasteboardMimeUrl::canConvert(const QString &mime, QString flav)
+{
+ return flav == QLatin1String("public.url")
+ && mime == QLatin1String("text/uri-list");
+}
+
+QVariant QMacPasteboardMimeUrl::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if(!canConvert(mime, flav))
+ return QVariant();
+
+ QList<QVariant> ret;
+ for (int i=0; i<data.size(); ++i) {
+ QUrl url = QUrl::fromEncoded(data.at(i));
+ if (url.host().toLower() == QLatin1String("localhost"))
+ url.setHost(QString());
+ url.setPath(url.path().normalized(QString::NormalizationForm_C));
+ ret.append(url);
+ }
+ return QVariant(ret);
+}
+
+QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QVariant data, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+
+ QList<QVariant> urls = data.toList();
+ for(int i=0; i<urls.size(); ++i) {
+ QUrl url = urls.at(i).toUrl();
+ if (url.scheme().isEmpty())
+ url.setScheme(QLatin1String("file"));
+ if (url.scheme().toLower() == QLatin1String("file")) {
+ if (url.host().isEmpty())
+ url.setHost(QLatin1String("localhost"));
+ url.setPath(url.path().normalized(QString::NormalizationForm_D));
+ }
+ ret.append(url.toEncoded());
+ }
+ return ret;
+}
+
#ifdef QT3_SUPPORT
class QMacPasteboardMimeQt3Any : public QMacPasteboardMime {
private:
@@ -1037,12 +1105,16 @@ void QMacPasteboardMime::initialize()
//standard types that we wrap
new QMacPasteboardMimeTiff;
#ifdef Q_WS_MAC32
- new QMacPasteboardMimePict;
+ // 10.6 does automatic synthesis to and from PICT to standard image types (like TIFF),
+ // so don't bother doing it ourselves, especially since it's not available in 64-bit.
+ if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6)
+ new QMacPasteboardMimePict;
#endif
new QMacPasteboardMimeUnicodeText;
new QMacPasteboardMimePlainText;
new QMacPasteboardMimeHTMLText;
new QMacPasteboardMimeFileUri;
+ new QMacPasteboardMimeUrl;
new QMacPasteboardMimeTypeName;
//make sure our "non-standard" types are always last! --Sam
new QMacPasteboardMimeAny;
diff --git a/src/gui/kernel/qmime_win.cpp b/src/gui/kernel/qmime_win.cpp
index 6633dfd..e81d511 100644
--- a/src/gui/kernel/qmime_win.cpp
+++ b/src/gui/kernel/qmime_win.cpp
@@ -170,7 +170,7 @@ static QByteArray getData(int cf, IDataObject *pDataObj)
if (pDataObj->GetData(&formatetc, &s) == S_OK) {
char szBuffer[4096];
ULONG actualRead = 0;
- LARGE_INTEGER pos = {0, 0};
+ LARGE_INTEGER pos = {{0, 0}};
//Move to front (can fail depending on the data model implemented)
HRESULT hr = s.pstm->Seek(pos, STREAM_SEEK_SET, NULL);
while(SUCCEEDED(hr)){
@@ -219,9 +219,7 @@ Q_GLOBAL_STATIC(QWindowsMimeList, theMimeList);
/*!
\class QWindowsMime
\brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats.
- \ingroup io
\ingroup draganddrop
- \ingroup misc
Qt's drag-and-drop and clipboard facilities use the MIME standard.
On X11, this maps trivially to the Xdnd protocol, but on Windows
@@ -281,11 +279,7 @@ QWindowsMime::~QWindowsMime()
*/
int QWindowsMime::registerMimeType(const QString &mime)
{
-#ifdef Q_OS_WINCE
int f = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (mime.utf16()));
-#else
- int f = RegisterClipboardFormatA(mime.toLocal8Bit());
-#endif
if (!f)
qErrnoWarning("QWindowsMime::registerMimeType: Failed to register clipboard format");
@@ -401,9 +395,9 @@ QStringList QWindowsMime::allMimesForFormats(IDataObject *pDataObj)
while (S_OK == fmtenum->Next(1, &fmtetc, 0)) {
#if defined(QMIME_DEBUG) && !defined(Q_OS_WINCE)
qDebug("QWindowsMime::allMimesForFormats()");
- char buf[256] = {0};
- GetClipboardFormatNameA(fmtetc.cfFormat, buf, 255);
- qDebug("CF = %d : %s", fmtetc.cfFormat, buf);
+ wchar_t buf[256] = {0};
+ GetClipboardFormatName(fmtetc.cfFormat, buf, 255);
+ qDebug("CF = %d : %s", fmtetc.cfFormat, QString::fromWCharArray(buf));
#endif
for (int i=mimes.size()-1; i>=0; --i) {
QString format = mimes.at(i)->mimeForFormat(fmtetc);
@@ -504,7 +498,7 @@ bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeDa
++u;
}
res.truncate(ri);
- const int byteLength = res.length()*2;
+ const int byteLength = res.length() * sizeof(ushort);
QByteArray r(byteLength + 2, '\0');
memcpy(r.data(), res.unicode(), byteLength);
r[byteLength] = 0;
@@ -549,7 +543,7 @@ QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pData
QString str;
QByteArray data = getData(CF_UNICODETEXT, pDataObj);
if (!data.isEmpty()) {
- str = QString::fromUtf16((const unsigned short *)data.data());
+ str = QString::fromWCharArray((const wchar_t *)data.data());
str.replace(QLatin1String("\r\n"), QLatin1String("\n"));
} else {
data = getData(CF_TEXT, pDataObj);
@@ -620,11 +614,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
for (int i=0; i<urls.size(); i++) {
QString fn = QDir::toNativeSeparators(urls.at(i).toLocalFile());
if (!fn.isEmpty()) {
- QT_WA({
- size += sizeof(TCHAR)*(fn.length()+1);
- } , {
- size += fn.toLocal8Bit().length()+1;
- });
+ size += sizeof(ushort) * (fn.length() + 1);
fileNames.append(fn);
}
}
@@ -636,36 +626,22 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
d->fNC = true;
char* files = ((char*)d) + d->pFiles;
- QT_WA({
- d->fWide = true;
- TCHAR* f = (TCHAR*)files;
- for (int i=0; i<fileNames.size(); i++) {
- int l = fileNames.at(i).length();
- memcpy(f, fileNames.at(i).utf16(), l*sizeof(TCHAR));
- f += l;
- *f++ = 0;
- }
- *f = 0;
- } , {
- d->fWide = false;
- char* f = files;
- for (int i=0; i<fileNames.size(); i++) {
- QByteArray c = fileNames.at(i).toLocal8Bit();
- if (!c.isEmpty()) {
- int l = c.length();
- memcpy(f, c.constData(), l);
- f += l;
- *f++ = 0;
- }
- }
- *f = 0;
- });
+ d->fWide = true;
+ wchar_t* f = (wchar_t*)files;
+ for (int i=0; i<fileNames.size(); i++) {
+ int l = fileNames.at(i).length();
+ memcpy(f, fileNames.at(i).utf16(), l * sizeof(ushort));
+ f += l;
+ *f++ = 0;
+ }
+ *f = 0;
+
return setData(result, pmedium);
} else if (getCf(formatetc) == CF_INETURL_W) {
QList<QUrl> urls = mimeData->urls();
QByteArray result;
QString url = urls.at(0).toString();
- result = QByteArray((const char *)url.utf16(), url.length() * 2);
+ result = QByteArray((const char *)url.utf16(), url.length() * sizeof(ushort));
result.append('\0');
result.append('\0');
return setData(result, pmedium);
@@ -720,15 +696,15 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD
LPDROPFILES hdrop = (LPDROPFILES)data.data();
if (hdrop->fWide) {
- const ushort* filesw = (const ushort*)(data.data() + hdrop->pFiles);
- int i=0;
+ const wchar_t* filesw = (const wchar_t *)(data.data() + hdrop->pFiles);
+ int i = 0;
while (filesw[i]) {
- QString fileurl = QString::fromUtf16(filesw+i);
+ QString fileurl = QString::fromWCharArray(filesw + i);
urls += QUrl::fromLocalFile(fileurl);
i += fileurl.length()+1;
}
} else {
- const char* files = (const char*)data.data() + hdrop->pFiles;
+ const char* files = (const char *)data.data() + hdrop->pFiles;
int i=0;
while (files[i]) {
urls += QUrl::fromLocalFile(QString::fromLocal8Bit(files+i));
@@ -744,7 +720,7 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD
QByteArray data = getData(CF_INETURL_W, pDataObj);
if (data.isEmpty())
return QVariant();
- return QUrl(QString::fromUtf16((const unsigned short *)data.constData()));
+ return QUrl(QString::fromWCharArray((const wchar_t *)data.constData()));
} else if (canGetData(CF_INETURL, pDataObj)) {
QByteArray data = getData(CF_INETURL, pDataObj);
if (data.isEmpty())
@@ -852,7 +828,7 @@ QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pData
if (end > start && start > 0) {
html = "<!--StartFragment-->" + html.mid(start, end - start);
html += "<!--EndFragment-->";
- html.replace("\r", "");
+ html.replace('\r', "");
result = QString::fromUtf8(html);
}
}
@@ -913,11 +889,7 @@ private:
QWindowsMimeImage::QWindowsMimeImage()
{
-#ifdef Q_OS_WINCE
- CF_PNG = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (QString::fromLatin1("PNG").utf16()));
-#else
- CF_PNG = RegisterClipboardFormatA("PNG");
-#endif
+ CF_PNG = RegisterClipboardFormat(L"PNG");
}
QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
@@ -1114,7 +1086,7 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData
++u;
}
res.truncate(ri);
- const int byteLength = res.length()*2;
+ const int byteLength = res.length() * sizeof(ushort);
QByteArray r(byteLength + 2, '\0');
memcpy(r.data(), res.unicode(), byteLength);
r[byteLength] = 0;
@@ -1154,8 +1126,8 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat
qDebug("QBuiltInMimes::convertToMime()");
#endif
if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) {
- // text/html is in wide chars on windows (compatible with mozillia)
- val = QString::fromUtf16((const unsigned short *)data.data());
+ // text/html is in wide chars on windows (compatible with Mozilla)
+ val = QString::fromWCharArray((const wchar_t *)data.data());
} else {
val = data; // it should be enough to return the data and let QMimeData do the rest.
}
@@ -1262,16 +1234,16 @@ QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, con
}
return formatetcs;
}
-static const char *x_qt_windows_mime = "application/x-qt-windows-mime;value=\"";
+static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\"";
-bool isCustomMimeType(const QString &mimeType)
+static bool isCustomMimeType(const QString &mimeType)
{
return mimeType.startsWith(QLatin1String(x_qt_windows_mime), Qt::CaseInsensitive);
}
-QString customMimeType(const QString &mimeType)
+static QString customMimeType(const QString &mimeType)
{
- int len = QString(QLatin1String(x_qt_windows_mime)).length();
+ int len = sizeof(x_qt_windows_mime) - 1;
int n = mimeType.lastIndexOf(QLatin1Char('\"'))-len;
return mimeType.mid(len, n);
}
@@ -1280,11 +1252,7 @@ bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pD
{
if (isCustomMimeType(mimeType)) {
QString clipFormat = customMimeType(mimeType);
-#ifdef Q_OS_WINCE
int cf = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (clipFormat.utf16()));
-#else
- int cf = RegisterClipboardFormatA(clipFormat.toLocal8Bit());
-#endif
return canGetData(cf, pDataObj);
} else if (formats.keys(mimeType).isEmpty()) {
// if it is not in there then register it an see if we can get it
@@ -1304,11 +1272,7 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p
QByteArray data;
if (isCustomMimeType(mimeType)) {
QString clipFormat = customMimeType(mimeType);
-#ifdef Q_OS_WINCE
int cf = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (clipFormat.utf16()));
-#else
- int cf = RegisterClipboardFormatA(clipFormat.toLocal8Bit());
-#endif
data = getData(cf, pDataObj);
} else if (formats.keys(mimeType).isEmpty()) {
int cf = QWindowsMime::registerMimeType(mimeType);
@@ -1325,46 +1289,38 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p
QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
{
QString format = formats.value(getCf(formatetc));
- if (format.isEmpty()) {
- QByteArray ba;
- QString clipFormat;
- int len;
- QT_WA({
- ba.resize(256*2);
- len = GetClipboardFormatNameW(getCf(formatetc), (TCHAR*)ba.data(), 255);
- if (len)
- clipFormat = QString::fromUtf16((ushort *)ba.data(), len);
- } , {
- ba.resize(256);
- len = GetClipboardFormatNameA(getCf(formatetc), ba.data(), 255);
- if (len)
- clipFormat = QString::fromLocal8Bit(ba.data(), len);
- });
- if (len) {
+ if (!format.isEmpty())
+ return format;
+
+ wchar_t buffer[256];
+ int len = GetClipboardFormatName(getCf(formatetc), buffer, 256);
+
+ if (len) {
+ QString clipFormat = QString::fromWCharArray(buffer, len);
#ifndef QT_NO_DRAGANDDROP
- if (QInternalMimeData::canReadData(clipFormat))
- format = clipFormat;
- else if((formatetc.cfFormat >= 0xC000)){
- //create the mime as custom. not registered.
- if (!excludeList.contains(clipFormat, Qt::CaseInsensitive)) {
- //check if this is a mime type
- bool ianaType = false;
- int sz = ianaTypes.size();
- for (int i = 0; i < sz; i++) {
- if (clipFormat.startsWith(ianaTypes[i], Qt::CaseInsensitive)) {
- ianaType = true;
- break;
- }
+ if (QInternalMimeData::canReadData(clipFormat))
+ format = clipFormat;
+ else if((formatetc.cfFormat >= 0xC000)){
+ //create the mime as custom. not registered.
+ if (!excludeList.contains(clipFormat, Qt::CaseInsensitive)) {
+ //check if this is a mime type
+ bool ianaType = false;
+ int sz = ianaTypes.size();
+ for (int i = 0; i < sz; i++) {
+ if (clipFormat.startsWith(ianaTypes[i], Qt::CaseInsensitive)) {
+ ianaType = true;
+ break;
}
- if (!ianaType)
- format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"');
- else
- format = clipFormat;
}
+ if (!ianaType)
+ format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"');
+ else
+ format = clipFormat;
}
-#endif //QT_NO_DRAGANDDROP
}
+#endif //QT_NO_DRAGANDDROP
}
+
return format;
}
diff --git a/src/gui/kernel/qmotifdnd_x11.cpp b/src/gui/kernel/qmotifdnd_x11.cpp
index bdf7092..5783970 100644
--- a/src/gui/kernel/qmotifdnd_x11.cpp
+++ b/src/gui/kernel/qmotifdnd_x11.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
/* The following copyright notice pertains to the code as contributed
-to Nokia, not to Nokia's modifications. It is replicated
+to Qt, not to Nokia's modifications. It is replicated
in doc/dnd.doc, where the documentation system can see it. */
/* Copyright 1996 Daniel Dardailler.
diff --git a/src/gui/kernel/qmultitouch_mac.mm b/src/gui/kernel/qmultitouch_mac.mm
new file mode 100644
index 0000000..aef66e4
--- /dev/null
+++ b/src/gui/kernel/qmultitouch_mac.mm
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qmultitouch_mac_p.h>
+#include <qcursor.h>
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_MAC_USE_COCOA
+
+QHash<qint64, QCocoaTouch*> QCocoaTouch::_currentTouches;
+QPointF QCocoaTouch::_screenReferencePos;
+QPointF QCocoaTouch::_trackpadReferencePos;
+int QCocoaTouch::_idAssignmentCount = 0;
+int QCocoaTouch::_touchCount = 0;
+bool QCocoaTouch::_updateInternalStateOnly = true;
+
+QCocoaTouch::QCocoaTouch(NSTouch *nstouch)
+{
+ if (_currentTouches.size() == 0)
+ _idAssignmentCount = 0;
+
+ _touchPoint.setId(_idAssignmentCount++);
+ _touchPoint.setPressure(1.0);
+ _identity = qint64([nstouch identity]);
+ _currentTouches.insert(_identity, this);
+ updateTouchData(nstouch, NSTouchPhaseBegan);
+}
+
+QCocoaTouch::~QCocoaTouch()
+{
+ _currentTouches.remove(_identity);
+}
+
+void QCocoaTouch::updateTouchData(NSTouch *nstouch, NSTouchPhase phase)
+{
+ if (_touchCount == 1)
+ _touchPoint.setState(toTouchPointState(phase) | Qt::TouchPointPrimary);
+ else
+ _touchPoint.setState(toTouchPointState(phase));
+
+ // From the normalized position on the trackpad, calculate
+ // where on screen the touchpoint should be according to the
+ // reference position:
+ NSPoint npos = [nstouch normalizedPosition];
+ QPointF qnpos = QPointF(npos.x, 1 - npos.y);
+ _touchPoint.setNormalizedPos(qnpos);
+
+ if (_touchPoint.id() == 0 && phase == NSTouchPhaseBegan) {
+ _trackpadReferencePos = qnpos;
+ _screenReferencePos = QCursor::pos();
+ }
+
+ NSSize dsize = [nstouch deviceSize];
+ float ppiX = (qnpos.x() - _trackpadReferencePos.x()) * dsize.width;
+ float ppiY = (qnpos.y() - _trackpadReferencePos.y()) * dsize.height;
+ QPointF relativePos = _trackpadReferencePos - QPointF(ppiX, ppiY);
+ _touchPoint.setScreenPos(_screenReferencePos - relativePos);
+}
+
+QCocoaTouch *QCocoaTouch::findQCocoaTouch(NSTouch *nstouch)
+{
+ qint64 identity = qint64([nstouch identity]);
+ if (_currentTouches.contains(identity))
+ return _currentTouches.value(identity);
+ return 0;
+}
+
+Qt::TouchPointState QCocoaTouch::toTouchPointState(NSTouchPhase nsState)
+{
+ Qt::TouchPointState qtState = Qt::TouchPointReleased;
+ switch (nsState) {
+ case NSTouchPhaseBegan:
+ qtState = Qt::TouchPointPressed;
+ break;
+ case NSTouchPhaseMoved:
+ qtState = Qt::TouchPointMoved;
+ break;
+ case NSTouchPhaseStationary:
+ qtState = Qt::TouchPointStationary;
+ break;
+ case NSTouchPhaseEnded:
+ case NSTouchPhaseCancelled:
+ qtState = Qt::TouchPointReleased;
+ break;
+ default:
+ break;
+ }
+ return qtState;
+}
+
+QList<QTouchEvent::TouchPoint>
+QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch)
+{
+ QMap<int, QTouchEvent::TouchPoint> touchPoints;
+ NSSet *ended = [event touchesMatchingPhase:NSTouchPhaseEnded | NSTouchPhaseCancelled inView:nil];
+ NSSet *active = [event
+ touchesMatchingPhase:NSTouchPhaseBegan | NSTouchPhaseMoved | NSTouchPhaseStationary
+ inView:nil];
+ _touchCount = [active count];
+
+ // First: remove touches that were ended by the user. If we are
+ // currently not accepting single touches, a corresponding 'begin'
+ // has never been send to the app for these events.
+ // So should therefore not send the following removes either.
+
+ for (int i=0; i<int([ended count]); ++i) {
+ NSTouch *touch = [[ended allObjects] objectAtIndex:i];
+ QCocoaTouch *qcocoaTouch = findQCocoaTouch(touch);
+ if (qcocoaTouch) {
+ qcocoaTouch->updateTouchData(touch, [touch phase]);
+ if (!_updateInternalStateOnly)
+ touchPoints.insert(qcocoaTouch->_touchPoint.id(), qcocoaTouch->_touchPoint);
+ delete qcocoaTouch;
+ }
+ }
+
+ bool wasUpdateInternalStateOnly = _updateInternalStateOnly;
+ _updateInternalStateOnly = !acceptSingleTouch && _touchCount < 2;
+
+ // Next: update, or create, existing touches.
+ // We always keep track of all touch points, even
+ // when not accepting single touches.
+
+ for (int i=0; i<int([active count]); ++i) {
+ NSTouch *touch = [[active allObjects] objectAtIndex:i];
+ QCocoaTouch *qcocoaTouch = findQCocoaTouch(touch);
+ if (!qcocoaTouch)
+ qcocoaTouch = new QCocoaTouch(touch);
+ else
+ qcocoaTouch->updateTouchData(touch, wasUpdateInternalStateOnly ? NSTouchPhaseBegan : [touch phase]);
+ if (!_updateInternalStateOnly)
+ touchPoints.insert(qcocoaTouch->_touchPoint.id(), qcocoaTouch->_touchPoint);
+ }
+
+ // Next: sadly, we need to check that our touch hash is in
+ // sync with cocoa. This is typically not the case after a system
+ // gesture happend (like a four-finger-swipe to show expose).
+
+ if (_touchCount != _currentTouches.size()) {
+ // Remove all instances, and basically start from scratch:
+ touchPoints.clear();
+ QList<QCocoaTouch *> list = _currentTouches.values();
+ foreach (QCocoaTouch *qcocoaTouch, _currentTouches.values()) {
+ if (!_updateInternalStateOnly) {
+ qcocoaTouch->_touchPoint.setState(Qt::TouchPointReleased);
+ touchPoints.insert(qcocoaTouch->_touchPoint.id(), qcocoaTouch->_touchPoint);
+ }
+ delete qcocoaTouch;
+ }
+ _currentTouches.clear();
+ _updateInternalStateOnly = !acceptSingleTouch;
+ return touchPoints.values();
+ }
+
+ // Finally: If this call _started_ to reject single
+ // touches, we need to fake a relase for the remaining
+ // touch now (and refake a begin for it later, if needed).
+
+ if (_updateInternalStateOnly && !wasUpdateInternalStateOnly && !_currentTouches.isEmpty()) {
+ QCocoaTouch *qcocoaTouch = _currentTouches.values().first();
+ qcocoaTouch->_touchPoint.setState(Qt::TouchPointReleased);
+ touchPoints.insert(qcocoaTouch->_touchPoint.id(), qcocoaTouch->_touchPoint);
+ // Since this last touch also will end up beeing the first
+ // touch (if the user adds a second finger without lifting
+ // the first), we promote it to be the primary touch:
+ qcocoaTouch->_touchPoint.setId(0);
+ _idAssignmentCount = 1;
+ }
+
+ return touchPoints.values();
+}
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+
diff --git a/src/gui/kernel/qmultitouch_mac_p.h b/src/gui/kernel/qmultitouch_mac_p.h
new file mode 100644
index 0000000..ab94d53
--- /dev/null
+++ b/src/gui/kernel/qmultitouch_mac_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QMULTITOUCH_MAC_P_H
+#define QMULTITOUCH_MAC_P_H
+
+#ifdef QT_MAC_USE_COCOA
+#import <Cocoa/Cocoa.h>
+#endif
+
+#include <qevent.h>
+#include <qhash.h>
+#include <QtCore>
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_MAC_USE_COCOA
+
+class QCocoaTouch
+{
+ public:
+ static QList<QTouchEvent::TouchPoint> getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch);
+ static void setMouseInDraggingState(bool inDraggingState);
+
+ private:
+ static QHash<qint64, QCocoaTouch*> _currentTouches;
+ static QPointF _screenReferencePos;
+ static QPointF _trackpadReferencePos;
+ static int _idAssignmentCount;
+ static int _touchCount;
+ static bool _updateInternalStateOnly;
+
+ QTouchEvent::TouchPoint _touchPoint;
+ qint64 _identity;
+
+ QCocoaTouch(NSTouch *nstouch);
+ ~QCocoaTouch();
+
+ void updateTouchData(NSTouch *nstouch, NSTouchPhase phase);
+ static QCocoaTouch *findQCocoaTouch(NSTouch *nstouch);
+ static Qt::TouchPointState toTouchPointState(NSTouchPhase nsState);
+};
+
+#endif // QT_MAC_USE_COCOA
+
+QT_END_NAMESPACE
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+
+#endif // QMULTITOUCH_MAC_P_H
+
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index 4ea5685..4c7a6a6 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -125,7 +125,7 @@ QDataStream &operator>>(QDataStream &s, QColorGroup &g)
{
return qt_stream_in_qcolorgroup(s, g);
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
Constructs a palette with the specified \a active, \a disabled and
@@ -158,7 +158,7 @@ void QPalette::setColorGroup(ColorGroup cg, const QColorGroup &g)
g.brush(LinkVisited), g.brush(ToolTipBase), g.brush(ToolTipText));
}
-#endif
+#endif // QT3_SUPPORT
/*!
\fn const QColor &QPalette::color(ColorRole role) const
@@ -399,8 +399,8 @@ void QPalette::setColorGroup(ColorGroup cg, const QColorGroup &g)
\ingroup appearance
\ingroup shared
- \ingroup multimedia
- \mainclass
+ \ingroup painting
+
A palette consists of three color groups: \e Active, \e Disabled,
and \e Inactive. All widgets in Qt contain a palette and
diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp
index ea08c6c..69efe01 100644
--- a/src/gui/kernel/qshortcut.cpp
+++ b/src/gui/kernel/qshortcut.cpp
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
\brief The QShortcut class is used to create keyboard shortcuts.
\ingroup events
- \mainclass
+
The QShortcut class provides a way of connecting keyboard
shortcuts to Qt's \l{signals and slots} mechanism, so that
@@ -163,7 +163,6 @@ public:
void QShortcutPrivate::redoGrab(QShortcutMap &map)
{
Q_Q(QShortcut);
- QWidget *parent = q->parentWidget();
if (!parent) {
qWarning("QShortcut: No widget parent defined");
return;
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
index b8cee02..d2779e0 100644
--- a/src/gui/kernel/qshortcutmap.cpp
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -61,8 +61,6 @@
QT_BEGIN_NAMESPACE
-extern bool qt_mac_no_native_menubar; // qmenu_mac.cpp
-
// To enable verbose output uncomment below
//#define DEBUG_QSHORTCUTMAP
@@ -101,17 +99,17 @@ struct QShortcutEntry
QObject *owner;
};
-#ifndef QT_NO_DEBUG_STREAM
+#if 0 //ndef QT_NO_DEBUG_STREAM
/*! \internal
QDebug operator<< for easy debug output of the shortcut entries.
*/
-QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) {
+static QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) {
if (!se)
return dbg << "QShortcutEntry(0x0)";
dbg.nospace()
<< "QShortcutEntry(" << se->keyseq
<< "), id(" << se->id << "), enabled(" << se->enabled << "), autorepeat(" << se->autorepeat
- << "), owner(" << se->owner << ")";
+ << "), owner(" << se->owner << ')';
return dbg.space();
}
#endif // QT_NO_DEBUGSTREAM
@@ -148,9 +146,8 @@ public:
QShortcutMap constructor.
*/
QShortcutMap::QShortcutMap()
+ : d_ptr(new QShortcutMapPrivate(this))
{
- d_ptr = new QShortcutMapPrivate(this);
- Q_ASSERT(d_ptr != 0);
resetState();
}
@@ -159,8 +156,6 @@ QShortcutMap::QShortcutMap()
*/
QShortcutMap::~QShortcutMap()
{
- delete d_ptr;
- d_ptr = 0;
}
/*! \internal
@@ -630,13 +625,13 @@ QKeySequence::SequenceMatch QShortcutMap::matches(const QKeySequence &seq1,
bool QShortcutMap::correctContext(const QShortcutEntry &item) const {
Q_ASSERT_X(item.owner, "QShortcutMap", "Shortcut has no owner. Illegal map state!");
- QWidget *active_window = qApp->activeWindow();
+ QWidget *active_window = QApplication::activeWindow();
// popups do not become the active window,
// so we fake it here to get the correct context
// for the shortcut system.
- if (qApp->activePopupWidget())
- active_window = qApp->activePopupWidget();
+ if (QApplication::activePopupWidget())
+ active_window = QApplication::activePopupWidget();
if (!active_window)
return false;
@@ -660,7 +655,7 @@ bool QShortcutMap::correctWidgetContext(Qt::ShortcutContext context, QWidget *w,
{
bool visible = w->isVisible();
#ifdef Q_WS_MAC
- if (!qt_mac_no_native_menubar && qobject_cast<QMenuBar *>(w))
+ if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
visible = true;
#endif
@@ -723,7 +718,7 @@ bool QShortcutMap::correctGraphicsWidgetContext(Qt::ShortcutContext context, QGr
{
bool visible = w->isVisible();
#ifdef Q_WS_MAC
- if (!qt_mac_no_native_menubar && qobject_cast<QMenuBar *>(w))
+ if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
visible = true;
#endif
@@ -878,7 +873,7 @@ void QShortcutMap::dispatchEvent(QKeyEvent *e)
qDebug().nospace()
<< "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""
<< (QString)next->keyseq << "\", " << next->id << ", "
- << (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ")";
+ << (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ')';
#endif
QShortcutEvent se(next->keyseq, next->id, enabledShortcuts>1);
QApplication::sendEvent(const_cast<QObject *>(next->owner), &se);
diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h
index 0be45be..f90113f 100644
--- a/src/gui/kernel/qshortcutmap_p.h
+++ b/src/gui/kernel/qshortcutmap_p.h
@@ -55,6 +55,7 @@
#include "QtGui/qkeysequence.h"
#include "QtCore/qvector.h"
+#include "QtCore/qscopedpointer.h"
QT_BEGIN_NAMESPACE
@@ -104,7 +105,7 @@ private:
#ifndef QT_NO_ACTION
bool correctContext(Qt::ShortcutContext context,QAction *a, QWidget *active_window) const;
#endif
- QShortcutMapPrivate *d_ptr;
+ QScopedPointer<QShortcutMapPrivate> d_ptr;
QKeySequence::SequenceMatch find(QKeyEvent *e);
QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const;
diff --git a/src/gui/kernel/qsizepolicy.h b/src/gui/kernel/qsizepolicy.h
index 8120ab8..4261dda 100644
--- a/src/gui/kernel/qsizepolicy.h
+++ b/src/gui/kernel/qsizepolicy.h
@@ -203,9 +203,11 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes)
+#ifndef QT_NO_DATASTREAM
// implemented in qlayout.cpp
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &);
+#endif
inline void QSizePolicy::transpose() {
Policy hData = horizontalPolicy();
diff --git a/src/gui/kernel/qsizepolicy.qdoc b/src/gui/kernel/qsizepolicy.qdoc
new file mode 100644
index 0000000..6a739da
--- /dev/null
+++ b/src/gui/kernel/qsizepolicy.qdoc
@@ -0,0 +1,521 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QSizePolicy
+ \brief The QSizePolicy class is a layout attribute describing horizontal
+ and vertical resizing policy.
+
+ \ingroup geomanagement
+
+ The size policy of a widget is an expression of its willingness to
+ be resized in various ways, and affects how the widget is treated
+ by the \l{Layout Management}{layout engine}. Each widget returns a
+ QSizePolicy that describes the horizontal and vertical resizing
+ policy it prefers when being laid out. You can change this for
+ a specific widget by changing its QWidget::sizePolicy property.
+
+ QSizePolicy contains two independent QSizePolicy::Policy values
+ and two stretch factors; one describes the widgets's horizontal
+ size policy, and the other describes its vertical size policy. It
+ also contains a flag to indicate whether the height and width of
+ its preferred size are related.
+
+ The horizontal and vertical policies can be set in the
+ constructor, and altered using the setHorizontalPolicy() and
+ setVerticalPolicy() functions. The stretch factors can be set
+ using the setHorizontalStretch() and setVerticalStretch()
+ functions. The flag indicating whether the widget's
+ \l{QWidget::sizeHint()}{sizeHint()} is width-dependent (such as a
+ menu bar or a word-wrapping label) can be set using the
+ setHeightForWidth() function.
+
+ The current size policies and stretch factors be retrieved using
+ the horizontalPolicy(), verticalPolicy(), horizontalStretch() and
+ verticalStretch() functions. Alternatively, use the transpose()
+ function to swap the horizontal and vertical policies and
+ stretches. The hasHeightForWidth() function returns the current
+ status of the flag indicating the size hint dependencies.
+
+ Use the expandingDirections() function to determine whether the
+ associated widget can make use of more space than its
+ \l{QWidget::sizeHint()}{sizeHint()} function indicates, as well as
+ find out in which directions it can expand.
+
+ Finally, the QSizePolicy class provides operators comparing this
+ size policy to a given policy, as well as a QVariant operator
+ storing this QSizePolicy as a QVariant object.
+
+ \sa QSize, QWidget::sizeHint(), QWidget::sizePolicy,
+ QLayoutItem::sizeHint()
+*/
+
+/*!
+ \enum QSizePolicy::PolicyFlag
+
+ These flags are combined together to form the various \l{Policy}
+ values:
+
+ \value GrowFlag The widget can grow beyond its size hint if necessary.
+ \value ExpandFlag The widget should get as much space as possible.
+ \value ShrinkFlag The widget can shrink below its size hint if necessary.
+ \value IgnoreFlag The widget's size hint is ignored. The widget will get
+ as much space as possible.
+
+ \sa Policy
+*/
+
+/*!
+ \enum QSizePolicy::Policy
+
+ This enum describes the various per-dimension sizing types used
+ when constructing a QSizePolicy.
+
+ \value Fixed The QWidget::sizeHint() is the only acceptable
+ alternative, so the widget can never grow or shrink (e.g. the
+ vertical direction of a push button).
+
+ \value Minimum The sizeHint() is minimal, and sufficient. The
+ widget can be expanded, but there is no advantage to it being
+ larger (e.g. the horizontal direction of a push button).
+ It cannot be smaller than the size provided by sizeHint().
+
+ \value Maximum The sizeHint() is a maximum. The widget can be
+ shrunk any amount without detriment if other widgets need the
+ space (e.g. a separator line).
+ It cannot be larger than the size provided by sizeHint().
+
+ \value Preferred The sizeHint() is best, but the widget can be
+ shrunk and still be useful. The widget can be expanded, but there
+ is no advantage to it being larger than sizeHint() (the default
+ QWidget policy).
+
+ \value Expanding The sizeHint() is a sensible size, but the
+ widget can be shrunk and still be useful. The widget can make use
+ of extra space, so it should get as much space as possible (e.g.
+ the horizontal direction of a horizontal slider).
+
+ \value MinimumExpanding The sizeHint() is minimal, and sufficient.
+ The widget can make use of extra space, so it should get as much
+ space as possible (e.g. the horizontal direction of a horizontal
+ slider).
+
+ \value Ignored The sizeHint() is ignored. The widget will get as
+ much space as possible.
+
+ \sa PolicyFlag, setHorizontalPolicy(), setVerticalPolicy()
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy()
+
+ Constructs a QSizePolicy object with \l Fixed as its horizontal
+ and vertical policies.
+
+ The policies can be altered using the setHorizontalPolicy() and
+ setVerticalPolicy() functions. Use the setHeightForWidth()
+ function if the preferred height of the widget is dependent on the
+ width of the widget (for example, a QLabel with line wrapping).
+
+ \sa setHorizontalStretch(), setVerticalStretch()
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical)
+
+ Constructs a QSizePolicy object with the given \a horizontal and
+ \a vertical policies, and DefaultType as the control type.
+
+ Use setHeightForWidth() if the preferred height of the widget is
+ dependent on the width of the widget (for example, a QLabel with
+ line wrapping).
+
+ \sa setHorizontalStretch(), setVerticalStretch()
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical, ControlType type)
+ \since 4.3
+
+ Constructs a QSizePolicy object with the given \a horizontal and
+ \a vertical policies, and the specified control \a type.
+
+ Use setHeightForWidth() if the preferred height of the widget is
+ dependent on the width of the widget (for example, a QLabel with
+ line wrapping).
+
+ \sa setHorizontalStretch(), setVerticalStretch(), controlType()
+*/
+
+/*!
+ \fn QSizePolicy::Policy QSizePolicy::horizontalPolicy() const
+
+ Returns the horizontal component of the size policy.
+
+ \sa setHorizontalPolicy(), verticalPolicy(), horizontalStretch()
+*/
+
+/*!
+ \fn QSizePolicy::Policy QSizePolicy::verticalPolicy() const
+
+ Returns the vertical component of the size policy.
+
+ \sa setVerticalPolicy(), horizontalPolicy(), verticalStretch()
+*/
+
+/*!
+ \fn void QSizePolicy::setHorizontalPolicy(Policy policy)
+
+ Sets the horizontal component to the given \a policy.
+
+ \sa horizontalPolicy(), setVerticalPolicy(), setHorizontalStretch()
+*/
+
+/*!
+ \fn void QSizePolicy::setVerticalPolicy(Policy policy)
+
+ Sets the vertical component to the given \a policy.
+
+ \sa verticalPolicy(), setHorizontalPolicy(), setVerticalStretch()
+*/
+
+/*!
+ \fn Qt::Orientations QSizePolicy::expandingDirections() const
+
+ Returns whether a widget can make use of more space than the
+ QWidget::sizeHint() function indicates.
+
+ A value of Qt::Horizontal or Qt::Vertical means that the widget
+ can grow horizontally or vertically (i.e., the horizontal or
+ vertical policy is \l Expanding or \l MinimumExpanding), whereas
+ Qt::Horizontal | Qt::Vertical means that it can grow in both
+ dimensions.
+
+ \sa horizontalPolicy(), verticalPolicy()
+*/
+
+/*!
+ \fn ControlType QSizePolicy::controlType() const
+ \since 4.3
+
+ Returns the control type associated with the widget for which
+ this size policy applies.
+*/
+
+/*!
+ \fn void QSizePolicy::setControlType(ControlType type)
+ \since 4.3
+
+ Sets the control type associated with the widget for which this
+ size policy applies to \a type.
+
+ The control type specifies the type of the widget for which this
+ size policy applies. It is used by some styles, notably
+ QMacStyle, to insert proper spacing between widgets. For example,
+ the Mac OS X Aqua guidelines specify that push buttons should be
+ separated by 12 pixels, whereas vertically stacked radio buttons
+ only require 6 pixels.
+
+ \sa QStyle::layoutSpacing()
+*/
+
+/*!
+ \fn void QSizePolicy::setHeightForWidth(bool dependent)
+
+ Sets the flag determining whether the widget's preferred height
+ depends on its width, to \a dependent.
+
+ \sa hasHeightForWidth()
+*/
+
+/*!
+ \fn bool QSizePolicy::hasHeightForWidth() const
+
+ Returns true if the widget's preferred height depends on its
+ width; otherwise returns false.
+
+ \sa setHeightForWidth()
+*/
+
+/*!
+ \fn bool QSizePolicy::operator==(const QSizePolicy &other) const
+
+ Returns true if this policy is equal to \a other; otherwise
+ returns false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QSizePolicy::operator!=(const QSizePolicy &other) const
+
+ Returns true if this policy is different from \a other; otherwise
+ returns false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn int QSizePolicy::horizontalStretch() const
+
+ Returns the horizontal stretch factor of the size policy.
+
+ \sa setHorizontalStretch(), verticalStretch(), horizontalPolicy()
+*/
+
+/*!
+ \fn int QSizePolicy::verticalStretch() const
+
+ Returns the vertical stretch factor of the size policy.
+
+ \sa setVerticalStretch(), horizontalStretch(), verticalPolicy()
+*/
+
+/*!
+ \fn void QSizePolicy::setHorizontalStretch(uchar stretchFactor)
+
+ Sets the horizontal stretch factor of the size policy to the given \a
+ stretchFactor.
+
+ \sa horizontalStretch(), setVerticalStretch(), setHorizontalPolicy()
+*/
+
+/*!
+ \fn void QSizePolicy::setVerticalStretch(uchar stretchFactor)
+
+ Sets the vertical stretch factor of the size policy to the given
+ \a stretchFactor.
+
+ \sa verticalStretch(), setHorizontalStretch(), setVerticalPolicy()
+*/
+
+/*!
+ \fn void QSizePolicy::transpose()
+
+ Swaps the horizontal and vertical policies and stretches.
+*/
+
+/*!
+ \enum QSizePolicy::ControlType
+ \since 4.3
+
+ This enum specifies the different types of widgets in terms of
+ layout interaction:
+
+ \value DefaultType The default type, when none is specified.
+ \value ButtonBox A QDialogButtonBox instance.
+ \value CheckBox A QCheckBox instance.
+ \value ComboBox A QComboBox instance.
+ \value Frame A QFrame instance.
+ \value GroupBox A QGroupBox instance.
+ \value Label A QLabel instance.
+ \value Line A QFrame instance with QFrame::HLine or QFrame::VLine.
+ \value LineEdit A QLineEdit instance.
+ \value PushButton A QPushButton instance.
+ \value RadioButton A QRadioButton instance.
+ \value Slider A QAbstractSlider instance.
+ \value SpinBox A QAbstractSpinBox instance.
+ \value TabWidget A QTabWidget instance.
+ \value ToolButton A QToolButton instance.
+
+ \sa setControlType(), controlType()
+*/
+
+#ifdef QT3_SUPPORT
+/*!
+ \typedef QSizePolicy::SizeType
+ \compat
+
+ Use the QSizePolicy::Policy enum instead.
+*/
+
+/*!
+ \enum QSizePolicy::ExpandData
+ \compat
+
+ Use the Qt::Orientations enum instead.
+
+ \value NoDirection Use 0 instead.
+ \value Horizontally Use Qt::Horizontal instead.
+ \value Vertically Use Qt::Vertical instead.
+ \value BothDirections Use Qt::Horizontal | Qt::Vertical instead.
+*/
+
+/*!
+ \fn bool QSizePolicy::mayShrinkHorizontally() const
+
+ Use the horizontalPolicy() function combined with the
+ QSizePolicy::PolicyFlag enum instead.
+
+ \oldcode
+ bool policy = mayShrinkHorizontally();
+ \newcode
+ bool policy = horizontalPolicy() & QSizePolicy::ShrinkFlag;
+ \endcode
+*/
+
+/*!
+ \fn bool QSizePolicy::mayShrinkVertically() const
+
+ Use the verticalPolicy() function combined with the
+ QSizePolicy::PolicyFlag enum instead.
+
+ \oldcode
+ bool policy = mayShrinkVertically();
+ \newcode
+ bool policy = verticalPolicy() & QSizePolicy::ShrinkFlag;
+ \endcode
+*/
+
+/*!
+ \fn bool QSizePolicy::mayGrowHorizontally() const
+
+ Use the horizontalPolicy() function combined with the
+ QSizePolicy::PolicyFlag enum instead.
+
+ \oldcode
+ bool policy = mayGrowHorizontally();
+ \newcode
+ bool policy = horizontalPolicy() & QSizePolicy::GrowFlag;
+ \endcode
+*/
+
+/*!
+ \fn bool QSizePolicy::mayGrowVertically() const
+
+ Use the verticalPolicy() function combined with the
+ QSizePolicy::PolicyFlag enum instead.
+
+ \oldcode
+ bool policy = mayGrowVertically();
+ \newcode
+ bool policy = verticalPolicy() & QSizePolicy::GrowFlag;
+ \endcode
+*/
+
+/*!
+ \fn Qt::QSizePolicy::Orientations QSizePolicy::expanding() const
+
+ Use expandingDirections() instead.
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical, bool dependent)
+
+ Use the QSizePolicy() constructor and the setHeightForWidth()
+ function instead.
+
+ \oldcode
+ QSizePolicy *policy = new QSizePolicy(horizontal, vertical, dependent);
+ \newcode
+ QSizePolicy *policy = new QSizePolicy(horizontal, vertical);
+ policy->setHeightForWidth(dependent);
+ \endcode
+*/
+
+/*!
+ \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical, uchar horizontalStretch,
+ uchar verticalStretch, bool dependent)
+
+ Use the QSizePolicy() constructor and call the
+ setHorizontalStretch(), setVerticalStretch(), and
+ setHeightForWidth() functions instead.
+
+ \oldcode
+ QSizePolicy *policy = new QSizePolicy(horizontal, vertical,
+ horizontalStretch, verticalStretch,
+ dependent);
+ \newcode
+ QSizePolicy *policy = new QSizePolicy(horizontal, vertical);
+ policy->setHorizontalStretch(horizontalStretch);
+ policy->setVerticalStretch(verticalStretch);
+ policy->setHeightForWidth(dependent);
+ \endcode
+*/
+
+/*!
+ \fn QSizePolicy::Policy QSizePolicy::horData() const
+
+ Use horizontalPolicy() instead.
+*/
+
+/*!
+ \fn QSizePolicy::Policy QSizePolicy::verData() const
+
+ Use verticalPolicy() instead.
+*/
+
+/*!
+ \fn void QSizePolicy::setHorData(Policy policy)
+
+ Use setHorizontalPolicy() instead.
+*/
+
+/*!
+ \fn void QSizePolicy::setVerData(Policy policy)
+
+ Use setVerticalPolicy() instead.
+*/
+
+/*!
+ \fn uint QSizePolicy::horStretch() const
+
+ Use horizontalStretch() instead.
+*/
+
+/*!
+ \fn uint QSizePolicy::verStretch() const
+
+ Use verticalStretch() instead.
+*/
+
+/*!
+ \fn void QSizePolicy::setHorStretch(uchar stretch)
+
+ Use setHorizontalStretch() instead.
+*/
+
+/*!
+ \fn void QSizePolicy::setVerStretch(uchar stretch)
+
+ Use setVerticalStretch() instead.
+*/
+#endif
diff --git a/src/gui/kernel/qsound.cpp b/src/gui/kernel/qsound.cpp
index 2250d61..3213c1b 100644
--- a/src/gui/kernel/qsound.cpp
+++ b/src/gui/kernel/qsound.cpp
@@ -106,7 +106,7 @@ public:
\brief The QSound class provides access to the platform audio facilities.
\ingroup multimedia
- \mainclass
+
Qt provides the most commonly required audio operation in GUI
applications: asynchronously playing a sound file. This is most
@@ -153,6 +153,9 @@ public:
\o Qt for Embedded Linux
\o A built-in mixing sound server is used, accessing \c /dev/dsp
directly. Only the WAVE format is supported.
+ \o Symbian
+ \o CMdaAudioPlayerUtility is used. All formats that Symbian OS or devices support
+ are supported also by Qt.
\endtable
Note that QSound does not support \l{resources.html}{resources}.
diff --git a/src/gui/kernel/qsound_qws.cpp b/src/gui/kernel/qsound_qws.cpp
index 7eea8c0..c802261 100644
--- a/src/gui/kernel/qsound_qws.cpp
+++ b/src/gui/kernel/qsound_qws.cpp
@@ -53,16 +53,16 @@
#include "qhash.h"
#include "qfileinfo.h"
-#ifdef MEDIA_SERVER
#include "qbytearray.h"
#include "quuid.h"
#include "qdatastream.h"
#include "qcopchannel_qws.h"
#include "qbuffer.h"
+
QT_BEGIN_NAMESPACE
-QT_USE_NAMESPACE
+#ifdef MEDIA_SERVER
#define SERVER_CHANNEL "QPE/MediaServer"
@@ -279,7 +279,7 @@ QAuBucketQWS::QAuBucketQWS( QAuServerQWS *server, QSound *sound, QObject* parent
sound->setObjectName( m_id.toString() );
- m_channel = new QCopChannel(QString( QLatin1String("QPE/QSound/") ).append( m_id ), this );
+ m_channel = new QCopChannel(QLatin1String("QPE/QSound/") + m_id ), this );
connect( m_channel, SIGNAL(received(QString,QByteArray)),
this, SLOT(processMessage(QString,QByteArray)) );
diff --git a/src/gui/kernel/qsound_s60.cpp b/src/gui/kernel/qsound_s60.cpp
new file mode 100644
index 0000000..b654567
--- /dev/null
+++ b/src/gui/kernel/qsound_s60.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+#ifndef QT_NO_SOUND
+
+#include "qdir.h"
+#include "qapplication.h"
+#include "qsound.h"
+#include "qsound_p.h"
+#include "qfileinfo.h"
+#include <private/qcore_symbian_p.h>
+
+#include <e32std.h>
+#include <MdaAudioSamplePlayer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAuServerS60;
+
+class QAuBucketS60 : public QAuBucket, public MMdaAudioPlayerCallback
+{
+public:
+ QAuBucketS60( QAuServerS60 *server, QSound *sound);
+ ~QAuBucketS60();
+
+ void play();
+ void stop();
+
+ inline QSound* sound() const { return m_sound; }
+
+public: // from MMdaAudioPlayerCallback
+ void MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration);
+ void MapcPlayComplete(TInt aError);
+
+private:
+ QSound *m_sound;
+ QAuServerS60 *m_server;
+ bool m_prepared;
+ bool m_playCalled;
+ CMdaAudioPlayerUtility* m_playUtility;
+};
+
+
+class QAuServerS60 : public QAuServer
+{
+public:
+ QAuServerS60( QObject* parent );
+
+ void init( QSound* s )
+ {
+ QAuBucketS60 *bucket = new QAuBucketS60( this, s );
+ setBucket( s, bucket );
+ }
+
+ void play( QSound* s )
+ {
+ bucket( s )->play();
+ }
+
+ void stop( QSound* s )
+ {
+ bucket( s )->stop();
+ }
+
+ bool okay() { return true; }
+
+protected:
+ void playCompleted(QAuBucketS60* bucket, int error)
+ {
+ QSound *sound = bucket->sound();
+ if(!error) {
+ // We need to handle repeats by ourselves, since with Symbian API we don't
+ // know how many loops have been played when user asks it
+ if( decLoop( sound ) ) {
+ play( sound );
+ }
+ } else {
+ // We don't have a way to inform about errors -> just decrement loops
+ // in order that QSound::isFinished will return true;
+ while(decLoop(sound)) {}
+ }
+ }
+
+protected:
+ QAuBucketS60* bucket( QSound *s )
+ {
+ return (QAuBucketS60*)QAuServer::bucket( s );
+ }
+
+ friend class QAuBucketS60;
+
+};
+
+QAuServerS60::QAuServerS60(QObject* parent) :
+ QAuServer(parent)
+{
+ setObjectName(QLatin1String("QAuServerS60"));
+}
+
+
+QAuServer* qt_new_audio_server()
+{
+ return new QAuServerS60(qApp);
+}
+
+QAuBucketS60::QAuBucketS60( QAuServerS60 *server, QSound *sound )
+ : m_sound( sound ), m_server( server ), m_prepared(false), m_playCalled(false)
+{
+ QString filepath = QFileInfo( m_sound->fileName() ).absoluteFilePath();
+ filepath = QDir::toNativeSeparators(filepath);
+ TPtrC filepathPtr(qt_QString2TPtrC(filepath));
+ TRAPD(err, m_playUtility = CMdaAudioPlayerUtility::NewL(*this);
+ m_playUtility->OpenFileL(filepathPtr));
+ if(err){
+ m_server->playCompleted(this, err);
+ }
+}
+
+void QAuBucketS60::play()
+{
+ if(m_prepared) {
+ // OpenFileL call is completed we can start playing immediately
+ m_playUtility->Play();
+ } else {
+ m_playCalled = true;
+ }
+
+}
+
+void QAuBucketS60::stop()
+{
+ m_playCalled = false;
+ m_playUtility->Stop();
+}
+
+void QAuBucketS60::MapcPlayComplete(TInt aError)
+{
+ m_server->playCompleted(this, aError);
+}
+
+void QAuBucketS60::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& /*aDuration*/)
+{
+ if(aError) {
+ m_server->playCompleted(this, aError);
+ } else {
+ m_prepared = true;
+ if(m_playCalled){
+ play();
+ }
+ }
+}
+
+QAuBucketS60::~QAuBucketS60()
+{
+ if(m_playUtility){
+ m_playUtility->Stop();
+ m_playUtility->Close();
+ }
+
+ delete m_playUtility;
+}
+
+
+#endif // QT_NO_SOUND
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qsound_win.cpp b/src/gui/kernel/qsound_win.cpp
index b5fe123..d998868 100644
--- a/src/gui/kernel/qsound_win.cpp
+++ b/src/gui/kernel/qsound_win.cpp
@@ -77,13 +77,8 @@ public:
QAuServerWindows::QAuServerWindows(QObject* parent) :
QAuServer(parent), current(0)
{
- QT_WA({
- mutex = CreateMutexW(0, 0, 0);
- event = CreateEventW(0, FALSE, FALSE, 0);
- } , {
- mutex = CreateMutexA(0, 0, 0);
- event = CreateEventA(0, FALSE, FALSE, 0);
- });
+ mutex = CreateMutex(0, 0, 0);
+ event = CreateEvent(0, FALSE, FALSE, 0);
}
QAuServerWindows::~QAuServerWindows()
@@ -133,13 +128,9 @@ DWORD WINAPI SoundPlayProc(LPVOID param)
if (loops == -1)
flags |= SND_LOOP;
- QT_WA({
- PlaySoundW((TCHAR*)filename.utf16(), 0, flags);
- } , {
- PlaySoundA(QFile::encodeName(filename).data(), 0, flags);
- });
- if (sound && loops == 1)
- server->decLoop(sound);
+ PlaySound((wchar_t*)filename.utf16(), 0, flags);
+ if (sound && loops == 1)
+ server->decLoop(sound);
// GUI thread continues, but we are done as well.
SetEvent(event);
@@ -148,18 +139,13 @@ DWORD WINAPI SoundPlayProc(LPVOID param)
QPointer<QSound> guarded_sound = sound;
SetEvent(event);
- for (int l = 0; l < loops && server->current; ++l) {
- QT_WA( {
- PlaySoundW( (TCHAR*)filename.utf16(), 0, SND_FILENAME|SND_SYNC );
- } , {
- PlaySoundA( QFile::encodeName(filename).data(), 0,
- SND_FILENAME|SND_SYNC );
- } );
-
- if (guarded_sound)
- server->decLoop(guarded_sound);
- }
- server->current = 0;
+ for (int l = 0; l < loops && server->current; ++l) {
+ PlaySound((wchar_t*)filename.utf16(), 0, SND_FILENAME | SND_SYNC);
+
+ if (guarded_sound)
+ server->decLoop(guarded_sound);
+ }
+ server->current = 0;
}
ReleaseMutex(mutex);
@@ -169,7 +155,7 @@ DWORD WINAPI SoundPlayProc(LPVOID param)
void QAuServerWindows::playHelper(const QString &filename, int loop, QSound *snd)
{
if (loop == 0)
- return;
+ return;
// busy?
if (WaitForSingleObject(mutex, 0) == WAIT_TIMEOUT)
return;
diff --git a/src/gui/kernel/qstackedlayout.cpp b/src/gui/kernel/qstackedlayout.cpp
index 732f2ce..e489c66 100644
--- a/src/gui/kernel/qstackedlayout.cpp
+++ b/src/gui/kernel/qstackedlayout.cpp
@@ -65,8 +65,6 @@ public:
only one widget is visible at a time.
\ingroup geomanagement
- \ingroup appearance
- \mainclass
QStackedLayout can be used to create a user interface similar to
the one provided by QTabWidget. There is also a convenience
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp
new file mode 100644
index 0000000..de6e7c7
--- /dev/null
+++ b/src/gui/kernel/qstandardgestures.cpp
@@ -0,0 +1,624 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstandardgestures.h"
+#include "qstandardgestures_p.h"
+
+#include <qabstractscrollarea.h>
+#include <qscrollbar.h>
+#include <private/qapplication_p.h>
+#include <private/qevent_p.h>
+#include <private/qwidget_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_WS_WIN
+QWidgetPrivate *qt_widget_private(QWidget *widget);
+#endif
+
+/*!
+ \class QPanGesture
+ \since 4.6
+
+ \brief The QPanGesture class represents a Pan gesture,
+ providing additional information related to panning.
+*/
+
+/*!
+ Creates a new Pan gesture handler object and marks it as a child of \a
+ parent.
+
+ On some platform like Windows it's necessary to provide a non-null widget
+ as \a parent to get native gesture support.
+*/
+QPanGesture::QPanGesture(QWidget *gestureTarget, QObject *parent)
+ : QGesture(*new QPanGesturePrivate, gestureTarget, parent)
+{
+ setObjectName(QLatin1String("QPanGesture"));
+}
+
+void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
+{
+ Q_Q(QPanGesture);
+ if (gestureTarget && gestureTarget->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(gestureTarget.data());
+ QApplicationPrivate::instance()->widgetGestures[w].pan = 0;
+#if defined(Q_WS_WIN)
+ qt_widget_private(w)->winSetupGestures();
+#elif defined(Q_WS_MAC)
+ w->setAttribute(Qt::WA_AcceptTouchEvents, false);
+ w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents, false);
+#endif
+ }
+
+ if (newGestureTarget && newGestureTarget->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(newGestureTarget);
+ QApplicationPrivate::instance()->widgetGestures[w].pan = q;
+#if defined(Q_WS_WIN)
+ qt_widget_private(w)->winSetupGestures();
+#elif defined(Q_WS_MAC)
+ w->setAttribute(Qt::WA_AcceptTouchEvents);
+ w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
+#endif
+ }
+ QGesturePrivate::setupGestureTarget(newGestureTarget);
+}
+
+/*! \internal */
+bool QPanGesture::event(QEvent *event)
+{
+#if defined(QT_MAC_USE_COCOA)
+ Q_D(QPanGesture);
+ if (event->type() == QEvent::Timer) {
+ const QTimerEvent *te = static_cast<QTimerEvent *>(event);
+ if (te->timerId() == d->singleTouchPanTimer.timerId()) {
+ d->singleTouchPanTimer.stop();
+ updateState(Qt::GestureStarted);
+ }
+ }
+#endif
+
+ return QObject::event(event);
+}
+
+bool QPanGesture::eventFilter(QObject *receiver, QEvent *event)
+{
+#ifdef Q_WS_WIN
+ Q_D(QPanGesture);
+ if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) {
+ QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
+ QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
+ QApplicationPrivate::WidgetStandardGesturesMap::iterator it;
+ it = qAppPriv->widgetGestures.find(static_cast<QWidget*>(receiver));
+ if (it == qAppPriv->widgetGestures.end())
+ return false;
+ if (this != it.value().pan)
+ return false;
+ Qt::GestureState nextState = Qt::NoGesture;
+ switch(ev->gestureType) {
+ case QNativeGestureEvent::GestureBegin:
+ // next we might receive the first gesture update event, so we
+ // prepare for it.
+ d->state = Qt::NoGesture;
+ return false;
+ case QNativeGestureEvent::Pan:
+ nextState = Qt::GestureUpdated;
+ event->accept();
+ break;
+ case QNativeGestureEvent::GestureEnd:
+ if (state() == Qt::NoGesture)
+ return false; // some other gesture has ended
+ nextState = Qt::GestureFinished;
+ break;
+ default:
+ return false;
+ }
+ if (state() == Qt::NoGesture) {
+ d->lastOffset = d->totalOffset = QSize();
+ } else {
+ d->lastOffset = QSize(ev->position.x() - d->lastPosition.x(),
+ ev->position.y() - d->lastPosition.y());
+ d->totalOffset += d->lastOffset;
+ }
+ d->lastPosition = ev->position;
+ updateState(nextState);
+ return true;
+ }
+#endif
+ return QGesture::eventFilter(receiver, event);
+}
+
+/*! \internal */
+bool QPanGesture::filterEvent(QEvent *event)
+{
+#if defined(Q_WS_WIN)
+ Q_D(QPanGesture);
+ const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
+
+ if (event->type() == QEvent::TouchBegin) {
+ QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
+ d->lastPosition = p.pos().toPoint();
+ d->lastOffset = d->totalOffset = QSize();
+ } else if (event->type() == QEvent::TouchEnd) {
+ if (state() != Qt::NoGesture) {
+ if (ev->touchPoints().size() == 2) {
+ QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
+ QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ d->lastOffset =
+ QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(),
+ p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2;
+ d->totalOffset += d->lastOffset;
+ }
+ updateState(Qt::GestureFinished);
+ }
+ reset();
+ } else if (event->type() == QEvent::TouchUpdate) {
+ if (ev->touchPoints().size() == 2) {
+ QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
+ QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ d->lastOffset =
+ QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(),
+ p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2;
+ d->totalOffset += d->lastOffset;
+ if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 ||
+ d->totalOffset.width() < -10 || d->totalOffset.height() < -10) {
+ updateState(Qt::GestureUpdated);
+ }
+ }
+ }
+#elif defined(QT_MAC_USE_COCOA)
+ // The following implements single touch
+ // panning on Mac:
+ Q_D(QPanGesture);
+ const int panBeginDelay = 300;
+ const int panBeginRadius = 3;
+ const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
+
+ switch (event->type()) {
+ case QEvent::TouchBegin: {
+ if (ev->touchPoints().size() == 1) {
+ d->lastPosition = QCursor::pos();
+ d->singleTouchPanTimer.start(panBeginDelay, this);
+ }
+ break;}
+ case QEvent::TouchEnd: {
+ if (state() != Qt::NoGesture)
+ updateState(Qt::GestureFinished);
+ reset();
+ break;}
+ case QEvent::TouchUpdate: {
+ if (ev->touchPoints().size() == 1) {
+ if (state() == Qt::NoGesture) {
+ // INVARIANT: The singleTouchTimer has still not fired.
+ // Lets check if the user moved his finger so much from
+ // the starting point that it makes sense to cancel:
+ const QPointF startPos = ev->touchPoints().at(0).startPos().toPoint();
+ const QPointF p = ev->touchPoints().at(0).pos().toPoint();
+ if ((startPos - p).manhattanLength() > panBeginRadius)
+ reset();
+ else
+ d->lastPosition = QCursor::pos();
+ } else {
+ QPointF mousePos = QCursor::pos();
+ QPointF dist = mousePos - d->lastPosition;
+ d->lastPosition = mousePos;
+ d->lastOffset = QSizeF(dist.x(), dist.y());
+ d->totalOffset += d->lastOffset;
+ updateState(Qt::GestureUpdated);
+ }
+ } else if (state() == Qt::NoGesture) {
+ reset();
+ }
+ break;}
+ default:
+ return false;
+ }
+#else
+ Q_UNUSED(event);
+#endif
+ return false;
+}
+
+/*! \internal */
+void QPanGesture::reset()
+{
+ Q_D(QPanGesture);
+ d->lastOffset = d->totalOffset = QSize(0, 0);
+ d->lastPosition = QPoint(0, 0);
+
+#if defined(QT_MAC_USE_COCOA)
+ d->singleTouchPanTimer.stop();
+ d->prevMousePos = QPointF(0, 0);
+#endif
+
+ QGesture::reset();
+}
+
+/*!
+ \property QPanGesture::totalOffset
+
+ Specifies a total pan offset since the start of the gesture.
+*/
+QSizeF QPanGesture::totalOffset() const
+{
+ Q_D(const QPanGesture);
+ return d->totalOffset;
+}
+
+/*!
+ \property QPanGesture::lastOffset
+
+ Specifies a pan offset since the last time the gesture was
+ triggered.
+*/
+QSizeF QPanGesture::lastOffset() const
+{
+ Q_D(const QPanGesture);
+ return d->lastOffset;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \class QPinchGesture
+ \since 4.6
+
+ \brief The QPinchGesture class represents a Pinch gesture,
+ providing additional information related to zooming and/or rotation.
+*/
+
+/*!
+ Creates a new Pinch gesture handler object and marks it as a child of \a
+ parent.
+
+ On some platform like Windows it's necessary to provide a non-null widget
+ as \a parent to get native gesture support.
+*/
+QPinchGesture::QPinchGesture(QWidget *gestureTarget, QObject *parent)
+ : QGesture(*new QPinchGesturePrivate, gestureTarget, parent)
+{
+ setObjectName(QLatin1String("QPinchGesture"));
+}
+
+void QPinchGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
+{
+ Q_Q(QPinchGesture);
+ if (gestureTarget && gestureTarget->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(gestureTarget.data());
+ QApplicationPrivate::instance()->widgetGestures[w].pinch = 0;
+#ifdef Q_WS_WIN
+ qt_widget_private(w)->winSetupGestures();
+#endif
+ }
+
+ if (newGestureTarget && newGestureTarget->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(newGestureTarget);
+ QApplicationPrivate::instance()->widgetGestures[w].pinch = q;
+#ifdef Q_WS_WIN
+ qt_widget_private(w)->winSetupGestures();
+#endif
+ }
+ QGesturePrivate::setupGestureTarget(newGestureTarget);
+}
+
+/*! \internal */
+bool QPinchGesture::event(QEvent *event)
+{
+ return QObject::event(event);
+}
+
+bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event)
+{
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+ Q_D(QPinchGesture);
+ if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) {
+ QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
+#if defined(Q_WS_WIN)
+ QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
+ QApplicationPrivate::WidgetStandardGesturesMap::iterator it;
+ it = qAppPriv->widgetGestures.find(static_cast<QWidget*>(receiver));
+ if (it == qAppPriv->widgetGestures.end())
+ return false;
+ if (this != it.value().pinch)
+ return false;
+#endif
+ Qt::GestureState nextState = Qt::NoGesture;
+
+ switch(ev->gestureType) {
+ case QNativeGestureEvent::GestureBegin:
+ // next we might receive the first gesture update event, so we
+ // prepare for it.
+ d->state = Qt::NoGesture;
+ d->scaleFactor = d->lastScaleFactor = 1;
+ d->rotationAngle = d->lastRotationAngle = 0;
+ d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF();
+#if defined(Q_WS_WIN)
+ d->initialDistance = 0;
+#endif
+ return false;
+ case QNativeGestureEvent::Rotate:
+ d->scaleFactor = 0;
+ d->lastRotationAngle = d->rotationAngle;
+#if defined(Q_WS_WIN)
+ d->rotationAngle = -1 * GID_ROTATE_ANGLE_FROM_ARGUMENT(ev->argument);
+#elif defined(Q_WS_MAC)
+ d->rotationAngle = ev->percentage;
+#endif
+ nextState = Qt::GestureUpdated;
+ event->accept();
+ break;
+ case QNativeGestureEvent::Zoom:
+ d->rotationAngle = 0;
+#if defined(Q_WS_WIN)
+ if (d->initialDistance != 0) {
+ d->lastScaleFactor = d->scaleFactor;
+ int distance = int(qint64(ev->argument));
+ d->scaleFactor = (qreal) distance / d->initialDistance;
+ } else {
+ d->initialDistance = int(qint64(ev->argument));
+ }
+#elif defined(Q_WS_MAC)
+ d->lastScaleFactor = d->scaleFactor;
+ d->scaleFactor = ev->percentage;
+#endif
+ nextState = Qt::GestureUpdated;
+ event->accept();
+ break;
+ case QNativeGestureEvent::GestureEnd:
+ if (state() == Qt::NoGesture)
+ return false; // some other gesture has ended
+ nextState = Qt::GestureFinished;
+ break;
+ default:
+ return false;
+ }
+ if (d->startCenterPoint.isNull())
+ d->startCenterPoint = d->centerPoint;
+ d->lastCenterPoint = d->centerPoint;
+ d->centerPoint = static_cast<QWidget*>(receiver)->mapFromGlobal(ev->position);
+ updateState(nextState);
+ return true;
+ }
+#endif
+ return QGesture::eventFilter(receiver, event);
+}
+
+
+/*! \internal */
+bool QPinchGesture::filterEvent(QEvent *event)
+{
+ Q_UNUSED(event);
+ return false;
+}
+
+/*! \internal */
+void QPinchGesture::reset()
+{
+ Q_D(QPinchGesture);
+ d->scaleFactor = d->lastScaleFactor = 0;
+ d->rotationAngle = d->lastRotationAngle = 0;
+ d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF();
+ QGesture::reset();
+}
+
+/*!
+ \property QPinchGesture::scaleFactor
+
+ Specifies a scale factor of the pinch gesture.
+*/
+qreal QPinchGesture::scaleFactor() const
+{
+ return d_func()->scaleFactor;
+}
+
+/*!
+ \property QPinchGesture::lastScaleFactor
+
+ Specifies a previous scale factor of the pinch gesture.
+*/
+qreal QPinchGesture::lastScaleFactor() const
+{
+ return d_func()->lastScaleFactor;
+}
+
+/*!
+ \property QPinchGesture::rotationAngle
+
+ Specifies a rotation angle of the gesture.
+*/
+qreal QPinchGesture::rotationAngle() const
+{
+ return d_func()->rotationAngle;
+}
+
+/*!
+ \property QPinchGesture::lastRotationAngle
+
+ Specifies a previous rotation angle of the gesture.
+*/
+qreal QPinchGesture::lastRotationAngle() const
+{
+ return d_func()->lastRotationAngle;
+}
+
+/*!
+ \property QPinchGesture::centerPoint
+
+ Specifies a center point of the gesture. The point can be used as a center
+ point that the object is rotated around.
+*/
+QPointF QPinchGesture::centerPoint() const
+{
+ return d_func()->centerPoint;
+}
+
+/*!
+ \property QPinchGesture::lastCenterPoint
+
+ Specifies a previous center point of the gesture.
+*/
+QPointF QPinchGesture::lastCenterPoint() const
+{
+ return d_func()->lastCenterPoint;
+}
+
+/*!
+ \property QPinchGesture::startCenterPoint
+
+ Specifies an initial center point of the gesture. Difference between the
+ startCenterPoint and the centerPoint is the distance at which pinching
+ fingers has shifted.
+*/
+QPointF QPinchGesture::startCenterPoint() const
+{
+ return d_func()->startCenterPoint;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \class QSwipeGesture
+ \since 4.6
+
+ \brief The QSwipeGesture class represents a swipe gesture,
+ providing additional information related to swiping.
+*/
+
+/*!
+ Creates a new Swipe gesture handler object and marks it as a child of \a
+ parent.
+
+ On some platform like Windows it's necessary to provide a non-null widget
+ as \a parent to get native gesture support.
+*/
+QSwipeGesture::QSwipeGesture(QWidget *gestureTarget, QObject *parent)
+ : QGesture(*new QSwipeGesturePrivate, gestureTarget, parent)
+{
+ setObjectName(QLatin1String("QSwipeGesture"));
+}
+
+void QSwipeGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
+{
+ Q_Q(QSwipeGesture);
+ if (gestureTarget && gestureTarget->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(gestureTarget.data());
+ QApplicationPrivate::instance()->widgetGestures[w].swipe = 0;
+#if defined(Q_WS_WIN)
+ qt_widget_private(w)->winSetupGestures();
+#endif
+ }
+
+ if (newGestureTarget && newGestureTarget->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(newGestureTarget);
+ QApplicationPrivate::instance()->widgetGestures[w].swipe = q;
+#if defined(Q_WS_WIN)
+ qt_widget_private(w)->winSetupGestures();
+#endif
+ }
+ QGesturePrivate::setupGestureTarget(newGestureTarget);
+}
+
+qreal QSwipeGesture::swipeAngle() const
+{
+ Q_D(const QSwipeGesture);
+ return d->swipeAngle;
+}
+
+QSwipeGesture::SwipeDirection QSwipeGesture::horizontalDirection() const
+{
+ Q_D(const QSwipeGesture);
+ if (d->swipeAngle < 0 || d->swipeAngle == 90 || d->swipeAngle == 270)
+ return QSwipeGesture::NoDirection;
+ else if (d->swipeAngle < 90 || d->swipeAngle > 270)
+ return QSwipeGesture::Right;
+ else
+ return QSwipeGesture::Left;
+}
+
+QSwipeGesture::SwipeDirection QSwipeGesture::verticalDirection() const
+{
+ Q_D(const QSwipeGesture);
+ if (d->swipeAngle <= 0 || d->swipeAngle == 180)
+ return QSwipeGesture::NoDirection;
+ else if (d->swipeAngle < 180)
+ return QSwipeGesture::Up;
+ else
+ return QSwipeGesture::Down;
+}
+
+bool QSwipeGesture::eventFilter(QObject *receiver, QEvent *event)
+{
+ Q_D(QSwipeGesture);
+ if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) {
+ QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
+ switch (ev->gestureType) {
+ case QNativeGestureEvent::Swipe:
+ d->swipeAngle = ev->angle;
+ updateState(Qt::GestureStarted);
+ updateState(Qt::GestureUpdated);
+ updateState(Qt::GestureFinished);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+ return QGesture::eventFilter(receiver, event);
+}
+
+/*! \internal */
+bool QSwipeGesture::filterEvent(QEvent *)
+{
+ return false;
+}
+
+/*! \internal */
+void QSwipeGesture::reset()
+{
+ Q_D(QSwipeGesture);
+ d->swipeAngle = -1;
+ QGesture::reset();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qstandardgestures.cpp"
+
diff --git a/src/gui/kernel/qstandardgestures.h b/src/gui/kernel/qstandardgestures.h
new file mode 100644
index 0000000..029e6dc
--- /dev/null
+++ b/src/gui/kernel/qstandardgestures.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTANDARDGESTURES_H
+#define QSTANDARDGESTURES_H
+
+#include <QtGui/qevent.h>
+#include <QtCore/qbasictimer.h>
+
+#include <QtGui/qgesture.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPanGesturePrivate;
+class Q_GUI_EXPORT QPanGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPanGesture)
+
+ Q_PROPERTY(QSizeF totalOffset READ totalOffset)
+ Q_PROPERTY(QSizeF lastOffset READ lastOffset)
+
+public:
+ QPanGesture(QWidget *gestureTarget, QObject *parent = 0);
+
+ bool filterEvent(QEvent *event);
+
+ QSizeF totalOffset() const;
+ QSizeF lastOffset() const;
+
+protected:
+ void reset();
+
+private:
+ bool event(QEvent *event);
+ bool eventFilter(QObject *receiver, QEvent *event);
+
+ friend class QWidget;
+};
+
+class QPinchGesturePrivate;
+class Q_GUI_EXPORT QPinchGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPinchGesture)
+
+ Q_PROPERTY(qreal scaleFactor READ scaleFactor)
+ Q_PROPERTY(qreal lastScaleFactor READ lastScaleFactor)
+
+ Q_PROPERTY(qreal rotationAngle READ rotationAngle)
+ Q_PROPERTY(qreal lastRotationAngle READ lastRotationAngle)
+
+ Q_PROPERTY(QPointF startCenterPoint READ startCenterPoint)
+ Q_PROPERTY(QPointF lastCenterPoint READ lastCenterPoint)
+ Q_PROPERTY(QPointF centerPoint READ centerPoint)
+
+public:
+ QPinchGesture(QWidget *gestureTarget, QObject *parent = 0);
+
+ bool filterEvent(QEvent *event);
+ void reset();
+
+ QPointF startCenterPoint() const;
+ QPointF lastCenterPoint() const;
+ QPointF centerPoint() const;
+
+ qreal scaleFactor() const;
+ qreal lastScaleFactor() const;
+
+ qreal rotationAngle() const;
+ qreal lastRotationAngle() const;
+
+private:
+ bool event(QEvent *event);
+ bool eventFilter(QObject *receiver, QEvent *event);
+
+ friend class QWidget;
+};
+
+class QSwipeGesturePrivate;
+class Q_GUI_EXPORT QSwipeGesture : public QGesture
+{
+ Q_OBJECT
+ Q_ENUMS(SwipeDirection)
+
+ Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection)
+ Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection)
+ Q_PROPERTY(qreal swipeAngle READ swipeAngle)
+
+ Q_DECLARE_PRIVATE(QSwipeGesture)
+
+public:
+ enum SwipeDirection { NoDirection, Left, Right, Up, Down };
+ QSwipeGesture(QWidget *gestureTarget, QObject *parent = 0);
+
+ bool filterEvent(QEvent *event);
+ void reset();
+
+ SwipeDirection horizontalDirection() const;
+ SwipeDirection verticalDirection() const;
+ qreal swipeAngle() const;
+
+private:
+ bool eventFilter(QObject *receiver, QEvent *event);
+
+ friend class QWidget;
+};
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSTANDARDGESTURES_H
diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h
new file mode 100644
index 0000000..9829cf0
--- /dev/null
+++ b/src/gui/kernel/qstandardgestures_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTANDARDGESTURES_P_H
+#define QSTANDARDGESTURES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qevent.h"
+#include "qbasictimer.h"
+#include "qdebug.h"
+
+#include "qgesture.h"
+#include "qgesture_p.h"
+
+#include "qstandardgestures.h"
+#include "qbasictimer.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPanGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QPanGesture)
+
+public:
+ void setupGestureTarget(QObject *o);
+
+ QSizeF totalOffset;
+ QSizeF lastOffset;
+ QPointF lastPosition;
+
+#if defined(QT_MAC_USE_COCOA)
+ QBasicTimer singleTouchPanTimer;
+ QPointF prevMousePos;
+#endif
+};
+
+class QPinchGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QPinchGesture)
+
+public:
+ QPinchGesturePrivate()
+ : scaleFactor(0), lastScaleFactor(0),
+ rotationAngle(0), lastRotationAngle(0)
+#ifdef Q_WS_WIN
+ ,initialDistance(0)
+#endif
+ {
+ }
+
+ void setupGestureTarget(QObject *o);
+
+ qreal scaleFactor;
+ qreal lastScaleFactor;
+ qreal rotationAngle;
+ qreal lastRotationAngle;
+ QPointF startCenterPoint;
+ QPointF lastCenterPoint;
+ QPointF centerPoint;
+#ifdef Q_WS_WIN
+ int initialDistance;
+#endif
+};
+
+class QSwipeGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QSwipeGesture)
+
+public:
+ QSwipeGesturePrivate()
+ : swipeAngle(-1)
+ {
+ }
+
+ void setupGestureTarget(QObject *o);
+ qreal swipeAngle;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSTANDARDGESTURES_P_H
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index 2bffdf8..1129818 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -74,9 +74,11 @@
****************************************************************************/
#include <private/qcore_mac_p.h>
+#include <qaction.h>
#include <qwidget.h>
#include <qdesktopwidget.h>
#include <qevent.h>
+#include <qpixmapcache.h>
#include <private/qevent_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
#include <private/qt_mac_p.h>
@@ -88,6 +90,52 @@
QT_BEGIN_NAMESPACE
+Q_GLOBAL_STATIC(QMacWindowFader, macwindowFader);
+
+QMacWindowFader::QMacWindowFader()
+ : m_duration(0.250)
+{
+}
+
+QMacWindowFader *QMacWindowFader::currentFader()
+{
+ return macwindowFader();
+}
+
+void QMacWindowFader::registerWindowToFade(QWidget *window)
+{
+ m_windowsToFade.append(window);
+}
+
+void QMacWindowFader::performFade()
+{
+ const QWidgetList myWidgetsToFade = m_windowsToFade;
+ const int widgetCount = myWidgetsToFade.count();
+#if QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ [NSAnimationContext beginGrouping];
+ [[NSAnimationContext currentContext] setDuration:NSTimeInterval(m_duration)];
+#endif
+
+ for (int i = 0; i < widgetCount; ++i) {
+ QWidget *widget = m_windowsToFade.at(i);
+ OSWindowRef window = qt_mac_window_for(widget);
+#if QT_MAC_USE_COCOA
+ [[window animator] setAlphaValue:0.0];
+ QTimer::singleShot(qRound(m_duration * 1000), widget, SLOT(hide()));
+#else
+ TransitionWindowOptions options = {0, m_duration, 0, 0};
+ TransitionWindowWithOptions(window, kWindowFadeTransitionEffect, kWindowHideTransitionAction,
+ 0, 1, &options);
+#endif
+ }
+#if QT_MAC_USE_COCOA
+ [NSAnimationContext endGrouping];
+#endif
+ m_duration = 0.250;
+ m_windowsToFade.clear();
+}
+
extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp;
extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
extern QWidget * mac_mouse_grabber;
@@ -95,29 +143,26 @@ extern QWidget * mac_mouse_grabber;
void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds)
{
OSWindowRef wnd = static_cast<OSWindowRef>(window);
- if( wnd ) {
+ if (wnd) {
+ QWidget *widget;
#if QT_MAC_USE_COCOA
- QMacCocoaAutoReleasePool pool;
- [NSAnimationContext beginGrouping];
- [[wnd animator] setAlphaValue:0.0];
- if (durationSeconds > 0) {
- [[NSAnimationContext currentContext] setDuration:NSTimeInterval(durationSeconds)];
- } else {
- durationSeconds = [[NSAnimationContext currentContext] duration];
- }
- [NSAnimationContext endGrouping];
- QTimer::singleShot(qRound(durationSeconds * 1000), [wnd QT_MANGLE_NAMESPACE(qt_qwidget)], SLOT(hide()));
+ widget = [wnd QT_MANGLE_NAMESPACE(qt_qwidget)];
#else
- if (durationSeconds <= 0)
- durationSeconds = 0.15;
- TransitionWindowOptions options = {0, durationSeconds, 0, 0};
- TransitionWindowWithOptions(wnd, kWindowFadeTransitionEffect, kWindowHideTransitionAction, 0, 1, &options);
+ const UInt32 kWidgetCreatorQt = kEventClassQt;
+ enum {
+ kWidgetPropertyQWidget = 'QWId' //QWidget *
+ };
+ if (GetWindowProperty(static_cast<WindowRef>(window), kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(widget), 0, &widget) != noErr)
+ widget = 0;
#endif
- }
+ if (widget) {
+ QMacWindowFader::currentFader()->setFadeDuration(durationSeconds);
+ QMacWindowFader::currentFader()->registerWindowToFade(widget);
+ QMacWindowFader::currentFader()->performFade();
+ }
+ }
}
-
-
bool macWindowIsTextured( void * /*OSWindowRef*/ window )
{
OSWindowRef wnd = static_cast<OSWindowRef>(window);
@@ -134,11 +179,10 @@ void macWindowToolbarShow(const QWidget *widget, bool show )
{
OSWindowRef wnd = qt_mac_window_for(widget);
#if QT_MAC_USE_COCOA
- NSToolbar *toolbar = [wnd toolbar];
- if (toolbar) {
+ if (NSToolbar *toolbar = [wnd toolbar]) {
QMacCocoaAutoReleasePool pool;
if (show != [toolbar isVisible]) {
- [wnd toggleToolbarShown:wnd];
+ [toolbar setVisible:show];
} else {
// The toolbar may be in sync, but we are not, update our framestrut.
qt_widget_private(const_cast<QWidget *>(widget))->updateFrameStrut();
@@ -154,22 +198,21 @@ void macWindowToolbarSet( void * /*OSWindowRef*/ window, void *toolbarRef )
{
OSWindowRef wnd = static_cast<OSWindowRef>(window);
#if QT_MAC_USE_COCOA
- [wnd setToolbar:static_cast<NSToolbar *>(toolbarRef)];
+ [wnd setToolbar:static_cast<NSToolbar *>(toolbarRef)];
#else
SetWindowToolbar(wnd, static_cast<HIToolbarRef>(toolbarRef));
#endif
}
-bool macWindowToolbarVisible( void * /*OSWindowRef*/ window )
+bool macWindowToolbarIsVisible( void * /*OSWindowRef*/ window )
{
OSWindowRef wnd = static_cast<OSWindowRef>(window);
#if QT_MAC_USE_COCOA
- NSToolbar *toolbar = [wnd toolbar];
- if (toolbar)
+ if (NSToolbar *toolbar = [wnd toolbar])
return [toolbar isVisible];
return false;
#else
- return IsWindowToolbarVisible(wnd);
+ return IsWindowToolbarVisible(wnd);
#endif
}
@@ -177,12 +220,12 @@ void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow )
{
OSWindowRef wnd = static_cast<OSWindowRef>(window);
#if QT_MAC_USE_COCOA
- [wnd setHasShadow:BOOL(hasShadow)];
+ [wnd setHasShadow:BOOL(hasShadow)];
#else
- if (hasShadow)
- ChangeWindowAttributes(wnd, 0, kWindowNoShadowAttribute);
- else
- ChangeWindowAttributes(wnd, kWindowNoShadowAttribute, 0);
+ if (hasShadow)
+ ChangeWindowAttributes(wnd, 0, kWindowNoShadowAttribute);
+ else
+ ChangeWindowAttributes(wnd, kWindowNoShadowAttribute, 0);
#endif
}
@@ -190,9 +233,9 @@ void macWindowFlush(void * /*OSWindowRef*/ window)
{
OSWindowRef wnd = static_cast<OSWindowRef>(window);
#if QT_MAC_USE_COCOA
- [wnd flushWindowIfNeeded];
+ [wnd flushWindowIfNeeded];
#else
- HIWindowFlush(wnd);
+ HIWindowFlush(wnd);
#endif
}
@@ -309,6 +352,12 @@ Qt::MouseButton qt_mac_get_button(EventMouseButton button)
return Qt::NoButton;
}
+void macSendToolbarChangeEvent(QWidget *widget)
+{
+ QToolBarChangeEvent ev(!(GetCurrentKeyModifiers() & cmdKey));
+ qt_sendSpontaneousEvent(widget, &ev);
+}
+
Q_GLOBAL_STATIC(QMacTabletHash, tablet_hash)
QMacTabletHash *qt_mac_tablet_hash()
{
@@ -1020,6 +1069,17 @@ void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::H
#endif
}
+void qt_mac_showBaseLineSeparator(void * /*OSWindowRef */window, bool show)
+{
+#if QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ OSWindowRef theWindow = static_cast<OSWindowRef>(window);
+ NSToolbar *macToolbar = [theWindow toolbar];
+ if (macToolbar)
+ [macToolbar setShowsBaselineSeparator: show];
+#endif
+}
+
QStringList qt_mac_NSArrayToQStringList(void *nsarray)
{
QStringList result;
@@ -1079,4 +1139,111 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget)
return context;
}
+CGFloat qt_mac_get_scalefactor()
+{
+#ifndef QT_MAC_USE_COCOA
+ return HIGetScaleFactor();
+#else
+ return [[NSScreen mainScreen] userSpaceScaleFactor];
+#endif
+}
+
+QString qt_mac_get_pasteboardString()
+{
+ QMacCocoaAutoReleasePool pool;
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+ NSString *text = [pb stringForType:NSStringPboardType];
+ if (text) {
+ return qt_mac_NSStringToQString(text);
+ } else {
+ return QString();
+ }
+}
+
+QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height)
+{
+ QPixmap ret(width, height);
+ ret.fill(QColor(0, 0, 0, 0));
+
+ CGRect rect = CGRectMake(0, 0, width, height);
+
+ CGContextRef ctx = qt_mac_cg_context(&ret);
+ CGAffineTransform old_xform = CGContextGetCTM(ctx);
+ CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform));
+ CGContextConcatCTM(ctx, CGAffineTransformIdentity);
+
+ ::RGBColor b;
+ b.blue = b.green = b.red = 255*255;
+ PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon);
+ CGContextRelease(ctx);
+ return ret;
+}
+
+void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayIcon, QIcon *retIcon, QStyle::StandardPixmap standardIcon)
+{
+ int size = 16;
+ while (size <= 128) {
+
+ const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size);
+ QPixmap mainIcon;
+ if (standardIcon >= QStyle::SP_CustomBase) {
+ mainIcon = qt_mac_convert_iconref(icon, size, size);
+ } else if (QPixmapCache::find(cacheKey, mainIcon) == false) {
+ mainIcon = qt_mac_convert_iconref(icon, size, size);
+ QPixmapCache::insert(cacheKey, mainIcon);
+ }
+
+ if (overlayIcon) {
+ int littleSize = size / 2;
+ QPixmap overlayPix = qt_mac_convert_iconref(overlayIcon, littleSize, littleSize);
+ QPainter painter(&mainIcon);
+ painter.drawPixmap(size - littleSize, size - littleSize, overlayPix);
+ }
+
+ retIcon->addPixmap(mainIcon);
+ size += size; // 16 -> 32 -> 64 -> 128
+ }
+}
+
+void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse)
+{
+ OSMenuRef menu = static_cast<OSMenuRef>(theMenu);
+ if (collapse) {
+ bool previousIsSeparator = true; // setting to true kills all the separators placed at the top.
+ NSMenuItem *previousItem = nil;
+
+ NSArray *itemArray = [menu itemArray];
+ for (unsigned int i = 0; i < [itemArray count]; ++i) {
+ NSMenuItem *item = reinterpret_cast<NSMenuItem *>([itemArray objectAtIndex:i]);
+ if ([item isSeparatorItem]) {
+ [item setHidden:previousIsSeparator];
+ }
+
+ if (![item isHidden]) {
+ previousItem = item;
+ previousIsSeparator = ([previousItem isSeparatorItem]);
+ }
+ }
+
+ // We now need to check the final item since we don't want any separators at the end of the list.
+ if (previousItem && previousIsSeparator)
+ [previousItem setHidden:YES];
+ } else {
+ NSArray *itemArray = [menu itemArray];
+ for (unsigned int i = 0; i < [itemArray count]; ++i) {
+ NSMenuItem *item = reinterpret_cast<NSMenuItem *>([itemArray objectAtIndex:i]);
+ if (QAction *action = reinterpret_cast<QAction *>([item tag]))
+ [item setHidden:!action->isVisible()];
+ }
+ }
+}
+
+#ifdef QT_MAC_USE_COCOA
+void qt_cocoaChangeOverrideCursor(const QCursor &cursor)
+{
+ QMacCocoaAutoReleasePool pool;
+ [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set];
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
index 6576c1a..d87a7f8 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h
+++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
@@ -120,10 +120,12 @@ void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0);
bool macWindowIsTextured(void * /*OSWindowRef*/ window);
void macWindowToolbarShow(const QWidget *widget, bool show );
void macWindowToolbarSet( void * /*OSWindowRef*/ window, void* toolbarRef );
-bool macWindowToolbarVisible( void * /*OSWindowRef*/ window );
+bool macWindowToolbarIsVisible( void * /*OSWindowRef*/ window );
void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow );
void macWindowFlush(void * /*OSWindowRef*/ window);
+void macSendToolbarChangeEvent(QWidget *widget);
void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::HIContentBorderMetrics &metrics);
+void qt_mac_showBaseLineSeparator(void * /*OSWindowRef */window, bool show);
void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm);
void qt_mac_update_mouseTracking(QWidget *widget);
OSStatus qt_mac_drawCGImage(CGContextRef cg, const CGRect *inbounds, CGImageRef);
@@ -131,7 +133,9 @@ bool qt_mac_checkForNativeSizeGrip(const QWidget *widget);
void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent);
#ifdef QT_MAC_USE_COCOA
bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent);
+void qt_cocoaChangeOverrideCursor(const QCursor &cursor);
#endif
+void qt_mac_menu_collapseSeparators(void * /*NSMenu */ menu, bool collapse);
bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent);
void qt_dispatchModifiersChanged(void * /*NSEvent * */flagsChangedEvent, QWidget *widgetToGetEvent);
void qt_mac_dispatchNCMouseMessage(void */* NSWindow* */eventWindow, void */* NSEvent* */mouseEvent,
@@ -143,6 +147,9 @@ struct ::TabletProximityRec;
void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec);
Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags);
Qt::KeyboardModifiers qt_cocoaDragOperation2QtModifiers(uint dragOperations);
+QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height);
+void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayIcon, QIcon *retIcon,
+ QStyle::StandardPixmap standardIcon = QStyle::SP_CustomBase);
inline int flipYCoordinate(int y)
{
return QApplication::desktop()->screenGeometry(0).height() - y;
@@ -162,6 +169,9 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list);
void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow);
+CGFloat qt_mac_get_scalefactor();
+QString qt_mac_get_pasteboardString();
+
#ifdef __OBJC__
inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist)
{ return reinterpret_cast<NSMutableArray *>(qt_mac_QStringListToNSMutableArrayVoid(qstrlist)); }
diff --git a/src/gui/kernel/qt_mac.cpp b/src/gui/kernel/qt_mac.cpp
index 6b2bbcb..2b9d073 100644
--- a/src/gui/kernel/qt_mac.cpp
+++ b/src/gui/kernel/qt_mac.cpp
@@ -1,11 +1,11 @@
/****************************************************************************
- **
- ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
- **
- ** This file is part of the QtGui module of the Qt Toolkit.
- **
- ** $QT_BEGIN_LICENSE:LGPL$
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
@@ -36,11 +36,8 @@
**
**
** $QT_END_LICENSE$
- **
- ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- **
- ****************************************************************************/
+**
+****************************************************************************/
#include <private/qt_mac_p.h>
#include <private/qpixmap_mac_p.h>
diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h
index 7ce5ffd..a1b7378 100644
--- a/src/gui/kernel/qt_mac_p.h
+++ b/src/gui/kernel/qt_mac_p.h
@@ -120,6 +120,21 @@ public:
}
};
+// Class for chaining to gether a bunch of fades. It pretty much is only used for qmenu fading.
+class QMacWindowFader
+{
+ QWidgetList m_windowsToFade;
+ float m_duration;
+ Q_DISABLE_COPY(QMacWindowFader)
+public:
+ QMacWindowFader(); // PLEASE DON'T CALL THIS.
+ static QMacWindowFader *currentFader();
+ void registerWindowToFade(QWidget *window);
+ void setFadeDuration(float durationInSecs) { m_duration = durationInSecs; }
+ float fadeDuration() const { return m_duration; }
+ void performFade();
+};
+
class Q_GUI_EXPORT QMacCocoaAutoReleasePool
{
private:
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
new file mode 100644
index 0000000..1523bcf
--- /dev/null
+++ b/src/gui/kernel/qt_s60_p.h
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_S60_P_H
+#define QT_S60_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 "QtGui/qwindowdefs.h"
+#include "private/qcore_symbian_p.h"
+#include "qhash.h"
+#include "qpoint.h"
+#include "QtGui/qfont.h"
+#include "QtGui/qimage.h"
+#include "QtGui/qevent.h"
+#include "qpointer.h"
+#include <w32std.h>
+#include <coecntrl.h>
+#include <eikenv.h>
+#include <eikappui.h>
+
+#ifdef Q_WS_S60
+#include <aknutils.h> // AknLayoutUtils
+#include <avkon.hrh> // EEikStatusPaneUidTitle
+#include <akntitle.h> // CAknTitlePane
+#include <akncontext.h> // CAknContextPane
+#include <eikspane.h> // CEikStatusPane
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// Application internal HandleResourceChangeL events,
+// system evens seems to start with 0x10
+const TInt KInternalStatusPaneChange = 0x50000000;
+
+class QS60Data
+{
+public:
+ TUid uid;
+ int screenDepth;
+ QPoint lastCursorPos;
+ QPoint lastPointerEventPos;
+ QPointer<QWidget> lastPointerEventTarget;
+ QPointer<QWidget> mousePressTarget;
+ int screenWidthInPixels;
+ int screenHeightInPixels;
+ int screenWidthInTwips;
+ int screenHeightInTwips;
+ int defaultDpiX;
+ int defaultDpiY;
+ static inline void updateScreenSize();
+ static inline RWsSession& wsSession();
+ static inline RWindowGroup& windowGroup();
+ static inline CWsScreenDevice* screenDevice();
+ static inline CCoeAppUi* appUi();
+#ifdef Q_WS_S60
+ static inline CEikStatusPane* statusPane();
+ static inline CCoeControl* statusPaneSubPane(TInt aPaneId);
+ static inline CAknTitlePane* titlePane();
+ static inline CAknContextPane* contextPane();
+ static inline CEikButtonGroupContainer* buttonGroupContainer();
+#endif
+};
+
+QS60Data* qGlobalS60Data();
+#define S60 qGlobalS60Data()
+
+class QAbstractLongTapObserver
+{
+public:
+ virtual void HandleLongTapEventL( const TPoint& aPenEventLocation,
+ const TPoint& aPenEventScreenLocation ) = 0;
+};
+class QLongTapTimer;
+
+class QSymbianControl : public CCoeControl, public QAbstractLongTapObserver
+{
+public:
+ DECLARE_TYPE_ID(0x51740000) // Fun fact: the two first values are "Qt" in ASCII.
+
+public:
+ QSymbianControl(QWidget *w);
+ void ConstructL(bool topLevel = false, bool desktop = false);
+ ~QSymbianControl();
+ void HandleResourceChange(int resourceType);
+ void HandlePointerEventL(const TPointerEvent& aPointerEvent);
+ TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+ TCoeInputCapabilities InputCapabilities() const;
+#endif
+ TTypeUid::Ptr MopSupplyObject(TTypeUid id);
+
+ inline QWidget* widget() const { return qwidget; };
+ void setWidget(QWidget *w);
+ void sendInputEvent(QWidget *widget, QInputEvent *inputEvent);
+ void setIgnoreFocusChanged(bool enabled) { m_ignoreFocusChanged = enabled; }
+ void CancelLongTapTimer();
+
+protected:
+ void Draw(const TRect& aRect) const;
+ void SizeChanged();
+ void PositionChanged();
+ void FocusChanged(TDrawNow aDrawNow);
+
+private:
+ void HandlePointerEvent(const TPointerEvent& aPointerEvent);
+ TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType);
+ TKeyResponse sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent);
+ bool sendMouseEvent(QWidget *widget, QMouseEvent *mEvent);
+ void HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation );
+
+private:
+ QWidget *qwidget;
+ bool m_ignoreFocusChanged;
+ QLongTapTimer* m_longTapDetector;
+ bool m_previousEventLongTap;
+};
+
+inline void QS60Data::updateScreenSize()
+{
+ TPixelsTwipsAndRotation params;
+ int mode = S60->screenDevice()->CurrentScreenMode();
+ S60->screenDevice()->GetScreenModeSizeAndRotation(mode, params);
+ S60->screenWidthInPixels = params.iPixelSize.iWidth;
+ S60->screenHeightInPixels = params.iPixelSize.iHeight;
+ S60->screenWidthInTwips = params.iTwipsSize.iWidth;
+ S60->screenHeightInTwips = params.iTwipsSize.iHeight;
+
+ TReal inches = S60->screenHeightInTwips / (TReal)KTwipsPerInch;
+ S60->defaultDpiY = S60->screenHeightInPixels / inches;
+ inches = S60->screenWidthInTwips / (TReal)KTwipsPerInch;
+ S60->defaultDpiX = S60->screenWidthInPixels / inches;
+}
+
+inline RWsSession& QS60Data::wsSession()
+{
+ return CCoeEnv::Static()->WsSession();
+}
+
+inline RWindowGroup& QS60Data::windowGroup()
+{
+ return CCoeEnv::Static()->RootWin();
+}
+
+inline CWsScreenDevice* QS60Data::screenDevice()
+{
+ return CCoeEnv::Static()->ScreenDevice();
+}
+
+inline CCoeAppUi* QS60Data::appUi()
+{
+ return CCoeEnv::Static()-> AppUi();
+}
+
+#ifdef Q_WS_S60
+inline CEikStatusPane* QS60Data::statusPane()
+{
+ return CEikonEnv::Static()->AppUiFactory()->StatusPane();
+}
+
+// Returns the application's status pane control, if not present returns NULL.
+inline CCoeControl* QS60Data::statusPaneSubPane( TInt aPaneId )
+{
+ const TUid paneUid = { aPaneId };
+ CEikStatusPane* statusPane = S60->statusPane();
+ if (statusPane && statusPane->PaneCapabilities(paneUid).IsPresent()) {
+ CCoeControl* control = NULL;
+ // ControlL shouldn't leave because the pane is present
+ TRAPD(err, control = statusPane->ControlL(paneUid));
+ return err != KErrNone ? NULL : control;
+ }
+ return NULL;
+}
+
+// Returns the application's title pane, if not present returns NULL.
+inline CAknTitlePane* QS60Data::titlePane()
+{
+ return static_cast<CAknTitlePane*>(S60->statusPaneSubPane(EEikStatusPaneUidTitle));
+}
+
+// Returns the application's title pane, if not present returns NULL.
+inline CAknContextPane* QS60Data::contextPane()
+{
+ return static_cast<CAknContextPane*>(S60->statusPaneSubPane(EEikStatusPaneUidContext));
+}
+
+inline CEikButtonGroupContainer* QS60Data::buttonGroupContainer()
+{
+ return CEikonEnv::Static()->AppUiFactory()->Cba();
+}
+#endif // Q_WS_S60
+
+static inline QFont qt_TFontSpec2QFontL(const TFontSpec &fontSpec)
+{
+ return QFont(
+ qt_TDesC2QString(fontSpec.iTypeface.iName),
+ fontSpec.iHeight / KTwipsPerPoint,
+ fontSpec.iFontStyle.StrokeWeight() == EStrokeWeightNormal ? QFont::Normal : QFont::Bold,
+ fontSpec.iFontStyle.Posture() == EPostureItalic
+ );
+}
+
+static inline QImage::Format qt_TDisplayMode2Format(TDisplayMode mode)
+{
+ QImage::Format format;
+ switch(mode) {
+ case EGray2:
+ format = QImage::Format_MonoLSB;
+ break;
+ case EColor256:
+ case EGray256:
+ format = QImage::Format_Indexed8;
+ break;
+ case EColor4K:
+ format = QImage::Format_RGB444;
+ break;
+ case EColor64K:
+ format = QImage::Format_RGB16;
+ break;
+ case EColor16M:
+ format = QImage::Format_RGB666;
+ break;
+ case EColor16MU:
+ format = QImage::Format_RGB32;
+ break;
+ case EColor16MA:
+ format = QImage::Format_ARGB32;
+ break;
+#if !defined(__SERIES60_31__) && !defined(__S60_32__)
+ case EColor16MAP:
+ format = QImage::Format_ARGB32_Premultiplied;
+ break;
+#endif
+ default:
+ format = QImage::Format_Invalid;
+ break;
+ }
+ return format;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_S60_P_H
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
index 6e546a4..74cec82 100644
--- a/src/gui/kernel/qt_x11_p.h
+++ b/src/gui/kernel/qt_x11_p.h
@@ -74,11 +74,19 @@
#include <X11/Xutil.h>
#include <X11/Xos.h>
#ifdef index
-# undef index
+# undef index
#endif
#ifdef rindex
-# undef rindex
+# undef rindex
#endif
+#ifdef Q_OS_VXWORS
+# ifdef open
+# undef open
+# endif
+# ifdef getpid
+# undef getpid
+# endif
+#endif // Q_OS_VXWORKS
#include <X11/Xatom.h>
//#define QT_NO_SHAPE
@@ -154,6 +162,10 @@ extern "C" {
# include <X11/extensions/Xrender.h>
#endif // QT_NO_XRENDER
+#ifndef QT_NO_XSYNC
+# include "X11/extensions/sync.h"
+#endif
+
// #define QT_NO_XKB
#ifndef QT_NO_XKB
# include <X11/XKBlib.h>
@@ -502,9 +514,9 @@ struct QX11Data
int fc_hint_style;
char *startupId;
- char *originalStartupId;
- DesktopEnvironment desktopEnvironment;
+ DesktopEnvironment desktopEnvironment : 8;
+ uint desktopVersion : 8; /* Used only for KDE */
/* Warning: if you modify this list, modify the names of atoms in qapplication_x11.cpp as well! */
enum X11Atom {
@@ -514,6 +526,8 @@ struct QX11Data
WM_TAKE_FOCUS,
_NET_WM_PING,
_NET_WM_CONTEXT_HELP,
+ _NET_WM_SYNC_REQUEST,
+ _NET_WM_SYNC_REQUEST_COUNTER,
// ICCCM window state
WM_STATE,
@@ -652,6 +666,10 @@ struct QX11Data
_XEMBED,
_XEMBED_INFO,
+ XWacomStylus,
+ XWacomCursor,
+ XWacomEraser,
+
NPredefinedAtoms,
_QT_SETTINGS_TIMESTAMP = NPredefinedAtoms,
diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp
index 575eb8b..4cc22d5 100644
--- a/src/gui/kernel/qtooltip.cpp
+++ b/src/gui/kernel/qtooltip.cpp
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
widget.
\ingroup helpsystem
- \mainclass
+
The tip is a short piece of text reminding the user of the
widget's function. It is drawn immediately below the given
@@ -126,14 +126,15 @@ public:
bool eventFilter(QObject *, QEvent *);
- QBasicTimer hideTimer;
+ QBasicTimer hideTimer, expireTimer;
+
bool fadingOut;
void reuseTip(const QString &text);
void hideTip();
void hideTipImmediately();
void setTipRect(QWidget *w, const QRect &r);
- void restartHideTimer();
+ void restartExpireTimer();
bool tipChanged(const QPoint &pos, const QString &text, QObject *o);
void placeTip(const QPoint &pos, QWidget *w);
@@ -190,16 +191,17 @@ QTipLabel::QTipLabel(const QString &text, QWidget *w)
reuseTip(text);
}
-void QTipLabel::restartHideTimer()
+void QTipLabel::restartExpireTimer()
{
int time = 10000 + 40 * qMax(0, text().length()-100);
- hideTimer.start(time, this);
+ expireTimer.start(time, this);
+ hideTimer.stop();
}
void QTipLabel::reuseTip(const QString &text)
{
#ifndef QT_NO_STYLE_STYLESHEET
- if (styleSheetParent) {
+ if (styleSheetParent){
disconnect(styleSheetParent, SIGNAL(destroyed()),
QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
styleSheetParent = 0;
@@ -213,7 +215,7 @@ void QTipLabel::reuseTip(const QString &text)
if (fm.descent() == 2 && fm.ascent() >= 11)
++extra.rheight();
resize(sizeHint() + extra);
- restartHideTimer();
+ restartExpireTimer();
}
void QTipLabel::paintEvent(QPaintEvent *ev)
@@ -257,7 +259,8 @@ QTipLabel::~QTipLabel()
void QTipLabel::hideTip()
{
- hideTimer.start(300, this);
+ if (!hideTimer.isActive())
+ hideTimer.start(300, this);
}
void QTipLabel::hideTipImmediately()
@@ -278,8 +281,10 @@ void QTipLabel::setTipRect(QWidget *w, const QRect &r)
void QTipLabel::timerEvent(QTimerEvent *e)
{
- if (e->timerId() == hideTimer.timerId()){
+ if (e->timerId() == hideTimer.timerId()
+ || e->timerId() == expireTimer.timerId()){
hideTimer.stop();
+ expireTimer.stop();
#if defined(Q_WS_MAC) && !defined(QT_NO_EFFECTS)
if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)){
// Fade out tip on mac (makes it invisible).
diff --git a/src/gui/kernel/qwhatsthis.cpp b/src/gui/kernel/qwhatsthis.cpp
index 3e5866a..512200f 100644
--- a/src/gui/kernel/qwhatsthis.cpp
+++ b/src/gui/kernel/qwhatsthis.cpp
@@ -78,7 +78,7 @@ QT_BEGIN_NAMESPACE
widget, i.e. answering the question "What's This?".
\ingroup helpsystem
- \mainclass
+
"What's This?" help is part of an application's online help
system, and provides users with information about the
@@ -226,7 +226,9 @@ QWhatsThat::QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor
text);
}
#if defined(Q_WS_WIN)
- if ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_2000) {
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ {
BOOL shadow;
SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
shadowWidth = shadow ? 0 : 6;
@@ -302,7 +304,9 @@ void QWhatsThat::paintEvent(QPaintEvent*)
{
bool drawShadow = true;
#if defined(Q_WS_WIN)
- if ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_2000) {
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ {
BOOL shadow;
SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0);
drawShadow = !shadow;
@@ -347,6 +351,7 @@ void QWhatsThat::paintEvent(QPaintEvent*)
rect.translate(-r.x(), -r.y());
p.setClipRect(rect);
QAbstractTextDocumentLayout::PaintContext context;
+ context.palette.setBrush(QPalette::Text, context.palette.toolTipText());
doc->documentLayout()->draw(&p, context);
}
else
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 25299a9..ab809df 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -82,6 +82,8 @@
#include "private/qstyle_p.h"
#include "private/qinputcontext_p.h"
#include "qfileinfo.h"
+#include "qstandardgestures.h"
+#include "qstandardgestures_p.h"
#if defined (Q_WS_WIN)
# include <private/qwininputcontext_p.h>
@@ -99,6 +101,10 @@
#endif
#include <private/qpaintengine_raster_p.h>
+#if defined(Q_OS_SYMBIAN)
+#include "private/qt_s60_p.h"
+#endif
+
#include "qwidget_p.h"
#include "qaction_p.h"
#include "qlayout_p.h"
@@ -107,6 +113,7 @@
#include "private/qgraphicsproxywidget_p.h"
#include "QtGui/qabstractscrollarea.h"
#include "private/qabstractscrollarea_p.h"
+#include "private/qevent_p.h"
#include "private/qgraphicssystem_p.h"
@@ -167,39 +174,52 @@ static inline bool bypassGraphicsProxyWidget(QWidget *p)
extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
-QWidgetPrivate::QWidgetPrivate(int version) :
- QObjectPrivate(version), extra(0), focus_child(0)
- ,layout(0), widgetItem(0)
- ,leftmargin(0), topmargin(0), rightmargin(0), bottommargin(0)
- ,leftLayoutItemMargin(0), topLayoutItemMargin(0), rightLayoutItemMargin(0)
- ,bottomLayoutItemMargin(0)
- ,fg_role(QPalette::NoRole)
- ,bg_role(QPalette::NoRole)
- ,hd(0)
- ,dirty(0)
- ,needsFlush(0)
- ,dirtyOpaqueChildren(1)
- ,isOpaque(0)
- ,inDirtyList(0)
- ,isScrolled(0)
- ,isMoved(0)
- ,usesDoubleBufferedGLContext(0)
-#ifdef Q_WS_WIN
- ,noPaintOnScreen(0)
-#endif
- ,inheritedFontResolveMask(0)
- ,inheritedPaletteResolveMask(0)
+QWidgetPrivate::QWidgetPrivate(int version)
+ : QObjectPrivate(version)
+ , extra(0)
+ , focus_next(0)
+ , focus_prev(0)
+ , focus_child(0)
+ , layout(0)
+ , needsFlush(0)
+ , redirectDev(0)
+ , widgetItem(0)
+ , extraPaintEngine(0)
+ , polished(0)
+ , graphicsEffect(0)
+#if !defined(QT_NO_IM)
+ , imHints(Qt::ImhNone)
+#endif
+ , inheritedFontResolveMask(0)
+ , inheritedPaletteResolveMask(0)
+ , leftmargin(0)
+ , topmargin(0)
+ , rightmargin(0)
+ , bottommargin(0)
+ , leftLayoutItemMargin(0)
+ , topLayoutItemMargin(0)
+ , rightLayoutItemMargin(0)
+ , bottomLayoutItemMargin(0)
+ , hd(0)
+ , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
+ , fg_role(QPalette::NoRole)
+ , bg_role(QPalette::NoRole)
+ , dirtyOpaqueChildren(1)
+ , isOpaque(0)
+ , inDirtyList(0)
+ , isScrolled(0)
+ , isMoved(0)
+ , usesDoubleBufferedGLContext(0)
#if defined(Q_WS_X11)
- ,picture(0)
-#endif
-#ifdef Q_WS_MAC
- ,needWindowChange(0)
- ,isGLWidget(0)
+ , picture(0)
+#elif defined(Q_WS_WIN)
+ , noPaintOnScreen(0)
+#elif defined(Q_WS_MAC)
+ , needWindowChange(0)
+ , isGLWidget(0)
+ , window_event(0)
+ , qd_hd(0)
#endif
- ,polished(0)
-
- , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
- , redirectDev(0)
{
if (!qApp) {
qFatal("QWidget: Must construct a QApplication before a QPaintDevice");
@@ -225,6 +245,8 @@ QWidgetPrivate::~QWidgetPrivate()
if (extra)
deleteExtra();
+
+ delete graphicsEffect;
}
QWindowSurface *QWidgetPrivate::createDefaultWindowSurface()
@@ -390,6 +412,7 @@ void QWidget::setEditFocus(bool on)
QApplication::sendEvent(f, &event);
QApplication::sendEvent(f->style(), &event);
}
+ f->repaint(); // Widget might want to repaint a focus indicator
}
#endif
@@ -442,7 +465,7 @@ void QWidget::setAutoFillBackground(bool enabled)
\brief The QWidget class is the base class of all user interface objects.
\ingroup basicwidgets
- \mainclass
+
The widget is the atom of the user interface: it receives mouse, keyboard
and other events from the window system, and paints a representation of
@@ -493,7 +516,7 @@ void QWidget::setAutoFillBackground(bool enabled)
been outlined to indicate their full sizes.
If you want to use a QWidget to hold child widgets you will usually want to
- add a layout to the parent QWidget. See \l{Layout Classes} for more
+ add a layout to the parent QWidget. See \l{Layout Management} for more
information.
@@ -851,8 +874,8 @@ void QWidget::setAutoFillBackground(bool enabled)
\list
\o X11: This feature relies on the use of an X server that supports ARGB visuals
and a compositing window manager.
- \o Windows: This feature requires Windows 2000 or later. The widget needs to have
- the Qt::FramelessWindowHint window flag set for the translucency to work.
+ \o Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
+ for the translucency to work.
\endlist
@@ -878,10 +901,34 @@ void QWidget::setAutoFillBackground(bool enabled)
\endlist
\sa QEvent, QPainter, QGridLayout, QBoxLayout
+
+ \section1 SoftKeys
+ \since 4.6
+ \preliminary
+
+ Softkeys API is a platform independent way of mapping actions to (hardware)keys
+ and toolbars provided by the underlying platform.
+
+ There are three major use cases supported. First one is a mobile device
+ with keypad navigation and no touch ui. Second use case is a mobile
+ device with touch ui. Third use case is desktop. For now the softkey API is
+ only implemented for Series60.
+
+ QActions are set to widget(s) via softkey API. Actions in focused widget are
+ mapped to native toolbar or hardware keys. Even though the API allows to set
+ any amount of widgets there might be physical restrictions to amount of
+ softkeys that can be used by the device.
+
+ \o Series60: For series60 menu button is automatically mapped to left
+ soft key if there is QMainWindow with QMenuBar in widgets parent hierarchy.
+
+ \sa softKeys()
+ \sa setSoftKey()
+
*/
-QWidgetMapper *QWidgetPrivate::mapper = 0; // widget with wid
-QWidgetSet *QWidgetPrivate::uncreatedWidgets = 0; // widgets with no wid
+QWidgetMapper *QWidgetPrivate::mapper = 0; // widget with wid
+QWidgetSet *QWidgetPrivate::allWidgets = 0; // widgets with no wid
/*****************************************************************************
@@ -921,6 +968,26 @@ QRegion qt_dirtyRegion(QWidget *widget)
\endlist
*/
+struct QWidgetExceptionCleaner
+{
+ /* this cleans up when the constructor throws an exception */
+ static inline void cleanup(QWidget *that, QWidgetPrivate *d)
+ {
+#ifdef QT_NO_EXCEPTIONS
+ Q_UNUSED(that);
+ Q_UNUSED(d);
+#else
+ QWidgetPrivate::allWidgets->remove(that);
+ if (d->focus_next != that) {
+ if (d->focus_next)
+ d->focus_next->d_func()->focus_prev = d->focus_prev;
+ if (d->focus_prev)
+ d->focus_prev->d_func()->focus_next = d->focus_next;
+ }
+#endif
+ }
+};
+
/*!
Constructs a widget which is a child of \a parent, with widget
flags set to \a f.
@@ -950,7 +1017,12 @@ QRegion qt_dirtyRegion(QWidget *widget)
QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
: QObject(*new QWidgetPrivate, 0), QPaintDevice()
{
- d_func()->init(parent, f);
+ QT_TRY {
+ d_func()->init(parent, f);
+ } QT_CATCH(...) {
+ QWidgetExceptionCleaner::cleanup(this, d_func());
+ QT_RETHROW;
+ }
}
#ifdef QT3_SUPPORT
@@ -961,8 +1033,13 @@ QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
QWidget::QWidget(QWidget *parent, const char *name, Qt::WindowFlags f)
: QObject(*new QWidgetPrivate, 0), QPaintDevice()
{
- d_func()->init(parent , f);
- setObjectName(QString::fromAscii(name));
+ QT_TRY {
+ d_func()->init(parent , f);
+ setObjectName(QString::fromAscii(name));
+ } QT_CATCH(...) {
+ QWidgetExceptionCleaner::cleanup(this, d_func());
+ QT_RETHROW;
+ }
}
#endif
@@ -971,7 +1048,13 @@ QWidget::QWidget(QWidget *parent, const char *name, Qt::WindowFlags f)
QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
: QObject(dd, 0), QPaintDevice()
{
- d_func()->init(parent, f);
+ Q_D(QWidget);
+ QT_TRY {
+ d->init(parent, f);
+ } QT_CATCH(...) {
+ QWidgetExceptionCleaner::cleanup(this, d_func());
+ QT_RETHROW;
+ }
}
/*!
@@ -1027,7 +1110,7 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
if (customize)
; // don't modify window flags if the user explicitely set them.
else if (type == Qt::Dialog || type == Qt::Sheet)
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint;
#else
flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
@@ -1043,11 +1126,11 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
{
Q_Q(QWidget);
- if (qApp->type() == QApplication::Tty)
+ if (QApplication::type() == QApplication::Tty)
qFatal("QWidget: Cannot create a QWidget when no GUI is being used");
- Q_ASSERT(uncreatedWidgets);
- uncreatedWidgets->insert(q);
+ Q_ASSERT(allWidgets);
+ allWidgets->insert(q);
QWidget *desktopWidget = 0;
if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
@@ -1058,7 +1141,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
q->data = &data;
#ifndef QT_NO_THREAD
- if (!q->parent()) {
+ if (!parent) {
Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
"Widgets must be created in the GUI thread.");
}
@@ -1094,7 +1177,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
if (f & Qt::MSWindowsOwnDC)
q->setAttribute(Qt::WA_NativeWindow);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
data.window_state_internal = 0;
#endif
@@ -1253,7 +1336,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
d->create_sys(window, initializeWindow, destroyOldWindow);
// a real toplevel window needs a backing store
- if (isWindow()) {
+ if (isWindow() && windowType() != Qt::Desktop) {
delete d->topData()->backingStore;
// QWidgetBackingStore will check this variable, hence it must be 0
d->topData()->backingStore = 0;
@@ -1336,19 +1419,35 @@ QWidget::~QWidget()
#ifdef QT3_SUPPORT
if (QApplicationPrivate::main_widget == this) { // reset main widget
QApplicationPrivate::main_widget = 0;
- qApp->quit();
+ QApplication::quit();
}
#endif
- clearFocus();
+ QT_TRY {
+ clearFocus();
+ } QT_CATCH(...) {
+ // swallow this problem because we are in a destructor
+ }
d->setDirtyOpaqueRegion();
- if (isWindow() && isVisible() && internalWinId())
- hide();
+ if (isWindow() && isVisible() && internalWinId()) {
+ QT_TRY {
+ d->close_helper(QWidgetPrivate::CloseNoEvent);
+ } QT_CATCH(...) {
+ // if we're out of memory, at least hide the window.
+ QT_TRY {
+ hide();
+ } QT_CATCH(...) {
+ // and if that also doesn't work, then give up
+ }
+ }
+ }
+
#if defined(Q_WS_WIN) || defined(Q_WS_X11)
- else if (!internalWinId() && isVisible())
+ else if (!internalWinId() && isVisible()) {
qApp->d_func()->sendSyntheticEnterLeave(this);
+ }
#endif
if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
@@ -1363,17 +1462,25 @@ QWidget::~QWidget()
// set all QPointers for this object to zero
QObjectPrivate::clearGuards(this);
+ if (d->declarativeData) {
+ d->declarativeData->destroyed(this);
+ d->declarativeData = 0; // don't activate again in ~QObject
+ }
+
if (!d->children.isEmpty())
d->deleteChildren();
QApplication::removePostedEvents(this);
- destroy(); // platform-dependent cleanup
-
+ QT_TRY {
+ destroy(); // platform-dependent cleanup
+ } QT_CATCH(...) {
+ // if this fails we can't do anything about it but at least we are not allowed to throw.
+ }
--QWidgetPrivate::instanceCounter;
- if (QWidgetPrivate::uncreatedWidgets) // might have been deleted by ~QApplication
- QWidgetPrivate::uncreatedWidgets->remove(this);
+ if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
+ QWidgetPrivate::allWidgets->remove(this);
QEvent e(QEvent::Destroy);
QCoreApplication::sendEvent(this, &e);
@@ -1393,7 +1500,6 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier
bool userDesktopWidget = qt_desktopWidget != 0 && qt_desktopWidget != q && q->windowType() == Qt::Desktop;
if (mapper && data.winid && !userDesktopWidget) {
mapper->remove(data.winid);
- uncreatedWidgets->insert(q);
}
data.winid = id;
@@ -1402,7 +1508,6 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier
#endif
if (mapper && id && !userDesktopWidget) {
mapper->insert(data.winid, q);
- uncreatedWidgets->remove(q);
}
}
@@ -1412,36 +1517,26 @@ void QWidgetPrivate::createTLExtra()
createExtra();
if (!extra->topextra) {
QTLWExtra* x = extra->topextra = new QTLWExtra;
+ x->icon = 0;
+ x->iconPixmap = 0;
+ x->backingStore = 0;
x->windowSurface = 0;
+ x->sharedPainter = 0;
+ x->incw = x->inch = 0;
+ x->basew = x->baseh = 0;
+ x->frameStrut.setCoords(0, 0, 0, 0);
+ x->normalGeometry = QRect(0,0,-1,-1);
+ x->savedFlags = 0;
x->opacity = 255;
x->posFromMove = false;
x->sizeAdjusted = false;
x->inTopLevelResize = false;
x->inRepaint = false;
- x->backingStore = 0;
- x->icon = 0;
- x->iconPixmap = 0;
- x->frameStrut.setCoords(0, 0, 0, 0);
- x->incw = x->inch = 0;
- x->basew = x->baseh = 0;
- x->normalGeometry = QRect(0,0,-1,-1);
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC)
x->embedded = 0;
-#endif
-#if defined(Q_WS_X11)
- x->parentWinId = 0;
- x->spont_unmapped = 0;
- x->dnd = 0;
-#endif
- x->savedFlags = 0;
-#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
- x->qwsManager = 0;
-#endif
- x->sharedPainter = 0;
createTLSysExtra();
#ifdef QWIDGET_EXTRA_DEBUG
- static int count = 0;
- qDebug() << "tlextra" << ++count;
+ static int count = 0;
+ qDebug() << "tlextra" << ++count;
#endif
}
}
@@ -1455,27 +1550,28 @@ void QWidgetPrivate::createExtra()
{
if (!extra) { // if not exists
extra = new QWExtra;
- extra->minw = extra->minh = 0;
- extra->maxw = extra->maxh = QWIDGETSIZE_MAX;
+ extra->glContext = 0;
+ extra->topextra = 0;
+ extra->proxyWidget = 0;
+#ifndef QT_NO_CURSOR
+ extra->curs = 0;
+#endif
+ extra->minw = 0;
+ extra->minh = 0;
+ extra->maxw = QWIDGETSIZE_MAX;
+ extra->maxh = QWIDGETSIZE_MAX;
+ extra->customDpiX = 0;
+ extra->customDpiY = 0;
extra->explicitMinSize = 0;
extra->explicitMaxSize = 0;
extra->autoFillBackground = 0;
extra->nativeChildrenForced = 0;
extra->inRenderWithPainter = 0;
extra->hasMask = 0;
-#ifndef QT_NO_CURSOR
- extra->curs = 0;
-#endif
- extra->style = 0;
- extra->topextra = 0;
- extra->proxyWidget = 0;
- extra->glContext = 0;
- extra->customDpiX = 0;
- extra->customDpiY = 0;
createSysExtra();
#ifdef QWIDGET_EXTRA_DEBUG
- static int count = 0;
- qDebug() << "extra" << ++count;
+ static int count = 0;
+ qDebug() << "extra" << ++count;
#endif
}
}
@@ -1516,45 +1612,6 @@ void QWidgetPrivate::deleteExtra()
}
/*
- Returns true if the background is inherited; otherwise returns
- false.
-
- Mainly used in the paintOnScreen case.
-*/
-
-bool QWidgetPrivate::isBackgroundInherited() const
-{
- Q_Q(const QWidget);
-
- // windows do not inherit their background
- if (q->isWindow() || q->windowType() == Qt::SubWindow)
- return false;
-
- if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
- return false;
-
- const QPalette &pal = q->palette();
- QPalette::ColorRole bg = q->backgroundRole();
- QBrush brush = pal.brush(bg);
-
- // non opaque brushes leaves us no choice, we must inherit
- if (!q->autoFillBackground() || !brush.isOpaque())
- return true;
-
- if (brush.style() == Qt::SolidPattern) {
- // the background is just a solid color. If there is no
- // propagated contents, then we claim as performance
- // optimization that it was not inheritet. This is the normal
- // case in standard Windows or Motif style.
- const QWidget *w = q->parentWidget();
- if (!w->d_func()->isBackgroundInherited())
- return false;
- }
-
- return true;
-}
-
-/*
Returns true if there are widgets above this which overlap with
\a rect, which is in parent's coordinate system (same as crect).
*/
@@ -1579,9 +1636,9 @@ bool QWidgetPrivate::isOverlapped(const QRect &rect) const
continue;
}
- if (qRectIntersects(sibling->data->crect, r)) {
+ if (qRectIntersects(sibling->d_func()->effectiveRectFor(sibling->data->crect), r)) {
const QWExtra *siblingExtra = sibling->d_func()->extra;
- if (siblingExtra && siblingExtra->hasMask
+ if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
&& !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
continue;
}
@@ -1680,7 +1737,7 @@ QRect QWidgetPrivate::clipRect() const
const QWidget * w = q;
if (!w->isVisible())
return QRect();
- QRect r = q->rect();
+ QRect r = effectiveRectFor(q->rect());
int ox = 0;
int oy = 0;
while (w
@@ -1822,12 +1879,14 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt
break;
QWidgetPrivate *pd = w->parentWidget()->d_func();
const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
+ const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
for (int i = myIndex + 1; i < pd->children.size(); ++i) {
QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
if (!sibling || !sibling->isVisible() || sibling->isWindow())
continue;
- if (!qRectIntersects(sibling->data->crect, w->data->crect))
+ const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
+ if (!qRectIntersects(siblingGeometry, widgetGeometry))
continue;
if (dirtyClipBoundingRect) {
@@ -1835,7 +1894,7 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt
dirtyClipBoundingRect = false;
}
- if (!qRectIntersects(sibling->data->crect, clipBoundingRect.translated(parentOffset)))
+ if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
continue;
if (dirtyParentClip) {
@@ -1847,7 +1906,8 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt
const QRect siblingClipRect(sibling->d_func()->clipRect());
QRegion siblingDirty(parentClip);
siblingDirty &= (siblingClipRect.translated(siblingPos));
- const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask;
+ const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
+ && !sibling->d_func()->graphicsEffect;
if (hasMask)
siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
if (siblingDirty.isEmpty())
@@ -1858,7 +1918,7 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt
siblingDirty.translate(-parentOffset);
sourceRegion -= siblingDirty;
} else {
- sourceRegion -= sibling->data->crect.translated(-parentOffset);
+ sourceRegion -= siblingGeometry.translated(-parentOffset);
}
} else {
if (hasDirtySiblingsAbove)
@@ -1889,6 +1949,11 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
const QWidget *w = q;
QPoint offset;
+ if (graphicsEffect) {
+ w = q->parentWidget();
+ offset -= data.crect.topLeft();
+ }
+
while (w) {
const QWidgetPrivate *wd = w->d_func();
if (wd->extra && wd->extra->hasMask)
@@ -1900,24 +1965,6 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
}
}
-bool QWidgetPrivate::hasBackground() const
-{
- Q_Q(const QWidget);
- if (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_PaintOnScreen))
- return true;
- if (q->testAttribute(Qt::WA_PaintOnScreen))
- return true;
- if (!q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
- const QPalette &pal = q->palette();
- QPalette::ColorRole bg = q->backgroundRole();
- QBrush bgBrush = pal.brush(bg);
- return (bgBrush.style() != Qt::NoBrush &&
- ((q->isWindow() || q->windowType() == Qt::SubWindow)
- || (QPalette::ColorRole(bg_role) != QPalette::NoRole || (pal.resolve() & (1<<bg)))));
- }
- return false;
-}
-
bool QWidgetPrivate::paintOnScreen() const
{
#if defined(Q_WS_QWS)
@@ -1940,6 +1987,12 @@ void QWidgetPrivate::updateIsOpaque()
// hw: todo: only needed if opacity actually changed
setDirtyOpaqueRegion();
+ if (graphicsEffect) {
+ // ### We should probably add QGraphicsEffect::isOpaque at some point.
+ setOpaque(false);
+ return;
+ }
+
Q_Q(QWidget);
#ifdef Q_WS_X11
if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) {
@@ -1987,6 +2040,9 @@ void QWidgetPrivate::setOpaque(bool opaque)
#ifdef Q_WS_WIN
winUpdateIsOpaque();
#endif
+#ifdef Q_OS_SYMBIAN
+ s60UpdateIsOpaque();
+#endif
}
void QWidgetPrivate::updateIsTranslucent()
@@ -2000,6 +2056,9 @@ void QWidgetPrivate::updateIsTranslucent()
#ifdef Q_WS_WIN
winUpdateIsOpaque();
#endif
+#ifdef Q_OS_SYMBIAN
+ s60UpdateIsOpaque();
+#endif
}
/*!
@@ -2020,10 +2079,9 @@ void QPixmap::fill( const QWidget *widget, const QPoint &off )
QPainter p(this);
p.translate(-off);
widget->d_func()->paintBackground(&p, QRect(off, size()));
-
}
-static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QPoint &offset, const QBrush &brush)
+static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
{
Q_ASSERT(painter);
@@ -2032,26 +2090,46 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QPoin
// Optimize pattern filling on mac by using HITheme directly
// when filling with the standard widget background.
// Defined in qmacstyle_mac.cpp
- extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QPoint &offset, const QBrush &brush);
- qt_mac_fill_background(painter, rgn, offset, brush);
+ extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush);
+ qt_mac_fill_background(painter, rgn, brush);
#else
- const QRegion translated = rgn.translated(offset);
- const QRect rect(translated.boundingRect());
- painter->setClipRegion(translated);
- painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
-#endif
+#if !defined(QT_NO_STYLE_S60)
+ // Defined in qs60style.cpp
+ extern bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush);
+ if (!qt_s60_fill_background(painter, rgn, brush))
+#endif // !defined(QT_NO_STYLE_S60)
+ {
+ const QRect rect(rgn.boundingRect());
+ painter->setClipRegion(rgn);
+ painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
+ }
+#endif // Q_WS_MAC
} else {
const QVector<QRect> &rects = rgn.rects();
for (int i = 0; i < rects.size(); ++i)
- painter->fillRect(rects.at(i).translated(offset), brush);
+ painter->fillRect(rects.at(i), brush);
}
}
-
-void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, const QPoint &offset, int flags) const
+void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const
{
Q_Q(const QWidget);
+#ifndef QT_NO_SCROLLAREA
+ bool resetBrushOrigin = false;
+ QPointF oldBrushOrigin;
+ //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
+ QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
+ if (scrollArea && scrollArea->viewport() == q) {
+ QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
+ QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
+ oldBrushOrigin = painter->brushOrigin();
+ resetBrushOrigin = true;
+ painter->setBrushOrigin(-priv->contentsOffset());
+
+ }
+#endif // QT_NO_SCROLLAREA
+
const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
@@ -2060,18 +2138,24 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, cons
if (!(flags & DontSetCompositionMode) && painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
painter->setCompositionMode(QPainter::CompositionMode_Source); //copy alpha straight in
#endif
- fillRegion(painter, rgn, offset, bg);
+ fillRegion(painter, rgn, bg);
}
if (q->autoFillBackground())
- fillRegion(painter, rgn, offset, autoFillBrush);
+ fillRegion(painter, rgn, autoFillBrush);
+
if (q->testAttribute(Qt::WA_StyledBackground)) {
- painter->setClipRegion(rgn.translated(offset));
+ painter->setClipRegion(rgn);
QStyleOption opt;
opt.initFrom(q);
q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
}
+
+#ifndef QT_NO_SCROLLAREA
+ if (resetBrushOrigin)
+ painter->setBrushOrigin(oldBrushOrigin);
+#endif // QT_NO_SCROLLAREA
}
/*
@@ -2091,8 +2175,8 @@ void QWidgetPrivate::deactivateWidgetCleanup()
{
Q_Q(QWidget);
// If this was the active application window, reset it
- if (qApp->activeWindow() == q)
- qApp->setActiveWindow(0);
+ if (QApplication::activeWindow() == q)
+ QApplication::setActiveWindow(0);
// If the is the active mouse press widget, reset it
if (q == qt_button_down)
qt_button_down = 0;
@@ -2293,7 +2377,7 @@ QStyle *QWidget::style() const
if (d->extra && d->extra->style)
return d->extra->style;
- return qApp->style();
+ return QApplication::style();
}
/*!
@@ -2612,7 +2696,7 @@ bool QWidget::isMaximized() const
*/
Qt::WindowStates QWidget::windowState() const
{
- return (Qt::WindowStates)data->window_state;
+ return Qt::WindowStates(data->window_state);
}
/*!\internal
@@ -2624,7 +2708,7 @@ Qt::WindowStates QWidget::windowState() const
*/
void QWidget::overrideWindowState(Qt::WindowStates newstate)
{
- QWindowStateChangeEvent e((Qt::WindowStates)data->window_state, true);
+ QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
data->window_state = newstate;
QApplication::sendEvent(this, &e);
}
@@ -2723,7 +2807,7 @@ void QWidget::showFullScreen()
Calling this function only affects \l{isWindow()}{windows}.
On X11, this function may not work properly with certain window
- managers. See \l{geometry.html}{Window Geometry} for an explanation.
+ managers. See the \l{Window Geometry} documentation for an explanation.
\sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
*/
@@ -2778,7 +2862,7 @@ void QWidget::showNormal()
bool QWidget::isEnabledTo(QWidget* ancestor) const
{
const QWidget * w = this;
- while (w && !w->testAttribute(Qt::WA_ForceDisabled)
+ while (!w->testAttribute(Qt::WA_ForceDisabled)
&& !w->isWindow()
&& w->parentWidget()
&& w->parentWidget() != ancestor)
@@ -2969,10 +3053,15 @@ void QWidgetPrivate::setEnabled_helper(bool enable)
#if defined(Q_WS_MAC)
setEnabled_helper_sys(enable);
#endif
-#if defined (Q_WS_WIN)
- if (q->hasFocus())
- QInputContextPrivate::updateImeStatus(q, true);
-#endif
+ if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
+ QInputContext *qic = inputContext();
+ if (enable) {
+ qic->setFocusWidget(q);
+ } else {
+ qic->reset();
+ qic->setFocusWidget(0);
+ }
+ }
QEvent e(QEvent::EnabledChange);
QApplication::sendEvent(q, &e);
#ifdef QT3_SUPPORT
@@ -3067,8 +3156,8 @@ void QWidget::setDisabled(bool disable)
\brief geometry of the widget relative to its parent including any
window frame
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of geometry issues with windows.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
By default, this property contains a value that depends on the user's
platform and screen geometry.
@@ -3094,8 +3183,8 @@ QRect QWidget::frameGeometry() const
\brief the x coordinate of the widget relative to its parent including
any window frame
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of window geometry.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
By default, this property has a value of 0.
@@ -3114,8 +3203,8 @@ int QWidget::x() const
\brief the y coordinate of the widget relative to its parent and
including any window frame
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of window geometry.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
By default, this property has a value of 0.
@@ -3147,8 +3236,8 @@ int QWidget::y() const
\warning Calling move() or setGeometry() inside moveEvent() can
lead to infinite recursion.
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of window geometry.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
\sa frameGeometry, size x(), y()
*/
@@ -3178,8 +3267,8 @@ QPoint QWidget::pos() const
\warning Calling setGeometry() inside resizeEvent() or moveEvent()
can lead to infinite recursion.
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of window geometry.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
By default, this property contains a value that depends on the user's
platform and screen geometry.
@@ -3228,8 +3317,8 @@ QPoint QWidget::pos() const
\property QWidget::width
\brief the width of the widget excluding any window frame
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of window geometry.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
\note Do not use this function to find the width of a screen on
a \l{QDesktopWidget}{multiple screen desktop}. Read
@@ -3245,8 +3334,8 @@ QPoint QWidget::pos() const
\property QWidget::height
\brief the height of the widget excluding any window frame
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of window geometry.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
\note Do not use this function to find the height of a screen
on a \l {QDesktopWidget} {multiple screen desktop}. Read
@@ -3265,8 +3354,8 @@ QPoint QWidget::pos() const
The rect property equals QRect(0, 0, width(), height()).
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of window geometry.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
By default, this property contains a value that depends on the user's
platform and screen geometry.
@@ -3506,27 +3595,32 @@ bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
}
}
#endif
+ int mw = minw, mh = minh;
+ if (mw == QWIDGETSIZE_MAX)
+ mw = 0;
+ if (mh == QWIDGETSIZE_MAX)
+ mh = 0;
if (minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX) {
qWarning("QWidget::setMinimumSize: (%s/%s) "
"The largest allowed size is (%d,%d)",
q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
QWIDGETSIZE_MAX);
- minw = qMin<int>(minw, QWIDGETSIZE_MAX);
- minh = qMin<int>(minh, QWIDGETSIZE_MAX);
+ minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
+ minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
}
if (minw < 0 || minh < 0) {
qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
"are not possible",
q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
- minw = qMax(minw, 0);
- minh = qMax(minh, 0);
+ minw = mw = qMax(minw, 0);
+ minh = mh = qMax(minh, 0);
}
createExtra();
- if (extra->minw == minw && extra->minh == minh)
+ if (extra->minw == mw && extra->minh == mh)
return false;
- extra->minw = minw;
- extra->minh = minh;
- extra->explicitMinSize = (minw ? Qt::Horizontal : 0) | (minh ? Qt::Vertical : 0);
+ extra->minw = mw;
+ extra->minh = mh;
+ extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
return true;
}
@@ -3586,7 +3680,8 @@ bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
return false;
extra->maxw = maxw;
extra->maxh = maxh;
- extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) | (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
+ extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
+ (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
return true;
}
@@ -3665,6 +3760,8 @@ void QWidget::setBaseSize(int basew, int baseh)
This will override the default size constraints set by QLayout.
+ To remove constraints, set the size to QWIDGETSIZE_MAX.
+
Alternatively, if you want the widget to have a
fixed size based on its contents, you can call
QLayout::setSizeConstraint(QLayout::SetFixedSize);
@@ -3706,7 +3803,8 @@ void QWidget::setFixedSize(int w, int h)
else
d->updateGeometry_helper(true);
- resize(w, h);
+ if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
+ resize(w, h);
}
void QWidget::setMinimumWidth(int w)
@@ -4079,6 +4177,10 @@ QPalette::ColorRole QWidget::backgroundRole() const
If \a role is QPalette::NoRole, then the widget inherits its
parent's background role.
+ Note that styles are free to choose any color from the palette.
+ You can modify the palette or set a style sheet if you don't
+ achieve the result you want with setBackgroundRole().
+
\sa backgroundRole(), foregroundRole()
*/
@@ -4141,6 +4243,10 @@ QPalette::ColorRole QWidget::foregroundRole() const
If \a role is QPalette::NoRole, the widget uses a foreground role
that contrasts with the background role.
+ Note that styles are free to choose any color from the palette.
+ You can modify the palette or set a style sheet if you don't
+ achieve the result you want with setForegroundRole().
+
\sa foregroundRole(), backgroundRole()
*/
void QWidget::setForegroundRole(QPalette::ColorRole role)
@@ -4209,7 +4315,7 @@ const QPalette &QWidget::palette() const
if (!isEnabled()) {
data->pal.setCurrentColorGroup(QPalette::Disabled);
} else if ((!isVisible() || isActiveWindow())
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_WIN) && !defined(Q_WS_WINCE)
&& !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
#endif
) {
@@ -4621,8 +4727,9 @@ void QWidget::setCursor(const QCursor &cursor)
#endif
{
d->createExtra();
+ QCursor *newCursor = new QCursor(cursor);
delete d->extra->curs;
- d->extra->curs = new QCursor(cursor);
+ d->extra->curs = newCursor;
}
setAttribute(Qt::WA_SetCursor);
d->setCursor_sys(cursor);
@@ -4802,7 +4909,7 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
}
const qreal opacity = painter->opacity();
- if (qFuzzyCompare(opacity + 1, qreal(1.0)))
+ if (qFuzzyIsNull(opacity))
return; // Fully transparent.
Q_D(QWidget);
@@ -4864,6 +4971,70 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
d->extra->inRenderWithPainter = false;
}
+#if !defined(Q_OS_SYMBIAN)
+void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys)
+{
+ Q_UNUSED(softkeys)
+}
+#endif // !defined(Q_OS_SYMBIAN)
+
+/*!
+ Returns a pointer to this widget's effect if it has one; otherwise 0.
+
+ \since 4.6
+
+ \sa setGraphicsEffect()
+*/
+QGraphicsEffect *QWidget::graphicsEffect() const
+{
+ Q_D(const QWidget);
+ return d->graphicsEffect;
+}
+
+/*!
+ Sets \a effect as the widget's effect. If there already is an effect installed
+ on this widget, QWidget will delete the existing effect before installing
+ the new \a effect.
+
+ If \a effect is the installed on a different widget, setGraphicsEffect() will remove
+ the effect from the widget and install it on this widget.
+
+ \note This function will apply the effect on itself and all its children.
+
+ \since 4.6
+
+ \sa graphicsEffect()
+*/
+void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
+{
+ Q_D(QWidget);
+ if (d->graphicsEffect == effect)
+ return;
+
+ if (d->graphicsEffect && effect) {
+ delete d->graphicsEffect;
+ d->graphicsEffect = 0;
+ }
+
+ if (!effect) {
+ // Unset current effect.
+ QGraphicsEffectPrivate *oldEffectPrivate = d->graphicsEffect->d_func();
+ d->graphicsEffect = 0;
+ if (oldEffectPrivate) {
+ oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source.
+ }
+ } else {
+ // Set new effect.
+ QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
+ QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
+ d->graphicsEffect = effect;
+ effect->d_func()->setGraphicsEffectSource(source);
+ }
+
+ d->updateIsOpaque();
+ update();
+}
+
bool QWidgetPrivate::isAboutToShow() const
{
if (data.in_show)
@@ -5008,6 +5179,33 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
return;
Q_Q(QWidget);
+ if (graphicsEffect && graphicsEffect->isEnabled()) {
+ QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
+ QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
+ (source->d_func());
+ if (!sourced->context) {
+ QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore);
+ sourced->context = &context;
+ if (!sharedPainter) {
+ QPaintEngine *paintEngine = pdev->paintEngine();
+ paintEngine->d_func()->systemClip = rgn.translated(offset);
+ QPainter p(pdev);
+ p.translate(offset);
+ context.painter = &p;
+ graphicsEffect->draw(&p, source);
+ paintEngine->d_func()->systemClip = QRegion();
+ } else {
+ context.painter = sharedPainter;
+ sharedPainter->save();
+ sharedPainter->translate(offset);
+ graphicsEffect->draw(sharedPainter, source);
+ sharedPainter->restore();
+ }
+ sourced->context = 0;
+ return;
+ }
+ }
+
const bool asRoot = flags & DrawAsRoot;
const bool alsoOnScreen = flags & DrawPaintOnScreen;
const bool recursive = flags & DrawRecursive;
@@ -5040,26 +5238,14 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
if (sharedPainter)
paintEngine->d_func()->systemClip = toBePainted;
else
- paintEngine->setSystemRect(q->data->crect);
+ paintEngine->d_func()->systemRect = q->data->crect;
//paint the background
if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
&& !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
QPainter p(q);
- QPoint scrollAreaOffset;
-
-#ifndef QT_NO_SCROLLAREA
- QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(q->parent());
- if (scrollArea && scrollArea->viewport() == q) {
- QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr;
- QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
- scrollAreaOffset = priv->contentsOffset();
- p.translate(-scrollAreaOffset);
- }
-#endif // QT_NO_SCROLLAREA
-
- paintBackground(&p, toBePainted, scrollAreaOffset, (asRoot || onScreen) ? flags | DrawAsRoot : 0);
+ paintBackground(&p, toBePainted, (asRoot || onScreen) ? flags | DrawAsRoot : 0);
}
if (!sharedPainter)
@@ -5091,7 +5277,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
if (paintEngine) {
restoreRedirected();
if (!sharedPainter)
- paintEngine->setSystemRect(QRect());
+ paintEngine->d_func()->systemRect = QRect();
else
paintEngine->d_func()->currentClipWidget = 0;
paintEngine->d_func()->systemClip = QRegion();
@@ -5154,7 +5340,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis
dirtyBoundingRect = false;
}
- if (qRectIntersects(boundingRect, x->data->crect)) {
+ if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
#ifdef Q_BACKINGSTORE_SUBSURFACES
if (x->windowSurface() == currentSurface)
#endif
@@ -5172,7 +5358,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis
QWidgetPrivate *wd = w->d_func();
const QPoint widgetPos(w->data->crect.topLeft());
- const bool hasMask = wd->extra && wd->extra->hasMask;
+ const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
if (index > 0) {
QRegion wr(rgn);
@@ -5187,7 +5373,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis
if (w->updatesEnabled() && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)) {
QRegion wRegion(rgn);
- wRegion &= w->data->crect;
+ wRegion &= wd->effectiveRectFor(w->data->crect);
wRegion.translate(-widgetPos);
if (hasMask)
wRegion &= wd->extra->mask;
@@ -5195,6 +5381,93 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis
}
}
+QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
+{
+ if (system != Qt::DeviceCoordinates)
+ return m_widget->rect();
+
+ if (!context) {
+ // Device coordinates without context not yet supported.
+ qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
+ return QRectF();
+ }
+
+ return context->painter->worldTransform().mapRect(m_widget->rect());
+}
+
+void QWidgetEffectSourcePrivate::draw(QPainter *painter)
+{
+ if (!context || context->painter != painter) {
+ m_widget->render(painter);
+ return;
+ }
+
+ // The region saved in the context is neither clipped to the rect
+ // nor the mask, so we have to clip it here before calling drawWidget.
+ QRegion toBePainted = context->rgn;
+ toBePainted &= m_widget->rect();
+ QWidgetPrivate *wd = qt_widget_private(m_widget);
+ if (wd->extra && wd->extra->hasMask)
+ toBePainted &= wd->extra->mask;
+
+ wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
+ context->sharedPainter, context->backingStore);
+}
+
+QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
+{
+ const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
+ if (!context && deviceCoordinates) {
+ // Device coordinates without context not yet supported.
+ qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
+ return QPixmap();
+ }
+
+ QPoint pixmapOffset;
+ QRectF sourceRect = m_widget->rect();
+
+ if (deviceCoordinates) {
+ const QTransform &painterTransform = context->painter->worldTransform();
+ sourceRect = painterTransform.mapRect(sourceRect);
+ pixmapOffset = painterTransform.map(pixmapOffset);
+ }
+
+ QRect effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
+ if (offset)
+ *offset = effectRect.topLeft();
+
+ if (deviceCoordinates) {
+ // Clip to device rect.
+ int left, top, right, bottom;
+ effectRect.getCoords(&left, &top, &right, &bottom);
+ if (left < 0) {
+ if (offset)
+ offset->rx() += -left;
+ effectRect.setX(0);
+ }
+ if (top < 0) {
+ if (offset)
+ offset->ry() += -top;
+ effectRect.setY(0);
+ }
+ // NB! We use +-1 for historical reasons (see QRect documentation).
+ QPaintDevice *device = context->painter->device();
+ const int deviceWidth = device->width();
+ const int deviceHeight = device->height();
+ if (right + 1 > deviceWidth)
+ effectRect.setRight(deviceWidth - 1);
+ if (bottom + 1 > deviceHeight)
+ effectRect.setBottom(deviceHeight -1);
+ }
+
+ pixmapOffset -= effectRect.topLeft();
+
+ QPixmap pixmap(effectRect.size());
+ pixmap.fill(Qt::transparent);
+ m_widget->render(&pixmap, pixmapOffset);
+ return pixmap;
+}
+
/*!
\internal
@@ -5293,7 +5566,7 @@ static QString constructWindowTitleFromFilePath(const QString &filePath)
#ifndef Q_WS_MAC
QString appName = QApplication::applicationName();
if (!appName.isEmpty())
- windowTitle += QLatin1String(" ") + QChar(0x2014) + QLatin1String(" ") + appName;
+ windowTitle += QLatin1Char(' ') + QChar(0x2014) + QLatin1Char(' ') + appName;
#endif
return windowTitle;
}
@@ -5328,6 +5601,17 @@ QString QWidget::windowTitle() const
return QString();
}
+/*!
+ Returns a modified window title with the [*] place holder
+ replaced according to the rules described in QWidget::setWindowTitle
+
+ This function assumes that "[*]" can be quoted by another
+ "[*]", so it will replace two place holders by one and
+ a single last one by either "*" or nothing depending on
+ the modified flag.
+
+ \internal
+*/
QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
{
Q_ASSERT(widget);
@@ -5339,16 +5623,21 @@ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widg
QString cap = title;
#endif
- QString placeHolder(QLatin1String("[*]"));
+ if (cap.isEmpty())
+ return cap;
+
+ QLatin1String placeHolder("[*]");
+ int placeHolderLength = 3; // QLatin1String doesn't have length()
int index = cap.indexOf(placeHolder);
+ // here the magic begins
while (index != -1) {
- index += placeHolder.length();
+ index += placeHolderLength;
int count = 1;
while (cap.indexOf(placeHolder, index) == index) {
++count;
- index += placeHolder.length();
+ index += placeHolderLength;
}
if (count%2) { // odd number of [*] -> replace last one
@@ -5357,13 +5646,13 @@ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widg
&& widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, 0, widget))
cap.replace(lastIndex, 3, QWidget::tr("*"));
else
- cap.replace(lastIndex, 3, QLatin1String(""));
+ cap.remove(lastIndex, 3);
}
index = cap.indexOf(placeHolder, index);
}
- cap.replace(QLatin1String("[*][*]"), QLatin1String("[*]"));
+ cap.replace(QLatin1String("[*][*]"), placeHolder);
return cap;
}
@@ -5429,7 +5718,7 @@ QIcon QWidget::windowIcon() const
return *d->extra->topextra->icon;
w = w->parentWidget();
}
- return qApp->windowIcon();
+ return QApplication::windowIcon();
}
void QWidgetPrivate::setWindowIcon_helper()
@@ -5492,8 +5781,6 @@ QString QWidget::windowIconText() const
\list
\o The file name of the specified path, obtained using QFileInfo::fileName().
- \o An optional \c{*} character, if the \l windowModified property is set,
- as per the Apple Human Interface Guidelines.
\endlist
On Windows and X11:
@@ -5542,7 +5829,7 @@ void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
{
if (extra->topextra && extra->topextra->caption.isEmpty()) {
#ifdef Q_WS_MAC
- setWindowTitle_helper(filePath);
+ setWindowTitle_helper(QFileInfo(filePath).fileName());
#else
Q_Q(QWidget);
Q_UNUSED(filePath);
@@ -5692,7 +5979,7 @@ bool QWidget::hasFocus() const
called from focusOutEvent() or focusInEvent(), you may get an
infinite recursion.
- \sa focus(), hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
+ \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
grabMouse(), {Keyboard Focus}
*/
@@ -5913,6 +6200,8 @@ QWidget *QWidget::focusWidget() const
/*!
Returns the next widget in this widget's focus chain.
+
+ \sa previousInFocusChain()
*/
QWidget *QWidget::nextInFocusChain() const
{
@@ -5920,6 +6209,18 @@ QWidget *QWidget::nextInFocusChain() const
}
/*!
+ Returns the previous widget in this widget's focus chain.
+
+ \sa nextInFocusChain()
+
+ \since 4.6
+*/
+QWidget *QWidget::previousInFocusChain() const
+{
+ return const_cast<QWidget *>(d_func()->focus_prev);
+}
+
+/*!
\property QWidget::isActiveWindow
\brief whether this widget's window is the active window
@@ -5937,7 +6238,7 @@ QWidget *QWidget::nextInFocusChain() const
bool QWidget::isActiveWindow() const
{
QWidget *tlw = window();
- if(tlw == qApp->activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
+ if(tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
return true;
#ifndef QT_NO_GRAPHICSVIEW
@@ -5952,13 +6253,17 @@ bool QWidget::isActiveWindow() const
if(qt_mac_is_macdrawer(tlw) &&
tlw->parentWidget() && tlw->parentWidget()->isActiveWindow())
return true;
+
+ extern bool qt_mac_insideKeyWindow(const QWidget *); //qwidget_mac.cpp
+ if (QApplication::testAttribute(Qt::AA_MacPluginApplication) && qt_mac_insideKeyWindow(tlw))
+ return true;
#endif
if(style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, this)) {
if(tlw->windowType() == Qt::Tool &&
!tlw->isModal() &&
(!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
return true;
- QWidget *w = qApp->activeWindow();
+ QWidget *w = QApplication::activeWindow();
while(w && tlw->windowType() == Qt::Tool &&
!w->isModal() && w->parentWidget()) {
w = w->parentWidget()->window();
@@ -6157,14 +6462,6 @@ int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r)
return dx + dy;
}
-QRect QWidgetPrivate::fromOrToLayoutItemRect(const QRect &rect, int sign) const
-{
- QRect r = rect;
- r.adjust(-sign * leftLayoutItemMargin, -sign * topLayoutItemMargin,
- +sign * rightLayoutItemMargin, +sign * bottomLayoutItemMargin);
- return r;
-}
-
/*!
\property QWidget::frameSize
\brief the size of the widget including any window frame
@@ -6253,8 +6550,8 @@ void QWidget::setGeometry(const QRect &r)
\snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 11
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of geometry issues with windows.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
Use QMainWindow::saveState() to save the geometry and the state of
toolbars and dock widgets.
@@ -6295,8 +6592,8 @@ QByteArray QWidget::saveGeometry() const
\snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 12
- See the \link geometry.html Window Geometry documentation\endlink
- for an overview of geometry issues with windows.
+ See the \l{Window Geometry} documentation for an overview of geometry
+ issues with windows.
Use QMainWindow::restoreState() to restore the geometry and the
state of toolbars and dock widgets.
@@ -6751,7 +7048,7 @@ void QWidgetPrivate::show_helper()
// On Windows, show the popup now so that our own focus handling
// stores the correct old focus widget even if it's stolen in the
// showevent
-#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN)
if (!isEmbedded && q->windowType() == Qt::Popup)
qApp->d_func()->openPopup(q);
#endif
@@ -6768,7 +7065,7 @@ void QWidgetPrivate::show_helper()
show_sys();
-#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
if (!isEmbedded && q->windowType() == Qt::Popup)
qApp->d_func()->openPopup(q);
#endif
@@ -6888,9 +7185,12 @@ void QWidgetPrivate::hide_helper()
widgets that are not visible.
- Widgets are hidden if they were created as independent
- windows or as children of visible widgets, or if hide() or setVisible(false) was called.
-
+ Widgets are hidden if:
+ \list
+ \o they were created as independent windows,
+ \o they were created as children of visible widgets,
+ \o hide() or setVisible(false) was called.
+ \endlist
*/
@@ -7136,7 +7436,7 @@ bool QWidgetPrivate::close_helper(CloseMode mode)
#ifdef QT3_SUPPORT
if (isMain)
- qApp->quit();
+ QApplication::quit();
#endif
// Attempt to close the application only if this widget has the
// WA_QuitOnClose flag set set and has a non-visible parent
@@ -7261,8 +7561,7 @@ bool QWidget::isVisibleTo(QWidget* ancestor) const
if (!ancestor)
return isVisible();
const QWidget * w = this;
- while (w
- && !w->isHidden()
+ while (!w->isHidden()
&& !w->isWindow()
&& w->parentWidget()
&& w->parentWidget() != ancestor)
@@ -7319,10 +7618,10 @@ QSize QWidgetPrivate::adjustedSize() const
if (q->isWindow()) {
Qt::Orientations exp;
- if (QLayout *l = q->layout()) {
- if (l->hasHeightForWidth())
- s.setHeight(l->totalHeightForWidth(s.width()));
- exp = l->expandingDirections();
+ if (layout) {
+ if (layout->hasHeightForWidth())
+ s.setHeight(layout->totalHeightForWidth(s.width()));
+ exp = layout->expandingDirections();
} else
{
if (q->sizePolicy().hasHeightForWidth())
@@ -7338,7 +7637,7 @@ QSize QWidgetPrivate::adjustedSize() const
#else // all others
QRect screen = QApplication::desktop()->screenGeometry(q->pos());
#endif
-#if defined (Q_OS_WINCE)
+#if defined (Q_WS_WINCE) || defined (Q_OS_SYMBIAN)
s.setWidth(qMin(s.width(), screen.width()));
s.setHeight(qMin(s.height(), screen.height()));
#else
@@ -7525,6 +7824,9 @@ bool QWidget::event(QEvent *event)
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
case QEvent::ContextMenu:
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
@@ -7646,16 +7948,11 @@ bool QWidget::event(QEvent *event)
}
break;
case QEvent::FocusIn:
-#if defined(Q_WS_WIN)
- QInputContextPrivate::updateImeStatus(this, true);
-#endif
+ d->setSoftKeys_sys(softKeys());
focusInEvent((QFocusEvent*)event);
break;
case QEvent::FocusOut:
-#if defined(Q_WS_WIN)
- QInputContextPrivate::updateImeStatus(this, false);
-#endif
focusOutEvent((QFocusEvent*)event);
break;
@@ -7801,6 +8098,10 @@ bool QWidget::event(QEvent *event)
if (w && w->isVisible() && !w->isWindow())
QApplication::sendEvent(w, event);
}
+
+ if (isWindow() && isActiveWindow())
+ d->setSoftKeys_sys(softKeys());
+
break; }
case QEvent::LanguageChange:
@@ -7841,7 +8142,7 @@ bool QWidget::event(QEvent *event)
QList<QObject*> childList = d->children;
for (int i = 0; i < childList.size(); ++i) {
QObject *o = childList.at(i);
- if (o != qApp->activeModalWidget()) {
+ if (o != QApplication::activeModalWidget()) {
if (qobject_cast<QWidget *>(o) && static_cast<QWidget *>(o)->isWindow()) {
// do not forward the event to child windows,
// QApplication does this for us
@@ -7930,6 +8231,49 @@ bool QWidget::event(QEvent *event)
d->needWindowChange = false;
break;
#endif
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ {
+ QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
+ const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().first();
+ if (touchPoint.isPrimary())
+ break;
+
+ // fake a mouse event!
+ QEvent::Type eventType = QEvent::None;
+ switch (touchEvent->type()) {
+ case QEvent::TouchBegin:
+ eventType = QEvent::MouseButtonPress;
+ break;
+ case QEvent::TouchUpdate:
+ eventType = QEvent::MouseMove;
+ break;
+ case QEvent::TouchEnd:
+ eventType = QEvent::MouseButtonRelease;
+ break;
+ default:
+ Q_ASSERT(!true);
+ break;
+ }
+ if (eventType == QEvent::None)
+ break;
+
+ QMouseEvent mouseEvent(eventType,
+ touchPoint.pos().toPoint(),
+ touchPoint.screenPos().toPoint(),
+ Qt::LeftButton,
+ Qt::LeftButton,
+ touchEvent->modifiers());
+ (void) QApplication::sendEvent(this, &mouseEvent);
+ break;
+ }
+ case QEvent::SymbianDeferredFocusChanged: {
+#ifdef Q_OS_SYMBIAN
+ d->handleSymbianDeferredFocusChanged();
+#endif
+ break;
+ }
#ifndef QT_NO_PROPERTIES
case QEvent::DynamicPropertyChange: {
const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
@@ -7981,10 +8325,12 @@ void QWidget::changeEvent(QEvent * event)
case QEvent::FontChange:
case QEvent::StyleChange: {
+ Q_D(QWidget);
update();
updateGeometry();
+ if (d->layout)
+ d->layout->invalidate();
#ifdef Q_WS_QWS
- Q_D(QWidget);
if (isWindow())
d->data.fstrut_dirty = true;
#endif
@@ -8064,9 +8410,9 @@ void QWidget::mousePressEvent(QMouseEvent *event)
if ((windowType() == Qt::Popup)) {
event->accept();
QWidget* w;
- while ((w = qApp->activePopupWidget()) && w != this){
+ while ((w = QApplication::activePopupWidget()) && w != this){
w->close();
- if (qApp->activePopupWidget() == w) // widget does not want to dissappear
+ if (QApplication::activePopupWidget() == w) // widget does not want to dissappear
w->hide(); // hide at least
}
if (!rect().contains(event->pos())){
@@ -8476,7 +8822,7 @@ void QWidget::inputMethodEvent(QInputMethodEvent *event)
\a query specifies which property is queried.
- \sa inputMethodEvent(), QInputMethodEvent, QInputContext
+ \sa inputMethodEvent(), QInputMethodEvent, QInputContext, inputMethodHints
*/
QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
{
@@ -8485,11 +8831,54 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
return QRect(width()/2, 0, 1, height());
case Qt::ImFont:
return font();
+ case Qt::ImAnchorPosition:
+ // Fallback.
+ return inputMethodQuery(Qt::ImCursorPosition);
default:
return QVariant();
}
}
+/*!
+ \property QWidget::inputMethodHints
+ \brief What input method specific hints the widget has.
+
+ This is only relevant for input widgets. It is used by
+ the input method to retrieve hints as to how the input method
+ should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
+ is set, the input method may change its visual components to reflect
+ that only numbers can be entered.
+
+ \note The flags are only hints, so the particular input method
+ implementation is free to ignore them. If you want to be
+ sure that a certain type of characters are entered,
+ you should also set a QValidator on the widget.
+
+ The default value is Qt::ImhNone.
+
+ \since 4.6
+
+ \sa inputMethodQuery(), QInputContext
+*/
+Qt::InputMethodHints QWidget::inputMethodHints() const
+{
+ Q_D(const QWidget);
+ return d->imHints;
+}
+
+void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
+{
+ Q_D(QWidget);
+ d->imHints = hints;
+ // Optimisation to update input context only it has already been created.
+ if (d->ic || qApp->d_func()->inputContext) {
+ QInputContext *ic = inputContext();
+ if (ic)
+ ic->update();
+ }
+}
+
+
#ifndef QT_NO_DRAGANDDROP
/*!
@@ -8806,7 +9195,7 @@ QRegion QWidget::mask() const
The layout manager sets the geometry of the widget's children
that have been added to the layout.
- \sa setLayout(), sizePolicy(), {Layout Classes}
+ \sa setLayout(), sizePolicy(), {Layout Management}
*/
QLayout *QWidget::layout() const
{
@@ -8836,7 +9225,7 @@ QLayout *QWidget::layout() const
The QWidget will take ownership of \a layout.
- \sa layout(), {Layout Classes}
+ \sa layout(), {Layout Management}
*/
void QWidget::setLayout(QLayout *l)
@@ -9261,11 +9650,12 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
d->resolveLayoutDirection();
d->resolveLocale();
- // Note: GL widgets under Windows will always need a ParentChange
- // event to handle recreation/rebinding of the GL context, hence
- // the (f & Qt::MSWindowsOwnDC) clause
+ // Note: GL widgets under WGL or EGL will always need a ParentChange
+ // event to handle recreation/rebinding of the GL context, hence the
+ // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
+ // platforms).
if (newParent
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) || defined(QT_OPENGL_ES)
|| (f & Qt::MSWindowsOwnDC)
#endif
) {
@@ -9815,27 +10205,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
QEvent e(QEvent::MouseTrackingChange);
QApplication::sendEvent(this, &e);
break; }
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
- case Qt::WA_MSWindowsUseDirect3D:
- if (!qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)) {
- if (on) {
- if (!d->extra)
- d->createExtra();
- d->extra->had_auto_fill_bg = d->extra->autoFillBackground;
- d->extra->had_no_system_bg = testAttribute(Qt::WA_NoSystemBackground);
- d->extra->had_paint_on_screen = testAttribute(Qt::WA_PaintOnScreen);
- // enforce the opaque widget state D3D needs
- d->extra->autoFillBackground = true;
- setAttribute(Qt::WA_PaintOnScreen);
- setAttribute(Qt::WA_NoSystemBackground);
- } else if (d->extra) {
- d->extra->autoFillBackground = d->extra->had_auto_fill_bg;
- setAttribute(Qt::WA_PaintOnScreen, d->extra->had_paint_on_screen);
- setAttribute(Qt::WA_NoSystemBackground, d->extra->had_no_system_bg);
- }
- }
- break;
-#endif
case Qt::WA_NativeWindow: {
QInputContext *ic = 0;
if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) {
@@ -9847,7 +10216,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
parentWidget()->d_func()->enforceNativeChildren();
if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
d->createWinId();
- if (ic)
+ if (ic && isEnabled())
ic->setFocusWidget(this);
break;
}
@@ -9878,15 +10247,11 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
#endif
break;
case Qt::WA_InputMethodEnabled: {
-#if defined(Q_WS_WIN) || (defined(Q_WS_QWS) && !defined(QT_NO_QWS_INPUTMETHODS))
- if (hasFocus())
- QInputContextPrivate::updateImeStatus(this, true);
-#endif
QInputContext *ic = d->ic;
if (!ic && (!on || hasFocus()))
ic = d->inputContext();
if (ic) {
- if (on && hasFocus() && ic->focusWidget() != this) {
+ if (on && hasFocus() && ic->focusWidget() != this && isEnabled()) {
ic->setFocusWidget(this);
} else if (!on && ic->focusWidget() == this) {
ic->reset();
@@ -9963,6 +10328,12 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
}
break;
+ case Qt::WA_AcceptTouchEvents:
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+ if (on)
+ d->registerTouchWindow();
+#endif
+ break;
default:
break;
}
@@ -9993,8 +10364,8 @@ bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
By default the value of this property is 1.0.
- This feature is available on Embedded Linux, Mac OS X, X11 platforms that
- support the Composite extension, and Windows 2000 and later.
+ This feature is available on Embedded Linux, Mac OS X, Windows,
+ and X11 platforms that support the Composite extension.
This feature is not available on Windows CE.
@@ -10318,7 +10689,7 @@ void QWidget::setShortcutAutoRepeat(int id, bool enable)
*/
void QWidget::updateMicroFocus()
{
-#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS))
+#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
Q_D(QWidget);
// and optimisation to update input context only it has already been created.
if (d->ic || qApp->d_func()->inputContext) {
@@ -11123,8 +11494,6 @@ Q_GUI_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
}
-
-
#ifndef QT_NO_GRAPHICSVIEW
/*!
\since 4.5
@@ -11452,6 +11821,67 @@ void QWidget::clearMask()
setMask(QRegion());
}
+/*!
+ \preliminary
+ \since 4.6
+
+ Returns the (possibly empty) list of this widget's softkeys.
+ Returned list cannot be changed. Softkeys should be added
+ and removed via method called setSoftKeys
+
+ \sa setSoftKey(), setSoftKeys()
+*/
+const QList<QAction*>& QWidget::softKeys() const
+{
+ Q_D(const QWidget);
+ if( d->softKeys.count() > 0)
+ return d->softKeys;
+ if (isWindow() || !parentWidget())
+ return d->softKeys;
+
+ return parentWidget()->softKeys();
+}
+
+/*!
+ \preliminary
+ \since 4.6
+
+ Sets the softkey \a softKey to this widget's list of softkeys.
+ Setting 0 as softkey will clear all the existing softkeys set
+ to the widget. A QWidget can have 0 or more softkeys.
+
+ \sa softKeys(), setSoftKeys()
+*/
+void QWidget::setSoftKey(QAction *softKey)
+{
+ Q_D(QWidget);
+ qDeleteAll(d->softKeys);
+ d->softKeys.clear();
+ if (softKey)
+ d->softKeys.append(softKey);
+ if ((!QApplication::focusWidget() && this == QApplication::activeWindow())
+ || QApplication::focusWidget() == this)
+ d->setSoftKeys_sys(this->softKeys());
+}
+
+/*!
+ Sets the list of softkeys \a softKeys to this widget's list of softkeys.
+ A QWidget can have 0 or more softkeys.
+
+ \sa softKeys(), setSoftKey()
+*/
+void QWidget::setSoftKeys(const QList<QAction*> &softKeys)
+{
+ Q_D(QWidget);
+ qDeleteAll(d->softKeys);
+ d->softKeys.clear();
+ d->softKeys = softKeys;
+
+ if ((!QApplication::focusWidget() && this == QApplication::activeWindow())
+ || QApplication::focusWidget() == this)
+ d->setSoftKeys_sys(this->softKeys());
+}
+
/*! \fn const QX11Info &QWidget::x11Info() const
Returns information about the configuration of the X display used to display
the widget.
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 0bb95a4..38650f0 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -95,6 +95,8 @@ class QIcon;
class QWindowSurface;
class QLocale;
class QGraphicsProxyWidget;
+class QGestureManager;
+class QGraphicsEffect;
#if defined(Q_WS_X11)
class QX11Info;
#endif
@@ -130,7 +132,7 @@ public:
int alloc_region_index;
// int alloc_region_revision;
#endif
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
uint window_state_internal : 4;
#endif
QRect wrect;
@@ -212,6 +214,7 @@ class Q_GUI_EXPORT QWidget : public QObject, public QPaintDevice
#endif
Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET unsetLocale)
Q_PROPERTY(QString windowFilePath READ windowFilePath WRITE setWindowFilePath DESIGNABLE isWindow)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
public:
enum RenderFlag {
@@ -351,6 +354,9 @@ public:
const QRegion &sourceRegion = QRegion(),
RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));
+ QGraphicsEffect *graphicsEffect() const;
+ void setGraphicsEffect(QGraphicsEffect *effect);
+
public Q_SLOTS:
void setWindowTitle(const QString &);
#ifndef QT_NO_STYLE_STYLESHEET
@@ -469,7 +475,7 @@ public Q_SLOTS:
virtual void setVisible(bool visible);
inline void setHidden(bool hidden) { setVisible(!hidden); }
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
inline void show() { setVisible(true); }
#else
void show();
@@ -539,6 +545,7 @@ public:
QWidget *focusWidget() const;
QWidget *nextInFocusChain() const;
+ QWidget *previousInFocusChain() const;
// drag and drop
bool acceptDrops() const;
@@ -553,6 +560,9 @@ public:
void removeAction(QAction *action);
QList<QAction*> actions() const;
#endif
+ const QList<QAction*>& softKeys() const;
+ void setSoftKey(QAction *softKey);
+ void setSoftKeys(const QList<QAction*> &softKeys);
QWidget *parentWidget() const;
@@ -673,6 +683,10 @@ protected:
virtual void inputMethodEvent(QInputMethodEvent *);
public:
virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const;
+
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
+
protected:
void resetInputContext();
protected Q_SLOTS:
@@ -723,6 +737,7 @@ private:
friend class QGraphicsProxyWidget;
friend class QGraphicsProxyWidgetPrivate;
friend class QStyleSheetStyle;
+ friend struct QWidgetExceptionCleaner;
#ifdef Q_WS_MAC
friend class QCoreGraphicsPaintEnginePrivate;
@@ -744,6 +759,10 @@ private:
friend bool isWidgetOpaque(const QWidget *);
friend class QGLWidgetPrivate;
#endif
+#ifdef Q_OS_SYMBIAN
+ friend class QSymbianControl;
+ friend class QS60WindowSurface;
+#endif
#ifdef Q_WS_X11
friend void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
friend void qt_net_remove_user_time(QWidget *tlw);
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index 00f658e..6869887 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -72,7 +72,6 @@
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/
-//#define QT_RASTER_PAINTENGINE
#include <private/qt_mac_p.h>
#include <private/qeventdispatcher_mac_p.h>
@@ -83,13 +82,11 @@
#include "qcursor.h"
#include "qdesktopwidget.h"
#include "qevent.h"
+#include "qfileinfo.h"
#include "qimage.h"
#include "qlayout.h"
#include "qmenubar.h"
#include <private/qbackingstore_p.h>
-#ifdef QT_RASTER_PAINTENGINE
-# include <private/qpaintengine_raster_p.h>
-#endif
#include <private/qwindowsurface_mac_p.h>
#include <private/qpaintengine_mac_p.h>
#include "qpainter.h"
@@ -110,6 +107,7 @@
#include <private/qcocoapanel_mac_p.h>
#include "qwidget_p.h"
+#include "qevent_p.h"
#include "qdnd_p.h"
#include <QtGui/qgraphicsproxywidget.h>
@@ -303,6 +301,14 @@ bool qt_mac_is_macdrawer(const QWidget *w)
return (w && w->parentWidget() && w->windowType() == Qt::Drawer);
}
+bool qt_mac_insideKeyWindow(const QWidget *w)
+{
+#ifdef QT_MAC_USE_COCOA
+ return [[reinterpret_cast<NSView *>(w->winId()) window] isKeyWindow];
+#endif
+ return false;
+}
+
bool qt_mac_set_drawer_preferred_edge(QWidget *w, Qt::DockWidgetArea where) //users of Qt for Mac OS X can use this..
{
if(!qt_mac_is_macdrawer(w))
@@ -390,21 +396,15 @@ QWidget *qt_mac_find_window(OSWindowRef window)
inline static void qt_mac_set_fullscreen_mode(bool b)
{
- extern bool qt_mac_app_fullscreen; //qapplication_mac.cpp
+ extern bool qt_mac_app_fullscreen; //qapplication_mac.mm
if(qt_mac_app_fullscreen == b)
return;
qt_mac_app_fullscreen = b;
-#if QT_MAC_USE_COCOA
- if(b)
- SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
- else
+ if (b) {
+ SetSystemUIMode(kUIModeAllSuppressed, 0);
+ } else {
SetSystemUIMode(kUIModeNormal, 0);
-#else
- if(b)
- HideMenuBar();
- else
- ShowMenuBar();
-#endif
+ }
}
Q_GUI_EXPORT OSViewRef qt_mac_nativeview_for(const QWidget *w)
@@ -511,16 +511,9 @@ static void qt_mac_release_window_group(WindowGroupRef group)
SInt32 qt_mac_get_group_level(WindowClass wclass)
{
SInt32 group_level;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- CGWindowLevel tmpLevel;
- GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel);
- group_level = tmpLevel;
- } else
-#endif
- {
- GetWindowGroupLevel(GetWindowGroupOfClass(wclass), &group_level);
- }
+ CGWindowLevel tmpLevel;
+ GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel);
+ group_level = tmpLevel;
return group_level;
}
#endif
@@ -734,6 +727,7 @@ static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAtt
static EventTypeSpec window_events[] = {
{ kEventClassWindow, kEventWindowClose },
{ kEventClassWindow, kEventWindowExpanded },
+ { kEventClassWindow, kEventWindowHidden },
{ kEventClassWindow, kEventWindowZoomed },
{ kEventClassWindow, kEventWindowCollapsed },
{ kEventClassWindow, kEventWindowToolbarSwitchMode },
@@ -741,12 +735,16 @@ static EventTypeSpec window_events[] = {
{ kEventClassWindow, kEventWindowProxyEndDrag },
{ kEventClassWindow, kEventWindowResizeCompleted },
{ kEventClassWindow, kEventWindowBoundsChanging },
- { kEventClassWindow, kEventWindowBoundsChanged },
{ kEventClassWindow, kEventWindowGetRegion },
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
{ kEventClassWindow, kEventWindowGetClickModality },
-#endif
{ kEventClassWindow, kEventWindowTransitionCompleted },
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ { kEventClassGesture, kEventGestureStarted },
+ { kEventClassGesture, kEventGestureEnded },
+ { kEventClassGesture, kEventGestureMagnify },
+ { kEventClassGesture, kEventGestureSwipe },
+ { kEventClassGesture, kEventGestureRotate },
+#endif
{ kEventClassMouse, kEventMouseDown }
};
static EventHandlerUPP mac_win_eventUPP = 0;
@@ -775,7 +773,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event,
QWidget *widget = qt_mac_find_window(wid);
if(!widget) {
handled_event = false;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
} else if(ekind == kEventWindowGetClickModality) {
// Carbon will send us kEventWindowGetClickModality before every
// mouse press / release event. By returning 'true', we tell Carbon
@@ -786,7 +783,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event,
// By also setting the current modal window back into the event, we
// help Carbon determining which window is supposed to be raised.
handled_event = qApp->activePopupWidget() ? true : false;
-#endif
} else if(ekind == kEventWindowClose) {
widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
QMenuBar::macUpdateMenuBar();
@@ -860,8 +856,7 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event,
extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
qt_button_down = 0;
} else if(ekind == kEventWindowToolbarSwitchMode) {
- QToolBarChangeEvent ev(!(GetCurrentKeyModifiers() & cmdKey));
- QApplication::sendSpontaneousEvent(widget, &ev);
+ macSendToolbarChangeEvent(widget);
HIToolbarRef toolbar;
if (GetWindowToolbar(wid, &toolbar) == noErr) {
if (toolbar) {
@@ -909,90 +904,94 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event,
SetEventParameter(mouseUpEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pos), &pos);
SendEventToApplication(mouseUpEvent);
ReleaseEvent(mouseUpEvent);
- } else if(ekind == kEventWindowBoundsChanging || ekind == kEventWindowBoundsChanged) {
- // Panther doesn't send Changing for sheets, only changed, so only
- // bother handling Changed event if we are on 10.3 and we are a
- // sheet.
- if (ekind == kEventWindowBoundsChanged
- && (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4
- || !(widget->windowFlags() & Qt::Sheet))) {
- handled_event = false;
+ } else if(ekind == kEventWindowBoundsChanging) {
+ UInt32 flags = 0;
+ GetEventParameter(event, kEventParamAttributes, typeUInt32, 0,
+ sizeof(flags), 0, &flags);
+ Rect nr;
+ GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, 0,
+ sizeof(nr), 0, &nr);
+
+ QRect newRect(nr.left, nr.top, nr.right - nr.left, nr.bottom - nr.top);
+
+ QTLWExtra * const tlwExtra = widget->d_func()->maybeTopData();
+ if (tlwExtra && tlwExtra->isSetGeometry == 1) {
+ widget->d_func()->setGeometry_sys_helper(newRect.left(), newRect.top(), newRect.width(), newRect.height(), tlwExtra->isMove);
} else {
- UInt32 flags = 0;
- GetEventParameter(event, kEventParamAttributes, typeUInt32, 0,
- sizeof(flags), 0, &flags);
- Rect nr;
- GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, 0,
- sizeof(nr), 0, &nr);
-
- QRect newRect(nr.left, nr.top, nr.right - nr.left, nr.bottom - nr.top);
-
- QTLWExtra * const tlwExtra = widget->d_func()->maybeTopData();
- if (tlwExtra && tlwExtra->isSetGeometry == 1) {
- widget->d_func()->setGeometry_sys_helper(newRect.left(), newRect.top(), newRect.width(), newRect.height(), tlwExtra->isMove);
- } else {
- //implicitly removes the maximized bit
- if((widget->data->window_state & Qt::WindowMaximized) &&
- IsWindowInStandardState(wid, 0, 0)) {
- widget->data->window_state &= ~Qt::WindowMaximized;
- QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state
- | Qt::WindowMaximized));
- QApplication::sendSpontaneousEvent(widget, &e);
+ //implicitly removes the maximized bit
+ if((widget->data->window_state & Qt::WindowMaximized) &&
+ IsWindowInStandardState(wid, 0, 0)) {
+ widget->data->window_state &= ~Qt::WindowMaximized;
+ QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state
+ | Qt::WindowMaximized));
+ QApplication::sendSpontaneousEvent(widget, &e);
- }
+ }
- handled_event = false;
- const QRect oldRect = widget->data->crect;
- if((flags & kWindowBoundsChangeOriginChanged)) {
- if(nr.left != oldRect.x() || nr.top != oldRect.y()) {
- widget->data->crect.moveTo(nr.left, nr.top);
- QMoveEvent qme(widget->data->crect.topLeft(), oldRect.topLeft());
- QApplication::sendSpontaneousEvent(widget, &qme);
- }
+ handled_event = false;
+ const QRect oldRect = widget->data->crect;
+ if((flags & kWindowBoundsChangeOriginChanged)) {
+ if(nr.left != oldRect.x() || nr.top != oldRect.y()) {
+ widget->data->crect.moveTo(nr.left, nr.top);
+ QMoveEvent qme(widget->data->crect.topLeft(), oldRect.topLeft());
+ QApplication::sendSpontaneousEvent(widget, &qme);
}
- if((flags & kWindowBoundsChangeSizeChanged)) {
- if (widget->isWindow()) {
- QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size());
- int dh = newSize.height() - newRect.height();
- int dw = newSize.width() - newRect.width();
- if (dw != 0 || dh != 0) {
- handled_event = true; // We want to change the bounds, so we handle the event
-
- // set the rect, so we can also do the resize down below (yes, we need to resize).
- newRect.setBottom(newRect.bottom() + dh);
- newRect.setRight(newRect.right() + dw);
-
- nr.left = newRect.x();
- nr.top = newRect.y();
- nr.right = nr.left + newRect.width();
- nr.bottom = nr.top + newRect.height();
- SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &nr);
- }
+ }
+ if((flags & kWindowBoundsChangeSizeChanged)) {
+ if (widget->isWindow()) {
+ QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size());
+ int dh = newSize.height() - newRect.height();
+ int dw = newSize.width() - newRect.width();
+ if (dw != 0 || dh != 0) {
+ handled_event = true; // We want to change the bounds, so we handle the event
+
+ // set the rect, so we can also do the resize down below (yes, we need to resize).
+ newRect.setBottom(newRect.bottom() + dh);
+ newRect.setRight(newRect.right() + dw);
+
+ nr.left = newRect.x();
+ nr.top = newRect.y();
+ nr.right = nr.left + newRect.width();
+ nr.bottom = nr.top + newRect.height();
+ SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &nr);
}
+ }
- if (oldRect.width() != newRect.width() || oldRect.height() != newRect.height()) {
- widget->data->crect.setSize(newRect.size());
- HIRect bounds = CGRectMake(0, 0, newRect.width(), newRect.height());
-
- // If the WA_StaticContents attribute is set we can optimize the resize
- // by only repainting the newly exposed area. We do this by disabling
- // painting when setting the size of the view. The OS will invalidate
- // the newly exposed area for us.
- const bool staticContents = widget->testAttribute(Qt::WA_StaticContents);
- const HIViewRef view = qt_mac_nativeview_for(widget);
- if (staticContents)
- HIViewSetDrawingEnabled(view, false);
- HIViewSetFrame(view, &bounds);
- if (staticContents)
- HIViewSetDrawingEnabled(view, true);
-
- QResizeEvent qre(newRect.size(), oldRect.size());
- QApplication::sendSpontaneousEvent(widget, &qre);
- qt_event_request_window_change(widget);
- }
+ if (oldRect.width() != newRect.width() || oldRect.height() != newRect.height()) {
+ widget->data->crect.setSize(newRect.size());
+ HIRect bounds = CGRectMake(0, 0, newRect.width(), newRect.height());
+
+ // If the WA_StaticContents attribute is set we can optimize the resize
+ // by only repainting the newly exposed area. We do this by disabling
+ // painting when setting the size of the view. The OS will invalidate
+ // the newly exposed area for us.
+ const bool staticContents = widget->testAttribute(Qt::WA_StaticContents);
+ const HIViewRef view = qt_mac_nativeview_for(widget);
+ if (staticContents)
+ HIViewSetDrawingEnabled(view, false);
+ HIViewSetFrame(view, &bounds);
+ if (staticContents)
+ HIViewSetDrawingEnabled(view, true);
+
+ QResizeEvent qre(newRect.size(), oldRect.size());
+ QApplication::sendSpontaneousEvent(widget, &qre);
+ qt_event_request_window_change(widget);
}
}
}
+ } else if (ekind == kEventWindowHidden) {
+ // Make sure that we also hide any visible sheets on our window.
+ // Cocoa does the right thing for us.
+ const QObjectList children = widget->children();
+ const int childCount = children.count();
+ for (int i = 0; i < childCount; ++i) {
+ QObject *obj = children.at(i);
+ if (obj->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget *>(obj);
+ if (qt_mac_is_macsheet(widget) && widget->isVisible())
+ widget->hide();
+ }
+ }
} else {
handled_event = false;
}
@@ -1030,6 +1029,76 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event,
return SendEventToApplication(event);
handled_event = false;
break; }
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ case kEventClassGesture: {
+ // First, find the widget that was under
+ // the mouse when the gesture happened:
+ HIPoint screenLocation;
+ if (GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, 0,
+ sizeof(screenLocation), 0, &screenLocation) != noErr) {
+ handled_event = false;
+ break;
+ }
+ QWidget *widget = QApplication::widgetAt(screenLocation.x, screenLocation.y);
+ if (!widget) {
+ handled_event = false;
+ break;
+ }
+
+ QNativeGestureEvent qNGEvent;
+ qNGEvent.position = QPoint(screenLocation.x, screenLocation.y);
+
+ switch (ekind) {
+ case kEventGestureStarted:
+ qNGEvent.gestureType = QNativeGestureEvent::GestureBegin;
+ break;
+ case kEventGestureEnded:
+ qNGEvent.gestureType = QNativeGestureEvent::GestureEnd;
+ break;
+ case kEventGestureRotate: {
+ CGFloat amount;
+ if (GetEventParameter(event, kEventParamRotationAmount, typeCGFloat, 0,
+ sizeof(amount), 0, &amount) != noErr) {
+ handled_event = false;
+ break;
+ }
+ qNGEvent.gestureType = QNativeGestureEvent::Rotate;
+ qNGEvent.percentage = float(-amount);
+ break; }
+ case kEventGestureSwipe: {
+ HIPoint swipeDirection;
+ if (GetEventParameter(event, kEventParamSwipeDirection, typeHIPoint, 0,
+ sizeof(swipeDirection), 0, &swipeDirection) != noErr) {
+ handled_event = false;
+ break;
+ }
+ qNGEvent.gestureType = QNativeGestureEvent::Swipe;
+ if (swipeDirection.x == 1)
+ qNGEvent.angle = 180.0f;
+ else if (swipeDirection.x == -1)
+ qNGEvent.angle = 0.0f;
+ else if (swipeDirection.y == 1)
+ qNGEvent.angle = 90.0f;
+ else if (swipeDirection.y == -1)
+ qNGEvent.angle = 270.0f;
+ break; }
+ case kEventGestureMagnify: {
+ CGFloat amount;
+ if (GetEventParameter(event, kEventParamMagnificationAmount, typeCGFloat, 0,
+ sizeof(amount), 0, &amount) != noErr) {
+ handled_event = false;
+ break;
+ }
+ qNGEvent.gestureType = QNativeGestureEvent::Zoom;
+ qNGEvent.percentage = float(amount);
+ break; }
+ }
+
+ QApplication::sendSpontaneousEvent(widget, &qNGEvent);
+ break; }
+#endif // gestures
+
default:
handled_event = false;
}
@@ -1129,23 +1198,9 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event,
//update handles
GrafPtr qd = 0;
CGContextRef cg = 0;
-#ifndef QT_MAC_NO_QUICKDRAW
- {
- if(GetEventParameter(event, kEventParamGrafPort, typeGrafPtr, 0, sizeof(qd), 0, &qd) != noErr) {
- GDHandle dev = 0;
- GetGWorld(&qd, &dev); //just use the global port..
- }
- }
- bool end_cg_context = false;
- if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr && qd) {
- end_cg_context = true;
- QDBeginCGContext(qd, &cg);
- }
-#else
if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr) {
Q_ASSERT(false);
}
-#endif
widget->d_func()->hd = cg;
widget->d_func()->qd_hd = qd;
CGContextSaveGState(cg);
@@ -1211,22 +1266,13 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event,
p.setClipping(false);
if(was_unclipped)
widget->setAttribute(Qt::WA_PaintUnclipped);
-
- QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(widget->parent());
- QPoint scrollAreaOffset;
- if (scrollArea && scrollArea->viewport() == widget) {
- QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(static_cast<QWidget *>(scrollArea)->d_ptr);
- scrollAreaOffset = priv->contentsOffset();
- p.translate(-scrollAreaOffset);
- }
-
- widget->d_func()->paintBackground(&p, qrgn, scrollAreaOffset, widget->isWindow() ? DrawAsRoot : 0);
+ widget->d_func()->paintBackground(&p, qrgn, widget->isWindow() ? DrawAsRoot : 0);
if (widget->testAttribute(Qt::WA_TintedBackground)) {
QColor tint = widget->palette().window().color();
tint.setAlphaF(.6);
const QVector<QRect> &rects = qrgn.rects();
for (int i = 0; i < rects.size(); ++i)
- p.fillRect(rects.at(i).translated(scrollAreaOffset), tint);
+ p.fillRect(rects.at(i), tint);
}
p.end();
if (!redirectionOffset.isNull())
@@ -1256,11 +1302,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event,
QApplication::sendSpontaneousEvent(widget, &e);
if (!redirectionOffset.isNull())
widget->d_func()->restoreRedirected();
-#ifdef QT_RASTER_PAINTENGINE
- if(engine && engine->type() == QPaintEngine::Raster)
- static_cast<QRasterPaintEngine*>(engine)->flush(widget,
- qrgn.boundingRect().topLeft());
-#endif
//cleanup
if (engine)
@@ -1274,10 +1315,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event,
widget->d_func()->hd = 0;
widget->d_func()->qd_hd = 0;
CGContextRestoreGState(cg);
-#ifndef QT_MAC_NO_QUICKDRAW
- if(end_cg_context)
- QDEndCGContext(qd, &cg);
-#endif
} else if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) {
CallNextEventHandler(er, event);
}
@@ -1382,6 +1419,14 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event,
// Set dropWidget to zero, so qt_mac_dnd_event
// doesn't get called a second time below:
dropWidget = 0;
+ } else if (ekind == kEventControlDragLeave) {
+ dropWidget = QDragManager::self()->currentTarget();
+ if (dropWidget) {
+ dropWidget->d_func()->qt_mac_dnd_event(kEventControlDragLeave, drag);
+ }
+ // Set dropWidget to zero, so qt_mac_dnd_event
+ // doesn't get called a second time below:
+ dropWidget = 0;
}
}
}
@@ -1598,24 +1643,6 @@ bool QWidgetPrivate::qt_create_root_win()
return true;
}
-bool QWidgetPrivate::qt_recreate_root_win()
-{
- if(!qt_root_win) //sanity check
- return false;
- //store old
- OSWindowRef old_root_win = qt_root_win;
- //recreate
- qt_root_win = 0;
- qt_create_root_win();
- //cleanup old window
-#ifdef QT_MAC_USE_COCOA
- [old_root_win release];
-#else
- CFRelease(old_root_win);
-#endif
- return true;
-}
-
bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, bool force = false)
{
bool ret = false;
@@ -1716,17 +1743,11 @@ void QWidgetPrivate::determineWindowClass()
bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint)));
if (framelessWindow) {
if(wclass == kDocumentWindowClass) {
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- wattr |= kWindowNoTitleBarAttribute;
- else
- wclass = kPlainWindowClass;
+ wattr |= kWindowNoTitleBarAttribute;
} else if(wclass == kFloatingWindowClass) {
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- wattr |= kWindowNoTitleBarAttribute;
- else
- wclass = kToolbarWindowClass;
+ wattr |= kWindowNoTitleBarAttribute;
} else if (wclass == kMovableModalWindowClass) {
- wclass = kModalWindowClass;
+ wclass = kModalWindowClass;
}
} else {
if(wclass != kModalWindowClass)
@@ -2024,14 +2045,10 @@ void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef)
if (!desktop)
SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true);
HIWindowChangeFeatures(windowRef, kWindowCanCollapse, 0);
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- if (wattr & kWindowHideOnSuspendAttribute)
- HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0);
- else
- HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden);
- }
-#endif
+ if (wattr & kWindowHideOnSuspendAttribute)
+ HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0);
+ else
+ HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden);
if ((flags & Qt::WindowStaysOnTopHint))
ChangeWindowAttributes(windowRef, kWindowNoAttributes, kWindowHideOnSuspendAttribute);
if (qt_mac_is_macdrawer(q) && parentWidget)
@@ -2305,7 +2322,7 @@ void QWidgetPrivate::createWindow_sys()
OSWindowRef windowRef = qt_mac_create_window(q, topExtra->wclass, wattr, data.crect);
if (windowRef == 0)
- qWarning("QWidget: Internal error: %s:%d: If you reach this error please contact Trolltech and include the\n"
+ qWarning("QWidget: Internal error: %s:%d: If you reach this error please contact Qt Support and include the\n"
" WidgetFlags used in creating the widget.", __FILE__, __LINE__);
#ifndef QT_MAC_USE_COCOA
finishCreateWindow_sys_Carbon(windowRef);
@@ -2524,9 +2541,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
setFocus_sys();
if (!topLevel && initializeWindow)
setWSGeometry();
-
if (destroyid)
qt_mac_destructView(destroyid);
+ if (q->testAttribute(Qt::WA_AcceptTouchEvents))
+ registerTouchWindow();
}
/*!
@@ -2564,7 +2582,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
{
Q_D(QWidget);
if (!isWindow() && parentWidget())
- parentWidget()->d_func()->invalidateBuffer(geometry());
+ parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
d->deactivateWidgetCleanup();
qt_mac_event_release(this);
if(testAttribute(Qt::WA_WState_Created)) {
@@ -2615,7 +2633,11 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
qt_mac_destructWindow(window);
}
}
- d->setWinId(0);
+ QT_TRY {
+ d->setWinId(0);
+ } QT_CATCH (const std::bad_alloc &) {
+ // swallow - destructors must not throw
+ }
}
}
@@ -2666,7 +2688,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
OSViewRef old_id = 0;
if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
- q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
+ q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
// Maintain the glWidgets list on parent change: remove "our" gl widgets
// from the list on the old parent and grandparents.
@@ -2897,8 +2919,7 @@ void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
SetWindowTitleWithCFString(qt_mac_window_for(q), QCFString(caption));
#else
QMacCocoaAutoReleasePool pool;
- [qt_mac_window_for(q)
- setTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(caption)))];
+ [qt_mac_window_for(q) setTitle:qt_mac_QStringToNSString(caption)];
#endif
}
}
@@ -2920,7 +2941,8 @@ void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
Q_Q(QWidget);
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
- [qt_mac_window_for(q) setRepresentedFilename:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(filePath)))];
+ QFileInfo fi(filePath);
+ [qt_mac_window_for(q) setRepresentedFilename:fi.exists() ? qt_mac_QStringToNSString(filePath) : @""];
#else
bool validRef = false;
FSRef ref;
@@ -2933,21 +2955,10 @@ void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
}
// Set the proxy regardless, since this is our way of clearing it as well, but ignore the
// return value as well.
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- if (validRef) {
- status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref);
- } else {
- status = RemoveWindowProxy(qt_mac_window_for(q));
- }
+ if (validRef) {
+ status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref);
} else {
- // Convert to an FSSpec and set it. It's deprecated but it works for where we don't have the other call.
- if (validRef) {
- FSSpec fsspec;
- FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, 0, &fsspec, 0);
- status = SetWindowProxyFSSpec(qt_mac_window_for(q), &fsspec);
- } else {
- status = RemoveWindowProxy(qt_mac_window_for(q));
- }
+ status = RemoveWindowProxy(qt_mac_window_for(q));
}
if (status != noErr)
qWarning("QWidget::setWindowFilePath: Error setting proxyicon for path (%s):%ld",
@@ -3021,8 +3032,7 @@ void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
SetWindowAlternateTitle(qt_mac_window_for(q), QCFString(iconText));
#else
QMacCocoaAutoReleasePool pool;
- [qt_mac_window_for(q)
- setMiniwindowTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(iconText)))];
+ [qt_mac_window_for(q) setMiniwindowTitle:qt_mac_QStringToNSString(iconText)];
#endif
}
}
@@ -3155,16 +3165,9 @@ void QWidgetPrivate::update_sys(const QRect &r)
if (updateRedirectedToGraphicsProxyWidget(q, updateRect))
return;
#ifndef QT_MAC_USE_COCOA
-# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- dirtyOnWidget += updateRect;
- HIRect r = CGRectMake(x, y, w, h);
- HIViewSetNeedsDisplayInRect(qt_mac_nativeview_for(q), &r, true);
- } else
- #endif
- {
- q->update(QRegion(updateRect));
- }
+ dirtyOnWidget += updateRect;
+ HIRect r = CGRectMake(x, y, w, h);
+ HIViewSetNeedsDisplayInRect(qt_mac_nativeview_for(q), &r, true);
#else
[qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(x, y, w, h)];
#endif
@@ -3178,7 +3181,12 @@ void QWidgetPrivate::update_sys(const QRegion &rgn)
return;
dirtyOnWidget += rgn;
#ifndef QT_MAC_USE_COCOA
- HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgn.toQDRgn()), true);
+ RgnHandle rgnHandle = rgn.toQDRgnForUpdate_sys();
+ if (rgnHandle)
+ HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgnHandle), true);
+ else {
+ HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow.
+ }
#else
// Cocoa doesn't do regions, it seems more efficient to just update the bounding rect instead of a potential number of message passes for each rect.
const QRect &boundingRect = rgn.boundingRect();
@@ -3270,10 +3278,13 @@ void QWidgetPrivate::show_sys()
#else
// sync the opacity value back (in case of a fade).
[window setAlphaValue:q->windowOpacity()];
-
[window makeKeyAndOrderFront:window];
+
+ // If this window is app modal, we need to start spinning
+ // a modal session for it. Interrupting
+ // the event dispatcher will make this happend:
if (data.window_modality == Qt::ApplicationModal)
- QCoreApplication::postEvent(qApp, new QEvent(QEvent::CocoaRequestModal));
+ QEventDispatcherMac::instance()->interrupt();
#endif
if (q->windowType() == Qt::Popup) {
if (q->focusWidget())
@@ -3291,13 +3302,6 @@ void QWidgetPrivate::show_sys()
#endif
} else if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) {
qt_event_request_activate(q);
-#ifdef QT_MAC_USE_COCOA
- if (q->windowModality() == Qt::ApplicationModal) {
- // We call 'activeModalSession' early to force creation of q's modal
- // session. This seems neccessary for child dialogs to pop to front:
- QEventDispatcherMacPrivate::activeModalSession();
- }
-#endif
}
} else if(topData()->embedded || !q->parentWidget() || q->parentWidget()->isVisible()) {
#ifndef QT_MAC_USE_COCOA
@@ -3882,8 +3886,6 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
Qt coordinate system for parent
X coordinate system for parent (relative to parent's wrect).
*/
- QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
- QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
QRect wrect;
//xrect is the X geometry of my X widget. (starts out in parent's Qt coord sys, and ends up in parent's X coord sys)
QRect xrect = data.crect;
@@ -3905,6 +3907,7 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
parentWRect = QRect(tmpRect.origin.x, tmpRect.origin.y,
tmpRect.size.width, tmpRect.size.height);
} else {
+ const QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
parentWRect = wrectRange;
}
} else {
@@ -3960,15 +3963,24 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
}
}
+ const QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
if (!validRange.contains(xrect)) {
// we are too big, and must clip
- xrect &=wrectRange;
+ QPoint screenOffset(0, 0); // offset of the part being on screen
+ const QWidget *parentWidget = q->parentWidget();
+ while (parentWidget && !parentWidget->isWindow()) {
+ screenOffset -= parentWidget->data->crect.topLeft();
+ parentWidget = parentWidget->parentWidget();
+ }
+ QRect cropRect(screenOffset.x() - WRECT_MAX,
+ screenOffset.y() - WRECT_MAX,
+ 2*WRECT_MAX,
+ 2*WRECT_MAX);
+
+ xrect &=cropRect;
wrect = xrect;
- wrect.translate(-data.crect.topLeft());
- //parent's X coord system is equal to parent's Qt coord
- //sys, so we don't need to map xrect.
+ wrect.translate(-data.crect.topLeft()); // translate wrect in my Qt coordinates
}
-
}
// unmap if we are outside the valid window system coord system
@@ -4008,10 +4020,9 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
qt_mac_update_widget_posisiton(q, oldRect, xrect);
- if (jump) {
- updateSystemBackground();
+ if (jump)
q->update();
- }
+
if (mapWindow && !dontShow) {
q->setAttribute(Qt::WA_Mapped);
#ifndef QT_MAC_USE_COCOA
@@ -4173,12 +4184,12 @@ void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isM
setWSGeometry(false, oldRect);
if (isResize && QApplicationPrivate::graphicsSystem()) {
invalidateBuffer(q->rect());
- if (extra && !extra->mask.isEmpty()) {
+ if (extra && !graphicsEffect && !extra->mask.isEmpty()) {
QRegion oldRegion(extra->mask.translated(oldp));
oldRegion &= oldRect;
q->parentWidget()->d_func()->invalidateBuffer(oldRegion);
} else {
- q->parentWidget()->d_func()->invalidateBuffer(oldRect);
+ q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(oldRect));
}
}
}
@@ -4332,32 +4343,14 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
OSViewRef view = qt_mac_nativeview_for(q);
#ifndef QT_MAC_USE_COCOA
HIRect scrollrect = CGRectMake(r.x(), r.y(), r.width(), r.height());
-# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- OSStatus err = _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid);
- if (err) {
- // The only parameter that can go wrong, is the rect.
- qWarning("QWidget::scroll: Your rectangle was too big for the widget, clipping rect");
- scrollrect = CGRectMake(qMax(r.x(), 0), qMax(r.y(), 0),
- qMin(r.width(), q->width()), qMin(r.height(), q->height()));
- _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid);
- }
- } else {
- if (HIViewGetNeedsDisplay(view)) {
- q->update(valid_rect ? r : q->rect());
- return;
- }
- HIRect scrollrect = CGRectMake(r.x(), r.y(), r.width(), r.height());
- OSStatus err = HIViewScrollRect(view, valid_rect ? &scrollrect : 0, dx, dy);
- if (err) {
- // The only parameter that can go wrong, is the rect.
- qWarning("QWidget::scroll: Your rectangle was too big for the widget, clipping rect");
- scrollrect = CGRectMake(qMax(r.x(), 0), qMax(r.y(), 0),
- qMin(r.width(), q->width()), qMin(r.height(), q->height()));
- HIViewScrollRect(view, valid_rect ? &scrollrect : 0, dx, dy);
- }
+ OSStatus err = _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid);
+ if (err) {
+ // The only parameter that can go wrong, is the rect.
+ qWarning("QWidget::scroll: Your rectangle was too big for the widget, clipping rect");
+ scrollrect = CGRectMake(qMax(r.x(), 0), qMax(r.y(), 0),
+ qMin(r.width(), q->width()), qMin(r.height(), q->height()));
+ _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid);
}
-# endif
#else
NSRect scrollRect = valid_rect ? NSMakeRect(r.x(), r.y(), r.width(), r.height())
: NSMakeRect(0, 0, q->width(), q->height());
@@ -4385,20 +4378,9 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
}
}
- // ### Scroll the dirty regions as well, the following is not correct.
- QRegion displayRegion = r.isNull() ? dirtyOnWidget : (dirtyOnWidget & r);
- const QVector<QRect> &rects = dirtyOnWidget.rects();
- const QVector<QRect>::const_iterator end = rects.end();
- QVector<QRect>::const_iterator it = rects.begin();
- while (it != end) {
- const QRect rect = *it;
- const NSRect dirtyRect = NSMakeRect(rect.x() + dx, rect.y() + dy,
- rect.width(), rect.height());
- [view setNeedsDisplayInRect:dirtyRect];
- ++it;
- }
- [view scrollRect:scrollRect by:NSMakeSize(dx, dy)];
- // Yes, we potentially send a duplicate area, but I think Cocoa can handle it.
+ NSSize deltaSize = NSMakeSize(dx, dy);
+ [view translateRectsNeedingDisplayInRect:scrollRect by:deltaSize];
+ [view scrollRect:scrollRect by:deltaSize];
[view setNeedsDisplayInRect:deltaXRect];
[view setNeedsDisplayInRect:deltaYRect];
#endif // QT_MAC_USE_COCOA
@@ -4468,11 +4450,13 @@ void QWidgetPrivate::deleteSysExtra()
void QWidgetPrivate::createTLSysExtra()
{
+ extra->topextra->resizer = 0;
+ extra->topextra->isSetGeometry = 0;
+ extra->topextra->isMove = 0;
+ extra->topextra->wattr = 0;
extra->topextra->wclass = 0;
extra->topextra->group = 0;
extra->topextra->windowIcon = 0;
- extra->topextra->resizer = 0;
- extra->topextra->isSetGeometry = 0;
extra->topextra->savedWindowAttributesFromMaximized = 0;
}
@@ -4527,6 +4511,23 @@ void QWidgetPrivate::registerDropSite(bool on)
#endif
}
+void QWidgetPrivate::registerTouchWindow()
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6)
+ return;
+ Q_Q(QWidget);
+ if (!q->testAttribute(Qt::WA_WState_Created))
+ return;
+#ifndef QT_MAC_USE_COCOA
+ // Needs implementation!
+#else
+ NSView *view = qt_mac_nativeview_for(q);
+ [view setAcceptsTouchEvents:YES];
+#endif
+#endif
+}
+
void QWidgetPrivate::setMask_sys(const QRegion &region)
{
Q_UNUSED(region);
@@ -4547,14 +4548,6 @@ void QWidgetPrivate::setMask_sys(const QRegion &region)
#endif
}
-extern "C" {
- typedef struct CGSConnection *CGSConnectionRef;
- typedef struct CGSWindow *CGSWindowRef;
- extern OSStatus CGSSetWindowAlpha(CGSConnectionRef, CGSWindowRef, float);
- extern CGSWindowRef GetNativeWindowFromWindowRef(WindowRef);
- extern CGSConnectionRef _CGSDefaultConnection();
-}
-
void QWidgetPrivate::setWindowOpacity_sys(qreal level)
{
Q_Q(QWidget);
@@ -4567,12 +4560,11 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level)
if (!q->testAttribute(Qt::WA_WState_Created))
return;
-#if QT_MAC_USE_COCOA
OSWindowRef oswindow = qt_mac_window_for(q);
+#if QT_MAC_USE_COCOA
[oswindow setAlphaValue:level];
#else
- CGSSetWindowAlpha(_CGSDefaultConnection(),
- GetNativeWindowFromWindowRef(qt_mac_window_for(q)), level);
+ SetWindowAlpha(oswindow, level);
#endif
}
@@ -4644,21 +4636,6 @@ Q_GLOBAL_STATIC(QPaintEngineCleanupHandler, engineHandler)
QPaintEngine *QWidget::paintEngine() const
{
QPaintEngine *&pe = engineHandler()->engine;
-#ifdef QT_RASTER_PAINTENGINE
- if (!pe) {
- if(qgetenv("QT_MAC_USE_COREGRAPHICS").isNull())
- pe = new QRasterPaintEngine();
- else
- pe = new QCoreGraphicsPaintEngine();
- }
- if (pe->isActive()) {
- QPaintEngine *engine =
- qgetenv("QT_MAC_USE_COREGRAPHICS").isNull()
- ? (QPaintEngine*)new QRasterPaintEngine() : (QPaintEngine*)new QCoreGraphicsPaintEngine();
- engine->setAutoDestruct(true);
- return engine;
- }
-#else
if (!pe)
pe = new QCoreGraphicsPaintEngine();
if (pe->isActive()) {
@@ -4666,7 +4643,6 @@ QPaintEngine *QWidget::paintEngine() const
engine->setAutoDestruct(true);
return engine;
}
-#endif
return pe;
}
@@ -4926,11 +4902,9 @@ void QWidgetPrivate::macUpdateMetalAttribute()
if (layout)
layout->updateHIToolBarStatus();
ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalAttribute, 0);
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0);
+ ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0);
} else {
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalNoContentSeparatorAttribute);
+ ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalNoContentSeparatorAttribute);
ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalAttribute);
if (layout)
layout->updateHIToolBarStatus();
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 4bbedfc..ff0c453 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -57,9 +57,12 @@
#include "private/qobject_p.h"
#include "QtCore/qrect.h"
#include "QtCore/qlocale.h"
+#include "QtCore/qset.h"
#include "QtGui/qregion.h"
#include "QtGui/qsizepolicy.h"
#include "QtGui/qstyle.h"
+#include "QtGui/qapplication.h"
+#include <private/qgraphicseffect_p.h>
#ifdef Q_WS_WIN
#include "QtCore/qt_windows.h"
@@ -79,6 +82,14 @@
#include "QtGui/qscreen_qws.h"
#endif
+#if defined(Q_OS_SYMBIAN)
+class RDrawableWindow;
+class CCoeControl;
+// The following 2 defines may only be needed for s60. To be seen.
+const int SOFTKEYSTART=5000;
+const int SOFTKEYEND=5004;
+#endif
+
QT_BEGIN_NAMESPACE
// Extra QWidget data
@@ -99,93 +110,101 @@ class QWidgetItemV2;
class QStyle;
struct QTLWExtra {
+ // *************************** Cross-platform variables *****************************
+
+ // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
+ QIcon *icon; // widget icon
+ QPixmap *iconPixmap;
+ QWidgetBackingStore *backingStore;
+ QWindowSurface *windowSurface;
+ QPainter *sharedPainter;
+
+ // Implicit pointers (shared_null).
QString caption; // widget caption
QString iconText; // widget icon text
QString role; // widget role
QString filePath; // widget file path
- QIcon *icon; // widget icon
- QPixmap *iconPixmap;
+
+ // Other variables.
short incw, inch; // size increments
+ short basew, baseh; // base sizes
// frame strut, don't use these directly, use QWidgetPrivate::frameStrut() instead.
QRect frameStrut;
+ QRect normalGeometry; // used by showMin/maximized/FullScreen
+ Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
+
+ // *************************** Cross-platform bit fields ****************************
uint opacity : 8;
uint posFromMove : 1;
uint sizeAdjusted : 1;
uint inTopLevelResize : 1;
uint inRepaint : 1;
- QWidgetBackingStore *backingStore;
-#if defined(Q_WS_WIN)
- ulong savedFlags; // Save window flags while showing fullscreen
- uint embedded : 1; // window is embedded in another application
-#else
- Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
-#endif
- short basew, baseh; // base sizes
-#if defined(Q_WS_X11)
- WId parentWinId; // parent window Id (valid after reparenting)
- uint embedded : 1; // window is embedded in another Qt application
+ uint embedded : 1;
+
+ // *************************** Platform specific values (bit fields first) **********
+#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
uint spont_unmapped: 1; // window was spontaneously unmapped
uint dnd : 1; // DND properties installed
uint validWMState : 1; // is WM_STATE valid?
uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet
+ WId parentWinId; // parent window Id (valid after reparenting)
WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom
QPoint fullScreenOffset;
+#ifndef QT_NO_XSYNC
+ WId syncUpdateCounter;
+ ulong syncRequestTimestamp;
+ qint32 newCounterValueHi;
+ quint32 newCounterValueLo;
#endif
-#if defined(Q_WS_MAC)
+#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
+ HICON winIconBig; // internal big Windows icon
+ HICON winIconSmall; // internal small Windows icon
+#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
+ uint resizer : 4;
+ uint isSetGeometry : 1;
+ uint isMove : 1;
quint32 wattr;
quint32 wclass;
WindowGroupRef group;
IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys.
quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys()
- uint resizer : 4;
- uint isSetGeometry : 1;
- uint isMove : 1;
- uint embedded : 1;
-#endif
-#if defined(Q_WS_QWS) && !defined (QT_NO_QWS_MANAGER)
+#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
+#ifndef QT_NO_QWS_MANAGER
QWSManager *qwsManager;
#endif
-#if defined(Q_WS_WIN)
- HICON winIconBig; // internal big Windows icon
- HICON winIconSmall; // internal small Windows icon
+#elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN
+ uint activated : 1; // RWindowBase::Activated has been called
+ RDrawableWindow *rwindow;
#endif
- QRect normalGeometry; // used by showMin/maximized/FullScreen
- QWindowSurface *windowSurface;
- QPainter *sharedPainter;
};
struct QWExtra {
- qint32 minw, minh; // minimum size
- qint32 maxw, maxh; // maximum size
- QPointer<QWidget> focus_proxy;
-#ifndef QT_NO_CURSOR
- QCursor *curs;
-#endif
+ // *************************** Cross-platform variables *****************************
+
+ // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
+ void *glContext; // if the widget is hijacked by QGLWindowSurface
QTLWExtra *topextra; // only useful for TLWs
QGraphicsProxyWidget *proxyWidget; // if the widget is embedded
- void *glContext; // if the widget is hijacked by QGLWindowSurface
-#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
- QOleDropTarget *dropTarget; // drop target
- QList<QPointer<QWidget> > oleDropWidgets;
-#endif
-#if defined(Q_WS_X11)
- WId xDndProxy; // XDND forwarding to embedded windows
+#ifndef QT_NO_CURSOR
+ QCursor *curs;
#endif
+ QPointer<QStyle> style;
+ QPointer<QWidget> focus_proxy;
+
+ // Implicit pointers (shared_empty/shared_null).
QRegion mask; // widget mask
+ QString styleSheet;
+
+ // Other variables.
+ qint32 minw;
+ qint32 minh; // minimum size
+ qint32 maxw;
+ qint32 maxh; // maximum size
+ quint16 customDpiX;
+ quint16 customDpiY;
QSize staticContentsSize;
-//bit flags at the end to improve packing
-#if defined(Q_WS_WIN)
- uint shown_mode : 8; // widget show mode
-#ifndef QT_NO_DIRECT3D
- uint had_paint_on_screen : 1;
- uint had_no_system_bg : 1;
- uint had_auto_fill_bg : 1;
-#endif
-#endif
-#if defined(Q_WS_X11)
- uint compress_events : 1;
-#endif
+ // *************************** Cross-platform bit fields ****************************
uint explicitMinSize : 2;
uint explicitMaxSize : 2;
uint autoFillBackground : 1;
@@ -193,16 +212,22 @@ struct QWExtra {
uint inRenderWithPainter : 1;
uint hasMask : 1;
- QPointer<QStyle> style;
- QString styleSheet;
-
- quint16 customDpiX;
- quint16 customDpiY;
-#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ // *************************** Platform specific values (bit fields first) **********
+#if defined(Q_WS_WIN) // <----------------------------------------------------------- WIN
+#ifndef QT_NO_DRAGANDDROP
+ QOleDropTarget *dropTarget; // drop target
+ QList<QPointer<QWidget> > oleDropWidgets;
+#endif
+#elif defined(Q_WS_X11) // <--------------------------------------------------------- X11
+ uint compress_events : 1;
+ WId xDndProxy; // XDND forwarding to embedded windows
+#elif defined(Q_WS_MAC) // <------------------------------------------------------ MAC
+#ifdef QT_MAC_USE_COCOA
// Cocoa Mask stuff
QImage maskBits;
CGImageRef imageMask;
#endif
+#endif
};
class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate
@@ -210,19 +235,34 @@ class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QWidget)
public:
+ // *************************** Cross-platform ***************************************
+ enum DrawWidgetFlags {
+ DrawAsRoot = 0x01,
+ DrawPaintOnScreen = 0x02,
+ DrawRecursive = 0x04,
+ DrawInvisible = 0x08,
+ DontSubtractOpaqueChildren = 0x10,
+ DontSetCompositionMode = 0x20,
+ DontDrawOpaqueChildren = 0x40
+ };
+
+ enum CloseMode {
+ CloseNoEvent,
+ CloseWithEvent,
+ CloseWithSpontaneousEvent
+ };
+
+ // Functions.
explicit QWidgetPrivate(int version = QObjectPrivateVersion);
~QWidgetPrivate();
+ void setSoftKeys_sys(const QList<QAction*> &softkeys);
QWExtra *extraData() const;
QTLWExtra *topData() const;
QTLWExtra *maybeTopData() const;
QPainter *sharedPainter() const;
void setSharedPainter(QPainter *painter);
QWidgetBackingStore *maybeBackingStore() const;
-#ifdef Q_WS_QWS
- void setMaxWindowState_helper();
- void setFullScreenSize_helper();
-#endif
void init(QWidget *desktopWidget, Qt::WindowFlags f);
void create_sys(WId window, bool initializeWindow, bool destroyOldWindow);
void createRecursively();
@@ -243,22 +283,8 @@ public:
QPalette naturalWidgetPalette(uint inheritedMask) const;
void setMask_sys(const QRegion &);
-#ifdef Q_WS_WIN
- bool shouldShowMaximizeButton();
- void winUpdateIsOpaque();
-#endif
-
-#ifdef Q_WS_MAC
- void macUpdateSizeAttribute();
- void macUpdateHideOnSuspend();
- void macUpdateOpaqueSizeGrip();
- void macUpdateIgnoreMouseEvents();
- void macUpdateMetalAttribute();
- void macUpdateIsOpaque();
- void setEnabled_helper_sys(bool enable);
- bool isRealWindow() const;
- void adjustWithinMaxAndMinSize(int &w, int &h);
- void applyMaxAndMinSizeOnWindow();
+#ifdef Q_OS_SYMBIAN
+ void handleSymbianDeferredFocusChanged();
#endif
void raise_sys();
@@ -285,20 +311,9 @@ public:
void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false);
void inheritStyle();
- bool isBackgroundInherited() const;
-
void setUpdatesEnabled_helper(bool );
- void paintBackground(QPainter *, const QRegion &, const QPoint & = QPoint(), int flags = DrawAsRoot) const;
- enum DrawWidgetFlags {
- DrawAsRoot = 0x01,
- DrawPaintOnScreen = 0x02,
- DrawRecursive = 0x04,
- DrawInvisible = 0x08,
- DontSubtractOpaqueChildren = 0x10,
- DontSetCompositionMode = 0x20,
- DontDrawOpaqueChildren = 0x40
- };
+ void paintBackground(QPainter *, const QRegion &, int flags = DrawAsRoot) const;
bool isAboutToShow() const;
QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);
void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion,
@@ -321,10 +336,6 @@ public:
QWindowSurface *createDefaultWindowSurface();
QWindowSurface *createDefaultWindowSurface_sys();
void repaint_sys(const QRegion &rgn);
-#ifdef Q_WS_MAC
- void update_sys(const QRect &rect);
- void update_sys(const QRegion &rgn);
-#endif
QRect clipRect() const;
QRegion clipRegion() const;
@@ -335,42 +346,20 @@ public:
void updateIsOpaque();
void setOpaque(bool opaque);
void updateIsTranslucent();
- bool hasBackground() const;
bool paintOnScreen() const;
QRegion getOpaqueRegion() const;
const QRegion &getOpaqueChildren() const;
void setDirtyOpaqueRegion();
- QRegion opaqueChildren;
-
- enum CloseMode {
- CloseNoEvent,
- CloseWithEvent,
- CloseWithSpontaneousEvent
- };
bool close_helper(CloseMode mode);
- bool compositeEvent(QEvent *e);
void setWindowIcon_helper();
void setWindowIcon_sys(bool forceReset = false);
void setWindowOpacity_sys(qreal opacity);
-
void adjustQuitOnCloseAttribute();
-#if defined(Q_WS_X11)
- void setWindowRole();
- void sendStartupMessage(const char *message) const;
- void setNetWmWindowTypes();
- void x11UpdateIsOpaque();
-#endif
-
-#if defined (Q_WS_WIN)
- void reparentChildren();
-#endif
-
void scrollChildren(int dx, int dy);
-
void moveRect(const QRect &, int dx, int dy);
void scrollRect(const QRect &, int dx, int dy);
void invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize);
@@ -384,7 +373,6 @@ public:
void reparentFocusWidgets(QWidget *oldtlw);
static int pointToRect(const QPoint &p, const QRect &r);
- QRect fromOrToLayoutItemRect(const QRect &rect, int sign) const;
void setWinId(WId);
void showChildren(bool spontaneous);
@@ -394,9 +382,6 @@ public:
void scroll_sys(int dx, int dy, const QRect &r);
void deactivateWidgetCleanup();
void setGeometry_sys(int, int, int, int, bool);
-#ifdef Q_WS_MAC
- void setGeometry_sys_helper(int, int, int, int, bool);
-#endif
void sendPendingMoveAndResizeEvents(bool recursive = false, bool disableUpdates = false);
void activateChildLayoutsRecursively();
void show_recursive();
@@ -408,10 +393,6 @@ public:
void setEnabled_helper(bool);
void registerDropSite(bool);
-#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
- QOleDropTarget *registerOleDnd(QWidget *widget);
- void unregisterOleDnd(QWidget *widget, QOleDropTarget *target);
-#endif
static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = 0);
void updateFrameStrut();
@@ -421,32 +402,11 @@ public:
void setWindowIconText_helper(const QString &cap);
void setWindowTitle_sys(const QString &cap);
-#ifdef Q_OS_WIN
- void grabMouseWhileInWindow();
-#endif
-
#ifndef QT_NO_CURSOR
void setCursor_sys(const QCursor &cursor);
void unsetCursor_sys();
#endif
-#ifdef Q_WS_MAC
- void setWindowModified_sys(bool b);
- void updateMaximizeButton_sys();
- void setWindowFilePath_sys(const QString &filePath);
- void createWindow_sys();
- void recreateMacWindow();
-#ifndef QT_MAC_USE_COCOA
- void initWindowPtr();
- void finishCreateWindow_sys_Carbon(OSWindowRef windowRef);
-#else
- void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef);
- void syncCocoaMask();
- void finishCocoaMaskSetup();
-#endif
- void determineWindowClass();
- void transferChildren();
-#endif
void setWindowTitle_helper(const QString &cap);
void setWindowFilePath_helper(const QString &filePath);
@@ -462,59 +422,113 @@ public:
QInputContext *inputContext() const;
-#if defined(Q_WS_QWS)
- void moveSurface(QWindowSurface *surface, const QPoint &offset);
+ void setModal_sys();
- QRegion localRequestedRegion() const;
- QRegion localAllocatedRegion() const;
+ inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)
+ {
+ Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent));
+ redirectDev = replacement;
+ redirectOffset = offset;
+ }
- void blitToScreen(const QRegion &globalrgn);
-#ifndef QT_NO_CURSOR
- void updateCursor() const;
-#endif
+ inline QPaintDevice *redirected(QPoint *offset) const
+ {
+ if (offset)
+ *offset = redirectDev ? redirectOffset : QPoint();
+ return redirectDev;
+ }
- QScreen* getScreen() const;
+ inline void restoreRedirected()
+ { redirectDev = 0; }
- friend class QWSManager;
- friend class QWSManagerPrivate;
- friend class QDecoration;
-#endif
+ inline void enforceNativeChildren()
+ {
+ if (!extra)
+ createExtra();
- static int instanceCounter; // Current number of widget instances
- static int maxInstances; // Maximum number of widget instances
+ if (extra->nativeChildrenForced)
+ return;
+ extra->nativeChildrenForced = 1;
-#ifdef QT_KEYPAD_NAVIGATION
- static QPointer<QWidget> editingWidget;
-#endif
+ for (int i = 0; i < children.size(); ++i) {
+ if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
+ child->setAttribute(Qt::WA_NativeWindow);
+ }
+ }
- QWidgetData data;
+ inline bool nativeChildrenForced() const
+ {
+ return extra ? extra->nativeChildrenForced : false;
+ }
+
+ inline QRect effectiveRectFor(const QRect &rect) const
+ {
+ if (graphicsEffect && graphicsEffect->isEnabled())
+ return graphicsEffect->boundingRectFor(rect).toAlignedRect();
+ return rect;
+ }
+ QSize adjustedSize() const;
+
+ inline void handleSoftwareInputPanel(Qt::MouseButton button, bool clickCausedFocus)
+ {
+ Q_Q(QWidget);
+ if (button == Qt::LeftButton && qApp->autoSipEnabled()) {
+ QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
+ q->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
+ if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
+ QEvent event(QEvent::RequestSoftwareInputPanel);
+ QApplication::sendEvent(q, &event);
+ }
+ }
+ }
+
+#ifndef Q_WS_QWS // Almost cross-platform :-)
+ void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect());
+
+ inline QPoint mapToWS(const QPoint &p) const
+ { return p - data.wrect.topLeft(); }
+
+ inline QPoint mapFromWS(const QPoint &p) const
+ { return p + data.wrect.topLeft(); }
+
+ inline QRect mapToWS(const QRect &r) const
+ { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; }
+
+ inline QRect mapFromWS(const QRect &r) const
+ { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
+#endif
+
+ // Variables.
+ // Regular pointers (keep them together to avoid gaps on 64 bit architectures).
QWExtra *extra;
QWidget *focus_next;
QWidget *focus_prev;
QWidget *focus_child;
-#ifndef QT_NO_ACTION
- QList<QAction*> actions;
-#endif
+ QList<QAction*> softKeys;
QLayout *layout;
+ QRegion *needsFlush;
+ QPaintDevice *redirectDev;
QWidgetItemV2 *widgetItem;
+ QPaintEngine *extraPaintEngine;
+ mutable const QMetaObject *polished;
+ QGraphicsEffect *graphicsEffect;
+ // All widgets are added into the allWidgets set. Once
+ // they receive a window id they are also added to the mapper.
+ // This should just ensure that all widgets are deleted by QApplication
+ static QWidgetMapper *mapper;
+ static QWidgetSet *allWidgets;
#if !defined(QT_NO_IM)
QPointer<QInputContext> ic;
+ Qt::InputMethodHints imHints;
+#endif
+#ifdef QT_KEYPAD_NAVIGATION
+ static QPointer<QWidget> editingWidget;
#endif
- // All widgets are initially added into the uncreatedWidgets set. Once
- // they receive a window id they are removed and added to the mapper
- static QWidgetMapper *mapper;
- static QWidgetSet *uncreatedWidgets;
-
- short leftmargin, topmargin, rightmargin, bottommargin;
-
- signed char leftLayoutItemMargin;
- signed char topLayoutItemMargin;
- signed char rightLayoutItemMargin;
- signed char bottomLayoutItemMargin;
- // ### TODO: reorganize private/extra/topextra to save memory
- QPointer<QWidget> compositeChildGrab;
+ // Implicit pointers (shared_null/shared_empty).
+ QRegion opaqueChildren;
+ QRegion dirty;
#ifndef QT_NO_TOOLTIP
QString toolTip;
#endif
@@ -524,14 +538,37 @@ public:
#ifndef QT_NO_WHATSTHIS
QString whatsThis;
#endif
- QString accessibleName, accessibleDescription;
+#ifndef QT_NO_ACCESSIBILITY
+ QString accessibleName;
+ QString accessibleDescription;
+#endif
+ // Other variables.
+ uint inheritedFontResolveMask;
+ uint inheritedPaletteResolveMask;
+ short leftmargin;
+ short topmargin;
+ short rightmargin;
+ short bottommargin;
+ signed char leftLayoutItemMargin;
+ signed char topLayoutItemMargin;
+ signed char rightLayoutItemMargin;
+ signed char bottomLayoutItemMargin;
+ static int instanceCounter; // Current number of widget instances
+ static int maxInstances; // Maximum number of widget instances
+ Qt::HANDLE hd;
+ QWidgetData data;
+ QSizePolicy size_policy;
+ QLocale locale;
+ QPoint redirectOffset;
+#ifndef QT_NO_ACTION
+ QList<QAction*> actions;
+#endif
+
+ // Bit fields.
+ uint high_attributes[3]; // the low ones are in QWidget::widget_attributes
QPalette::ColorRole fg_role : 8;
QPalette::ColorRole bg_role : 8;
- uint high_attributes[3]; // the low ones are in QWidget::widget_attributes
- Qt::HANDLE hd;
- QRegion dirty;
- QRegion *needsFlush;
uint dirtyOpaqueChildren : 1;
uint isOpaque : 1;
uint inDirtyList : 1;
@@ -539,35 +576,35 @@ public:
uint isMoved : 1;
uint usesDoubleBufferedGLContext : 1;
-#ifdef Q_WS_WIN
- uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
-#endif
-
- uint inheritedFontResolveMask;
- uint inheritedPaletteResolveMask;
-#if defined(Q_WS_X11)
+ // *************************** Platform specific ************************************
+#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
QX11Info xinfo;
Qt::HANDLE picture;
+ static QWidget *mouseGrabber;
+ static QWidget *keyboardGrabber;
+
+ void setWindowRole();
+ void sendStartupMessage(const char *message) const;
+ void setNetWmWindowTypes();
+ void x11UpdateIsOpaque();
+ bool isBackgroundInherited() const;
+#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
+ uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
+
+ bool shouldShowMaximizeButton();
+ void winUpdateIsOpaque();
+ void reparentChildren();
+#ifndef QT_NO_DRAGANDDROP
+ QOleDropTarget *registerOleDnd(QWidget *widget);
+ void unregisterOleDnd(QWidget *widget, QOleDropTarget *target);
#endif
-#if defined(Q_WS_MAC)
- enum PaintChildrenOPs {
- PC_None = 0x00,
- PC_Now = 0x01,
- PC_NoPaint = 0x04,
- PC_Later = 0x10
- };
- EventHandlerRef window_event;
- bool qt_mac_dnd_event(uint, DragRef);
- void toggleDrawers(bool);
- //mac event functions
- static bool qt_create_root_win();
- static void qt_clean_root_win();
- static bool qt_recreate_root_win();
- static bool qt_mac_update_sizer(QWidget *, int up = 0);
- static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *);
- static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *);
- static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool);
- static bool qt_widget_shape(QWidget *, short, HIMutableShapeRef, bool);
+ void grabMouseWhileInWindow();
+ void registerTouchWindow();
+ void winSetupGestures();
+#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
+ // This is new stuff
+ uint needWindowChange : 1;
+ uint isGLWidget : 1;
// Each wiget keeps a list of all its child and grandchild OpenGL widgets.
// This list is used to update the gl context whenever a parent and a granparent
@@ -580,95 +617,128 @@ public:
QWidget * widget;
QWidget * lastUpdateWidget;
};
- QList<GlWidgetInfo> glWidgets;
// dirtyOnWidget contains the areas in the widget that needs to be repained,
// in the same way as dirtyOnScreen does for the window. Areas are added in
// dirtyWidget_sys and cleared in the paint event. In scroll_sys we then use
// this information repaint invalid areas when widgets are scrolled.
QRegion dirtyOnWidget;
+ EventHandlerRef window_event;
+ QList<GlWidgetInfo> glWidgets;
//these are here just for code compat (HIViews)
Qt::HANDLE qd_hd;
- // This is new stuff
- uint needWindowChange : 1;
- uint isGLWidget : 1;
-#endif
-
-#if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC)
-#ifdef Q_WS_MAC
- void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect());
+ void macUpdateSizeAttribute();
+ void macUpdateHideOnSuspend();
+ void macUpdateOpaqueSizeGrip();
+ void macUpdateIgnoreMouseEvents();
+ void macUpdateMetalAttribute();
+ void macUpdateIsOpaque();
+ void setEnabled_helper_sys(bool enable);
+ bool isRealWindow() const;
+ void adjustWithinMaxAndMinSize(int &w, int &h);
+ void applyMaxAndMinSizeOnWindow();
+ void update_sys(const QRect &rect);
+ void update_sys(const QRegion &rgn);
+ void setGeometry_sys_helper(int, int, int, int, bool);
+ void setWindowModified_sys(bool b);
+ void updateMaximizeButton_sys();
+ void setWindowFilePath_sys(const QString &filePath);
+ void createWindow_sys();
+ void recreateMacWindow();
+#ifndef QT_MAC_USE_COCOA
+ void initWindowPtr();
+ void finishCreateWindow_sys_Carbon(OSWindowRef windowRef);
#else
- void setWSGeometry(bool dontShow=false);
+ void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef);
+ void syncCocoaMask();
+ void finishCocoaMaskSetup();
#endif
+ void determineWindowClass();
+ void transferChildren();
+ bool qt_mac_dnd_event(uint, DragRef);
+ void toggleDrawers(bool);
+ //mac event functions
+ static bool qt_create_root_win();
+ static void qt_clean_root_win();
+ static bool qt_mac_update_sizer(QWidget *, int up = 0);
+ static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *);
+ static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *);
+ static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool);
+ void registerTouchWindow();
+#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
+ void setMaxWindowState_helper();
+ void setFullScreenSize_helper();
+ void moveSurface(QWindowSurface *surface, const QPoint &offset);
+ QRegion localRequestedRegion() const;
+ QRegion localAllocatedRegion() const;
- inline QPoint mapToWS(const QPoint &p) const
- { return p - data.wrect.topLeft(); }
-
- inline QPoint mapFromWS(const QPoint &p) const
- { return p + data.wrect.topLeft(); }
-
- inline QRect mapToWS(const QRect &r) const
- { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; }
-
- inline QRect mapFromWS(const QRect &r) const
- { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
+ friend class QWSManager;
+ friend class QWSManagerPrivate;
+ friend class QDecoration;
+#ifndef QT_NO_CURSOR
+ void updateCursor() const;
+#endif
+ QScreen* getScreen() const;
+#elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN
+ static QWidget *mouseGrabber;
+ static QWidget *keyboardGrabber;
+ void s60UpdateIsOpaque();
+ void reparentChildren();
#endif
- QPaintEngine *extraPaintEngine;
+};
- mutable const QMetaObject *polished;
+struct QWidgetPaintContext
+{
+ inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, int f,
+ QPainter *p, QWidgetBackingStore *b)
+ : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), backingStore(b), painter(0) {}
+
+ QPaintDevice *pdev;
+ QRegion rgn;
+ QPoint offset;
+ int flags;
+ QPainter *sharedPainter;
+ QWidgetBackingStore *backingStore;
+ QPainter *painter;
+};
- void setModal_sys();
- QSizePolicy size_policy;
- QLocale locale;
+class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate
+{
+public:
+ QWidgetEffectSourcePrivate(QWidget *widget)
+ : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0)
+ {}
-#ifdef Q_WS_X11
- static QWidget *mouseGrabber;
- static QWidget *keyboardGrabber;
-#endif
- QPaintDevice *redirectDev;
- QPoint redirectOffset;
+ inline void detach()
+ { m_widget->setGraphicsEffect(0); }
- inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)
- {
- Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent));
- redirectDev = replacement;
- redirectOffset = offset;
- }
+ inline const QGraphicsItem *graphicsItem() const
+ { return 0; }
- inline QPaintDevice *redirected(QPoint *offset) const
- {
- if (offset)
- *offset = redirectDev ? redirectOffset : QPoint();
- return redirectDev;
- }
+ inline const QWidget *widget() const
+ { return m_widget; }
- inline void restoreRedirected()
- { redirectDev = 0; }
+ inline void update()
+ { m_widget->update(); }
- inline void enforceNativeChildren()
- {
- if (!extra)
- createExtra();
+ inline bool isPixmap() const
+ { return false; }
- if (extra->nativeChildrenForced)
- return;
- extra->nativeChildrenForced = 1;
+ inline const QStyleOption *styleOption() const
+ { return 0; }
- for (int i = 0; i < children.size(); ++i) {
- if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
- child->setAttribute(Qt::WA_NativeWindow);
- }
- }
+ inline QRect deviceRect() const
+ { return m_widget->window()->rect(); }
- inline bool nativeChildrenForced() const
- {
- return extra ? extra->nativeChildrenForced : false;
- }
+ QRectF boundingRect(Qt::CoordinateSystem system) const;
+ void draw(QPainter *p);
+ QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const;
- QSize adjustedSize() const;
+ QWidget *m_widget;
+ QWidgetPaintContext *context;
};
inline QWExtra *QWidgetPrivate::extraData() const
diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp
index ae82cd2..82a88ac 100644
--- a/src/gui/kernel/qwidget_qws.cpp
+++ b/src/gui/kernel/qwidget_qws.cpp
@@ -258,7 +258,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
Q_D(QWidget);
if (!isWindow() && parentWidget())
- parentWidget()->d_func()->invalidateBuffer(geometry());
+ parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
d->deactivateWidgetCleanup();
if (testAttribute(Qt::WA_WState_Created)) {
@@ -298,11 +298,16 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
d->hide_sys();
}
if (destroyWindow && isWindow()) {
- d->extra->topextra->backingStore->windowSurface->setGeometry(QRect());
+ if (d->extra && d->extra->topextra && d->extra->topextra->backingStore)
+ d->extra->topextra->backingStore->windowSurface->setGeometry(QRect());
qwsDisplay()->destroyRegion(internalWinId());
}
}
- d->setWinId(0);
+ QT_TRY {
+ d->setWinId(0);
+ } QT_CATCH (const std::bad_alloc &) {
+ // swallow - destructors must not throw
+ }
}
}
@@ -312,7 +317,7 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
Q_Q(QWidget);
bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
- q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
+ q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
#ifndef QT_NO_CURSOR
QCursor oldcurs;
bool setcurs=q->testAttribute(Qt::WA_SetCursor);
@@ -565,20 +570,6 @@ void QWidget::activateWindow()
}
}
-/*
- Should we require that q is a toplevel window ???
-
- Used by QWSManager
- */
-void QWidgetPrivate::blitToScreen(const QRegion &globalrgn)
-{
- Q_Q(QWidget);
- QWidget *win = q->window();
- QBrush bgBrush = win->palette().brush(win->backgroundRole());
- bool opaque = bgBrush.style() == Qt::NoBrush || bgBrush.isOpaque();
- QWidget::qwsDisplay()->repaintRegion(win->data->winid, win->windowFlags(), opaque, globalrgn);
-}
-
void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
@@ -590,6 +581,15 @@ void QWidgetPrivate::show_sys()
if (q->isWindow()) {
+
+ if (!q->testAttribute(Qt::WA_ShowWithoutActivating)
+ && q->windowType() != Qt::Popup
+ && q->windowType() != Qt::Tool
+ && q->windowType() != Qt::ToolTip) {
+ QWidget::qwsDisplay()->requestFocus(data.winid,true);
+ }
+
+
if (QWindowSurface *surface = q->windowSurface()) {
const QRect frameRect = q->frameGeometry();
if (surface->geometry() != frameRect)
@@ -606,12 +606,6 @@ void QWidgetPrivate::show_sys()
#endif
data.fstrut_dirty = true;
invalidateBuffer(r);
- if (!q->testAttribute(Qt::WA_ShowWithoutActivating)
- && q->windowType() != Qt::Popup
- && q->windowType() != Qt::Tool
- && q->windowType() != Qt::ToolTip) {
- QWidget::qwsDisplay()->requestFocus(data.winid,true);
- }
bool staysontop =
(q->windowFlags() & Qt::WindowStaysOnTopHint)
|| q->windowType() == Qt::Popup;
@@ -652,7 +646,8 @@ void QWidgetPrivate::hide_sys()
q->releaseMouse();
// requestWindowRegion(QRegion());
- extra->topextra->backingStore->releaseBuffer();
+ if (extra->topextra->backingStore)
+ extra->topextra->backingStore->releaseBuffer();
QWidget::qwsDisplay()->requestFocus(data.winid,false);
@@ -819,7 +814,7 @@ void QWidgetPrivate::lower_sys()
QWSChangeAltitudeCommand::Lower);
} else if (QWidget *p = q->parentWidget()) {
setDirtyOpaqueRegion();
- p->d_func()->invalidateBuffer(q->geometry());
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
}
}
@@ -828,7 +823,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget*)
Q_Q(QWidget);
if (QWidget *p = q->parentWidget()) {
setDirtyOpaqueRegion();
- p->d_func()->invalidateBuffer(q->geometry());
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
}
}
@@ -1037,6 +1032,9 @@ void QWidgetPrivate::deleteSysExtra()
void QWidgetPrivate::createTLSysExtra()
{
+#ifndef QT_NO_QWS_MANAGER
+ extra->topextra->qwsManager = 0;
+#endif
}
void QWidgetPrivate::deleteTLSysExtra()
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
new file mode 100644
index 0000000..d28e2c0
--- /dev/null
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -0,0 +1,1206 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidget_p.h"
+#include "qdesktopwidget.h"
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "private/qbackingstore_p.h"
+#include "qevent.h"
+#include "qt_s60_p.h"
+
+#include "qbitmap.h"
+#include "private/qwindowsurface_s60_p.h"
+
+#include <qinputcontext.h>
+
+#ifdef Q_WS_S60
+#include <aknappui.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern bool qt_nograb();
+
+QWidget *QWidgetPrivate::mouseGrabber = 0;
+QWidget *QWidgetPrivate::keyboardGrabber = 0;
+
+static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b)
+{
+ if ( a.count() != b.count())
+ return false;
+ int index=0;
+ while (index<a.count()) {
+ if (a.at(index)->softKeyRole() != b.at(index)->softKeyRole())
+ return false;
+ if (a.at(index)->text().compare(b.at(index)->text())!=0)
+ return false;
+ index++;
+ }
+ return true;
+}
+
+
+void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys)
+{
+#ifdef Q_WS_S60
+ Q_Q(QWidget);
+ if (QApplication::focusWidget() && q!=QApplication::focusWidget()) {
+ QList<QAction *> old = QApplication::focusWidget()->softKeys();
+ if (isEqual(old, softkeys ))
+ return;
+ }
+ CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer();
+ QT_TRAP_THROWING(nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS));
+
+ int position = -1;
+ int command;
+ bool needsExitButton = true;
+
+ for (int index = 0; index < softkeys.count(); index++) {
+ const QAction* softKeyAction = softkeys.at(index);
+ switch (softKeyAction->softKeyRole()) {
+ // Positive Actions go on LSK
+ case QAction::OptionsSoftKey:
+ case QAction::MenuSoftKey:
+ case QAction::ContextMenuSoftKey:
+ command = EAknSoftkeyOptions; //Calls DynInitMenuPane in AppUI
+ position = 0;
+ break;
+ case QAction::SelectSoftKey:
+ case QAction::PreviousSoftKey:
+ case QAction::OkSoftKey:
+ case QAction::EditSoftKey:
+ case QAction::ViewSoftKey:
+ case QAction::EndEditSoftKey:
+ case QAction::FinishSoftKey:
+ command = SOFTKEYSTART + index;
+ position = 0;
+ break;
+ // Negative Actions on the RSK
+ case QAction::BackSoftKey:
+ case QAction::NextSoftKey:
+ case QAction::CancelSoftKey:
+ case QAction::BackSpaceSoftKey:
+ case QAction::RevertEditSoftKey:
+ case QAction::DeselectSoftKey:
+ needsExitButton = false;
+ command = SOFTKEYSTART + index;
+ position = 2;
+ break;
+ case QAction::ExitSoftKey:
+ needsExitButton = false;
+ command = EAknSoftkeyExit; //Calls HandleCommand in AppUI
+ position = 2;
+ break;
+ default:
+ break;
+ }
+
+ if (position != -1) {
+ TPtrC text = qt_QString2TPtrC(softKeyAction->text());
+ QT_TRAP_THROWING(nativeContainer->SetCommandL(position, command, text));
+ }
+ }
+
+ if (needsExitButton)
+ QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QObject::tr("Exit"))));
+
+ nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation
+#else
+ Q_UNUSED(softkeys)
+#endif
+}
+
+void QWidgetPrivate::setWSGeometry(bool /* dontShow */, const QRect & /* rect */)
+{
+
+}
+
+void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ if ((q->windowType() == Qt::Desktop))
+ return;
+ if (extra) { // any size restrictions?
+ w = qMin(w,extra->maxw);
+ h = qMin(h,extra->maxh);
+ w = qMax(w,extra->minw);
+ h = qMax(h,extra->minh);
+ }
+
+ if (q->isWindow())
+ topData()->normalGeometry = QRect(0, 0, -1, -1);
+ else {
+ uint s = data.window_state;
+ s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
+ data.window_state = s;
+ }
+
+ QPoint oldPos(q->pos());
+ QSize oldSize(q->size());
+ QRect oldGeom(data.crect);
+
+ bool isResize = w != oldSize.width() || h != oldSize.height();
+ if (!isMove && !isResize)
+ return;
+
+ if (isResize)
+ data.window_state &= ~Qt::WindowMaximized;
+
+ if(q->isWindow()) {
+ if (w == 0 || h == 0) {
+ q->setAttribute(Qt::WA_OutsideWSRange, true);
+ if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
+ hide_sys();
+ data.crect = QRect(x, y, w, h);
+ data.window_state &= ~Qt::WindowFullScreen;
+ } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+
+ // put the window in its place and show it
+ q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+ data.crect.setRect(x, y, w, h);
+
+ show_sys();
+ } else {
+ QRect r = QRect(x, y, w, h);
+ data.crect = r;
+ q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+ topData()->normalGeometry = data.crect;
+ }
+ } else {
+ data.crect.setRect(x, y, w, h);
+
+ QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+ const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
+
+ if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) {
+ // Top-level resize optimization does not work for native child widgets;
+ // disable it for this particular widget.
+ if (inTopLevelResize)
+ tlwExtra->inTopLevelResize = false;
+ if (!isResize && maybeBackingStore())
+ moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
+ else
+ invalidateBuffer_resizeHelper(oldPos, oldSize);
+
+ if (inTopLevelResize)
+ tlwExtra->inTopLevelResize = true;
+ }
+ if (q->testAttribute(Qt::WA_WState_Created))
+ setWSGeometry();
+ }
+
+ if (q->isVisible()) {
+ if (isMove && q->pos() != oldPos) {
+ QMoveEvent e(q->pos(), oldPos);
+ QApplication::sendEvent(q, &e);
+ }
+ if (isResize) {
+ bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+ const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
+ && !extra->topextra->inTopLevelResize;
+ if (setTopLevelResize)
+ extra->topextra->inTopLevelResize = true;
+ QResizeEvent e(q->size(), oldSize);
+ QApplication::sendEvent(q, &e);
+ if (!q->testAttribute(Qt::WA_StaticContents) && q->internalWinId())
+ q->internalWinId()->DrawDeferred();
+ if (setTopLevelResize)
+ extra->topextra->inTopLevelResize = false;
+ }
+ } else {
+ if (isMove && q->pos() != oldPos)
+ q->setAttribute(Qt::WA_PendingMoveEvent, true);
+ if (isResize)
+ q->setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+}
+
+void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool destroyOldWindow)
+{
+ Q_Q(QWidget);
+
+ Qt::WindowType type = q->windowType();
+ Qt::WindowFlags &flags = data.window_flags;
+ QWidget *parentWidget = q->parentWidget();
+
+ bool topLevel = (flags & Qt::Window);
+ bool popup = (type == Qt::Popup);
+ bool dialog = (type == Qt::Dialog
+ || type == Qt::Sheet
+ || (flags & Qt::MSWindowsFixedSizeDialogHint));
+ bool desktop = (type == Qt::Desktop);
+ //bool tool = (type == Qt::Tool || type == Qt::Drawer);
+
+ WId id = 0;
+
+ if (popup)
+ flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
+
+ TRect clientRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ int sw = clientRect.Width();
+ int sh = clientRect.Height();
+
+ if (desktop) {
+ TSize screenSize = S60->screenDevice()->SizeInPixels();
+ data.crect.setRect(0, 0, screenSize.iWidth, screenSize.iHeight);
+ q->setAttribute(Qt::WA_DontShowOnScreen);
+ } else if(topLevel && !q->testAttribute(Qt::WA_Resized)){
+ int width = sw;
+ int height = sh;
+ if (extra) {
+ width = qMax(qMin(width, extra->maxw), extra->minw);
+ height = qMax(qMin(height, extra->maxh), extra->minh);
+ }
+ data.crect.setSize(QSize(width, height));
+ }
+
+ CCoeControl *destroyw = 0;
+
+ createExtra();
+ if(window) {
+ if (destroyOldWindow)
+ destroyw = data.winid;
+ id = window;
+ setWinId(window);
+ TRect tr = window->Rect();
+ data.crect.setRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height());
+
+ } else if (topLevel) {
+ if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen))
+ data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY));
+ QSymbianControl *control= q_check_ptr(new QSymbianControl(q));
+ id = (WId)control;
+ setWinId(id);
+ QT_TRAP_THROWING(control->ConstructL(true,desktop));
+
+ if (!desktop) {
+ TInt stackingFlags;
+ if ((q->windowType() & Qt::Popup) == Qt::Popup) {
+ stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus;
+ } else {
+ stackingFlags = ECoeStackFlagStandard;
+ }
+ QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags));
+
+ QTLWExtra *topExtra = topData();
+ topExtra->rwindow = control->DrawableWindow();
+ // Request mouse move events.
+ topExtra->rwindow->PointerFilter(EPointerFilterEnterExit
+ | EPointerFilterMove | EPointerFilterDrag, 0);
+ topExtra->rwindow->EnableVisibilityChangeEvents();
+
+ if (!isOpaque) {
+ RWindow *rwindow = static_cast<RWindow*>(topExtra->rwindow);
+ TDisplayMode gotDM = (TDisplayMode)rwindow->SetRequiredDisplayMode(EColor16MA);
+ if (rwindow->SetTransparencyAlphaChannel() == KErrNone)
+ rwindow->SetBackgroundColor(TRgb(255, 255, 255, 0));
+ }
+ }
+
+ q->setAttribute(Qt::WA_WState_Created);
+
+ int x, y, w, h;
+ data.crect.getRect(&x, &y, &w, &h);
+ control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+ } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget
+ QSymbianControl *control = new QSymbianControl(q);
+ setWinId(control);
+ QT_TRAP_THROWING(control->ConstructL(!parentWidget));
+
+ TInt stackingFlags;
+ if ((q->windowType() & Qt::Popup) == Qt::Popup) {
+ stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus;
+ } else {
+ stackingFlags = ECoeStackFlagStandard;
+ }
+ QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags));
+
+ WId parentw = parentWidget->effectiveWinId();
+ QT_TRAP_THROWING(control->SetContainerWindowL(*parentw));
+
+ q->setAttribute(Qt::WA_WState_Created);
+ int x, y, w, h;
+ data.crect.getRect(&x, &y, &w, &h);
+ control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+ }
+
+ if (destroyw) {
+ destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw);
+ CBase::Delete(destroyw);
+ }
+}
+
+
+void QWidgetPrivate::show_sys()
+{
+ Q_Q(QWidget);
+
+ if (q->testAttribute(Qt::WA_OutsideWSRange))
+ return;
+
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ q->setAttribute(Qt::WA_Mapped);
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ return;
+ }
+
+ if (q->isWindow() && q->internalWinId()) {
+
+ WId id = q->internalWinId();
+ if (!extra->topextra->activated) {
+ QT_TRAP_THROWING(id->ActivateL());
+ extra->topextra->activated = 1;
+ }
+ id->MakeVisible(true);
+ id->SetFocus(true);
+
+ // Force setting of the icon after window is made visible,
+ // this is needed even WA_SetWindowIcon is not set, as in that case we need
+ // to reset to the application level window icon
+ setWindowIcon_sys(true);
+ }
+
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ deactivateWidgetCleanup();
+ WId id = q->internalWinId();
+ if (q->isWindow() && id) {
+ if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
+ id->SetFocus(false);
+ id->MakeVisible(false);
+ if (QWidgetBackingStore *bs = maybeBackingStore())
+ bs->releaseBuffer();
+ } else {
+ invalidateBuffer(q->rect());
+ }
+
+ q->setAttribute(Qt::WA_Mapped, false);
+}
+
+void QWidgetPrivate::setFocus_sys()
+{
+ Q_Q(QWidget);
+ if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup)
+ if(!q->effectiveWinId()->IsFocused()) // Avoid unnecessry calls to FocusChanged()
+ q->effectiveWinId()->SetFocus(true);
+}
+
+void QWidgetPrivate::handleSymbianDeferredFocusChanged()
+{
+ Q_Q(QWidget);
+ WId control = q->internalWinId();
+ if (!control) {
+ // This could happen if the widget was reparented, while the focuschange
+ // was in the event queue.
+ return;
+ }
+
+ if (control->IsFocused()) {
+ QApplication::setActiveWindow(q);
+#ifdef Q_WS_S60
+ // If widget is fullscreen, hide status pane and button container
+ // otherwise show them.
+ CEikStatusPane* statusPane = S60->statusPane();
+ CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
+ bool isFullscreen = q->windowState() & Qt::WindowFullScreen;
+ if (statusPane && (statusPane->IsVisible() == isFullscreen))
+ statusPane->MakeVisible(!isFullscreen);
+ if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen))
+ buttonGroup->MakeVisible(!isFullscreen);
+#endif
+ } else {
+ QApplication::setActiveWindow(0);
+ }
+}
+
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ QTLWExtra *tlwExtra = maybeTopData();
+ if (q->internalWinId() && tlwExtra) {
+ tlwExtra->rwindow->SetOrdinalPosition(0);
+ }
+}
+
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ QTLWExtra *tlwExtra = maybeTopData();
+ if (q->internalWinId() && tlwExtra) {
+ tlwExtra->rwindow->SetOrdinalPosition(-1);
+ }
+ if(!q->isWindow())
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::setModal_sys()
+{
+
+}
+
+void QWidgetPrivate::stackUnder_sys(QWidget* w)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ QTLWExtra *tlwExtra = maybeTopData();
+ QTLWExtra *tlwExtraSibling = w->d_func()->maybeTopData();
+ if (q->internalWinId() && tlwExtra && w->internalWinId() && tlwExtraSibling)
+ tlwExtra->rwindow->SetOrdinalPosition(tlwExtraSibling->rwindow->OrdinalPosition() + 1);
+ if(!q->isWindow() || !w->internalWinId())
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::reparentChildren()
+{
+ Q_Q(QWidget);
+ QObjectList chlist = q->children();
+ for (int i = 0; i < chlist.size(); ++i) { // reparent children
+ QObject *obj = chlist.at(i);
+ if (obj->isWidgetType()) {
+ QWidget *w = (QWidget *)obj;
+ if (!w->testAttribute(Qt::WA_WState_Created))
+ continue;
+ if (!w->isWindow()) {
+ w->d_func()->invalidateBuffer(w->rect());
+ WId parent = q->effectiveWinId();
+ WId child = w->effectiveWinId();
+ if (parent != child)
+ child->SetParent(parent);
+ // ### TODO: We probably also need to update the component array here
+ w->d_func()->reparentChildren();
+ } else {
+ bool showIt = w->isVisible();
+ QPoint old_pos = w->pos();
+ w->setParent(q, w->windowFlags());
+ w->move(old_pos);
+ if (showIt)
+ w->show();
+ }
+ }
+ }
+}
+
+void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+ bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
+
+ if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
+ q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
+
+ if (q->testAttribute(Qt::WA_DropSiteRegistered))
+ q->setAttribute(Qt::WA_DropSiteRegistered, false);
+
+ WId old_winid = wasCreated ? data.winid : 0;
+ if ((q->windowType() == Qt::Desktop))
+ old_winid = 0;
+ setWinId(0);
+
+ // hide and reparent our own window away. Otherwise we might get
+ // destroyed when emitting the child remove event below. See QWorkspace.
+ if (wasCreated && old_winid) {
+ old_winid->MakeVisible(false);
+ if(old_winid->IsFocused()) // Avoid unnecessary calls to FocusChanged()
+ old_winid->SetFocus(false);
+ old_winid->SetParent(0);
+ }
+
+ QObjectPrivate::setParent_helper(parent);
+ bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ data.window_flags = f;
+ data.fstrut_dirty = true;
+ q->setAttribute(Qt::WA_WState_Created, false);
+ q->setAttribute(Qt::WA_WState_Visible, false);
+ q->setAttribute(Qt::WA_WState_Hidden, false);
+ adjustFlags(data.window_flags, q);
+ // keep compatibility with previous versions, we need to preserve the created state
+ // (but we recreate the winId for the widget being reparented, again for compatibility)
+ if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
+ createWinId();
+ if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
+ q->setAttribute(Qt::WA_WState_Hidden);
+ q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
+
+ if (wasCreated)
+ reparentChildren();
+
+ if (old_winid) {
+ CBase::Delete(old_winid);
+ }
+
+ if (q->testAttribute(Qt::WA_AcceptDrops)
+ || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
+ q->setAttribute(Qt::WA_DropSiteRegistered, true);
+
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::setConstraints_sys()
+{
+
+}
+
+
+void QWidgetPrivate::s60UpdateIsOpaque()
+{
+ Q_Q(QWidget);
+
+ if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
+ return;
+
+ if ((data.window_flags & Qt::FramelessWindowHint) == 0)
+ return;
+
+ if (!isOpaque) {
+ QTLWExtra *topExtra = topData();
+ RWindow *rwindow = static_cast<RWindow*>(topExtra->rwindow);
+ TDisplayMode gotDM = (TDisplayMode)rwindow->SetRequiredDisplayMode(EColor16MA);
+ if (rwindow->SetTransparencyAlphaChannel() == KErrNone)
+ rwindow->SetBackgroundColor(TRgb(255, 255, 255, 0));
+ } else {
+ QTLWExtra *topExtra = topData();
+ RWindow *rwindow = static_cast<RWindow*>(topExtra->rwindow);
+ rwindow->SetTransparentRegion(TRegionFix<1>());
+ }
+}
+
+CFbsBitmap* qt_pixmapToNativeBitmap(QPixmap pixmap, bool invert)
+{
+ CFbsBitmap* fbsBitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new
+ TSize size(pixmap.size().width(), pixmap.size().height());
+ TDisplayMode mode(EColor16MU);
+
+ bool isNull = pixmap.isNull();
+ int depth = pixmap.depth();
+
+ // TODO: dummy assumptions from bit amounts for each color
+ // Will fix later on when native pixmap is implemented
+ switch(pixmap.depth()) {
+ case 1:
+ mode = EGray2;
+ break;
+ case 4:
+ mode = EColor16;
+ break;
+ case 8:
+ mode = EColor256;
+ break;
+ case 12:
+ mode = EColor4K;
+ break;
+ case 16:
+ mode = EColor64K;
+ break;
+ case 24:
+ mode = EColor16M;
+ break;
+ case 32:
+ case EColor16MU:
+ break;
+ default:
+ qFatal("Unsupported pixmap depth");
+ break;
+ }
+
+ qt_symbian_throwIfError(fbsBitmap->Create(size, mode));
+ fbsBitmap->LockHeap();
+ QImage image = pixmap.toImage();
+
+ if(invert)
+ image.invertPixels();
+
+ int height = pixmap.size().height();
+ for(int i=0;i<height;i++ )
+ {
+ TPtr8 scanline(image.scanLine(i), image.bytesPerLine(), image.bytesPerLine());
+ fbsBitmap->SetScanLine( scanline, i );
+ }
+
+ fbsBitmap->UnlockHeap();
+ return fbsBitmap;
+}
+
+void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
+{
+#ifdef Q_WS_S60
+ Q_Q(QWidget);
+
+ if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow() )
+ return;
+
+ QTLWExtra* topData = this->topData();
+ if (topData->iconPixmap && !forceReset)
+ // already been set
+ return;
+
+ TRect cPaneRect;
+ TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EContextPane, cPaneRect );
+ CAknContextPane* contextPane = S60->contextPane();
+ if (found && contextPane) { // We have context pane with valid metrics
+ QIcon icon = q->windowIcon();
+ if (!icon.isNull()) {
+ // Valid icon -> set it as an context pane picture
+ QSize size = icon.actualSize(QSize(cPaneRect.Size().iWidth, cPaneRect.Size().iHeight));
+ QPixmap pm = icon.pixmap(size);
+ QBitmap mask = pm.mask();
+ if (mask.isNull()) {
+ mask = QBitmap(pm.size());
+ mask.fill(Qt::color1);
+ }
+
+ // Convert to CFbsBitmp
+ // TODO: When QPixmap is adapted to use native CFbsBitmap,
+ // it could be set directly to context pane
+ CFbsBitmap* nBitmap = qt_pixmapToNativeBitmap(pm, false);
+ CFbsBitmap* nMask = qt_pixmapToNativeBitmap(mask, true);
+
+ contextPane->SetPicture(nBitmap,nMask);
+ } else {
+ // Icon set to null -> set context pane picture to default
+ QT_TRAP_THROWING(contextPane->SetPictureToDefaultL());
+ }
+ } else {
+ // Context pane does not exist, try setting small icon to title pane
+ TRect titlePaneRect;
+ TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ETitlePane, titlePaneRect );
+ CAknTitlePane* titlePane = S60->titlePane();
+ if (found && titlePane) { // We have title pane with valid metrics
+ // The API to get title_pane graphics size is not public -> assume square space based
+ // on titlebar font height. CAknBitmap would be optimum, wihtout setting the size, since
+ // then title pane would automatically scale the bitmap. Unfortunately it is not public API
+ const CFont * font = AknLayoutUtils::FontFromId(EAknLogicalFontTitleFont);
+ TSize iconSize(font->HeightInPixels(), font->HeightInPixels());
+
+ QIcon icon = q->windowIcon();
+ if (!icon.isNull()) {
+ // Valid icon -> set it as an title pane small picture
+ QSize size = icon.actualSize(QSize(iconSize.iWidth, iconSize.iHeight));
+ QPixmap pm = icon.pixmap(size);
+ QBitmap mask = pm.mask();
+ if (mask.isNull()) {
+ mask = QBitmap(pm.size());
+ mask.fill(Qt::color1);
+ }
+
+ // Convert to CFbsBitmp
+ // TODO: When QPixmap is adapted to use native CFbsBitmap,
+ // it could be set directly to context pane
+ CFbsBitmap* nBitmap = qt_pixmapToNativeBitmap(pm, false);
+ CFbsBitmap* nMask = qt_pixmapToNativeBitmap(mask, true);
+
+ titlePane->SetSmallPicture( nBitmap, nMask, ETrue );
+ } else {
+ // Icon set to null -> set context pane picture to default
+ titlePane->SetSmallPicture( NULL, NULL, EFalse );
+ }
+ }
+ }
+
+#else
+ Q_UNUSED(forceReset)
+#endif
+}
+
+void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
+{
+#ifdef Q_WS_S60
+ Q_Q(QWidget);
+ if (q->isWindow()) {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ CAknTitlePane* titlePane = S60->titlePane();
+ if(titlePane) {
+ if(caption.isEmpty()) {
+ QT_TRAP_THROWING(titlePane->SetTextToDefaultL());
+ } else {
+ QT_TRAP_THROWING(titlePane->SetTextL(qt_QString2TPtrC(caption)));
+ }
+ }
+ }
+#else
+ Q_UNUSED(caption)
+#endif
+}
+
+void QWidgetPrivate::setWindowIconText_sys(const QString & /*iconText */)
+{
+
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy)
+{
+ Q_Q(QWidget);
+
+ scrollChildren(dx, dy);
+ if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) {
+ scrollRect(q->rect(), dx, dy);
+ } else {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ RDrawableWindow* rw = topData()->rwindow;
+ rw->Scroll(TPoint(dx, dy));
+ }
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
+{
+ Q_Q(QWidget);
+
+ if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) {
+ scrollRect(r, dx, dy);
+ } else {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ RDrawableWindow* rw = topData()->rwindow;
+ rw->Scroll(TPoint(dx, dy), qt_QRect2TRect(r));
+ }
+}
+
+/*!
+ For this function to work in the emulator, you must add:
+ TRANSPARENCY
+ To a line in the wsini.ini file.
+*/
+void QWidgetPrivate::setWindowOpacity_sys(qreal)
+{
+ // ### TODO: Implement uniform window transparency
+}
+
+void QWidgetPrivate::updateFrameStrut()
+{
+
+}
+
+void QWidgetPrivate::updateSystemBackground()
+{
+
+}
+
+void QWidgetPrivate::registerDropSite(bool /* on */)
+{
+
+}
+
+void QWidgetPrivate::createTLSysExtra()
+{
+ extra->topextra->backingStore = 0;
+ extra->topextra->activated = 0;
+ extra->topextra->rwindow = 0;
+}
+
+void QWidgetPrivate::deleteTLSysExtra()
+{
+ delete extra->topextra->backingStore;
+ extra->topextra->backingStore = 0;
+}
+
+void QWidgetPrivate::createSysExtra()
+{
+
+}
+
+void QWidgetPrivate::deleteSysExtra()
+{
+ // this should only be non-zero if destroy() has not run due to constructor fail
+ if (data.winid) {
+ data.winid->ControlEnv()->AppUi()->RemoveFromStack(data.winid);
+ delete data.winid;
+ data.winid = 0;
+ }
+}
+
+QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
+{
+ return new QS60WindowSurface(q_func());
+}
+
+void QWidgetPrivate::setMask_sys(const QRegion& /* region */)
+{
+
+}
+
+int QWidget::metric(PaintDeviceMetric m) const
+{
+ Q_D(const QWidget);
+ int val;
+ if (m == PdmWidth) {
+ val = data->crect.width();
+ } else if (m == PdmHeight) {
+ val = data->crect.height();
+ } else {
+ CWsScreenDevice *scr = S60->screenDevice();
+ switch(m) {
+ case PdmDpiX:
+ case PdmPhysicalDpiX:
+ if (d->extra && d->extra->customDpiX) {
+ val = d->extra->customDpiX;
+ } else {
+ const QWidgetPrivate *p = d;
+ while (p->parent) {
+ p = static_cast<const QWidget *>(p->parent)->d_func();
+ if (p->extra && p->extra->customDpiX) {
+ val = p->extra->customDpiX;
+ break;
+ }
+ }
+ if (p == d || !(p->extra && p->extra->customDpiX))
+ val = S60->defaultDpiX;
+ }
+ break;
+ case PdmDpiY:
+ case PdmPhysicalDpiY:
+ if (d->extra && d->extra->customDpiY) {
+ val = d->extra->customDpiY;
+ } else {
+ const QWidgetPrivate *p = d;
+ while (p->parent) {
+ p = static_cast<const QWidget *>(p->parent)->d_func();
+ if (p->extra && p->extra->customDpiY) {
+ val = p->extra->customDpiY;
+ break;
+ }
+ }
+ if (p == d || !(p->extra && p->extra->customDpiY))
+ val = S60->defaultDpiY;
+ }
+ break;
+ case PdmWidthMM:
+ {
+ TInt twips = scr->HorizontalPixelsToTwips(data->crect.width());
+ val = (int)(twips * (25.4/KTwipsPerInch));
+ break;
+ }
+ case PdmHeightMM:
+ {
+ TInt twips = scr->VerticalPixelsToTwips(data->crect.height());
+ val = (int)(twips * (25.4/KTwipsPerInch));
+ break;
+ }
+ case PdmNumColors:
+ val = TDisplayModeUtils::NumDisplayModeColors(scr->DisplayMode());
+ break;
+ case PdmDepth:
+ val = TDisplayModeUtils::NumDisplayModeBitsPerPixel(scr->DisplayMode());
+ break;
+ default:
+ val = 0;
+ qWarning("QWidget::metric: Invalid metric command");
+ }
+ }
+ return val;
+}
+
+QPaintEngine *QWidget::paintEngine() const
+{
+ return 0;
+}
+
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+
+ QPoint p = pos + data->crect.topLeft();
+ return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p);
+
+ } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel
+ QPoint tp = geometry().topLeft();
+ return pos + tp;
+ }
+
+ // This is the native window case. Consider using CCoeControl::PositionRelativeToScreen()
+ // if we decide to go with CCoeControl
+ return QPoint();
+}
+
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+ QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos);
+ return p - data->crect.topLeft();
+ } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel
+ QPoint tp = geometry().topLeft();
+ return pos - tp;
+ }
+
+ // ### TODO native window
+ return QPoint();
+}
+
+void QWidget::setWindowState(Qt::WindowStates newstate)
+{
+ Q_D(QWidget);
+ Qt::WindowStates oldstate = windowState();
+ if (oldstate == newstate)
+ return;
+
+ if (isWindow()) {
+ createWinId();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ QTLWExtra *top = d->topData();
+
+ // Ensure the initial size is valid, since we store it as normalGeometry below.
+ if (!testAttribute(Qt::WA_Resized) && !isVisible())
+ adjustSize();
+
+ if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
+ if ((newstate & Qt::WindowMaximized)) {
+ const QRect normalGeometry = geometry();
+
+ const QRect r = top->normalGeometry;
+ setGeometry(qApp->desktop()->availableGeometry(this));
+ top->normalGeometry = r;
+
+ if (top->normalGeometry.width() < 0)
+ top->normalGeometry = normalGeometry;
+ } else {
+ // restore original geometry
+ setGeometry(top->normalGeometry);
+ }
+ }
+ if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
+#ifdef Q_WS_S60
+ CEikStatusPane* statusPane = S60->statusPane();
+ CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
+#endif
+ if (newstate & Qt::WindowFullScreen) {
+ const QRect normalGeometry = geometry();
+ const QRect r = top->normalGeometry;
+ setGeometry(qApp->desktop()->screenGeometry(this));
+#ifdef Q_WS_S60
+ if (statusPane)
+ statusPane->MakeVisible(false);
+ if (buttonGroup)
+ buttonGroup->MakeVisible(false);
+#endif
+ top->normalGeometry = r;
+ if (top->normalGeometry.width() < 0)
+ top->normalGeometry = normalGeometry;
+ } else {
+#ifdef Q_WS_S60
+ if (statusPane)
+ statusPane->MakeVisible(true);
+ if (buttonGroup)
+ buttonGroup->MakeVisible(true);
+#endif
+ if (newstate & Qt::WindowMaximized) {
+ const QRect r = top->normalGeometry;
+ setGeometry(qApp->desktop()->availableGeometry(this));
+ top->normalGeometry = r;
+ } else {
+ setGeometry(top->normalGeometry);
+ }
+ }
+ }
+ if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
+ if (newstate & Qt::WindowMinimized) {
+ if (isVisible()) {
+ WId id = effectiveWinId();
+ if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
+ id->SetFocus(false);
+ id->MakeVisible(false);
+ }
+ } else {
+ if (isVisible()) {
+ WId id = effectiveWinId();
+ id->MakeVisible(true);
+ if(!id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
+ id->SetFocus(true);
+ }
+ const QRect normalGeometry = geometry();
+ const QRect r = top->normalGeometry;
+ top->normalGeometry = r;
+ if (top->normalGeometry.width() < 0)
+ top->normalGeometry = normalGeometry;
+ }
+ }
+ }
+
+ data->window_state = newstate;
+
+ if (newstate & Qt::WindowActive)
+ activateWindow();
+
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
+
+
+void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+{
+ Q_D(QWidget);
+ if (!isWindow() && parentWidget())
+ parentWidget()->d_func()->invalidateBuffer(geometry());
+ d->deactivateWidgetCleanup();
+ WId id = internalWinId();
+ if (testAttribute(Qt::WA_WState_Created)) {
+
+#ifndef QT_NO_IM
+ if (d->ic) {
+ delete d->ic;
+ } else {
+ QInputContext *ic = inputContext();
+ if (ic) {
+ ic->widgetDestroyed(this);
+ }
+ }
+#endif
+
+ setAttribute(Qt::WA_WState_Created, false);
+ QObjectList childList = children();
+ for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
+ register QObject *obj = childList.at(i);
+ if (obj->isWidgetType())
+ static_cast<QWidget*>(obj)->destroy(destroySubWindows,
+ destroySubWindows);
+ }
+ if (QWidgetPrivate::mouseGrabber == this)
+ releaseMouse();
+ if (QWidgetPrivate::keyboardGrabber == this)
+ releaseKeyboard();
+ if (destroyWindow && !(windowType() == Qt::Desktop) && id) {
+ if(id->IsFocused()) // Avoid unnecessry calls to FocusChanged()
+ id->SetFocus(false);
+ id->ControlEnv()->AppUi()->RemoveFromStack(id);
+
+ // Hack to activate window under destroyed one. With this activation
+ // the next visible window will get keyboard focus
+ WId wid = CEikonEnv::Static()->AppUi()->TopFocusedControl();
+ if (wid) {
+ QWidget *widget = QWidget::find(wid);
+ QApplication::setActiveWindow(widget);
+ if (widget) {
+ // Reset global window title for focusing window
+ widget->d_func()->setWindowTitle_sys(widget->windowTitle());
+ }
+ }
+ }
+ }
+
+ QT_TRY {
+ d->setWinId(0);
+ } QT_CATCH (const std::bad_alloc &) {
+ // swallow - destructors must not throw
+ }
+
+ if (destroyWindow) {
+ delete id;
+ }
+}
+
+QWidget *QWidget::mouseGrabber()
+{
+ return QWidgetPrivate::mouseGrabber;
+}
+
+QWidget *QWidget::keyboardGrabber()
+{
+ return QWidgetPrivate::keyboardGrabber;
+}
+
+void QWidget::grabKeyboard()
+{
+ if (!qt_nograb()) {
+ if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
+ QWidgetPrivate::keyboardGrabber->releaseKeyboard();
+
+ // ### TODO: Native keyboard grab
+
+ QWidgetPrivate::keyboardGrabber = this;
+ }
+}
+
+void QWidget::releaseKeyboard()
+{
+ if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
+ // ### TODO: Native keyboard release
+ QWidgetPrivate::keyboardGrabber = 0;
+ }
+}
+
+void QWidget::grabMouse()
+{
+ if (!qt_nograb()) {
+ if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
+ QWidgetPrivate::mouseGrabber->releaseMouse();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ WId id = effectiveWinId();
+ id->SetPointerCapture(true);
+ QWidgetPrivate::mouseGrabber = this;
+ }
+}
+
+void QWidget::releaseMouse()
+{
+ if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ WId id = effectiveWinId();
+ id->SetPointerCapture(false);
+ QWidgetPrivate::mouseGrabber = 0;
+ }
+}
+
+void QWidget::activateWindow()
+{
+ Q_D(QWidget);
+ QWidget *tlw = window();
+ if (tlw->isVisible()) {
+ S60->windowGroup().SetOrdinalPosition(0);
+ window()->createWinId();
+ RDrawableWindow* rw = tlw->d_func()->topData()->rwindow;
+ rw->SetOrdinalPosition(0);
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index b94a490..8e60fb3 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -56,11 +56,9 @@
#include "private/qbackingstore_p.h"
#include "private/qwindowsurface_raster_p.h"
-#ifndef QT_NO_DIRECT3D
-#include "private/qpaintengine_d3d_p.h"
-#include "private/qwindowsurface_d3d_p.h"
-#endif
-
+#include "qscrollbar.h"
+#include "qabstractscrollarea.h"
+#include <private/qabstractscrollarea_p.h>
#include <qdebug.h>
@@ -68,7 +66,7 @@
#include <private/qwininputcontext_p.h>
#include <private/qpaintengine_raster_p.h>
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qguifunctions_wince.h"
QT_USE_NAMESPACE
extern void qt_wince_maximize(QWidget *widget); //defined in qguifunctions_wince.cpp
@@ -146,14 +144,8 @@ static void init_wintab_functions()
if (!qt_is_gui_used)
return;
QLibrary library(QLatin1String("wintab32"));
- QT_WA({
- ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW");
- ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
- } , {
- ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenA");
- ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoA");
- });
-
+ ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW");
+ ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
ptrWTClose = (PtrWTClose)library.resolve("WTClose");
ptrWTQueueSizeGet = (PtrWTQueueSizeGet)library.resolve("WTQueueSizeGet");
ptrWTQueueSizeSet = (PtrWTQueueSizeSet)library.resolve("WTQueueSizeSet");
@@ -257,7 +249,7 @@ extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
QWidget member functions
*****************************************************************************/
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
{
Q_Q(QWidget);
@@ -276,7 +268,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
HINSTANCE appinst = qWinAppInst();
HWND parentw, destroyw = 0;
- WId id;
+ WId id = 0;
QString windowClassName = qt_reg_winclass(q);
@@ -293,25 +285,18 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget
popup = false; // force this flags off
- if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95)
- data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */),
+ data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */),
GetSystemMetrics(78 /* SM_CXVIRTUALSCREEN */), GetSystemMetrics(79 /* SM_CYVIRTUALSCREEN */));
- else
- data.crect.setRect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
}
parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0;
-#ifdef UNICODE
QString title;
- const TCHAR *ttitle = 0;
-#endif
- QByteArray title95;
int style = WS_CHILD;
int exsty = 0;
if (window) {
- style = GetWindowLongA(window, GWL_STYLE);
+ style = GetWindowLong(window, GWL_STYLE);
if (!style)
qErrnoWarning("QWidget::create: GetWindowLong failed");
topLevel = false; // #### needed for some IE plugins??
@@ -367,12 +352,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
if (flags & Qt::WindowTitleHint) {
- QT_WA({
- title = q->isWindow() ? qAppName() : q->objectName();
- ttitle = (TCHAR*)title.utf16();
- } , {
- title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1();
- });
+ title = q->isWindow() ? qAppName() : q->objectName();
}
// The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
@@ -385,13 +365,13 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
destroyw = data.winid;
id = window;
setWinId(window);
- LONG res = SetWindowLongA(window, GWL_STYLE, style);
+ LONG res = SetWindowLong(window, GWL_STYLE, style);
if (!res)
qErrnoWarning("QWidget::create: Failed to set window style");
#ifdef _WIN64
- res = SetWindowLongPtrA( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc );
+ res = SetWindowLongPtr( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc );
#else
- res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc );
+ res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc );
#endif
if (!res)
qErrnoWarning("QWidget::create: Failed to set window procedure");
@@ -442,16 +422,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
}
- QT_WA({
- const TCHAR *cname = (TCHAR*)windowClassName.utf16();
- id = CreateWindowEx(exsty, cname, ttitle, style,
- x, y, w, h,
- parentw, 0, appinst, 0);
- } , {
- id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
- x, y, w, h,
- parentw, 0, appinst, 0);
- });
+ id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()),
+ reinterpret_cast<const wchar_t *>(title.utf16()), style,
+ x, y, w, h,
+ parentw, NULL, appinst, NULL);
if (!id)
qErrnoWarning("QWidget::create: Failed to create window");
setWinId(id);
@@ -463,16 +437,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
SetWindowPos(id, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
winUpdateIsOpaque();
} else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget
- QT_WA({
- const TCHAR *cname = (TCHAR*)windowClassName.utf16();
- id = CreateWindowEx(exsty, cname, ttitle, style,
- data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
- parentw, NULL, appinst, NULL);
- } , {
- id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
- data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
+ id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()),
+ reinterpret_cast<const wchar_t *>(title.utf16()), style,
+ data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
parentw, NULL, appinst, NULL);
- });
if (!id)
qErrnoWarning("QWidget::create: Failed to create window");
SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
@@ -503,9 +471,23 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
}
+ if (topLevel) {
+ if (data.window_flags & Qt::CustomizeWindowHint
+ && data.window_flags & Qt::WindowTitleHint) {
+ HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE);
+ if (data.window_flags & Qt::WindowCloseButtonHint)
+ EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
+ else
+ EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
+ }
+ }
+
q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
hd = 0; // no display context
+ if (q->testAttribute(Qt::WA_AcceptTouchEvents))
+ registerTouchWindow();
+
if (window) { // got window from outside
if (IsWindowVisible(window))
q->setAttribute(Qt::WA_WState_Visible);
@@ -546,14 +528,14 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
{
Q_D(QWidget);
if (!isWindow() && parentWidget())
- parentWidget()->d_func()->invalidateBuffer(geometry());
+ parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
d->deactivateWidgetCleanup();
if (testAttribute(Qt::WA_WState_Created)) {
setAttribute(Qt::WA_WState_Created, false);
@@ -574,13 +556,17 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
if (destroyWindow && !(windowType() == Qt::Desktop) && internalWinId()) {
DestroyWindow(internalWinId());
}
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (destroyWindow && (windowType() == Qt::Desktop) && !GetDesktopWindow()) {
DestroyWindow(internalWinId());
}
#endif
- d->setWinId(0);
+ QT_TRY {
+ d->setWinId(0);
+ } QT_CATCH (const std::bad_alloc &) {
+ // swallow - destructors must not throw
+ }
}
}
@@ -615,7 +601,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
Q_Q(QWidget);
bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
- q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
+ q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
WId old_winid = data.winid;
// hide and reparent our own window away. Otherwise we might get
@@ -671,21 +657,11 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
|| (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
q->setAttribute(Qt::WA_DropSiteRegistered, true);
-
- if (data.window_flags & Qt::CustomizeWindowHint
- && data.window_flags & Qt::WindowTitleHint) {
- HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE);
- if (data.window_flags & Qt::WindowCloseButtonHint)
- EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
- else
- EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
- }
-
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
// Show borderless toplevel windows in tasklist & NavBar
if (!parent) {
QString txt = q->windowTitle().isEmpty()?qAppName():q->windowTitle();
- SetWindowText(q->internalWinId(), (TCHAR*)txt.utf16());
+ SetWindowText(q->internalWinId(), (wchar_t*)txt.utf16());
}
#endif
invalidateBuffer(q->rect());
@@ -770,11 +746,7 @@ void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
return;
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- QT_WA({
- SetWindowText(q->internalWinId(), (TCHAR*)caption.utf16());
- } , {
- SetWindowTextA(q->internalWinId(), caption.toLocal8Bit());
- });
+ SetWindowText(q->internalWinId(), (wchar_t*)caption.utf16());
}
/*
@@ -856,11 +828,11 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
&(x->iconPixmap));
if (x->winIconBig) {
- SendMessageA(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
- SendMessageA(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig);
+ SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
+ SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig);
} else {
- SendMessageA(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
- SendMessageA(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall);
+ SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
+ SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall);
}
}
@@ -877,17 +849,17 @@ QCursor *qt_grab_cursor()
}
// The procedure does nothing, but is required for mousegrabbing to work
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(journalRec, nCode, wParam, lParam);
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
/* Works only as long as pointer is inside the application's window,
which is good enough for QDockWidget.
- Doesn't call SetWindowsHookExA() - this function causes a system-wide
+ Doesn't call SetWindowsHookEx() - this function causes a system-wide
freeze if any other app on the system installs a hook and fails to
process events. */
void QWidgetPrivate::grabMouseWhileInWindow()
@@ -905,13 +877,13 @@ void QWidgetPrivate::grabMouseWhileInWindow()
}
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidget::grabMouse()
{
if (!qt_nograb()) {
if (mouseGrb)
mouseGrb->releaseMouse();
- journalRec = SetWindowsHookExA(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandleA(0), 0);
+ journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0);
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
SetCapture(effectiveWinId());
mouseGrb = this;
@@ -924,7 +896,7 @@ void QWidget::grabMouse(const QCursor &cursor)
if (!qt_nograb()) {
if (mouseGrb)
mouseGrb->releaseMouse();
- journalRec = SetWindowsHookExA(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandleA(0), 0);
+ journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0);
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
SetCapture(effectiveWinId());
mouseGrbCur = new QCursor(cursor);
@@ -982,7 +954,7 @@ void QWidget::activateWindow()
SetForegroundWindow(window()->internalWinId());
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidget::setWindowState(Qt::WindowStates newstate)
{
Q_D(QWidget);
@@ -1031,18 +1003,18 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
if (newstate & Qt::WindowFullScreen) {
if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized))
d->topData()->normalGeometry = geometry();
- d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE);
+ d->topData()->savedFlags = Qt::WindowFlags(GetWindowLong(internalWinId(), GWL_STYLE));
#ifndef Q_FLATTEN_EXPOSE
UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
#else
UINT style = WS_POPUP;
#endif
- if (d->topData()->savedFlags & WS_SYSMENU)
+ if (ulong(d->topData()->savedFlags) & WS_SYSMENU)
style |= WS_SYSMENU;
if (isVisible())
style |= WS_VISIBLE;
- SetWindowLongA(internalWinId(), GWL_STYLE, style);
- QRect r = qApp->desktop()->screenGeometry(this);
+ SetWindowLong(internalWinId(), GWL_STYLE, style);
+ QRect r = QApplication::desktop()->screenGeometry(this);
UINT swpf = SWP_FRAMECHANGED;
if (newstate & Qt::WindowActive)
swpf |= SWP_NOACTIVATE;
@@ -1053,7 +1025,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
UINT style = d->topData()->savedFlags;
if (isVisible())
style |= WS_VISIBLE;
- SetWindowLongA(internalWinId(), GWL_STYLE, style);
+ SetWindowLong(internalWinId(), GWL_STYLE, style);
UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
if (newstate & Qt::WindowActive)
@@ -1084,7 +1056,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
QWindowStateChangeEvent e(oldstate);
QApplication::sendEvent(this, &e);
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
/*
@@ -1097,7 +1069,7 @@ void QWidgetPrivate::hide_sys()
Q_Q(QWidget);
deactivateWidgetCleanup();
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (!qt_wince_is_mobile() && q->isFullScreen()) {
HWND handle = FindWindow(L"HHTaskBar", L"");
if (handle) {
@@ -1126,7 +1098,7 @@ void QWidgetPrivate::hide_sys()
\internal
Platform-specific part of QWidget::show().
*/
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
@@ -1192,9 +1164,11 @@ void QWidgetPrivate::show_sys()
data.window_state |= Qt::WindowMaximized;
}
+ winSetupGestures();
+
invalidateBuffer(q->rect());
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
void QWidgetPrivate::setFocus_sys()
{
@@ -1240,7 +1214,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget* w)
(In all comments below: s/X/Windows/g)
*/
-void QWidgetPrivate::setWSGeometry(bool dontShow)
+void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
{
Q_Q(QWidget);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
@@ -1398,7 +1372,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
UINT style = top->savedFlags;
if (q->isVisible())
style |= WS_VISIBLE;
- SetWindowLongA(q->internalWinId(), GWL_STYLE, style);
+ SetWindowLong(q->internalWinId(), GWL_STYLE, style);
UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
if (data.window_state & Qt::WindowActive)
@@ -1413,7 +1387,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
const bool isTranslucentWindow = !isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint)
- && GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED;
+ && GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED;
if (q->testAttribute(Qt::WA_WState_ConfigPending)) { // processing config event
if (q->internalWinId())
@@ -1452,7 +1426,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
show_sys();
} else if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
q->setAttribute(Qt::WA_OutsideWSRange, false);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// If the window is hidden and in maximized state or minimized, instead of moving the
// window, set the normal position of the window.
WINDOWPLACEMENT wndpl;
@@ -1573,7 +1547,7 @@ bool QWidgetPrivate::shouldShowMaximizeButton()
void QWidgetPrivate::winUpdateIsOpaque()
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
Q_Q(QWidget);
if (!q->isWindow() || !q->testAttribute(Qt::WA_TranslucentBackground))
@@ -1583,26 +1557,26 @@ void QWidgetPrivate::winUpdateIsOpaque()
return;
if (!isOpaque && ptrUpdateLayeredWindowIndirect) {
- SetWindowLongA(q->internalWinId(), GWL_EXSTYLE,
- GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED);
+ SetWindowLong(q->internalWinId(), GWL_EXSTYLE,
+ GetWindowLong(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED);
} else {
- SetWindowLongA(q->internalWinId(), GWL_EXSTYLE,
- GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED);
+ SetWindowLong(q->internalWinId(), GWL_EXSTYLE,
+ GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED);
}
#endif
}
void QWidgetPrivate::setConstraints_sys()
{
-#ifndef Q_OS_WINCE_WM
+#ifndef Q_WS_WINCE_WM
Q_Q(QWidget);
if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) {
- int style = GetWindowLongA(q->internalWinId(), GWL_STYLE);
+ int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
if (shouldShowMaximizeButton())
style |= WS_MAXIMIZEBOX;
else
style &= ~WS_MAXIMIZEBOX;
- SetWindowLongA(q->internalWinId(), GWL_STYLE, style);
+ SetWindowLong(q->internalWinId(), GWL_STYLE, style);
}
#endif
}
@@ -1712,28 +1686,24 @@ int QWidget::metric(PaintDeviceMetric m) const
return val;
}
-#ifndef Q_OS_WINCE
void QWidgetPrivate::createSysExtra()
{
#ifndef QT_NO_DRAGANDDROP
extra->dropTarget = 0;
#endif
-#ifndef QT_NO_DIRECT3D
- extra->had_auto_fill_bg = 0;
- extra->had_paint_on_screen = 0;
- extra->had_no_system_bg = 0;
-#endif
}
+#ifndef Q_WS_WINCE
void QWidgetPrivate::deleteSysExtra()
{
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
void QWidgetPrivate::createTLSysExtra()
{
- extra->topextra->winIconSmall = 0;
+ extra->topextra->savedFlags = 0;
extra->topextra->winIconBig = 0;
+ extra->topextra->winIconSmall = 0;
}
void QWidgetPrivate::deleteTLSysExtra()
@@ -1857,7 +1827,8 @@ void QWidgetPrivate::setMask_sys(const QRegion &region)
OffsetRgn(wr, offset.x(), offset.y());
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- SetWindowRgn(data.winid, wr, true);
+ if (!SetWindowRgn(data.winid, wr, true))
+ DeleteObject(wr);
}
void QWidgetPrivate::updateFrameStrut()
@@ -1875,11 +1846,9 @@ void QWidgetPrivate::updateFrameStrut()
RECT rect = {0,0,0,0};
QTLWExtra *top = topData();
- uint exstyle = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_EXSTYLE),
- GetWindowLongA(q->internalWinId(), GWL_EXSTYLE));
- uint style = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_STYLE),
- GetWindowLongA(q->internalWinId(), GWL_STYLE));
-#ifndef Q_OS_WINCE
+ uint exstyle = GetWindowLong(q->internalWinId(), GWL_EXSTYLE);
+ uint style = GetWindowLong(q->internalWinId(), GWL_STYLE);
+#ifndef Q_WS_WINCE
if (AdjustWindowRectEx(&rect, style & ~(WS_OVERLAPPED), FALSE, exstyle)) {
#else
if (AdjustWindowRectEx(&rect, style, FALSE, exstyle)) {
@@ -1889,16 +1858,15 @@ void QWidgetPrivate::updateFrameStrut()
}
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidgetPrivate::setWindowOpacity_sys(qreal level)
{
Q_Q(QWidget);
- if (!isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint)) {
- if (GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) {
- Q_BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), Q_AC_SRC_ALPHA};
- Q_UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA, NULL};
- (*ptrUpdateLayeredWindowIndirect)(q->internalWinId(), &info);
+ if (!isOpaque && ptrUpdateLayeredWindow && (data.window_flags & Qt::FramelessWindowHint)) {
+ if (GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) {
+ BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), AC_SRC_ALPHA};
+ ptrUpdateLayeredWindow(q->internalWinId(), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA);
}
return;
}
@@ -1914,17 +1882,17 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level)
if (!ptrSetLayeredWindowAttributes)
return;
- int wl = GetWindowLongA(q->internalWinId(), GWL_EXSTYLE);
+ int wl = GetWindowLong(q->internalWinId(), GWL_EXSTYLE);
if (level != 1.0) {
if ((wl&Q_WS_EX_LAYERED) == 0)
- SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, wl|Q_WS_EX_LAYERED);
+ SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl | Q_WS_EX_LAYERED);
} else if (wl&Q_WS_EX_LAYERED) {
- SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED);
+ SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED);
}
- (*ptrSetLayeredWindowAttributes)(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA);
+ ptrSetLayeredWindowAttributes(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA);
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
// class QGlobalRasterPaintEngine: public QRasterPaintEngine
// {
@@ -1933,22 +1901,6 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level)
// };
// Q_GLOBAL_STATIC(QGlobalRasterPaintEngine, globalRasterPaintEngine)
-#ifndef QT_NO_DIRECT3D
-static void cleanup_d3d_engine();
-Q_GLOBAL_STATIC_WITH_INITIALIZER(QDirect3DPaintEngine, _qt_d3dEngine,
- {
- qAddPostRoutine(cleanup_d3d_engine);
- })
-static void cleanup_d3d_engine()
-{
- _qt_d3dEngine()->cleanup();
-}
-QDirect3DPaintEngine* qt_d3dEngine()
-{
- return _qt_d3dEngine();
-}
-#endif
-
#ifndef QT_NO_DIRECTDRAW
static uchar *qt_primary_surface_bits;
@@ -2004,8 +1956,8 @@ public:
// in
QOnScreenRasterPaintEngine()
: QRasterPaintEngine(new QImage(qt_primary_surface_bits,
- qApp->desktop()->width(),
- qApp->desktop()->height(),
+ QApplication::desktop()->width(),
+ QApplication::desktop()->height(),
qt_primary_surface_stride,
qt_primary_surface_format))
{
@@ -2061,19 +2013,6 @@ void qt_win_initialize_directdraw() { }
QPaintEngine *QWidget::paintEngine() const
{
-#ifndef QT_NO_DIRECT3D
- if ((qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)
- || testAttribute(Qt::WA_MSWindowsUseDirect3D))
- && qt_d3dEngine()->hasDirect3DSupport())
- {
- QDirect3DPaintEngine *engine = qt_d3dEngine();
- if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault))
- engine->setFlushOnEnd(false);
- else
- engine->setFlushOnEnd(true);
- return engine;
- }
-#endif
#ifndef QT_NO_DIRECTDRAW
QOnScreenRasterPaintEngine *pe = onScreenPaintEngine();
pe->widget = this;
@@ -2102,13 +2041,6 @@ QPaintEngine *QWidget::paintEngine() const
QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
{
Q_Q(QWidget);
-#ifndef QT_NO_DIRECT3D
- extern QDirect3DPaintEngine *qt_d3dEngine();
- if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault) && (q->windowOpacity() == 1.0f)
- && qt_d3dEngine()->hasDirect3DSupport()) {
- return new QD3DWindowSurface(q);
- }
-#endif
return new QRasterWindowSurface(q);
}
@@ -2116,11 +2048,94 @@ void QWidgetPrivate::setModal_sys()
{
}
+void QWidgetPrivate::registerTouchWindow()
+{
+ Q_Q(QWidget);
+
+ // enable WM_TOUCH* messages on our window
+ if (q->testAttribute(Qt::WA_WState_Created)
+ && QApplicationPrivate::RegisterTouchWindow
+ && q->windowType() != Qt::Desktop)
+ QApplicationPrivate::RegisterTouchWindow(q->effectiveWinId(), 0);
+}
+
+void QWidgetPrivate::winSetupGestures()
+{
+ Q_Q(QWidget);
+ if (!q)
+ return;
+ if (!q->isVisible())
+ return;
+ QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
+ bool needh = false;
+ bool needv = false;
+ bool singleFingerPanEnabled = false;
+ QApplicationPrivate::WidgetStandardGesturesMap::const_iterator it =
+ qAppPriv->widgetGestures.find(q);
+ if (it == qAppPriv->widgetGestures.end())
+ return;
+ const QStandardGestures &gestures = it.value();
+ WId winid = 0;
+
+ if (QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea*>(q)) {
+ winid = asa->viewport()->internalWinId();
+ if (!winid) {
+ QWidget *nativeParent = asa->viewport()->nativeParentWidget();
+ if (!nativeParent)
+ return;
+ winid = nativeParent->internalWinId();
+ }
+ QScrollBar *hbar = asa->horizontalScrollBar();
+ QScrollBar *vbar = asa->verticalScrollBar();
+ Qt::ScrollBarPolicy hbarpolicy = asa->horizontalScrollBarPolicy();
+ Qt::ScrollBarPolicy vbarpolicy = asa->verticalScrollBarPolicy();
+ needh = (hbarpolicy == Qt::ScrollBarAlwaysOn ||
+ (hbarpolicy == Qt::ScrollBarAsNeeded && hbar->minimum() < hbar->maximum()));
+ needv = (vbarpolicy == Qt::ScrollBarAlwaysOn ||
+ (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum()));
+ singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled;
+ } else {
+ winid = q->internalWinId();
+ if (!winid) {
+ if (QWidget *nativeParent = q->nativeParentWidget())
+ winid = nativeParent->internalWinId();
+ }
+ }
+ if (winid && qAppPriv->SetGestureConfig) {
+ GESTURECONFIG gc[3];
+ memset(gc, 0, sizeof(gc));
+ gc[0].dwID = GID_PAN;
+ if (gestures.pan) {
+ gc[0].dwWant = GC_PAN;
+ if (needv && singleFingerPanEnabled)
+ gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
+ else
+ gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
+ if (needh && singleFingerPanEnabled)
+ gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
+ else
+ gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
+ } else {
+ gc[0].dwBlock = GC_PAN;
+ }
+ gc[1].dwID = GID_ZOOM;
+ if (gestures.pinch)
+ gc[1].dwWant = GC_ZOOM;
+ else
+ gc[1].dwBlock = GC_ZOOM;
+ gc[2].dwID = GID_ROTATE;
+ if (gestures.pinch)
+ gc[2].dwWant = GC_ROTATE;
+ else
+ gc[2].dwBlock = GC_ROTATE;
+ qAppPriv->SetGestureConfig(winid, 0, sizeof(gc)/sizeof(gc[0]), gc, sizeof(gc[0]));
+ }
+}
QT_END_NAMESPACE
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
# include "qwidget_wince.cpp"
#endif
diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp
index 20d434b..878ed5b 100644
--- a/src/gui/kernel/qwidget_wince.cpp
+++ b/src/gui/kernel/qwidget_wince.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qguifunctions_wince.h"
@@ -188,11 +188,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0;
-#ifdef UNICODE
QString title;
- const TCHAR *ttitle = 0;
-#endif
- QByteArray title95;
int style = WS_CHILD;
int exsty = WS_EX_NOPARENTNOTIFY;
@@ -211,7 +207,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
style |= WS_SYSMENU;
if (flags & Qt::WindowContextHelpButtonHint)
exsty |= WS_EX_CONTEXTHELP;
-#ifndef Q_OS_WINCE_WM
+#ifndef Q_WS_WINCE_WM
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
if (shouldShowMaximizeButton())
@@ -236,12 +232,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
if (flags & Qt::WindowTitleHint) {
- QT_WA({
- title = q->isWindow() ? qAppName() : q->objectName();
- ttitle = (TCHAR*)title.utf16();
- } , {
- title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1();
- });
+ title = q->isWindow() ? qAppName() : q->objectName();
}
// The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
@@ -254,11 +245,11 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
destroyw = data.winid;
id = window;
setWinId(window);
- LONG res = SetWindowLongA(window, GWL_STYLE, style);
+ LONG res = SetWindowLong(window, GWL_STYLE, style);
if (!res)
qErrnoWarning("QWidget::create: Failed to set window style");
- res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc );
+ res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc );
if (!res)
qErrnoWarning("QWidget::create: Failed to set window procedure");
@@ -267,10 +258,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if (!id) { //Create a dummy desktop
RECT r;
SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
- const TCHAR *cname = reinterpret_cast<const TCHAR *> (windowClassName.utf16());
- id = CreateWindow(cname, ttitle, style,
- r.left, r.top, r.right - r.left, r.bottom - r.top,
- 0, 0, appinst, 0);
+ id = CreateWindow(reinterpret_cast<const wchar_t *>(windowClassName.utf16()),
+ reinterpret_cast<const wchar_t *>(title.utf16()), style,
+ r.left, r.top, r.right - r.left, r.bottom - r.top,
+ 0, 0, appinst, 0);
}
setWinId(id);
} else if (topLevel) { // create top-level widget
@@ -303,8 +294,8 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
}
- const TCHAR *cname = reinterpret_cast<const TCHAR *> (windowClassName.utf16());
- id = CreateWindowEx(exsty, cname, ttitle, style,
+ id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()),
+ reinterpret_cast<const wchar_t *>(title.utf16()), style,
x, y, w, h,
0, 0, appinst, 0);
@@ -314,16 +305,9 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip))
SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
} else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget
- QT_WA({
- const TCHAR *cname = (TCHAR*)windowClassName.utf16();
- id = CreateWindowEx(exsty, cname, ttitle, style,
- data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
- parentw, NULL, appinst, NULL);
- } , {
- id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
- data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
+ id = CreateWindowEx(exsty, (wchar_t*)windowClassName.utf16(), (wchar_t*)title.utf16(), style,
+ data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
parentw, NULL, appinst, NULL);
- });
if (!id)
qErrnoWarning("QWidget::create: Failed to create window");
SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
@@ -414,7 +398,7 @@ void QWidgetPrivate::show_sys() {
int sm = SW_SHOW;
bool fakedMaximize = false;
if (q->isWindow()) {
-#ifndef Q_OS_WINCE_WM
+#ifndef Q_WS_WINCE_WM
if (q->isMinimized()) {
sm = SW_SHOWMINIMIZED;
} else if (q->isMaximized()) {
@@ -450,7 +434,7 @@ void QWidgetPrivate::show_sys() {
if (q->isMaximized() && q->isWindow())
qt_wince_maximize(q);
-#ifndef Q_OS_WINCE_WM
+#ifndef Q_WS_WINCE_WM
if (!qt_wince_is_mobile() && q->isFullScreen()) {
HWND handle = FindWindow(L"HHTaskBar", L"");
if (handle) {
@@ -510,7 +494,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
}
if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
if (!(newstate & Qt::WindowMaximized)) {
- int style = GetWindowLongW(internalWinId(), GWL_STYLE) | WS_BORDER | WS_POPUP | WS_CAPTION;
+ int style = GetWindowLong(internalWinId(), GWL_STYLE) | WS_BORDER | WS_POPUP | WS_CAPTION;
SetWindowLong(internalWinId(), GWL_STYLE, style);
SetWindowLong(internalWinId(), GWL_EXSTYLE, GetWindowLong (internalWinId(), GWL_EXSTYLE) & ~ WS_EX_NODRAG);
}
@@ -535,11 +519,11 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
if (newstate & Qt::WindowFullScreen) {
if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized))
d->topData()->normalGeometry = geometry();
- d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE);
+ d->topData()->savedFlags = (Qt::WindowFlags)GetWindowLong(internalWinId(), GWL_STYLE);
UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
if (isVisible())
style |= WS_VISIBLE;
- SetWindowLongA(internalWinId(), GWL_STYLE, style);
+ SetWindowLong(internalWinId(), GWL_STYLE, style);
QRect r = qApp->desktop()->screenGeometry(this);
UINT swpf = SWP_FRAMECHANGED;
if (newstate & Qt::WindowActive)
@@ -550,7 +534,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
UINT style = d->topData()->savedFlags;
if (isVisible())
style |= WS_VISIBLE;
- SetWindowLongA(internalWinId(), GWL_STYLE, style);
+ SetWindowLong(internalWinId(), GWL_STYLE, style);
UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
if (newstate & Qt::WindowActive)
swpf |= SWP_NOACTIVATE;
@@ -583,7 +567,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
}
if ((newstate & Qt::WindowMaximized) && !(newstate & Qt::WindowFullScreen)) {
QRect r = d->topData()->normalGeometry;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
if (!inherits("QDialog") && !inherits("QMdiArea") && !isVisible()) {
d->data.crect.setRect(0, 0, -1, -1);
}
@@ -598,13 +582,6 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
QApplication::sendEvent(this, &e);
}
-
-void QWidgetPrivate::createSysExtra() {
-#ifndef QT_NO_DRAGANDDROP
- extra->dropTarget = 0;
-#endif
-}
-
void QWidgetPrivate::deleteSysExtra()
{
Q_Q(QWidget);
@@ -704,4 +681,4 @@ void QWidget::show()
QT_END_NAMESPACE
-#endif Q_OS_WINCE
+#endif // Q_WS_WINCE
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index aae1355..7bb7933 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -512,6 +512,13 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
dialog = popup = false; // force these flags off
data.crect.setRect(0, 0, sw, sh);
} else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
+ QDesktopWidget *desktopWidget = qApp->desktop();
+ if (desktopWidget->isVirtualDesktop()) {
+ QRect r = desktopWidget->screenGeometry();
+ sw = r.width();
+ sh = r.height();
+ }
+
int width = sw / 2;
int height = 4 * sh / 10;
if (extra) {
@@ -754,11 +761,14 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
qBound(1, data.crect.width(), XCOORD_MAX),
qBound(1, data.crect.height(), XCOORD_MAX));
XStoreName(dpy, id, appName.data());
- Atom protocols[4];
+ Atom protocols[5];
int n = 0;
protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol
protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol
protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol
+#ifndef QT_NO_XSYNC
+ protocols[n++] = ATOM(_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol
+#endif // QT_NO_XSYNC
if (flags & Qt::WindowContextHelpButtonHint)
protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
XSetWMProtocols(dpy, id, protocols, n);
@@ -893,24 +903,75 @@ void QWidgetPrivate::x11UpdateIsOpaque()
int screen = xinfo.screen();
if (topLevel && X11->use_xrender
&& X11->argbVisuals[screen] && xinfo.depth() != 32) {
- // recreate widget
- QPoint pos = q->pos();
- bool visible = q->isVisible();
- if (visible)
- q->hide();
- q->setParent(q->parentWidget(), q->windowFlags());
- q->move(pos);
- if (visible)
- q->show();
+
+ if (q->inherits("QGLWidget")) {
+ // We send QGLWidgets a ParentChange event which causes them to
+ // recreate their GL context, which in turn causes them to choose
+ // their visual again. Now that WA_TranslucentBackground is set,
+ // QGLContext::chooseVisual will select an ARGB visual.
+ QEvent e(QEvent::ParentChange);
+ QApplication::sendEvent(q, &e);
+ }
+ else {
+ // For regular widgets, reparent them with their parent which
+ // also triggers a recreation of the native window
+ QPoint pos = q->pos();
+ bool visible = q->isVisible();
+ if (visible)
+ q->hide();
+
+ q->setParent(q->parentWidget(), q->windowFlags());
+ q->move(pos);
+ if (visible)
+ q->show();
+ }
}
#endif
}
+/*
+ Returns true if the background is inherited; otherwise returns
+ false.
+
+ Mainly used in the paintOnScreen case.
+*/
+bool QWidgetPrivate::isBackgroundInherited() const
+{
+ Q_Q(const QWidget);
+
+ // windows do not inherit their background
+ if (q->isWindow() || q->windowType() == Qt::SubWindow)
+ return false;
+
+ if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
+ return false;
+
+ const QPalette &pal = q->palette();
+ QPalette::ColorRole bg = q->backgroundRole();
+ QBrush brush = pal.brush(bg);
+
+ // non opaque brushes leaves us no choice, we must inherit
+ if (!q->autoFillBackground() || !brush.isOpaque())
+ return true;
+
+ if (brush.style() == Qt::SolidPattern) {
+ // the background is just a solid color. If there is no
+ // propagated contents, then we claim as performance
+ // optimization that it was not inheritet. This is the normal
+ // case in standard Windows or Motif style.
+ const QWidget *w = q->parentWidget();
+ if (!w->d_func()->isBackgroundInherited())
+ return false;
+ }
+
+ return true;
+}
+
void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
{
Q_D(QWidget);
if (!isWindow() && parentWidget())
- parentWidget()->d_func()->invalidateBuffer(geometry());
+ parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
d->deactivateWidgetCleanup();
if (testAttribute(Qt::WA_WState_Created)) {
setAttribute(Qt::WA_WState_Created, false);
@@ -954,7 +1015,11 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
if (destroyWindow)
qt_XDestroyWindow(this, X11->display, data->winid);
}
- d->setWinId(0);
+ QT_TRY {
+ d->setWinId(0);
+ } QT_CATCH (const std::bad_alloc &) {
+ // swallow - destructors must not throw
+ }
extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp
if (testAttribute(Qt::WA_WState_Reparented))
@@ -989,7 +1054,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
QTLWExtra *topData = maybeTopData();
bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
- q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
+ q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
extern void qPRCreate(const QWidget *, Window);
#ifndef QT_NO_CURSOR
QCursor oldcurs;
@@ -1215,7 +1280,7 @@ void QWidgetPrivate::updateSystemBackground()
else if (brush.style() == Qt::TexturePattern) {
extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
XSetWindowBackgroundPixmap(X11->display, q->internalWinId(),
- static_cast<QX11PixmapData*>(qt_toX11Pixmap(brush.texture()).data)->x11ConvertToDefaultDepth());
+ static_cast<QX11PixmapData*>(qt_toX11Pixmap(brush.texture()).data.data())->x11ConvertToDefaultDepth());
} else
XSetWindowBackground(X11->display, q->internalWinId(),
QColormap::instance(xinfo.screen()).pixel(brush.color()));
@@ -1308,17 +1373,10 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
// already been set
return;
- XWMHints *h = 0;
- if (q->internalWinId())
- h = XGetWMHints(X11->display, q->internalWinId());
- XWMHints wm_hints;
- if (!h) {
- memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
- h = &wm_hints;
- }
-
// preparing images to set the _NET_WM_ICON property
QIcon icon = q->windowIcon();
+ QVector<long> icon_data;
+ Qt::HANDLE pixmap_handle = 0;
if (!icon.isNull()) {
QList<QSize> availableSizes = icon.availableSizes();
if(availableSizes.isEmpty()) {
@@ -1328,7 +1386,6 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
availableSizes.push_back(QSize(64,64));
availableSizes.push_back(QSize(128,128));
}
- QVector<long> icon_data;
for(int i = 0; i < availableSizes.size(); ++i) {
QSize size = availableSizes.at(i);
QPixmap pixmap = icon.pixmap(size);
@@ -1350,11 +1407,6 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
}
}
if (!icon_data.isEmpty()) {
- if (q->internalWinId()) {
- XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
- PropModeReplace, (unsigned char *) icon_data.data(),
- icon_data.size());
- }
extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
/*
if the app is running on an unknown desktop, or it is not
@@ -1368,22 +1420,44 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
// unknown DE or non-default visual/colormap, use 1bpp bitmap
if (!forceReset || !topData->iconPixmap)
topData->iconPixmap = new QBitmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
- h->icon_pixmap = topData->iconPixmap->handle();
+ pixmap_handle = topData->iconPixmap->handle();
} else {
// default depth, use a normal pixmap (even though this
// violates the ICCCM), since this works on all DEs known to Qt
if (!forceReset || !topData->iconPixmap)
topData->iconPixmap = new QPixmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
- h->icon_pixmap = static_cast<QX11PixmapData*>(topData->iconPixmap->data)->x11ConvertToDefaultDepth();
+ pixmap_handle = static_cast<QX11PixmapData*>(topData->iconPixmap->data.data())->x11ConvertToDefaultDepth();
}
- h->flags |= IconPixmapHint;
- } else {
- h->flags &= ~(IconPixmapHint | IconMaskHint);
}
}
- if (q->internalWinId())
- XSetWMHints(X11->display, q->internalWinId(), h);
+ if (!q->internalWinId())
+ return;
+
+ if (!icon_data.isEmpty()) {
+ XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *) icon_data.data(),
+ icon_data.size());
+ } else {
+ XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON));
+ }
+
+ XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
+ XWMHints wm_hints;
+ if (!h) {
+ memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
+ h = &wm_hints;
+ }
+
+ if (pixmap_handle) {
+ h->icon_pixmap = pixmap_handle;
+ h->flags |= IconPixmapHint;
+ } else {
+ h->icon_pixmap = 0;
+ h->flags &= ~(IconPixmapHint | IconMaskHint);
+ }
+
+ XSetWMHints(X11->display, q->internalWinId(), h);
if (h != &wm_hints)
XFree((char *)h);
}
@@ -1817,6 +1891,23 @@ void QWidgetPrivate::show_sys()
if (setUserTime)
qt_net_update_user_time(q, userTime);
+#ifndef QT_NO_XSYNC
+ if (!topData()->syncUpdateCounter) {
+ XSyncValue value;
+ XSyncIntToValue(&value, 0);
+ topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value);
+
+ XChangeProperty(X11->display, q->internalWinId(),
+ ATOM(_NET_WM_SYNC_REQUEST_COUNTER),
+ XA_CARDINAL,
+ 32, PropModeReplace,
+ (uchar *) &topData()->syncUpdateCounter, 1);
+
+ topData()->newCounterValueHi = 0;
+ topData()->newCounterValueLo = 0;
+ }
+#endif
+
if (!topData()->embedded
&& (topData()->validWMState || topData()->waitingForMapNotify)
&& !q->isMinimized()) {
@@ -2151,7 +2242,7 @@ static void do_size_hints(QWidget* widget, QWExtra *x)
parentWRect is the geometry of the parent's X rect, measured in
parent's coord sys
*/
-void QWidgetPrivate::setWSGeometry(bool dontShow)
+void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
{
Q_Q(QWidget);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
@@ -2611,8 +2702,8 @@ int QWidget::metric(PaintDeviceMetric m) const
void QWidgetPrivate::createSysExtra()
{
- extra->xDndProxy = 0;
extra->compress_events = true;
+ extra->xDndProxy = 0;
}
void QWidgetPrivate::deleteSysExtra()
@@ -2621,9 +2712,18 @@ void QWidgetPrivate::deleteSysExtra()
void QWidgetPrivate::createTLSysExtra()
{
+ extra->topextra->spont_unmapped = 0;
+ extra->topextra->dnd = 0;
extra->topextra->validWMState = 0;
extra->topextra->waitingForMapNotify = 0;
+ extra->topextra->parentWinId = 0;
extra->topextra->userTimeWindow = 0;
+#ifndef QT_NO_XSYNC
+ extra->topextra->syncUpdateCounter = 0;
+ extra->topextra->syncRequestTimestamp = 0;
+ extra->topextra->newCounterValueHi = 0;
+ extra->topextra->newCounterValueLo = 0;
+#endif
}
void QWidgetPrivate::deleteTLSysExtra()
diff --git a/src/gui/kernel/qwidgetaction.cpp b/src/gui/kernel/qwidgetaction.cpp
index 5598413..cf314a7 100644
--- a/src/gui/kernel/qwidgetaction.cpp
+++ b/src/gui/kernel/qwidgetaction.cpp
@@ -54,6 +54,8 @@ QT_BEGIN_NAMESPACE
for inserting custom widgets into action based containers, such
as toolbars.
+ \ingroup mainwindow-classes
+
Most actions in an application are represented as items in menus or
buttons in toolbars. However sometimes more complex widgets are
necessary. For example a zoom action in a word processor may be
@@ -100,9 +102,6 @@ QT_BEGIN_NAMESPACE
DirectConnection.
\endlist
- \ingroup application
- \mainclass
-
\sa QAction, QActionGroup, QWidget
*/
@@ -228,8 +227,8 @@ bool QWidgetAction::event(QEvent *event)
if (event->type() == QEvent::ActionChanged) {
if (d->defaultWidget)
d->defaultWidget->setEnabled(isEnabled());
- foreach (QWidget *w, d->createdWidgets)
- w->setEnabled(isEnabled());
+ for (int i = 0; i < d->createdWidgets.count(); ++i)
+ d->createdWidgets.at(i)->setEnabled(isEnabled());
}
return QAction::event(event);
}
diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h
index e3e0cff..da3425d 100644
--- a/src/gui/kernel/qwindowdefs.h
+++ b/src/gui/kernel/qwindowdefs.h
@@ -131,6 +131,11 @@ QT_END_HEADER
#endif // Q_WS_QWS
+#if defined(Q_OS_SYMBIAN)
+class CCoeControl;
+typedef CCoeControl * WId;
+#endif // Q_OS_SYMBIAN
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/gui/kernel/qwindowdefs_win.h b/src/gui/kernel/qwindowdefs_win.h
index eb99020..aab9cf5 100644
--- a/src/gui/kernel/qwindowdefs_win.h
+++ b/src/gui/kernel/qwindowdefs_win.h
@@ -122,7 +122,7 @@ QT_BEGIN_NAMESPACE
Q_CORE_EXPORT HINSTANCE qWinAppInst();
Q_CORE_EXPORT HINSTANCE qWinAppPrevInst();
-Q_GUI_EXPORT int qWinAppCmdShow();
+Q_CORE_EXPORT int qWinAppCmdShow();
Q_GUI_EXPORT HDC qt_win_display_dc();
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp
index d654386..8e2eb1e 100644
--- a/src/gui/kernel/qx11embed_x11.cpp
+++ b/src/gui/kernel/qx11embed_x11.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
#include "qx11embed_x11.h"
#include <qapplication.h>
#include <qevent.h>
@@ -826,7 +827,7 @@ bool QX11EmbedWidget::x11Event(XEvent *event)
&actual_format_return, &nitems_return,
&bytes_after_return, &prop_return) == Success) {
if (nitems_return > 1) {
- if (((int * )prop_return)[1] & XEMBED_MAPPED) {
+ if (((long * )prop_return)[1] & XEMBED_MAPPED) {
XMapWindow(x11Info().display(), internalWinId());
} else {
XUnmapWindow(x11Info().display(), internalWinId());
@@ -1297,9 +1298,6 @@ bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event)
// focus is set to our focus proxy. We want to intercept all
// keypresses.
if (o == window() && d->client) {
- if (!d->isEmbedded() && d->activeContainer == this)
- d->moveInputToProxy();
-
if (d->clientIsXEmbed) {
sendXEmbedMessage(d->client, x11Info().display(), XEMBED_WINDOW_ACTIVATE);
} else {
@@ -1307,6 +1305,8 @@ bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event)
if (hasFocus())
XSetInputFocus(x11Info().display(), d->client, XRevertToParent, x11Time());
}
+ if (!d->isEmbedded())
+ d->moveInputToProxy();
}
break;
case QEvent::WindowDeactivate:
@@ -1671,9 +1671,9 @@ void QX11EmbedContainerPrivate::acceptClient(WId window)
// Clients with the _XEMBED_INFO property are XEMBED clients.
clientIsXEmbed = true;
- unsigned int *p = (unsigned int *)prop_return;
+ long *p = (long *)prop_return;
if (nitems_return >= 2)
- clientversion = p[0];
+ clientversion = (unsigned int)p[0];
}
XFree(prop_return);
@@ -1729,10 +1729,10 @@ void QX11EmbedContainerPrivate::acceptClient(WId window)
checkGrab();
if (q->hasFocus()) {
XSetInputFocus(q->x11Info().display(), client, XRevertToParent, x11Time());
- } else {
- if (!isEmbedded())
- moveInputToProxy();
}
+ } else {
+ if (!isEmbedded())
+ moveInputToProxy();
}
emit q->clientIsEmbedded();
@@ -1749,11 +1749,9 @@ void QX11EmbedContainerPrivate::acceptClient(WId window)
void QX11EmbedContainerPrivate::moveInputToProxy()
{
Q_Q(QX11EmbedContainer);
- WId focus;
- int revert_to;
- XGetInputFocus(q->x11Info().display(), &focus, &revert_to);
- if (focus != focusProxy->internalWinId())
- XSetInputFocus(q->x11Info().display(), focusProxy->internalWinId(), XRevertToParent, x11Time());
+ // Following Owen Taylor's advice from the XEmbed specification to
+ // always use CurrentTime when no explicit user action is involved.
+ XSetInputFocus(q->x11Info().display(), focusProxy->internalWinId(), XRevertToParent, CurrentTime);
}
/*! \internal
diff --git a/src/gui/kernel/qx11info_x11.cpp b/src/gui/kernel/qx11info_x11.cpp
index 28a327d..87c16ef 100644
--- a/src/gui/kernel/qx11info_x11.cpp
+++ b/src/gui/kernel/qx11info_x11.cpp
@@ -179,6 +179,7 @@ QX11InfoData* QX11Info::getX11Data(bool def) const
QX11InfoData* res = 0;
if (def) {
res = new QX11InfoData;
+ res->ref = 0;
res->screen = appScreen();
res->depth = appDepth();
res->cells = appCells();
@@ -189,8 +190,8 @@ QX11InfoData* QX11Info::getX11Data(bool def) const
} else if (x11data) {
res = new QX11InfoData;
*res = *x11data;
+ res->ref = 0;
}
- res->ref = 0;
return res;
}
diff --git a/src/gui/kernel/symbian.pri b/src/gui/kernel/symbian.pri
new file mode 100644
index 0000000..d267a53
--- /dev/null
+++ b/src/gui/kernel/symbian.pri
@@ -0,0 +1,3 @@
+symbian {
+ contains(QT_CONFIG, s60): LIBS+= $$QMAKE_LIBS_S60
+}
diff --git a/src/gui/kernel/x11.pri b/src/gui/kernel/x11.pri
index ac40f69..82de1b6 100644
--- a/src/gui/kernel/x11.pri
+++ b/src/gui/kernel/x11.pri
@@ -1,4 +1,4 @@
x11 {
- contains(QT_CONFIG, nas): LIBS += -laudio -lXt
+ contains(QT_CONFIG, nas): LIBS_PRIVATE += -laudio -lXt
}
diff --git a/src/gui/mac/images/leopard-unified-toolbar-on.png b/src/gui/mac/images/leopard-unified-toolbar-on.png
new file mode 100644
index 0000000..6716597
--- /dev/null
+++ b/src/gui/mac/images/leopard-unified-toolbar-on.png
Binary files differ
diff --git a/src/gui/mac/maccursors.qrc b/src/gui/mac/macresources.qrc
index d80a63b..9696002 100644
--- a/src/gui/mac/maccursors.qrc
+++ b/src/gui/mac/macresources.qrc
@@ -6,4 +6,7 @@
<file>images/waitcursor.png</file>
<file>images/pluscursor.png</file>
</qresource>
+<qresource prefix="/trolltech/mac/style">
+<file>images/leopard-unified-toolbar-on.png</file>
+</qresource>
</RCC>
diff --git a/src/gui/math3d/math3d.pri b/src/gui/math3d/math3d.pri
new file mode 100644
index 0000000..e4dd53a
--- /dev/null
+++ b/src/gui/math3d/math3d.pri
@@ -0,0 +1,15 @@
+HEADERS += \
+ math3d/qgenericmatrix.h \
+ math3d/qmatrix4x4.h \
+ math3d/qquaternion.h \
+ math3d/qvector2d.h \
+ math3d/qvector3d.h \
+ math3d/qvector4d.h
+
+SOURCES += \
+ math3d/qgenericmatrix.cpp \
+ math3d/qmatrix4x4.cpp \
+ math3d/qquaternion.cpp \
+ math3d/qvector2d.cpp \
+ math3d/qvector3d.cpp \
+ math3d/qvector4d.cpp
diff --git a/src/gui/math3d/qgenericmatrix.cpp b/src/gui/math3d/qgenericmatrix.cpp
new file mode 100644
index 0000000..1c924c7
--- /dev/null
+++ b/src/gui/math3d/qgenericmatrix.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgenericmatrix.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGenericMatrix
+ \brief The QGenericMatrix class is a template class that represents a NxM transformation matrix with N columns and M rows.
+ \since 4.6
+ \ingroup painting
+ \ingroup painting-3D
+
+ The QGenericMatrix template has four parameters:
+
+ \table
+ \row \i N \i Number of columns.
+ \row \i M \i Number of rows.
+ \row \i T \i Element type that is visible to users of the class.
+ \row \i InnerT \i Element type that is used inside the class.
+ \endtable
+
+ Normally T and InnerT are the same type; e.g. float or double.
+ But they can be different if the user wants to store elements
+ internally in a fixed-point format for the underlying hardware.
+
+ \sa QMatrix4x4
+*/
+
+/*!
+ \fn QGenericMatrix::QGenericMatrix()
+
+ Constructs a NxM identity matrix.
+*/
+
+/*!
+ \fn QGenericMatrix::QGenericMatrix(const QGenericMatrix<N, M, T, InnerT>& other)
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn QGenericMatrix::QGenericMatrix(const T *values)
+
+ Constructs a matrix from the given N * M floating-point \a values.
+ The contents of the array \a values is assumed to be in
+ row-major order.
+
+ \sa toValueArray()
+*/
+
+/*!
+ \fn T QGenericMatrix::operator()(int row, int column) const
+
+ Returns the element at position (\a row, \a column) in this matrix.
+*/
+
+/*!
+ \fn InnerT& QGenericMatrix::operator()(int row, int column)
+
+ Returns a reference to the element at position (\a row, \a column)
+ in this matrix so that the element can be assigned to.
+*/
+
+/*!
+ \fn bool QGenericMatrix::isIdentity() const
+
+ Returns true if this matrix is the identity; false otherwise.
+
+ \sa setIdentity()
+*/
+
+/*!
+ \fn void QGenericMatrix::setIdentity()
+
+ Sets this matrix to the identity.
+
+ \sa isIdentity()
+*/
+
+/*!
+ \fn void QGenericMatrix::fill(T value)
+
+ Fills all elements of this matrix with \a value.
+*/
+
+/*!
+ \fn QGenericMatrix<M, N> QGenericMatrix::transposed() const
+
+ Returns this matrix, transposed about its diagonal.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator+=(const QGenericMatrix<N, M, T, InnerT>& other)
+
+ Adds the contents of \a other to this matrix.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator-=(const QGenericMatrix<N, M, T, InnerT>& other)
+
+ Subtracts the contents of \a other from this matrix.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator*=(T factor)
+
+ Multiplies all elements of this matrix by \a factor.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator/=(T divisor)
+
+ Divides all elements of this matrix by \a divisor.
+*/
+
+/*!
+ \fn bool QGenericMatrix::operator==(const QGenericMatrix<N, M, T, InnerT>& other) const
+
+ Returns true if this matrix is identical to \a other; false otherwise.
+*/
+
+/*!
+ \fn bool QGenericMatrix::operator!=(const QGenericMatrix<N, M, T, InnerT>& other) const
+
+ Returns true if this matrix is not identical to \a other; false otherwise.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator+(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+ \relates QGenericMatrix
+
+ Returns the sum of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+ \relates QGenericMatrix
+
+ Returns the difference of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QGenericMatrix<M1, M2, T, InnerT> operator*(const QGenericMatrix<N, M2, T, InnerT>& m1, const QGenericMatrix<M1, N, T, InnerT>& m2)
+ \relates QGenericMatrix
+
+ Returns the product of the NxM2 matrix \a m1 and the M1xN matrix \a m2
+ to produce a M1xM2 matrix result.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& matrix)
+ \overload
+ \relates QGenericMatrix
+
+ Returns the negation of \a matrix.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator*(T factor, const QGenericMatrix<N, M, T, InnerT>& matrix)
+ \relates QGenericMatrix
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator*(const QGenericMatrix<N, M, T, InnerT>& matrix, T factor)
+ \relates QGenericMatrix
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator/(const QGenericMatrix<N, M, T, InnerT>& matrix, T divisor)
+ \relates QGenericMatrix
+
+ Returns the result of dividing all elements of \a matrix by \a divisor.
+*/
+
+/*!
+ \fn void QGenericMatrix::toValueArray(T *values)
+
+ Retrieves the N * M items in this matrix and writes them to \a values
+ in row-major order.
+*/
+
+/*!
+ \fn InnerT *QGenericMatrix::data()
+
+ Returns a pointer to the raw data of this matrix. This is intended
+ for use with raw GL functions.
+
+ \sa constData()
+*/
+
+/*!
+ \fn const InnerT *QGenericMatrix::data() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is intended for use with raw GL functions.
+
+ \sa constData()
+*/
+
+/*!
+ \fn const InnerT *QGenericMatrix::constData() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is intended for use with raw GL functions.
+
+ \sa data()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h
new file mode 100644
index 0000000..0ffe7f8
--- /dev/null
+++ b/src/gui/math3d/qgenericmatrix.h
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGENERICMATRIX_H
+#define QGENERICMATRIX_H
+
+#include <QtCore/qmetatype.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+template <int N, int M, typename T, typename InnerT = T>
+class QGenericMatrix
+{
+public:
+ QGenericMatrix();
+ QGenericMatrix(const QGenericMatrix<N, M, T, InnerT>& other);
+ explicit QGenericMatrix(const T *values);
+
+ T operator()(int row, int column) const;
+ InnerT& operator()(int row, int column);
+
+ bool isIdentity() const;
+ void setIdentity();
+
+ void fill(T value);
+
+ QGenericMatrix<M, N, T, InnerT> transposed() const;
+
+ QGenericMatrix<N, M, T, InnerT>& operator+=(const QGenericMatrix<N, M, T, InnerT>& other);
+ QGenericMatrix<N, M, T, InnerT>& operator-=(const QGenericMatrix<N, M, T, InnerT>& other);
+ QGenericMatrix<N, M, T, InnerT>& operator*=(T factor);
+ QGenericMatrix<N, M, T, InnerT>& operator/=(T divisor);
+ bool operator==(const QGenericMatrix<N, M, T, InnerT>& other) const;
+ bool operator!=(const QGenericMatrix<N, M, T, InnerT>& other) const;
+
+ void toValueArray(T *values);
+
+ InnerT *data() { return m[0]; }
+ const InnerT *data() const { return m[0]; }
+ const InnerT *constData() const { return m[0]; }
+
+#if !defined(Q_NO_TEMPLATE_FRIENDS)
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator+(const QGenericMatrix<NN, MM, TT, ITT>& m1, const QGenericMatrix<NN, MM, TT, ITT>& m2);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator-(const QGenericMatrix<NN, MM, TT, ITT>& m1, const QGenericMatrix<NN, MM, TT, ITT>& m2);
+ template<int NN, int M1, int M2, typename TT, typename ITT>
+ friend QGenericMatrix<M1, M2, TT, ITT> operator*(const QGenericMatrix<NN, M2, TT, ITT>& m1, const QGenericMatrix<M1, NN, TT, ITT>& m2);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator-(const QGenericMatrix<NN, MM, TT, ITT>& matrix);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator*(TT factor, const QGenericMatrix<NN, MM, TT, ITT>& matrix);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator*(const QGenericMatrix<NN, MM, TT, ITT>& matrix, TT factor);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator/(const QGenericMatrix<NN, MM, TT, ITT>& matrix, TT divisor);
+
+private:
+#endif
+ InnerT m[N][M]; // Column-major order to match OpenGL.
+
+ QGenericMatrix(int) {} // Construct without initializing identity matrix.
+
+#if !defined(Q_NO_TEMPLATE_FRIENDS)
+ template <int NN, int MM, typename TT, typename ITT>
+ friend class QGenericMatrix;
+#endif
+};
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>::QGenericMatrix()
+{
+ setIdentity();
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>::QGenericMatrix(const QGenericMatrix<N, M, T, InnerT>& other)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ m[col][row] = other.m[col][row];
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>::QGenericMatrix(const T *values)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ m[col][row] = values[row * N + col];
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE T QGenericMatrix<N, M, T, InnerT>::operator()(int row, int column) const
+{
+ Q_ASSERT(row >= 0 && row < M && column >= 0 && column < N);
+ return T(m[column][row]);
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE InnerT& QGenericMatrix<N, M, T, InnerT>::operator()(int row, int column)
+{
+ Q_ASSERT(row >= 0 && row < M && column >= 0 && column < N);
+ return m[column][row];
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T, InnerT>::isIdentity() const
+{
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (row == col) {
+ if (m[col][row] != 1.0f)
+ return false;
+ } else {
+ if (m[col][row] != 0.0f)
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T, InnerT>::setIdentity()
+{
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (row == col)
+ m[col][row] = 1.0f;
+ else
+ m[col][row] = 0.0f;
+ }
+ }
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T, InnerT>::fill(T value)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ m[col][row] = value;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<M, N, T, InnerT> QGenericMatrix<N, M, T, InnerT>::transposed() const
+{
+ QGenericMatrix<M, N, T, InnerT> result(1);
+ for (int row = 0; row < M; ++row)
+ for (int col = 0; col < N; ++col)
+ result.m[row][col] = m[col][row];
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator+=(const QGenericMatrix<N, M, T, InnerT>& other)
+{
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] += other.m[0][index];
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator-=(const QGenericMatrix<N, M, T, InnerT>& other)
+{
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] -= other.m[0][index];
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator*=(T factor)
+{
+ InnerT f(factor);
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] *= f;
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T, InnerT>::operator==(const QGenericMatrix<N, M, T, InnerT>& other) const
+{
+ for (int index = 0; index < N * M; ++index) {
+ if (m[0][index] != other.m[0][index])
+ return false;
+ }
+ return true;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T, InnerT>::operator!=(const QGenericMatrix<N, M, T, InnerT>& other) const
+{
+ for (int index = 0; index < N * M; ++index) {
+ if (m[0][index] != other.m[0][index])
+ return true;
+ }
+ return false;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator/=(T divisor)
+{
+ InnerT d(divisor);
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] /= d;
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator+(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+{
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = m1.m[0][index] + m2.m[0][index];
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+{
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = m1.m[0][index] - m2.m[0][index];
+ return result;
+}
+
+template <int N, int M1, int M2, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<M1, M2, T, InnerT> operator*(const QGenericMatrix<N, M2, T, InnerT>& m1, const QGenericMatrix<M1, N, T, InnerT>& m2)
+{
+ QGenericMatrix<M1, M2, T, InnerT> result(1);
+ for (int row = 0; row < M2; ++row) {
+ for (int col = 0; col < M1; ++col) {
+ InnerT sum(0.0f);
+ for (int j = 0; j < N; ++j)
+ sum += m1.m[j][row] * m2.m[col][j];
+ result.m[col][row] = sum;
+ }
+ }
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& matrix)
+{
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = -matrix.m[0][index];
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator*(T factor, const QGenericMatrix<N, M, T, InnerT>& matrix)
+{
+ InnerT f(factor);
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = matrix.m[0][index] * f;
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator*(const QGenericMatrix<N, M, T, InnerT>& matrix, T factor)
+{
+ InnerT f(factor);
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = matrix.m[0][index] * f;
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator/(const QGenericMatrix<N, M, T, InnerT>& matrix, T divisor)
+{
+ InnerT d(divisor);
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = matrix.m[0][index] / d;
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T, InnerT>::toValueArray(T *values)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ values[row * N + col] = T(m[col][row]);
+}
+
+// Define aliases for the useful variants of QGenericMatrix.
+typedef QGenericMatrix<2, 2, qreal, float> QMatrix2x2;
+typedef QGenericMatrix<2, 3, qreal, float> QMatrix2x3;
+typedef QGenericMatrix<2, 4, qreal, float> QMatrix2x4;
+typedef QGenericMatrix<3, 2, qreal, float> QMatrix3x2;
+typedef QGenericMatrix<3, 3, qreal, float> QMatrix3x3;
+typedef QGenericMatrix<3, 4, qreal, float> QMatrix3x4;
+typedef QGenericMatrix<4, 2, qreal, float> QMatrix4x2;
+typedef QGenericMatrix<4, 3, qreal, float> QMatrix4x3;
+
+#ifndef QT_NO_DEBUG_STREAM
+
+template <int N, int M, typename T, typename InnerT>
+QDebug operator<<(QDebug dbg, const QGenericMatrix<N, M, T, InnerT> &m)
+{
+ dbg.nospace() << "QGenericMatrix<" << N << ", " << M
+ << ", " << QTypeInfo<T>::name() << ", " << QTypeInfo<InnerT>::name()
+ << ">(" << endl << qSetFieldWidth(10);
+ for (int row = 0; row < M; ++row) {
+ for (int col = 0; col < N; ++col)
+ dbg << m(row, col);
+ dbg << endl;
+ }
+ dbg << qSetFieldWidth(0) << ')';
+ return dbg.space();
+}
+
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMatrix2x2)
+Q_DECLARE_METATYPE(QMatrix2x3)
+Q_DECLARE_METATYPE(QMatrix2x4)
+Q_DECLARE_METATYPE(QMatrix3x2)
+Q_DECLARE_METATYPE(QMatrix3x3)
+Q_DECLARE_METATYPE(QMatrix3x4)
+Q_DECLARE_METATYPE(QMatrix4x2)
+Q_DECLARE_METATYPE(QMatrix4x3)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
new file mode 100644
index 0000000..eb87052
--- /dev/null
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -0,0 +1,1908 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmatrix4x4.h"
+#include <QtCore/qmath.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qmatrix.h>
+#include <QtGui/qtransform.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_MATRIX4X4
+
+/*!
+ \class QMatrix4x4
+ \brief The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
+ \since 4.6
+ \ingroup painting-3D
+
+ \sa QVector3D, QGenericMatrix
+*/
+
+/*!
+ \fn QMatrix4x4::QMatrix4x4()
+
+ Constructs an identity matrix.
+*/
+
+/*!
+ Constructs a matrix from the given 16 floating-point \a values.
+ The contents of the array \a values is assumed to be in
+ row-major order.
+
+ If the matrix has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa toValueArray(), inferSpecialType()
+*/
+QMatrix4x4::QMatrix4x4(const qreal *values)
+{
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ m[col][row] = values[row * 4 + col];
+ flagBits = General;
+}
+
+/*!
+ \fn QMatrix4x4::QMatrix4x4(qreal m11, qreal m12, qreal m13, qreal m14, qreal m21, qreal m22, qreal m23, qreal m24, qreal m31, qreal m32, qreal m33, qreal m34, qreal m41, qreal m42, qreal m43, qreal m44)
+
+ Constructs a matrix from the 16 elements \a m11, \a m12, \a m13, \a m14,
+ \a m21, \a m22, \a m23, \a m24, \a m31, \a m32, \a m33, \a m34,
+ \a m41, \a m42, \a m43, and \a m44. The elements are specified in
+ row-major order.
+
+ If the matrix has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa inferSpecialType()
+*/
+
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+
+/*!
+ \fn QMatrix4x4::QMatrix4x4(const QGenericMatrix<N, M, qreal, float>& matrix)
+
+ Constructs a 4x4 matrix from the left-most 4 columns and top-most
+ 4 rows of \a matrix. If \a matrix has less than 4 columns or rows,
+ the remaining elements are filled with elements from the identity
+ matrix.
+
+ \sa toGenericMatrix(), qGenericMatrixToMatrix4x4()
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, qreal, float> QMatrix4x4::toGenericMatrix() const
+
+ Constructs a NxM generic matrix from the left-most N columns and
+ top-most M rows of this 4x4 matrix. If N or M is greater than 4,
+ then the remaining elements are filled with elements from the
+ identity matrix.
+
+ \sa qGenericMatrixFromMatrix4x4()
+*/
+
+#endif
+
+/*!
+ \fn QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal, float>& matrix)
+ \relates QMatrix4x4
+
+ Returns a 4x4 matrix constructed from the left-most 4 columns and
+ top-most 4 rows of \a matrix. If \a matrix has less than 4 columns
+ or rows, the remaining elements are filled with elements from the
+ identity matrix.
+
+ \sa qGenericMatrixFromMatrix4x4()
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, qreal, float> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns a NxM generic matrix constructed from the left-most N columns
+ and top-most M rows of \a matrix. If N or M is greater than 4,
+ then the remaining elements are filled with elements from the
+ identity matrix.
+
+ \sa qGenericMatrixToMatrix4x4(), QMatrix4x4::toGenericMatrix()
+*/
+
+/*!
+ \internal
+*/
+QMatrix4x4::QMatrix4x4(const float *values, int cols, int rows)
+{
+ for (int col = 0; col < 4; ++col) {
+ for (int row = 0; row < 4; ++row) {
+ if (col < cols && row < rows)
+ m[col][row] = values[col * rows + row];
+ else if (col == row)
+ m[col][row] = 1.0f;
+ else
+ m[col][row] = 0.0f;
+ }
+ }
+ flagBits = General;
+}
+
+/*!
+ Constructs a 4x4 matrix from a conventional Qt 2D affine
+ transformation \a matrix.
+
+ If \a matrix has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa toAffine(), inferSpecialType()
+*/
+QMatrix4x4::QMatrix4x4(const QMatrix& matrix)
+{
+ m[0][0] = matrix.m11();
+ m[0][1] = matrix.m12();
+ m[0][2] = 0.0f;
+ m[0][3] = 0.0f;
+ m[1][0] = matrix.m21();
+ m[1][1] = matrix.m22();
+ m[1][2] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+ m[2][3] = 0.0f;
+ m[3][0] = matrix.dx();
+ m[3][1] = matrix.dy();
+ m[3][2] = 0.0f;
+ m[3][3] = 1.0f;
+ flagBits = General;
+}
+
+/*!
+ Constructs a 4x4 matrix from the conventional Qt 2D
+ transformation matrix \a transform.
+
+ If \a transform has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa toTransform(), inferSpecialType()
+*/
+QMatrix4x4::QMatrix4x4(const QTransform& transform)
+{
+ m[0][0] = transform.m11();
+ m[0][1] = transform.m12();
+ m[0][2] = 0.0f;
+ m[0][3] = transform.m13();
+ m[1][0] = transform.m21();
+ m[1][1] = transform.m22();
+ m[1][2] = 0.0f;
+ m[1][3] = transform.m23();
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+ m[2][3] = 0.0f;
+ m[3][0] = transform.dx();
+ m[3][1] = transform.dy();
+ m[3][2] = 0.0f;
+ m[3][3] = transform.m33();
+ flagBits = General;
+}
+
+/*!
+ \fn qreal QMatrix4x4::operator()(int row, int column) const
+
+ Returns the element at position (\a row, \a column) in this matrix.
+
+ \sa column(), row()
+*/
+
+/*!
+ \fn float& QMatrix4x4::operator()(int row, int column)
+
+ Returns a reference to the element at position (\a row, \a column)
+ in this matrix so that the element can be assigned to.
+
+ \sa inferSpecialType(), setColumn(), setRow()
+*/
+
+/*!
+ \fn QVector4D QMatrix4x4::column(int index) const
+
+ Returns the elements of column \a index as a 4D vector.
+
+ \sa setColumn(), row()
+*/
+
+/*!
+ \fn void QMatrix4x4::setColumn(int index, const QVector4D& value)
+
+ Sets the elements of column \a index to the components of \a value.
+
+ \sa column(), setRow()
+*/
+
+/*!
+ \fn QVector4D QMatrix4x4::row(int index) const
+
+ Returns the elements of row \a index as a 4D vector.
+
+ \sa setRow(), column()
+*/
+
+/*!
+ \fn void QMatrix4x4::setRow(int index, const QVector4D& value)
+
+ Sets the elements of row \a index to the components of \a value.
+
+ \sa row(), setColumn()
+*/
+
+/*!
+ \fn bool QMatrix4x4::isIdentity() const
+
+ Returns true if this matrix is the identity; false otherwise.
+
+ \sa setIdentity()
+*/
+
+/*!
+ \fn void QMatrix4x4::setIdentity()
+
+ Sets this matrix to the identity.
+
+ \sa isIdentity()
+*/
+
+/*!
+ \fn void QMatrix4x4::fill(qreal value)
+
+ Fills all elements of this matrx with \a value.
+*/
+
+// The 4x4 matrix inverse algorithm is based on that described at:
+// http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q24
+// Some optimization has been done to avoid making copies of 3x3
+// sub-matrices and to unroll the loops.
+
+// Calculate the determinant of a 3x3 sub-matrix.
+// | A B C |
+// M = | D E F | det(M) = A * (EI - HF) - B * (DI - GF) + C * (DH - GE)
+// | G H I |
+static inline float matrixDet3
+ (const float m[4][4], int col0, int col1, int col2,
+ int row0, int row1, int row2)
+{
+ return m[col0][row0] *
+ (m[col1][row1] * m[col2][row2] -
+ m[col1][row2] * m[col2][row1]) -
+ m[col1][row0] *
+ (m[col0][row1] * m[col2][row2] -
+ m[col0][row2] * m[col2][row1]) +
+ m[col2][row0] *
+ (m[col0][row1] * m[col1][row2] -
+ m[col0][row2] * m[col1][row1]);
+}
+
+// Calculate the determinant of a 4x4 matrix.
+static inline float matrixDet4(const float m[4][4])
+{
+ float det;
+ det = m[0][0] * matrixDet3(m, 1, 2, 3, 1, 2, 3);
+ det -= m[1][0] * matrixDet3(m, 0, 2, 3, 1, 2, 3);
+ det += m[2][0] * matrixDet3(m, 0, 1, 3, 1, 2, 3);
+ det -= m[3][0] * matrixDet3(m, 0, 1, 2, 1, 2, 3);
+ return det;
+}
+
+/*!
+ Returns the determinant of this matrix.
+*/
+qreal QMatrix4x4::determinant() const
+{
+ return qreal(matrixDet4(m));
+}
+
+/*!
+ Returns the inverse of this matrix. Returns the identity if
+ this matrix cannot be inverted; i.e. determinant() is zero.
+ If \a invertible is not null, then true will be written to
+ that location if the matrix can be inverted; false otherwise.
+
+ If the matrix is recognized as the identity or an orthonormal
+ matrix, then this function will quickly invert the matrix
+ using optimized routines.
+
+ \sa determinant(), normalMatrix()
+*/
+QMatrix4x4 QMatrix4x4::inverted(bool *invertible) const
+{
+ // Handle some of the easy cases first.
+ if (flagBits == Identity) {
+ if (invertible)
+ *invertible = true;
+ return QMatrix4x4();
+ } else if (flagBits == Translation) {
+ QMatrix4x4 inv;
+ inv.m[3][0] = -m[3][0];
+ inv.m[3][1] = -m[3][1];
+ inv.m[3][2] = -m[3][2];
+ inv.flagBits = Translation;
+ if (invertible)
+ *invertible = true;
+ return inv;
+ } else if (flagBits == Rotation || flagBits == (Rotation | Translation)) {
+ if (invertible)
+ *invertible = true;
+ return orthonormalInverse();
+ }
+
+ QMatrix4x4 inv(1); // The "1" says to not load the identity.
+
+ float det = matrixDet4(m);
+ if (det == 0.0f) {
+ if (invertible)
+ *invertible = false;
+ return QMatrix4x4();
+ }
+ det = 1.0f / det;
+
+ inv.m[0][0] = matrixDet3(m, 1, 2, 3, 1, 2, 3) * det;
+ inv.m[0][1] = -matrixDet3(m, 0, 2, 3, 1, 2, 3) * det;
+ inv.m[0][2] = matrixDet3(m, 0, 1, 3, 1, 2, 3) * det;
+ inv.m[0][3] = -matrixDet3(m, 0, 1, 2, 1, 2, 3) * det;
+ inv.m[1][0] = -matrixDet3(m, 1, 2, 3, 0, 2, 3) * det;
+ inv.m[1][1] = matrixDet3(m, 0, 2, 3, 0, 2, 3) * det;
+ inv.m[1][2] = -matrixDet3(m, 0, 1, 3, 0, 2, 3) * det;
+ inv.m[1][3] = matrixDet3(m, 0, 1, 2, 0, 2, 3) * det;
+ inv.m[2][0] = matrixDet3(m, 1, 2, 3, 0, 1, 3) * det;
+ inv.m[2][1] = -matrixDet3(m, 0, 2, 3, 0, 1, 3) * det;
+ inv.m[2][2] = matrixDet3(m, 0, 1, 3, 0, 1, 3) * det;
+ inv.m[2][3] = -matrixDet3(m, 0, 1, 2, 0, 1, 3) * det;
+ inv.m[3][0] = -matrixDet3(m, 1, 2, 3, 0, 1, 2) * det;
+ inv.m[3][1] = matrixDet3(m, 0, 2, 3, 0, 1, 2) * det;
+ inv.m[3][2] = -matrixDet3(m, 0, 1, 3, 0, 1, 2) * det;
+ inv.m[3][3] = matrixDet3(m, 0, 1, 2, 0, 1, 2) * det;
+
+ if (invertible)
+ *invertible = true;
+ return inv;
+}
+
+/*!
+ Returns the normal matrix corresponding to this 4x4 transformation.
+ The normal matrix is the transpose of the inverse of the top-left
+ 3x3 part of this 4x4 matrix. If the 3x3 sub-matrix is not invertible,
+ this function returns the identity.
+
+ \sa inverted()
+*/
+QMatrix3x3 QMatrix4x4::normalMatrix() const
+{
+ QMatrix3x3 inv;
+
+ // Handle the simple cases first.
+ if (flagBits == Identity || flagBits == Translation) {
+ return inv;
+ } else if (flagBits == Scale || flagBits == (Translation | Scale)) {
+ if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
+ return inv;
+ inv.data()[0] = 1.0f / m[0][0];
+ inv.data()[4] = 1.0f / m[1][1];
+ inv.data()[8] = 1.0f / m[2][2];
+ return inv;
+ }
+
+ float det = matrixDet3(m, 0, 1, 2, 0, 1, 2);
+ if (det == 0.0f)
+ return inv;
+ det = 1.0f / det;
+
+ float *invm = inv.data();
+
+ // Invert and transpose in a single step.
+ invm[0 + 0 * 3] = (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * det;
+ invm[1 + 0 * 3] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) * det;
+ invm[2 + 0 * 3] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * det;
+ invm[0 + 1 * 3] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * det;
+ invm[1 + 1 * 3] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * det;
+ invm[2 + 1 * 3] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) * det;
+ invm[0 + 2 * 3] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * det;
+ invm[1 + 2 * 3] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) * det;
+ invm[2 + 2 * 3] = (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * det;
+
+ return inv;
+}
+
+/*!
+ Returns this matrix, transposed about its diagonal.
+*/
+QMatrix4x4 QMatrix4x4::transposed() const
+{
+ QMatrix4x4 result(1); // The "1" says to not load the identity.
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ result.m[col][row] = m[row][col];
+ }
+ }
+ return result;
+}
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
+
+ Adds the contents of \a other to this matrix.
+*/
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
+
+ Subtracts the contents of \a other from this matrix.
+*/
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
+
+ Multiplies the contents of \a other by this matrix.
+*/
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator*=(qreal factor)
+ \overload
+
+ Multiplies all elements of this matrix by \a factor.
+*/
+
+/*!
+ \overload
+
+ Divides all elements of this matrix by \a divisor.
+*/
+QMatrix4x4& QMatrix4x4::operator/=(qreal divisor)
+{
+ m[0][0] /= divisor;
+ m[0][1] /= divisor;
+ m[0][2] /= divisor;
+ m[0][3] /= divisor;
+ m[1][0] /= divisor;
+ m[1][1] /= divisor;
+ m[1][2] /= divisor;
+ m[1][3] /= divisor;
+ m[2][0] /= divisor;
+ m[2][1] /= divisor;
+ m[2][2] /= divisor;
+ m[2][3] /= divisor;
+ m[3][0] /= divisor;
+ m[3][1] /= divisor;
+ m[3][2] /= divisor;
+ m[3][3] /= divisor;
+ flagBits = General;
+ return *this;
+}
+
+/*!
+ \fn bool QMatrix4x4::operator==(const QMatrix4x4& other) const
+
+ Returns true if this matrix is identical to \a other; false otherwise.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
+
+ Returns true if this matrix is not identical to \a other; false otherwise.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns the sum of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns the difference of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns the product of \a m1 and \a m2.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \fn QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied post-vector.
+*/
+
+/*!
+ \fn QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied pre-vector.
+*/
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \fn QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied post-vector.
+*/
+
+/*!
+ \fn QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied pre-vector.
+*/
+
+#endif
+
+/*!
+ \fn QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied post-point.
+*/
+
+/*!
+ \fn QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied post-point.
+*/
+
+/*!
+ \fn QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied pre-point.
+*/
+
+/*!
+ \fn QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied pre-point.
+*/
+
+/*!
+ \fn QMatrix4x4 operator-(const QMatrix4x4& matrix)
+ \overload
+ \relates QMatrix4x4
+
+ Returns the negation of \a matrix.
+*/
+
+/*!
+ \fn QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \fn QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor)
+ \relates QMatrix4x4
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \relates QMatrix4x4
+
+ Returns the result of dividing all elements of \a matrix by \a divisor.
+*/
+QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor)
+{
+ QMatrix4x4 m(1); // The "1" says to not load the identity.
+ m.m[0][0] = matrix.m[0][0] / divisor;
+ m.m[0][1] = matrix.m[0][1] / divisor;
+ m.m[0][2] = matrix.m[0][2] / divisor;
+ m.m[0][3] = matrix.m[0][3] / divisor;
+ m.m[1][0] = matrix.m[1][0] / divisor;
+ m.m[1][1] = matrix.m[1][1] / divisor;
+ m.m[1][2] = matrix.m[1][2] / divisor;
+ m.m[1][3] = matrix.m[1][3] / divisor;
+ m.m[2][0] = matrix.m[2][0] / divisor;
+ m.m[2][1] = matrix.m[2][1] / divisor;
+ m.m[2][2] = matrix.m[2][2] / divisor;
+ m.m[2][3] = matrix.m[2][3] / divisor;
+ m.m[3][0] = matrix.m[3][0] / divisor;
+ m.m[3][1] = matrix.m[3][1] / divisor;
+ m.m[3][2] = matrix.m[3][2] / divisor;
+ m.m[3][3] = matrix.m[3][3] / divisor;
+ return m;
+}
+
+/*!
+ \fn bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns true if \a m1 and \a m2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Multiplies this matrix by another that scales coordinates by
+ the components of \a vector. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(const QVector3D& vector)
+{
+ float vx = vector.xp;
+ float vy = vector.yp;
+ float vz = vector.zp;
+ if (flagBits == Identity) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= vx;
+ m[1][1] *= vy;
+ m[2][2] *= vz;
+ } else if (flagBits == Translation) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= vx;
+ m[0][1] *= vx;
+ m[0][2] *= vx;
+ m[0][3] *= vx;
+ m[1][0] *= vy;
+ m[1][1] *= vy;
+ m[1][2] *= vy;
+ m[1][3] *= vy;
+ m[2][0] *= vz;
+ m[2][1] *= vz;
+ m[2][2] *= vz;
+ m[2][3] *= vz;
+ flagBits = General;
+ }
+ return *this;
+}
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that scales coordinates by the
+ components \a x, and \a y. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y)
+{
+ float vx(x);
+ float vy(y);
+ if (flagBits == Identity) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= vx;
+ m[1][1] *= vy;
+ } else if (flagBits == Translation) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= vx;
+ m[0][1] *= vx;
+ m[0][2] *= vx;
+ m[0][3] *= vx;
+ m[1][0] *= vy;
+ m[1][1] *= vy;
+ m[1][2] *= vy;
+ m[1][3] *= vy;
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that scales coordinates by the
+ components \a x, \a y, and \a z. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y, qreal z)
+{
+ float vx(x);
+ float vy(y);
+ float vz(z);
+ if (flagBits == Identity) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= vx;
+ m[1][1] *= vy;
+ m[2][2] *= vz;
+ } else if (flagBits == Translation) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= vx;
+ m[0][1] *= vx;
+ m[0][2] *= vx;
+ m[0][3] *= vx;
+ m[1][0] *= vy;
+ m[1][1] *= vy;
+ m[1][2] *= vy;
+ m[1][3] *= vy;
+ m[2][0] *= vz;
+ m[2][1] *= vz;
+ m[2][2] *= vz;
+ m[2][3] *= vz;
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that scales coordinates by the
+ given \a factor. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(qreal factor)
+{
+ if (flagBits == Identity) {
+ m[0][0] = factor;
+ m[1][1] = factor;
+ m[2][2] = factor;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= factor;
+ m[1][1] *= factor;
+ m[2][2] *= factor;
+ } else if (flagBits == Translation) {
+ m[0][0] = factor;
+ m[1][1] = factor;
+ m[2][2] = factor;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= factor;
+ m[0][1] *= factor;
+ m[0][2] *= factor;
+ m[0][3] *= factor;
+ m[1][0] *= factor;
+ m[1][1] *= factor;
+ m[1][2] *= factor;
+ m[1][3] *= factor;
+ m[2][0] *= factor;
+ m[2][1] *= factor;
+ m[2][2] *= factor;
+ m[2][3] *= factor;
+ flagBits = General;
+ }
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR3D
+/*!
+ Multiplies this matrix by another that translates coordinates by
+ the components of \a vector. Returns this matrix.
+
+ \sa scale(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::translate(const QVector3D& vector)
+{
+ float vx = vector.xp;
+ float vy = vector.yp;
+ float vz = vector.zp;
+ if (flagBits == Identity) {
+ m[3][0] = vx;
+ m[3][1] = vy;
+ m[3][2] = vz;
+ flagBits = Translation;
+ } else if (flagBits == Translation) {
+ m[3][0] += vx;
+ m[3][1] += vy;
+ m[3][2] += vz;
+ } else if (flagBits == Scale) {
+ m[3][0] = m[0][0] * vx;
+ m[3][1] = m[1][1] * vy;
+ m[3][2] = m[2][2] * vz;
+ flagBits |= Translation;
+ } else if (flagBits == (Scale | Translation)) {
+ m[3][0] += m[0][0] * vx;
+ m[3][1] += m[1][1] * vy;
+ m[3][2] += m[2][2] * vz;
+ } else {
+ m[3][0] += m[0][0] * vx + m[1][0] * vy + m[2][0] * vz;
+ m[3][1] += m[0][1] * vx + m[1][1] * vy + m[2][1] * vz;
+ m[3][2] += m[0][2] * vx + m[1][2] * vy + m[2][2] * vz;
+ m[3][3] += m[0][3] * vx + m[1][3] * vy + m[2][3] * vz;
+ if (flagBits == Rotation)
+ flagBits |= Translation;
+ else if (flagBits != (Rotation | Translation))
+ flagBits = General;
+ }
+ return *this;
+}
+
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that translates coordinates
+ by the components \a x, and \a y. Returns this matrix.
+
+ \sa scale(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y)
+{
+ float vx(x);
+ float vy(y);
+ if (flagBits == Identity) {
+ m[3][0] = vx;
+ m[3][1] = vy;
+ flagBits = Translation;
+ } else if (flagBits == Translation) {
+ m[3][0] += vx;
+ m[3][1] += vy;
+ } else if (flagBits == Scale) {
+ m[3][0] = m[0][0] * vx;
+ m[3][1] = m[1][1] * vy;
+ m[3][2] = 0.;
+ flagBits |= Translation;
+ } else if (flagBits == (Scale | Translation)) {
+ m[3][0] += m[0][0] * vx;
+ m[3][1] += m[1][1] * vy;
+ } else {
+ m[3][0] += m[0][0] * vx + m[1][0] * vy;
+ m[3][1] += m[0][1] * vx + m[1][1] * vy;
+ m[3][2] += m[0][2] * vx + m[1][2] * vy;
+ m[3][3] += m[0][3] * vx + m[1][3] * vy;
+ if (flagBits == Rotation)
+ flagBits |= Translation;
+ else if (flagBits != (Rotation | Translation))
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that translates coordinates
+ by the components \a x, \a y, and \a z. Returns this matrix.
+
+ \sa scale(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y, qreal z)
+{
+ float vx(x);
+ float vy(y);
+ float vz(z);
+ if (flagBits == Identity) {
+ m[3][0] = vx;
+ m[3][1] = vy;
+ m[3][2] = vz;
+ flagBits = Translation;
+ } else if (flagBits == Translation) {
+ m[3][0] += vx;
+ m[3][1] += vy;
+ m[3][2] += vz;
+ } else if (flagBits == Scale) {
+ m[3][0] = m[0][0] * vx;
+ m[3][1] = m[1][1] * vy;
+ m[3][2] = m[2][2] * vz;
+ flagBits |= Translation;
+ } else if (flagBits == (Scale | Translation)) {
+ m[3][0] += m[0][0] * vx;
+ m[3][1] += m[1][1] * vy;
+ m[3][2] += m[2][2] * vz;
+ } else {
+ m[3][0] += m[0][0] * vx + m[1][0] * vy + m[2][0] * vz;
+ m[3][1] += m[0][1] * vx + m[1][1] * vy + m[2][1] * vz;
+ m[3][2] += m[0][2] * vx + m[1][2] * vy + m[2][2] * vz;
+ m[3][3] += m[0][3] * vx + m[1][3] * vy + m[2][3] * vz;
+ if (flagBits == Rotation)
+ flagBits |= Translation;
+ else if (flagBits != (Rotation | Translation))
+ flagBits = General;
+ }
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Multiples this matrix by another that rotates coordinates through
+ \a angle degrees about \a vector. Returns this matrix.
+
+ \sa scale(), translate()
+*/
+QMatrix4x4& QMatrix4x4::rotate(qreal angle, const QVector3D& vector)
+{
+ return rotate(angle, vector.x(), vector.y(), vector.z());
+}
+
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that rotates coordinates through
+ \a angle degrees about the vector (\a x, \a y, \a z). Returns this matrix.
+
+ \sa scale(), translate()
+*/
+QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z)
+{
+ if (angle == 0.0f)
+ return *this;
+ QMatrix4x4 m(1); // The "1" says to not load the identity.
+ qreal c, s, ic;
+ if (angle == 90.0f || angle == -270.0f) {
+ s = 1.0f;
+ c = 0.0f;
+ } else if (angle == -90.0f || angle == 270.0f) {
+ s = -1.0f;
+ c = 0.0f;
+ } else if (angle == 180.0f || angle == -180.0f) {
+ s = 0.0f;
+ c = -1.0f;
+ } else {
+ qreal a = angle * M_PI / 180.0f;
+ c = qCos(a);
+ s = qSin(a);
+ }
+ bool quick = false;
+ if (x == 0.0f) {
+ if (y == 0.0f) {
+ if (z != 0.0f) {
+ // Rotate around the Z axis.
+ m.setIdentity();
+ m.m[0][0] = c;
+ m.m[1][1] = c;
+ if (z < 0.0f) {
+ m.m[1][0] = s;
+ m.m[0][1] = -s;
+ } else {
+ m.m[1][0] = -s;
+ m.m[0][1] = s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ } else if (z == 0.0f) {
+ // Rotate around the Y axis.
+ m.setIdentity();
+ m.m[0][0] = c;
+ m.m[2][2] = c;
+ if (y < 0.0f) {
+ m.m[2][0] = -s;
+ m.m[0][2] = s;
+ } else {
+ m.m[2][0] = s;
+ m.m[0][2] = -s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ } else if (y == 0.0f && z == 0.0f) {
+ // Rotate around the X axis.
+ m.setIdentity();
+ m.m[1][1] = c;
+ m.m[2][2] = c;
+ if (x < 0.0f) {
+ m.m[2][1] = s;
+ m.m[1][2] = -s;
+ } else {
+ m.m[2][1] = -s;
+ m.m[1][2] = s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ if (!quick) {
+ qreal len = x * x + y * y + z * z;
+ if (!qFuzzyIsNull(len - 1.0f) && !qFuzzyIsNull(len)) {
+ len = qSqrt(len);
+ x /= len;
+ y /= len;
+ z /= len;
+ }
+ ic = 1.0f - c;
+ m.m[0][0] = x * x * ic + c;
+ m.m[1][0] = x * y * ic - z * s;
+ m.m[2][0] = x * z * ic + y * s;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = y * x * ic + z * s;
+ m.m[1][1] = y * y * ic + c;
+ m.m[2][1] = y * z * ic - x * s;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = x * z * ic - y * s;
+ m.m[1][2] = y * z * ic + x * s;
+ m.m[2][2] = z * z * ic + c;
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+ }
+ int flags = flagBits;
+ *this *= m;
+ if (flags != Identity)
+ flagBits = flags | Rotation;
+ else
+ flagBits = Rotation;
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Multiples this matrix by another that rotates coordinates according
+ to a specified \a quaternion. The \a quaternion is assumed to have
+ been normalized. Returns this matrix.
+
+ \sa scale(), translate(), QQuaternion
+*/
+QMatrix4x4& QMatrix4x4::rotate(const QQuaternion& quaternion)
+{
+ // Algorithm from:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54
+ QMatrix4x4 m(1);
+ float xx = quaternion.xp * quaternion.xp;
+ float xy = quaternion.xp * quaternion.yp;
+ float xz = quaternion.xp * quaternion.zp;
+ float xw = quaternion.xp * quaternion.wp;
+ float yy = quaternion.yp * quaternion.yp;
+ float yz = quaternion.yp * quaternion.zp;
+ float yw = quaternion.yp * quaternion.wp;
+ float zz = quaternion.zp * quaternion.zp;
+ float zw = quaternion.zp * quaternion.wp;
+ m.m[0][0] = 1.0f - 2 * (yy + zz);
+ m.m[1][0] = 2 * (xy - zw);
+ m.m[2][0] = 2 * (xz + yw);
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = 2 * (xy + zw);
+ m.m[1][1] = 1.0f - 2 * (xx + zz);
+ m.m[2][1] = 2 * (yz - xw);
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = 2 * (xz - yw);
+ m.m[1][2] = 2 * (yz + xw);
+ m.m[2][2] = 1.0f - 2 * (xx + yy);
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+ int flags = flagBits;
+ *this *= m;
+ if (flags != Identity)
+ flagBits = flags | Rotation;
+ else
+ flagBits = Rotation;
+ return *this;
+}
+
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that applies an orthographic
+ projection for a window with boundaries specified by \a rect.
+ The near and far clipping planes will be -1 and 1 respectively.
+ Returns this matrix.
+
+ \sa frustum(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::ortho(const QRect& rect)
+{
+ // Note: rect.right() and rect.bottom() subtract 1 in QRect,
+ // which gives the location of a pixel within the rectangle,
+ // instead of the extent of the rectangle. We want the extent.
+ // QRectF expresses the extent properly.
+ return ortho(rect.x(), rect.x() + rect.width(), rect.y() + rect.height(), rect.y(), -1.0f, 1.0f);
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that applies an orthographic
+ projection for a window with boundaries specified by \a rect.
+ The near and far clipping planes will be -1 and 1 respectively.
+ Returns this matrix.
+
+ \sa frustum(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::ortho(const QRectF& rect)
+{
+ return ortho(rect.left(), rect.right(), rect.bottom(), rect.top(), -1.0f, 1.0f);
+}
+
+/*!
+ Multiplies this matrix by another that applies an orthographic
+ projection for a window with lower-left corner (\a left, \a bottom),
+ upper-right corner (\a right, \a top), and the specified \a nearPlane
+ and \a farPlane clipping planes. Returns this matrix.
+
+ \sa frustum(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
+{
+ // Bail out if the projection volume is zero-sized.
+ if (left == right || bottom == top || nearPlane == farPlane)
+ return *this;
+
+ // Construct the projection.
+ qreal width = right - left;
+ qreal invheight = top - bottom;
+ qreal clip = farPlane - nearPlane;
+#ifndef QT_NO_VECTOR3D
+ if (clip == 2.0f && (nearPlane + farPlane) == 0.0f) {
+ // We can express this projection as a translate and scale
+ // which will be more efficient to modify with further
+ // transformations than producing a "General" matrix.
+ translate(QVector3D
+ (-(left + right) / width,
+ -(top + bottom) / invheight,
+ 0.0f, 1));
+ scale(QVector3D
+ (2.0f / width,
+ 2.0f / invheight,
+ -1.0f, 1));
+ return *this;
+ }
+#endif
+ QMatrix4x4 m(1);
+ m.m[0][0] = 2.0f / width;
+ m.m[1][0] = 0.0f;
+ m.m[2][0] = 0.0f;
+ m.m[3][0] = -(left + right) / width;
+ m.m[0][1] = 0.0f;
+ m.m[1][1] = 2.0f / invheight;
+ m.m[2][1] = 0.0f;
+ m.m[3][1] = -(top + bottom) / invheight;
+ m.m[0][2] = 0.0f;
+ m.m[1][2] = 0.0f;
+ m.m[2][2] = -2.0f / clip;
+ m.m[3][2] = -(nearPlane + farPlane) / clip;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+
+ // Apply the projection.
+ *this *= m;
+ return *this;
+}
+
+/*!
+ Multiplies this matrix by another that applies a perspective
+ frustum projection for a window with lower-left corner (\a left, \a bottom),
+ upper-right corner (\a right, \a top), and the specified \a nearPlane
+ and \a farPlane clipping planes. Returns this matrix.
+
+ \sa ortho(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
+{
+ // Bail out if the projection volume is zero-sized.
+ if (left == right || bottom == top || nearPlane == farPlane)
+ return *this;
+
+ // Construct the projection.
+ QMatrix4x4 m(1);
+ qreal width = right - left;
+ qreal invheight = top - bottom;
+ qreal clip = farPlane - nearPlane;
+ m.m[0][0] = 2.0f * nearPlane / width;
+ m.m[1][0] = 0.0f;
+ m.m[2][0] = (left + right) / width;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = 0.0f;
+ m.m[1][1] = 2.0f * nearPlane / invheight;
+ m.m[2][1] = (top + bottom) / invheight;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = 0.0f;
+ m.m[1][2] = 0.0f;
+ m.m[2][2] = -(nearPlane + farPlane) / clip;
+ m.m[3][2] = -2.0f * nearPlane * farPlane / clip;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = -1.0f;
+ m.m[3][3] = 0.0f;
+
+ // Apply the projection.
+ *this *= m;
+ return *this;
+}
+
+/*!
+ Multiplies this matrix by another that applies a perspective
+ projection. The field of view will be \a angle degrees within
+ a window with a given \a aspect ratio. The projection will
+ have the specified \a nearPlane and \a farPlane clipping planes.
+ Returns this matrix.
+
+ \sa ortho(), frustum()
+*/
+QMatrix4x4& QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane)
+{
+ // Bail out if the projection volume is zero-sized.
+ if (nearPlane == farPlane || aspect == 0.0f)
+ return *this;
+
+ // Construct the projection.
+ QMatrix4x4 m(1);
+ qreal radians = (angle / 2.0f) * M_PI / 180.0f;
+ qreal sine = qSin(radians);
+ if (sine == 0.0f)
+ return *this;
+ qreal cotan = qCos(radians) / sine;
+ qreal clip = farPlane - nearPlane;
+ m.m[0][0] = cotan / aspect;
+ m.m[1][0] = 0.0f;
+ m.m[2][0] = 0.0f;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = 0.0f;
+ m.m[1][1] = cotan;
+ m.m[2][1] = 0.0f;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = 0.0f;
+ m.m[1][2] = 0.0f;
+ m.m[2][2] = -(nearPlane + farPlane) / clip;
+ m.m[3][2] = -(2.0f * nearPlane * farPlane) / clip;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = -1.0f;
+ m.m[3][3] = 0.0f;
+
+ // Apply the projection.
+ *this *= m;
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Multiplies this matrix by another that applies an \a eye position
+ transformation. The \a center value indicates the center of the
+ view that the \a eye is looking at. The \a up value indicates
+ which direction should be considered up with respect to the \a eye.
+ Returns this matrix.
+*/
+QMatrix4x4& QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up)
+{
+ QVector3D forward = (center - eye).normalized();
+ QVector3D side = QVector3D::crossProduct(forward, up).normalized();
+ QVector3D upVector = QVector3D::crossProduct(side, forward);
+
+ QMatrix4x4 m(1);
+
+ m.m[0][0] = side.xp;
+ m.m[1][0] = side.yp;
+ m.m[2][0] = side.zp;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = upVector.xp;
+ m.m[1][1] = upVector.yp;
+ m.m[2][1] = upVector.zp;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = -forward.xp;
+ m.m[1][2] = -forward.yp;
+ m.m[2][2] = -forward.zp;
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+
+ *this *= m;
+ return translate(-eye);
+}
+
+#endif
+
+/*!
+ Flips between right-handed and left-handed coordinate systems
+ by multiplying the y and z co-ordinates by -1. This is normally
+ used to create a left-handed orthographic view without scaling
+ the viewport as ortho() does. Returns this matrix.
+
+ \sa ortho()
+*/
+QMatrix4x4& QMatrix4x4::flipCoordinates()
+{
+ if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[1][1] = -m[1][1];
+ m[2][2] = -m[2][2];
+ } else if (flagBits == Translation) {
+ m[1][1] = -m[1][1];
+ m[2][2] = -m[2][2];
+ flagBits |= Scale;
+ } else if (flagBits == Identity) {
+ m[1][1] = -1.0f;
+ m[2][2] = -1.0f;
+ flagBits = Scale;
+ } else {
+ m[1][0] = -m[1][0];
+ m[1][1] = -m[1][1];
+ m[1][2] = -m[1][2];
+ m[1][3] = -m[1][3];
+ m[2][0] = -m[2][0];
+ m[2][1] = -m[2][1];
+ m[2][2] = -m[2][2];
+ m[2][3] = -m[2][3];
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ Retrieves the 16 items in this matrix and writes them to \a values
+ in row-major order.
+*/
+void QMatrix4x4::toValueArray(qreal *values) const
+{
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ values[row * 4 + col] = qreal(m[col][row]);
+}
+
+/*!
+ Returns the conventional Qt 2D affine transformation matrix that
+ corresponds to this matrix. It is assumed that this matrix
+ only contains 2D affine transformation elements.
+
+ \sa toTransform()
+*/
+QMatrix QMatrix4x4::toAffine() const
+{
+ return QMatrix(qreal(m[0][0]), qreal(m[0][1]),
+ qreal(m[1][0]), qreal(m[1][1]),
+ qreal(m[3][0]), qreal(m[3][1]));
+}
+
+static const qreal inv_dist_to_plane = 1. / 1024.;
+
+/*!
+ Returns the conventional Qt 2D transformation matrix that
+ corresponds to this matrix.
+
+ If \a distanceToPlane is non-zero, it indicates a projection
+ factor to use to adjust for the z co-ordinate. The default
+ value of 1024 corresponds to the projection factor used
+ by QTransform::rotate() for the x and y axes.
+
+ If \a distanceToPlane is zero, then the returned QTransform
+ is formed by simply dropping the third row and third column
+ of the QMatrix4x4. This is suitable for implementing
+ orthographic projections where the z co-ordinate should
+ be dropped rather than projected.
+
+ \sa toAffine()
+*/
+QTransform QMatrix4x4::toTransform(qreal distanceToPlane) const
+{
+ if (distanceToPlane == 1024.0f) {
+ // Optimize the common case with constants.
+ return QTransform(qreal(m[0][0]), qreal(m[0][1]),
+ qreal(m[0][3]) - qreal(m[0][2]) *
+ inv_dist_to_plane,
+ qreal(m[1][0]), qreal(m[1][1]),
+ qreal(m[1][3]) - qreal(m[1][2]) *
+ inv_dist_to_plane,
+ qreal(m[3][0]), qreal(m[3][1]),
+ qreal(m[3][3]) - qreal(m[3][2]) *
+ inv_dist_to_plane);
+ } else if (distanceToPlane != 0.0f) {
+ // The following projection matrix is pre-multiplied with "matrix":
+ // | 1 0 0 0 |
+ // | 0 1 0 0 |
+ // | 0 0 1 0 |
+ // | 0 0 d 1 |
+ // where d = -1 / distanceToPlane. After projection, row 3 and
+ // column 3 are dropped to form the final QTransform.
+ qreal d = 1.0f / distanceToPlane;
+ return QTransform(qreal(m[0][0]), qreal(m[0][1]),
+ qreal(m[0][3]) - qreal(m[0][2]) * d,
+ qreal(m[1][0]), qreal(m[1][1]),
+ qreal(m[1][3]) - qreal(m[1][2]) * d,
+ qreal(m[3][0]), qreal(m[3][1]),
+ qreal(m[3][3]) - qreal(m[3][2]) * d);
+ } else {
+ // Orthographic projection: drop row 3 and column 3.
+ return QTransform(qreal(m[0][0]), qreal(m[0][1]), qreal(m[0][3]),
+ qreal(m[1][0]), qreal(m[1][1]), qreal(m[1][3]),
+ qreal(m[3][0]), qreal(m[3][1]), qreal(m[3][3]));
+ }
+}
+
+/*!
+ \fn QPoint QMatrix4x4::map(const QPoint& point) const
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+/*!
+ \fn QPointF QMatrix4x4::map(const QPointF& point) const
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \fn QVector3D QMatrix4x4::map(const QVector3D& point) const
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \fn QVector4D QMatrix4x4::map(const QVector4D& point) const;
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+#endif
+
+/*!
+ Maps \a rect by multiplying this matrix by the corners
+ of \a rect and then forming a new rectangle from the results.
+ The returned rectangle will be an ordinary 2D rectangle
+ with sides parallel to the horizontal and vertical axes.
+
+ \sa map()
+*/
+QRect QMatrix4x4::mapRect(const QRect& rect) const
+{
+ if (flagBits == (Translation | Scale) || flagBits == Scale) {
+ qreal x = rect.x() * m[0][0] + m[3][0];
+ qreal y = rect.y() * m[1][1] + m[3][1];
+ qreal w = rect.width() * m[0][0];
+ qreal h = rect.height() * m[1][1];
+ if (w < 0) {
+ w = -w;
+ x -= w;
+ }
+ if (h < 0) {
+ h = -h;
+ y -= h;
+ }
+ return QRect(qRound(x), qRound(y), qRound(w), qRound(h));
+ } else if (flagBits == Translation) {
+ return QRect(qRound(rect.x() + m[3][0]),
+ qRound(rect.y() + m[3][1]),
+ rect.width(), rect.height());
+ }
+
+ QPoint tl = map(rect.topLeft());
+ QPoint tr = map(QPoint(rect.x() + rect.width(), rect.y()));
+ QPoint bl = map(QPoint(rect.x(), rect.y() + rect.height()));
+ QPoint br = map(QPoint(rect.x() + rect.width(),
+ rect.y() + rect.height()));
+
+ int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
+ int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
+ int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
+ int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
+
+ return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
+}
+
+/*!
+ Maps \a rect by multiplying this matrix by the corners
+ of \a rect and then forming a new rectangle from the results.
+ The returned rectangle will be an ordinary 2D rectangle
+ with sides parallel to the horizontal and vertical axes.
+
+ \sa map()
+*/
+QRectF QMatrix4x4::mapRect(const QRectF& rect) const
+{
+ if (flagBits == (Translation | Scale) || flagBits == Scale) {
+ qreal x = rect.x() * m[0][0] + m[3][0];
+ qreal y = rect.y() * m[1][1] + m[3][1];
+ qreal w = rect.width() * m[0][0];
+ qreal h = rect.height() * m[1][1];
+ if (w < 0) {
+ w = -w;
+ x -= w;
+ }
+ if (h < 0) {
+ h = -h;
+ y -= h;
+ }
+ return QRectF(x, y, w, h);
+ } else if (flagBits == Translation) {
+ return rect.translated(m[3][0], m[3][1]);
+ }
+
+ QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
+ QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
+
+ qreal xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
+ qreal xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
+ qreal ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
+ qreal ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
+
+ return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
+}
+
+/*!
+ \fn float *QMatrix4x4::data()
+
+ Returns a pointer to the raw data of this matrix. This is intended
+ for use with raw GL functions.
+
+ \sa constData(), inferSpecialType()
+*/
+
+/*!
+ \fn const float *QMatrix4x4::data() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is intended for use with raw GL functions.
+
+ \sa constData()
+*/
+
+/*!
+ \fn const float *QMatrix4x4::constData() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is intended for use with raw GL functions.
+
+ \sa data()
+*/
+
+// Helper routine for inverting orthonormal matrices that consist
+// of just rotations and translations.
+QMatrix4x4 QMatrix4x4::orthonormalInverse() const
+{
+ QMatrix4x4 result(1); // The '1' says not to load identity
+
+ result.m[0][0] = m[0][0];
+ result.m[1][0] = m[0][1];
+ result.m[2][0] = m[0][2];
+
+ result.m[0][1] = m[1][0];
+ result.m[1][1] = m[1][1];
+ result.m[2][1] = m[1][2];
+
+ result.m[0][2] = m[2][0];
+ result.m[1][2] = m[2][1];
+ result.m[2][2] = m[2][2];
+
+ result.m[0][3] = 0.0f;
+ result.m[1][3] = 0.0f;
+ result.m[2][3] = 0.0f;
+
+ result.m[3][0] = -(result.m[0][0] * m[3][0] + result.m[1][0] * m[3][1] + result.m[2][0] * m[3][2]);
+ result.m[3][1] = -(result.m[0][1] * m[3][0] + result.m[1][1] * m[3][1] + result.m[2][1] * m[3][2]);
+ result.m[3][2] = -(result.m[0][2] * m[3][0] + result.m[1][2] * m[3][1] + result.m[2][2] * m[3][2]);
+ result.m[3][3] = 1.0f;
+
+ return result;
+}
+
+#ifndef QT_NO_VECTOR3D
+/*!
+ Decomposes the current rotation matrix into an \a axis of rotation plus
+ an \a angle. The result can be used to construct an equivalent rotation
+ matrix using glRotate(). It is assumed that the homogenous coordinate
+ is 1.0. The returned vector is guaranteed to be normalized.
+
+ \code
+ qreal angle;
+ QVector3D axis;
+
+ matrix.extractAxisAngle(angle, axis);
+ glRotate(angle, axis[0], axis[1], axis[2]);
+ \endcode
+
+ \sa rotate()
+*/
+void QMatrix4x4::extractAxisRotation(qreal &angle, QVector3D &axis) const
+{
+ // Orientation is dependent on the upper 3x3 matrix; subtract the
+ // homogeneous scaling element from the trace of the 4x4 matrix
+ float tr = m[0][0] + m[1][1] + m[2][2];
+ qreal cosa = qreal(0.5f * (tr - 1.0f));
+ angle = acos(cosa) * 180.0f / M_PI;
+
+ // Any axis will work if r is zero (means no rotation)
+ if (qFuzzyIsNull(angle)) {
+ axis.setX(1.0f);
+ axis.setY(0.0f);
+ axis.setZ(0.0f);
+ return;
+ }
+
+ if (angle < 180.0f) {
+ axis.xp = m[1][2] - m[2][1];
+ axis.yp = m[2][0] - m[0][2];
+ axis.zp = m[0][1] - m[1][0];
+ axis.normalize();
+ return;
+ }
+
+ // rads == PI
+ float tmp;
+
+ // r00 is maximum
+ if ((m[0][0] >= m[2][2]) && (m[0][0] >= m[1][1])) {
+ axis.xp = 0.5f * qSqrt(m[0][0] - m[1][1] - m[2][2] + 1.0f);
+ tmp = 0.5f / axis.x();
+ axis.yp = m[1][0] * tmp;
+ axis.zp = m[2][0] * tmp;
+ }
+
+ // r11 is maximum
+ if ((m[1][1] >= m[2][2]) && (m[1][1] >= m[0][0])) {
+ axis.yp = 0.5f * qSqrt(m[1][1] - m[0][0] - m[2][2] + 1.0f);
+ tmp = 0.5f / axis.y();
+ axis.xp = tmp * m[1][0];
+ axis.zp = tmp * m[2][1];
+ }
+
+ // r22 is maximum
+ if ((m[2][2] >= m[1][1]) && (m[2][2] >= m[0][0])) {
+ axis.zp = 0.5f * qSqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f);
+ tmp = 0.5f / axis.z();
+ axis.xp = m[2][0]*tmp;
+ axis.yp = m[2][1]*tmp;
+ }
+}
+
+/*!
+ If this is an orthonormal transformation matrix (e.g. only rotations and
+ translations have been applied to the matrix, no scaling, or shearing)
+ then the world translational component can be obtained by calling this function.
+
+ This is most useful for camera matrices, where the negation of this vector
+ is effectively the camera world coordinates.
+*/
+QVector3D QMatrix4x4::extractTranslation() const
+{
+ return QVector3D
+ (m[0][0] * m[3][0] + m[0][1] * m[3][1] + m[0][2] * m[3][2],
+ m[1][0] * m[3][0] + m[1][1] * m[3][1] + m[1][2] * m[3][2],
+ m[2][0] * m[3][0] + m[2][1] * m[3][1] + m[2][2] * m[3][2], 1);
+}
+#endif
+
+/*!
+ Infers the special type of this matrix from its current elements.
+
+ Some operations such as translate(), scale(), and rotate() can be
+ performed more efficiently if the matrix being modified is already
+ known to be the identity, a previous translate(), a previous
+ scale(), etc.
+
+ Normally the QMatrix4x4 class keeps track of this special type internally
+ as operations are performed. However, if the matrix is modified
+ directly with operator()() or data(), then QMatrix4x4 will lose track of
+ the special type and will revert to the safest but least efficient
+ operations thereafter.
+
+ By calling inferSpecialType() after directly modifying the matrix,
+ the programmer can force QMatrix4x4 to recover the special type if
+ the elements appear to conform to one of the known optimized types.
+
+ \sa operator()(), data(), translate()
+*/
+void QMatrix4x4::inferSpecialType()
+{
+ // If the last element is not 1, then it can never be special.
+ if (m[3][3] != 1.0f) {
+ flagBits = General;
+ return;
+ }
+
+ // If the upper three elements m12, m13, and m21 are not all zero,
+ // or the lower elements below the diagonal are not all zero, then
+ // the matrix can never be special.
+ if (m[1][0] != 0.0f || m[2][0] != 0.0f || m[2][1] != 0.0f) {
+ flagBits = General;
+ return;
+ }
+ if (m[0][1] != 0.0f || m[0][2] != 0.0f || m[0][3] != 0.0f ||
+ m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][3] != 0.0f) {
+ flagBits = General;
+ return;
+ }
+
+ // Determine what we have in the remaining regions of the matrix.
+ bool identityAlongDiagonal
+ = (m[0][0] == 1.0f && m[1][1] == 1.0f && m[2][2] == 1.0f);
+ bool translationPresent
+ = (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f);
+
+ // Now determine the special matrix type.
+ if (translationPresent && identityAlongDiagonal)
+ flagBits = Translation;
+ else if (translationPresent)
+ flagBits = (Translation | Scale);
+ else if (identityAlongDiagonal)
+ flagBits = Identity;
+ else
+ flagBits = Scale;
+}
+
+/*!
+ Returns the matrix as a QVariant.
+*/
+QMatrix4x4::operator QVariant() const
+{
+ return QVariant(QVariant::Matrix4x4, this);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QMatrix4x4 &m)
+{
+ // Create a string that represents the matrix type.
+ QByteArray bits;
+ if ((m.flagBits & QMatrix4x4::Identity) != 0)
+ bits += "Identity,";
+ if ((m.flagBits & QMatrix4x4::General) != 0)
+ bits += "General,";
+ if ((m.flagBits & QMatrix4x4::Translation) != 0)
+ bits += "Translation,";
+ if ((m.flagBits & QMatrix4x4::Scale) != 0)
+ bits += "Scale,";
+ if ((m.flagBits & QMatrix4x4::Rotation) != 0)
+ bits += "Rotation,";
+ if (bits.size() > 0)
+ bits = bits.left(bits.size() - 1);
+
+ // Output in row-major order because it is more human-readable.
+ dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << endl
+ << qSetFieldWidth(10)
+ << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << endl
+ << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << endl
+ << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << endl
+ << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << endl
+ << qSetFieldWidth(0) << ')';
+ return dbg.space();
+}
+
+#endif
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QMatrix4x4 &matrix)
+ \relates QMatrix4x4
+
+ Writes the given \a matrix to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator<<(QDataStream &stream, const QMatrix4x4 &matrix)
+{
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ stream << double(matrix(row, col));
+ return stream;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QMatrix4x4 &matrix)
+ \relates QMatrix4x4
+
+ Reads a 4x4 matrix from the given \a stream into the given \a matrix
+ and returns a reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator>>(QDataStream &stream, QMatrix4x4 &matrix)
+{
+ double x;
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ stream >> x;
+ matrix(row, col) = float(x);
+ }
+ }
+ matrix.inferSpecialType();
+ return stream;
+}
+
+#endif // QT_NO_DATASTREAM
+
+#endif // QT_NO_MATRIX4X4
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
new file mode 100644
index 0000000..10e628b
--- /dev/null
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -0,0 +1,1002 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMATRIX4X4_H
+#define QMATRIX4X4_H
+
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qquaternion.h>
+#include <QtGui/qgenericmatrix.h>
+#include <QtCore/qrect.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_MATRIX4X4
+
+class QMatrix;
+class QTransform;
+class QVariant;
+
+class Q_GUI_EXPORT QMatrix4x4
+{
+public:
+ inline QMatrix4x4() { setIdentity(); }
+ explicit QMatrix4x4(const qreal *values);
+ inline QMatrix4x4(qreal m11, qreal m12, qreal m13, qreal m14,
+ qreal m21, qreal m22, qreal m23, qreal m24,
+ qreal m31, qreal m32, qreal m33, qreal m34,
+ qreal m41, qreal m42, qreal m43, qreal m44);
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+ template <int N, int M>
+ explicit QMatrix4x4(const QGenericMatrix<N, M, qreal, float>& matrix);
+#endif
+ QMatrix4x4(const float *values, int cols, int rows);
+ QMatrix4x4(const QTransform& transform);
+ QMatrix4x4(const QMatrix& matrix);
+
+ inline qreal operator()(int row, int column) const;
+ inline float& operator()(int row, int column);
+
+ inline QVector4D column(int index) const;
+ inline void setColumn(int index, const QVector4D& value);
+
+ inline QVector4D row(int index) const;
+ inline void setRow(int index, const QVector4D& value);
+
+ inline bool isIdentity() const;
+ inline void setIdentity();
+
+ inline void fill(qreal value);
+
+ qreal determinant() const;
+ QMatrix4x4 inverted(bool *invertible = 0) const;
+ QMatrix4x4 transposed() const;
+ QMatrix3x3 normalMatrix() const;
+
+ inline QMatrix4x4& operator+=(const QMatrix4x4& other);
+ inline QMatrix4x4& operator-=(const QMatrix4x4& other);
+ inline QMatrix4x4& operator*=(const QMatrix4x4& other);
+ inline QMatrix4x4& operator*=(qreal factor);
+ QMatrix4x4& operator/=(qreal divisor);
+ inline bool operator==(const QMatrix4x4& other) const;
+ inline bool operator!=(const QMatrix4x4& other) const;
+
+ friend QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2);
+ friend QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2);
+ friend QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2);
+#ifndef QT_NO_VECTOR3D
+ friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
+ friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
+#endif
+#ifndef QT_NO_VECTOR4D
+ friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
+ friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
+#endif
+ friend QPoint operator*(const QPoint& point, const QMatrix4x4& matrix);
+ friend QPointF operator*(const QPointF& point, const QMatrix4x4& matrix);
+ friend QMatrix4x4 operator-(const QMatrix4x4& matrix);
+ friend QPoint operator*(const QMatrix4x4& matrix, const QPoint& point);
+ friend QPointF operator*(const QMatrix4x4& matrix, const QPointF& point);
+ friend QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix);
+ friend QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor);
+ friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2);
+
+#ifndef QT_NO_VECTOR3D
+ QMatrix4x4& scale(const QVector3D& vector);
+ QMatrix4x4& translate(const QVector3D& vector);
+ QMatrix4x4& rotate(qreal angle, const QVector3D& vector);
+#endif
+ QMatrix4x4& scale(qreal x, qreal y);
+ QMatrix4x4& scale(qreal x, qreal y, qreal z);
+ QMatrix4x4& scale(qreal factor);
+ QMatrix4x4& translate(qreal x, qreal y);
+ QMatrix4x4& translate(qreal x, qreal y, qreal z);
+ QMatrix4x4& rotate(qreal angle, qreal x, qreal y, qreal z = 0.0f);
+#ifndef QT_NO_QUATERNION
+ QMatrix4x4& rotate(const QQuaternion& quaternion);
+#endif
+
+#ifndef QT_NO_VECTOR3D
+ void extractAxisRotation(qreal &angle, QVector3D &axis) const;
+ QVector3D extractTranslation() const;
+#endif
+
+ QMatrix4x4& ortho(const QRect& rect);
+ QMatrix4x4& ortho(const QRectF& rect);
+ QMatrix4x4& ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane);
+ QMatrix4x4& frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane);
+ QMatrix4x4& perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane);
+#ifndef QT_NO_VECTOR3D
+ QMatrix4x4& lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up);
+#endif
+ QMatrix4x4& flipCoordinates();
+
+ void toValueArray(qreal *values) const;
+
+ QMatrix toAffine() const;
+ QTransform toTransform(qreal distanceToPlane = 1024.0f) const;
+
+ QPoint map(const QPoint& point) const;
+ QPointF map(const QPointF& point) const;
+#ifndef QT_NO_VECTOR3D
+ QVector3D map(const QVector3D& point) const;
+#endif
+#ifndef QT_NO_VECTOR4D
+ QVector4D map(const QVector4D& point) const;
+#endif
+ QRect mapRect(const QRect& rect) const;
+ QRectF mapRect(const QRectF& rect) const;
+
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+ template <int N, int M>
+ QGenericMatrix<N, M, qreal, float> toGenericMatrix() const;
+#endif
+
+ inline float *data();
+ inline const float *data() const { return m[0]; }
+ inline const float *constData() const { return m[0]; }
+
+ void inferSpecialType();
+
+ operator QVariant() const;
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
+#endif
+
+private:
+ float m[4][4]; // Column-major order to match OpenGL.
+ int flagBits; // Flag bits from the enum below.
+
+ enum {
+ Identity = 0x0001, // Identity matrix
+ General = 0x0002, // General matrix, unknown contents
+ Translation = 0x0004, // Contains a simple translation
+ Scale = 0x0008, // Contains a simple scale
+ Rotation = 0x0010 // Contains a simple rotation
+ };
+
+ // Construct without initializing identity matrix.
+ QMatrix4x4(int) { flagBits = General; }
+
+ QMatrix4x4 orthonormalInverse() const;
+};
+
+inline QMatrix4x4::QMatrix4x4
+ (qreal m11, qreal m12, qreal m13, qreal m14,
+ qreal m21, qreal m22, qreal m23, qreal m24,
+ qreal m31, qreal m32, qreal m33, qreal m34,
+ qreal m41, qreal m42, qreal m43, qreal m44)
+{
+ m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
+ m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
+ m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
+ m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
+ flagBits = General;
+}
+
+#if !defined(QT_NO_MEMBER_TEMPLATES)
+
+template <int N, int M>
+Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
+ (const QGenericMatrix<N, M, qreal, float>& matrix)
+{
+ const float *values = matrix.constData();
+ for (int col = 0; col < 4; ++col) {
+ for (int row = 0; row < 4; ++row) {
+ if (col < N && row < M)
+ m[col][row] = values[col * M + row];
+ else if (col == row)
+ m[col][row] = 1.0f;
+ else
+ m[col][row] = 0.0f;
+ }
+ }
+ flagBits = General;
+}
+
+template <int N, int M>
+QGenericMatrix<N, M, qreal, float> QMatrix4x4::toGenericMatrix() const
+{
+ QGenericMatrix<N, M, qreal, float> result;
+ float *values = result.data();
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (col < 4 && row < 4)
+ values[col * M + row] = m[col][row];
+ else if (col == row)
+ values[col * M + row] = 1.0f;
+ else
+ values[col * M + row] = 0.0f;
+ }
+ }
+ return result;
+}
+
+#endif
+
+inline qreal QMatrix4x4::operator()(int row, int column) const
+{
+ Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4);
+ return qreal(m[column][row]);
+}
+
+inline float& QMatrix4x4::operator()(int row, int column)
+{
+ Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4);
+ flagBits = General;
+ return m[column][row];
+}
+
+inline QVector4D QMatrix4x4::column(int index) const
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3], 1);
+}
+
+inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ m[index][0] = value.xp;
+ m[index][1] = value.yp;
+ m[index][2] = value.zp;
+ m[index][3] = value.wp;
+ flagBits = General;
+}
+
+inline QVector4D QMatrix4x4::row(int index) const
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index], 1);
+}
+
+inline void QMatrix4x4::setRow(int index, const QVector4D& value)
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ m[0][index] = value.xp;
+ m[1][index] = value.yp;
+ m[2][index] = value.zp;
+ m[3][index] = value.wp;
+ flagBits = General;
+}
+
+Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor);
+
+inline bool QMatrix4x4::isIdentity() const
+{
+ if (flagBits == Identity)
+ return true;
+ if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
+ return false;
+ if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
+ return false;
+ if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
+ return false;
+ if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
+ return false;
+ if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
+ return false;
+ return (m[3][3] == 1.0f);
+}
+
+inline void QMatrix4x4::setIdentity()
+{
+ m[0][0] = 1.0f;
+ m[0][1] = 0.0f;
+ m[0][2] = 0.0f;
+ m[0][3] = 0.0f;
+ m[1][0] = 0.0f;
+ m[1][1] = 1.0f;
+ m[1][2] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+ m[2][3] = 0.0f;
+ m[3][0] = 0.0f;
+ m[3][1] = 0.0f;
+ m[3][2] = 0.0f;
+ m[3][3] = 1.0f;
+ flagBits = Identity;
+}
+
+inline void QMatrix4x4::fill(qreal value)
+{
+ m[0][0] = value;
+ m[0][1] = value;
+ m[0][2] = value;
+ m[0][3] = value;
+ m[1][0] = value;
+ m[1][1] = value;
+ m[1][2] = value;
+ m[1][3] = value;
+ m[2][0] = value;
+ m[2][1] = value;
+ m[2][2] = value;
+ m[2][3] = value;
+ m[3][0] = value;
+ m[3][1] = value;
+ m[3][2] = value;
+ m[3][3] = value;
+ flagBits = General;
+}
+
+inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
+{
+ m[0][0] += other.m[0][0];
+ m[0][1] += other.m[0][1];
+ m[0][2] += other.m[0][2];
+ m[0][3] += other.m[0][3];
+ m[1][0] += other.m[1][0];
+ m[1][1] += other.m[1][1];
+ m[1][2] += other.m[1][2];
+ m[1][3] += other.m[1][3];
+ m[2][0] += other.m[2][0];
+ m[2][1] += other.m[2][1];
+ m[2][2] += other.m[2][2];
+ m[2][3] += other.m[2][3];
+ m[3][0] += other.m[3][0];
+ m[3][1] += other.m[3][1];
+ m[3][2] += other.m[3][2];
+ m[3][3] += other.m[3][3];
+ flagBits = General;
+ return *this;
+}
+
+inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
+{
+ m[0][0] -= other.m[0][0];
+ m[0][1] -= other.m[0][1];
+ m[0][2] -= other.m[0][2];
+ m[0][3] -= other.m[0][3];
+ m[1][0] -= other.m[1][0];
+ m[1][1] -= other.m[1][1];
+ m[1][2] -= other.m[1][2];
+ m[1][3] -= other.m[1][3];
+ m[2][0] -= other.m[2][0];
+ m[2][1] -= other.m[2][1];
+ m[2][2] -= other.m[2][2];
+ m[2][3] -= other.m[2][3];
+ m[3][0] -= other.m[3][0];
+ m[3][1] -= other.m[3][1];
+ m[3][2] -= other.m[3][2];
+ m[3][3] -= other.m[3][3];
+ flagBits = General;
+ return *this;
+}
+
+inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
+{
+ if (flagBits == Identity) {
+ *this = other;
+ return *this;
+ } else if (other.flagBits == Identity) {
+ return *this;
+ } else {
+ *this = *this * other;
+ return *this;
+ }
+}
+
+inline QMatrix4x4& QMatrix4x4::operator*=(qreal factor)
+{
+ m[0][0] *= factor;
+ m[0][1] *= factor;
+ m[0][2] *= factor;
+ m[0][3] *= factor;
+ m[1][0] *= factor;
+ m[1][1] *= factor;
+ m[1][2] *= factor;
+ m[1][3] *= factor;
+ m[2][0] *= factor;
+ m[2][1] *= factor;
+ m[2][2] *= factor;
+ m[2][3] *= factor;
+ m[3][0] *= factor;
+ m[3][1] *= factor;
+ m[3][2] *= factor;
+ m[3][3] *= factor;
+ flagBits = General;
+ return *this;
+}
+
+inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
+{
+ return m[0][0] == other.m[0][0] &&
+ m[0][1] == other.m[0][1] &&
+ m[0][2] == other.m[0][2] &&
+ m[0][3] == other.m[0][3] &&
+ m[1][0] == other.m[1][0] &&
+ m[1][1] == other.m[1][1] &&
+ m[1][2] == other.m[1][2] &&
+ m[1][3] == other.m[1][3] &&
+ m[2][0] == other.m[2][0] &&
+ m[2][1] == other.m[2][1] &&
+ m[2][2] == other.m[2][2] &&
+ m[2][3] == other.m[2][3] &&
+ m[3][0] == other.m[3][0] &&
+ m[3][1] == other.m[3][1] &&
+ m[3][2] == other.m[3][2] &&
+ m[3][3] == other.m[3][3];
+}
+
+inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
+{
+ return m[0][0] != other.m[0][0] ||
+ m[0][1] != other.m[0][1] ||
+ m[0][2] != other.m[0][2] ||
+ m[0][3] != other.m[0][3] ||
+ m[1][0] != other.m[1][0] ||
+ m[1][1] != other.m[1][1] ||
+ m[1][2] != other.m[1][2] ||
+ m[1][3] != other.m[1][3] ||
+ m[2][0] != other.m[2][0] ||
+ m[2][1] != other.m[2][1] ||
+ m[2][2] != other.m[2][2] ||
+ m[2][3] != other.m[2][3] ||
+ m[3][0] != other.m[3][0] ||
+ m[3][1] != other.m[3][1] ||
+ m[3][2] != other.m[3][2] ||
+ m[3][3] != other.m[3][3];
+}
+
+inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = m1.m[0][0] + m2.m[0][0];
+ m.m[0][1] = m1.m[0][1] + m2.m[0][1];
+ m.m[0][2] = m1.m[0][2] + m2.m[0][2];
+ m.m[0][3] = m1.m[0][3] + m2.m[0][3];
+ m.m[1][0] = m1.m[1][0] + m2.m[1][0];
+ m.m[1][1] = m1.m[1][1] + m2.m[1][1];
+ m.m[1][2] = m1.m[1][2] + m2.m[1][2];
+ m.m[1][3] = m1.m[1][3] + m2.m[1][3];
+ m.m[2][0] = m1.m[2][0] + m2.m[2][0];
+ m.m[2][1] = m1.m[2][1] + m2.m[2][1];
+ m.m[2][2] = m1.m[2][2] + m2.m[2][2];
+ m.m[2][3] = m1.m[2][3] + m2.m[2][3];
+ m.m[3][0] = m1.m[3][0] + m2.m[3][0];
+ m.m[3][1] = m1.m[3][1] + m2.m[3][1];
+ m.m[3][2] = m1.m[3][2] + m2.m[3][2];
+ m.m[3][3] = m1.m[3][3] + m2.m[3][3];
+ return m;
+}
+
+inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = m1.m[0][0] - m2.m[0][0];
+ m.m[0][1] = m1.m[0][1] - m2.m[0][1];
+ m.m[0][2] = m1.m[0][2] - m2.m[0][2];
+ m.m[0][3] = m1.m[0][3] - m2.m[0][3];
+ m.m[1][0] = m1.m[1][0] - m2.m[1][0];
+ m.m[1][1] = m1.m[1][1] - m2.m[1][1];
+ m.m[1][2] = m1.m[1][2] - m2.m[1][2];
+ m.m[1][3] = m1.m[1][3] - m2.m[1][3];
+ m.m[2][0] = m1.m[2][0] - m2.m[2][0];
+ m.m[2][1] = m1.m[2][1] - m2.m[2][1];
+ m.m[2][2] = m1.m[2][2] - m2.m[2][2];
+ m.m[2][3] = m1.m[2][3] - m2.m[2][3];
+ m.m[3][0] = m1.m[3][0] - m2.m[3][0];
+ m.m[3][1] = m1.m[3][1] - m2.m[3][1];
+ m.m[3][2] = m1.m[3][2] - m2.m[3][2];
+ m.m[3][3] = m1.m[3][3] - m2.m[3][3];
+ return m;
+}
+
+inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ if (m1.flagBits == QMatrix4x4::Identity)
+ return m2;
+ else if (m2.flagBits == QMatrix4x4::Identity)
+ return m1;
+
+ QMatrix4x4 m(1);
+ m.m[0][0] = m1.m[0][0] * m2.m[0][0] +
+ m1.m[1][0] * m2.m[0][1] +
+ m1.m[2][0] * m2.m[0][2] +
+ m1.m[3][0] * m2.m[0][3];
+ m.m[0][1] = m1.m[0][1] * m2.m[0][0] +
+ m1.m[1][1] * m2.m[0][1] +
+ m1.m[2][1] * m2.m[0][2] +
+ m1.m[3][1] * m2.m[0][3];
+ m.m[0][2] = m1.m[0][2] * m2.m[0][0] +
+ m1.m[1][2] * m2.m[0][1] +
+ m1.m[2][2] * m2.m[0][2] +
+ m1.m[3][2] * m2.m[0][3];
+ m.m[0][3] = m1.m[0][3] * m2.m[0][0] +
+ m1.m[1][3] * m2.m[0][1] +
+ m1.m[2][3] * m2.m[0][2] +
+ m1.m[3][3] * m2.m[0][3];
+ m.m[1][0] = m1.m[0][0] * m2.m[1][0] +
+ m1.m[1][0] * m2.m[1][1] +
+ m1.m[2][0] * m2.m[1][2] +
+ m1.m[3][0] * m2.m[1][3];
+ m.m[1][1] = m1.m[0][1] * m2.m[1][0] +
+ m1.m[1][1] * m2.m[1][1] +
+ m1.m[2][1] * m2.m[1][2] +
+ m1.m[3][1] * m2.m[1][3];
+ m.m[1][2] = m1.m[0][2] * m2.m[1][0] +
+ m1.m[1][2] * m2.m[1][1] +
+ m1.m[2][2] * m2.m[1][2] +
+ m1.m[3][2] * m2.m[1][3];
+ m.m[1][3] = m1.m[0][3] * m2.m[1][0] +
+ m1.m[1][3] * m2.m[1][1] +
+ m1.m[2][3] * m2.m[1][2] +
+ m1.m[3][3] * m2.m[1][3];
+ m.m[2][0] = m1.m[0][0] * m2.m[2][0] +
+ m1.m[1][0] * m2.m[2][1] +
+ m1.m[2][0] * m2.m[2][2] +
+ m1.m[3][0] * m2.m[2][3];
+ m.m[2][1] = m1.m[0][1] * m2.m[2][0] +
+ m1.m[1][1] * m2.m[2][1] +
+ m1.m[2][1] * m2.m[2][2] +
+ m1.m[3][1] * m2.m[2][3];
+ m.m[2][2] = m1.m[0][2] * m2.m[2][0] +
+ m1.m[1][2] * m2.m[2][1] +
+ m1.m[2][2] * m2.m[2][2] +
+ m1.m[3][2] * m2.m[2][3];
+ m.m[2][3] = m1.m[0][3] * m2.m[2][0] +
+ m1.m[1][3] * m2.m[2][1] +
+ m1.m[2][3] * m2.m[2][2] +
+ m1.m[3][3] * m2.m[2][3];
+ m.m[3][0] = m1.m[0][0] * m2.m[3][0] +
+ m1.m[1][0] * m2.m[3][1] +
+ m1.m[2][0] * m2.m[3][2] +
+ m1.m[3][0] * m2.m[3][3];
+ m.m[3][1] = m1.m[0][1] * m2.m[3][0] +
+ m1.m[1][1] * m2.m[3][1] +
+ m1.m[2][1] * m2.m[3][2] +
+ m1.m[3][1] * m2.m[3][3];
+ m.m[3][2] = m1.m[0][2] * m2.m[3][0] +
+ m1.m[1][2] * m2.m[3][1] +
+ m1.m[2][2] * m2.m[3][2] +
+ m1.m[3][2] * m2.m[3][3];
+ m.m[3][3] = m1.m[0][3] * m2.m[3][0] +
+ m1.m[1][3] * m2.m[3][1] +
+ m1.m[2][3] * m2.m[3][2] +
+ m1.m[3][3] * m2.m[3][3];
+ return m;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
+{
+ float x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[0][1] +
+ vector.zp * matrix.m[0][2] +
+ matrix.m[0][3];
+ y = vector.xp * matrix.m[1][0] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[1][2] +
+ matrix.m[1][3];
+ z = vector.xp * matrix.m[2][0] +
+ vector.yp * matrix.m[2][1] +
+ vector.zp * matrix.m[2][2] +
+ matrix.m[2][3];
+ w = vector.xp * matrix.m[3][0] +
+ vector.yp * matrix.m[3][1] +
+ vector.zp * matrix.m[3][2] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QVector3D(x, y, z, 1);
+ else
+ return QVector3D(x / w, y / w, z / w, 1);
+}
+
+inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
+{
+ float x, y, z, w;
+ if (matrix.flagBits == QMatrix4x4::Identity) {
+ return vector;
+ } else if (matrix.flagBits == QMatrix4x4::Translation) {
+ return QVector3D(vector.xp + matrix.m[3][0],
+ vector.yp + matrix.m[3][1],
+ vector.zp + matrix.m[3][2], 1);
+ } else if (matrix.flagBits ==
+ (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
+ return QVector3D(vector.xp * matrix.m[0][0] + matrix.m[3][0],
+ vector.yp * matrix.m[1][1] + matrix.m[3][1],
+ vector.zp * matrix.m[2][2] + matrix.m[3][2], 1);
+ } else if (matrix.flagBits == QMatrix4x4::Scale) {
+ return QVector3D(vector.xp * matrix.m[0][0],
+ vector.yp * matrix.m[1][1],
+ vector.zp * matrix.m[2][2], 1);
+ } else {
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[1][0] +
+ vector.zp * matrix.m[2][0] +
+ matrix.m[3][0];
+ y = vector.xp * matrix.m[0][1] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[2][1] +
+ matrix.m[3][1];
+ z = vector.xp * matrix.m[0][2] +
+ vector.yp * matrix.m[1][2] +
+ vector.zp * matrix.m[2][2] +
+ matrix.m[3][2];
+ w = vector.xp * matrix.m[0][3] +
+ vector.yp * matrix.m[1][3] +
+ vector.zp * matrix.m[2][3] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QVector3D(x, y, z, 1);
+ else
+ return QVector3D(x / w, y / w, z / w, 1);
+ }
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
+{
+ float x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[0][1] +
+ vector.zp * matrix.m[0][2] +
+ vector.wp * matrix.m[0][3];
+ y = vector.xp * matrix.m[1][0] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[1][2] +
+ vector.wp * matrix.m[1][3];
+ z = vector.xp * matrix.m[2][0] +
+ vector.yp * matrix.m[2][1] +
+ vector.zp * matrix.m[2][2] +
+ vector.wp * matrix.m[2][3];
+ w = vector.xp * matrix.m[3][0] +
+ vector.yp * matrix.m[3][1] +
+ vector.zp * matrix.m[3][2] +
+ vector.wp * matrix.m[3][3];
+ return QVector4D(x, y, z, w, 1);
+}
+
+inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
+{
+ float x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[1][0] +
+ vector.zp * matrix.m[2][0] +
+ vector.wp * matrix.m[3][0];
+ y = vector.xp * matrix.m[0][1] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[2][1] +
+ vector.wp * matrix.m[3][1];
+ z = vector.xp * matrix.m[0][2] +
+ vector.yp * matrix.m[1][2] +
+ vector.zp * matrix.m[2][2] +
+ vector.wp * matrix.m[3][2];
+ w = vector.xp * matrix.m[0][3] +
+ vector.yp * matrix.m[1][3] +
+ vector.zp * matrix.m[2][3] +
+ vector.wp * matrix.m[3][3];
+ return QVector4D(x, y, z, w, 1);
+}
+
+#endif
+
+inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
+{
+ float xin, yin;
+ float x, y, w;
+ xin = point.x();
+ yin = point.y();
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[0][1] +
+ matrix.m[0][3];
+ y = xin * matrix.m[1][0] +
+ yin * matrix.m[1][1] +
+ matrix.m[1][3];
+ w = xin * matrix.m[3][0] +
+ yin * matrix.m[3][1] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QPoint(qRound(x), qRound(y));
+ else
+ return QPoint(qRound(x / w), qRound(y / w));
+}
+
+inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
+{
+ float xin, yin;
+ float x, y, w;
+ xin = point.x();
+ yin = point.y();
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[0][1] +
+ matrix.m[0][3];
+ y = xin * matrix.m[1][0] +
+ yin * matrix.m[1][1] +
+ matrix.m[1][3];
+ w = xin * matrix.m[3][0] +
+ yin * matrix.m[3][1] +
+ matrix.m[3][3];
+ if (w == 1.0f) {
+ return QPointF(qreal(x), qreal(y));
+ } else {
+ return QPointF(qreal(x / w), qreal(y / w));
+ }
+}
+
+inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
+{
+ float xin, yin;
+ float x, y, w;
+ xin = point.x();
+ yin = point.y();
+ if (matrix.flagBits == QMatrix4x4::Identity) {
+ return point;
+ } else if (matrix.flagBits == QMatrix4x4::Translation) {
+ return QPoint(qRound(xin + matrix.m[3][0]),
+ qRound(yin + matrix.m[3][1]));
+ } else if (matrix.flagBits ==
+ (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
+ return QPoint(qRound(xin * matrix.m[0][0] + matrix.m[3][0]),
+ qRound(yin * matrix.m[1][1] + matrix.m[3][1]));
+ } else if (matrix.flagBits == QMatrix4x4::Scale) {
+ return QPoint(qRound(xin * matrix.m[0][0]),
+ qRound(yin * matrix.m[1][1]));
+ } else {
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[1][0] +
+ matrix.m[3][0];
+ y = xin * matrix.m[0][1] +
+ yin * matrix.m[1][1] +
+ matrix.m[3][1];
+ w = xin * matrix.m[0][3] +
+ yin * matrix.m[1][3] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QPoint(qRound(x), qRound(y));
+ else
+ return QPoint(qRound(x / w), qRound(y / w));
+ }
+}
+
+inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
+{
+ float xin, yin;
+ float x, y, w;
+ xin = point.x();
+ yin = point.y();
+ if (matrix.flagBits == QMatrix4x4::Identity) {
+ return point;
+ } else if (matrix.flagBits == QMatrix4x4::Translation) {
+ return QPointF(xin + matrix.m[3][0],
+ yin + matrix.m[3][1]);
+ } else if (matrix.flagBits ==
+ (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
+ return QPointF(xin * matrix.m[0][0] + matrix.m[3][0],
+ yin * matrix.m[1][1] + matrix.m[3][1]);
+ } else if (matrix.flagBits == QMatrix4x4::Scale) {
+ return QPointF(xin * matrix.m[0][0],
+ yin * matrix.m[1][1]);
+ } else {
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[1][0] +
+ matrix.m[3][0];
+ y = xin * matrix.m[0][1] +
+ yin * matrix.m[1][1] +
+ matrix.m[3][1];
+ w = xin * matrix.m[0][3] +
+ yin * matrix.m[1][3] +
+ matrix.m[3][3];
+ if (w == 1.0f) {
+ return QPointF(qreal(x), qreal(y));
+ } else {
+ return QPointF(qreal(x / w), qreal(y / w));
+ }
+ }
+}
+
+inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = -matrix.m[0][0];
+ m.m[0][1] = -matrix.m[0][1];
+ m.m[0][2] = -matrix.m[0][2];
+ m.m[0][3] = -matrix.m[0][3];
+ m.m[1][0] = -matrix.m[1][0];
+ m.m[1][1] = -matrix.m[1][1];
+ m.m[1][2] = -matrix.m[1][2];
+ m.m[1][3] = -matrix.m[1][3];
+ m.m[2][0] = -matrix.m[2][0];
+ m.m[2][1] = -matrix.m[2][1];
+ m.m[2][2] = -matrix.m[2][2];
+ m.m[2][3] = -matrix.m[2][3];
+ m.m[3][0] = -matrix.m[3][0];
+ m.m[3][1] = -matrix.m[3][1];
+ m.m[3][2] = -matrix.m[3][2];
+ m.m[3][3] = -matrix.m[3][3];
+ return m;
+}
+
+inline QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = matrix.m[0][0] * factor;
+ m.m[0][1] = matrix.m[0][1] * factor;
+ m.m[0][2] = matrix.m[0][2] * factor;
+ m.m[0][3] = matrix.m[0][3] * factor;
+ m.m[1][0] = matrix.m[1][0] * factor;
+ m.m[1][1] = matrix.m[1][1] * factor;
+ m.m[1][2] = matrix.m[1][2] * factor;
+ m.m[1][3] = matrix.m[1][3] * factor;
+ m.m[2][0] = matrix.m[2][0] * factor;
+ m.m[2][1] = matrix.m[2][1] * factor;
+ m.m[2][2] = matrix.m[2][2] * factor;
+ m.m[2][3] = matrix.m[2][3] * factor;
+ m.m[3][0] = matrix.m[3][0] * factor;
+ m.m[3][1] = matrix.m[3][1] * factor;
+ m.m[3][2] = matrix.m[3][2] * factor;
+ m.m[3][3] = matrix.m[3][3] * factor;
+ return m;
+}
+
+inline QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = matrix.m[0][0] * factor;
+ m.m[0][1] = matrix.m[0][1] * factor;
+ m.m[0][2] = matrix.m[0][2] * factor;
+ m.m[0][3] = matrix.m[0][3] * factor;
+ m.m[1][0] = matrix.m[1][0] * factor;
+ m.m[1][1] = matrix.m[1][1] * factor;
+ m.m[1][2] = matrix.m[1][2] * factor;
+ m.m[1][3] = matrix.m[1][3] * factor;
+ m.m[2][0] = matrix.m[2][0] * factor;
+ m.m[2][1] = matrix.m[2][1] * factor;
+ m.m[2][2] = matrix.m[2][2] * factor;
+ m.m[2][3] = matrix.m[2][3] * factor;
+ m.m[3][0] = matrix.m[3][0] * factor;
+ m.m[3][1] = matrix.m[3][1] * factor;
+ m.m[3][2] = matrix.m[3][2] * factor;
+ m.m[3][3] = matrix.m[3][3] * factor;
+ return m;
+}
+
+inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
+ qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
+ qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
+ qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
+ qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
+ qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
+ qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
+ qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
+ qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
+ qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
+ qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
+ qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
+ qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
+ qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
+ qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
+ qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
+}
+
+inline QPoint QMatrix4x4::map(const QPoint& point) const
+{
+ return *this * point;
+}
+
+inline QPointF QMatrix4x4::map(const QPointF& point) const
+{
+ return *this * point;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+inline QVector3D QMatrix4x4::map(const QVector3D& point) const
+{
+ return *this * point;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+inline QVector4D QMatrix4x4::map(const QVector4D& point) const
+{
+ return *this * point;
+}
+
+#endif
+
+inline float *QMatrix4x4::data()
+{
+ // We have to assume that the caller will modify the matrix elements,
+ // so we flip it over to "General" mode.
+ flagBits = General;
+ return m[0];
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
+#endif
+
+#ifndef QT_NO_DATASTREAM
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
+#endif
+
+template <int N, int M>
+QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal, float>& matrix)
+{
+ return QMatrix4x4(matrix.constData(), N, M);
+}
+
+template <int N, int M>
+QGenericMatrix<N, M, qreal, float> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
+{
+ QGenericMatrix<N, M, qreal, float> result;
+ const float *m = matrix.constData();
+ float *values = result.data();
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (col < 4 && row < 4)
+ values[col * M + row] = m[col * 4 + row];
+ else if (col == row)
+ values[col * M + row] = 1.0f;
+ else
+ values[col * M + row] = 0.0f;
+ }
+ }
+ return result;
+}
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
new file mode 100644
index 0000000..f279388
--- /dev/null
+++ b/src/gui/math3d/qquaternion.cpp
@@ -0,0 +1,631 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquaternion.h"
+#include <QtCore/qmath.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_QUATERNION
+
+/*!
+ \class QQuaternion
+ \brief The QQuaternion class represents a quaternion consisting of a vector and scalar.
+ \since 4.6
+ \ingroup painting-3D
+
+ Quaternions are used to represent rotations in 3D space, and
+ consist of a 3D rotation axis specified by the x, y, and z
+ coordinates, and a scalar representing the rotation angle.
+*/
+
+/*!
+ \fn QQuaternion::QQuaternion()
+
+ Constructs an identity quaternion, i.e. with coordinates (1, 0, 0, 0).
+*/
+
+/*!
+ \fn QQuaternion::QQuaternion(qreal scalar, qreal xpos, qreal ypos, qreal zpos)
+
+ Constructs a quaternion with the vector (\a xpos, \a ypos, \a zpos)
+ and \a scalar.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \fn QQuaternion::QQuaternion(qreal scalar, const QVector3D& vector)
+
+ Constructs a quaternion vector from the specified \a vector and
+ \a scalar.
+
+ \sa vector(), scalar()
+*/
+
+/*!
+ \fn QVector3D QQuaternion::vector() const
+
+ Returns the vector component of this quaternion.
+
+ \sa setVector(), scalar()
+*/
+
+/*!
+ \fn void QQuaternion::setVector(const QVector3D& vector)
+
+ Sets the vector component of this quaternion to \a vector.
+
+ \sa vector(), setScalar()
+*/
+
+#endif
+
+/*!
+ \fn void QQuaternion::setVector(qreal x, qreal y, qreal z)
+
+ Sets the vector component of this quaternion to (\a x, \a y, \a z).
+
+ \sa vector(), setScalar()
+*/
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \fn QQuaternion::QQuaternion(const QVector4D& vector)
+
+ Constructs a quaternion from the components of \a vector.
+*/
+
+/*!
+ \fn QVector4D QQuaternion::toVector4D() const
+
+ Returns this quaternion as a 4D vector.
+*/
+
+#endif
+
+/*!
+ \fn bool QQuaternion::isNull() const
+
+ Returns true if the x, y, z, and scalar components of this
+ quaternion are set to 0.0; otherwise returns false.
+*/
+
+/*!
+ \fn bool QQuaternion::isIdentity() const
+
+ Returns true if the x, y, and z components of this
+ quaternion are set to 0.0, and the scalar component is set
+ to 1.0; otherwise returns false.
+*/
+
+/*!
+ \fn qreal QQuaternion::x() const
+
+ Returns the x coordinate of this quaternion's vector.
+
+ \sa setX(), y(), z(), scalar()
+*/
+
+/*!
+ \fn qreal QQuaternion::y() const
+
+ Returns the y coordinate of this quaternion's vector.
+
+ \sa setY(), x(), z(), scalar()
+*/
+
+/*!
+ \fn qreal QQuaternion::z() const
+
+ Returns the z coordinate of this quaternion's vector.
+
+ \sa setZ(), x(), y(), scalar()
+*/
+
+/*!
+ \fn qreal QQuaternion::scalar() const
+
+ Returns the scalar component of this quaternion.
+
+ \sa setScalar(), x(), y(), z()
+*/
+
+/*!
+ \fn void QQuaternion::setX(qreal x)
+
+ Sets the x coordinate of this quaternion's vector to the given
+ \a x coordinate.
+
+ \sa x(), setY(), setZ(), setScalar()
+*/
+
+/*!
+ \fn void QQuaternion::setY(qreal y)
+
+ Sets the y coordinate of this quaternion's vector to the given
+ \a y coordinate.
+
+ \sa y(), setX(), setZ(), setScalar()
+*/
+
+/*!
+ \fn void QQuaternion::setZ(qreal z)
+
+ Sets the z coordinate of this quaternion's vector to the given
+ \a z coordinate.
+
+ \sa z(), setX(), setY(), setScalar()
+*/
+
+/*!
+ \fn void QQuaternion::setScalar(qreal scalar)
+
+ Sets the scalar component of this quaternion to \a scalar.
+
+ \sa scalar(), setX(), setY(), setZ()
+*/
+
+/*!
+ Returns the length of the quaternion. This is also called the "norm".
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QQuaternion::length() const
+{
+ return qSqrt(xp * xp + yp * yp + zp * zp + wp * wp);
+}
+
+/*!
+ Returns the squared length of the quaternion.
+
+ \sa length()
+*/
+qreal QQuaternion::lengthSquared() const
+{
+ return xp * xp + yp * yp + zp * zp + wp * wp;
+}
+
+/*!
+ Returns the normalized unit form of this quaternion.
+
+ If this quaternion is null, then a null quaternion is returned.
+ If the length of the quaternion is very close to 1, then the quaternion
+ will be returned as-is. Otherwise the normalized form of the
+ quaternion of length 1 will be returned.
+
+ \sa length(), normalize()
+*/
+QQuaternion QQuaternion::normalized() const
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f))
+ return *this;
+ else if (!qFuzzyIsNull(len))
+ return *this / qSqrt(len);
+ else
+ return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+/*!
+ Normalizes the currect quaternion in place. Nothing happens if this
+ is a null quaternion or the length of the quaternion is very close to 1.
+
+ \sa length(), normalized()
+*/
+void QQuaternion::normalize()
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
+ return;
+
+ len = qSqrt(len);
+
+ xp /= len;
+ yp /= len;
+ zp /= len;
+ wp /= len;
+}
+
+/*!
+ \fn QQuaternion QQuaternion::conjugate() const
+
+ Returns the conjugate of this quaternion, which is
+ (-x, -y, -z, scalar).
+*/
+
+/*!
+ Rotates \a vector with this quaternion to produce a new vector
+ in 3D space. The following code:
+
+ \code
+ QVector3D result = q.rotateVector(vector);
+ \endcode
+
+ is equivalent to the following:
+
+ \code
+ QVector3D result = (q * QQuaternion(0, vector) * q.conjugate()).vector();
+ \endcode
+*/
+QVector3D QQuaternion::rotateVector(const QVector3D& vector) const
+{
+ return (*this * QQuaternion(0, vector) * conjugate()).vector();
+}
+
+/*!
+ \fn QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
+
+ Adds the given \a quaternion to this quaternion and returns a reference to
+ this quaternion.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)
+
+ Subtracts the given \a quaternion from this quaternion and returns a
+ reference to this quaternion.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator*=(qreal factor)
+
+ Multiplies this quaternion's components by the given \a factor, and
+ returns a reference to this quaternion.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion)
+
+ Multiplies this quaternion by \a quaternion and returns a reference
+ to this quaternion.
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator/=(qreal divisor)
+
+ Divides this quaternion's components by the given \a divisor, and
+ returns a reference to this quaternion.
+
+ \sa operator*=()
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Creates a normalized quaternion that corresponds to rotating through
+ \a angle degrees about the specified 3D \a axis.
+*/
+QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, qreal angle)
+{
+ // Algorithm from:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56
+ // We normalize the result just in case the values are close
+ // to zero, as suggested in the above FAQ.
+ qreal a = (angle / 2.0f) * M_PI / 180.0f;
+ qreal s = qSin(a);
+ qreal c = qCos(a);
+ QVector3D ax = axis.normalized();
+ return QQuaternion(c, ax.xp * s, ax.yp * s, ax.zp * s, 1).normalized();
+}
+
+#endif
+
+/*!
+ Creates a normalized quaternion that corresponds to rotating through
+ \a angle degrees about the 3D axis (\a x, \a y, \a z).
+*/
+QQuaternion QQuaternion::fromAxisAndAngle
+ (qreal x, qreal y, qreal z, qreal angle)
+{
+ float xp = x;
+ float yp = y;
+ float zp = z;
+ qreal length = qSqrt(xp * xp + yp * yp + zp * zp);
+ if (!qIsNull(length)) {
+ xp /= length;
+ yp /= length;
+ zp /= length;
+ }
+ qreal a = (angle / 2.0f) * M_PI / 180.0f;
+ qreal s = qSin(a);
+ qreal c = qCos(a);
+ return QQuaternion(c, xp * s, yp * s, zp * s, 1).normalized();
+}
+
+/*!
+ \fn bool operator==(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns true if \a q1 is equal to \a q2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns true if \a q1 is not equal to \a q2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns a QQuaternion object that is the sum of the given quaternions,
+ \a q1 and \a q2; each component is added separately.
+
+ \sa QQuaternion::operator+=()
+*/
+
+/*!
+ \fn const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns a QQuaternion object that is formed by subtracting
+ \a q2 from \a q1; each component is subtracted separately.
+
+ \sa QQuaternion::operator-=()
+*/
+
+/*!
+ \fn const QQuaternion operator*(qreal factor, const QQuaternion &quaternion)
+ \relates QQuaternion
+
+ Returns a copy of the given \a quaternion, multiplied by the
+ given \a factor.
+
+ \sa QQuaternion::operator*=()
+*/
+
+/*!
+ \fn const QQuaternion operator*(const QQuaternion &quaternion, qreal factor)
+ \relates QQuaternion
+
+ Returns a copy of the given \a quaternion, multiplied by the
+ given \a factor.
+
+ \sa QQuaternion::operator*=()
+*/
+
+/*!
+ \fn const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
+ \relates QQuaternion
+
+ Multiplies \a q1 and \a q2 using quaternion multiplication.
+ The result corresponds to applying both of the rotations specified
+ by \a q1 and \a q2.
+
+ \sa QQuaternion::operator*=()
+*/
+
+/*!
+ \fn const QQuaternion operator-(const QQuaternion &quaternion)
+ \relates QQuaternion
+ \overload
+
+ Returns a QQuaternion object that is formed by changing the sign of
+ all three components of the given \a quaternion.
+
+ Equivalent to \c {QQuaternion(0,0,0,0) - quaternion}.
+*/
+
+/*!
+ \fn const QQuaternion operator/(const QQuaternion &quaternion, qreal divisor)
+ \relates QQuaternion
+
+ Returns the QQuaternion object formed by dividing all components of
+ the given \a quaternion by the given \a divisor.
+
+ \sa QQuaternion::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)
+ \relates QQuaternion
+
+ Returns true if \a q1 and \a q2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+/*!
+ Interpolates along the shortest spherical path between the
+ rotational positions \a q1 and \a q2. The value \a t should
+ be between 0 and 1, indicating the spherical distance to travel
+ between \a q1 and \a q2.
+
+ If \a t is less than or equal to 0, then \a q1 will be returned.
+ If \a t is greater than or equal to 1, then \a q2 will be returned.
+
+ \sa nlerp()
+*/
+QQuaternion QQuaternion::slerp
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t)
+{
+ // Handle the easy cases first.
+ if (t <= 0.0f)
+ return q1;
+ else if (t >= 1.0f)
+ return q2;
+
+ // Determine the angle between the two quaternions.
+ QQuaternion q2b;
+ qreal dot;
+ dot = q1.xp * q2.xp + q1.yp * q2.yp + q1.zp * q2.zp + q1.wp * q2.wp;
+ if (dot >= 0.0f) {
+ q2b = q2;
+ } else {
+ q2b = -q2;
+ dot = -dot;
+ }
+
+ // Get the scale factors. If they are too small,
+ // then revert to simple linear interpolation.
+ qreal factor1 = 1.0f - t;
+ qreal factor2 = t;
+ if ((1.0f - dot) > 0.0000001) {
+ qreal angle = qreal(qAcos(dot));
+ qreal sinOfAngle = qreal(qSin(angle));
+ if (sinOfAngle > 0.0000001) {
+ factor1 = qreal(qSin((1.0f - t) * angle)) / sinOfAngle;
+ factor2 = qreal(qSin(t * angle)) / sinOfAngle;
+ }
+ }
+
+ // Construct the result quaternion.
+ return q1 * factor1 + q2b * factor2;
+}
+
+/*!
+ Interpolates along the shortest linear path between the rotational
+ positions \a q1 and \a q2. The value \a t should be between 0 and 1,
+ indicating the distance to travel between \a q1 and \a q2.
+ The result will be normalized().
+
+ If \a t is less than or equal to 0, then \a q1 will be returned.
+ If \a t is greater than or equal to 1, then \a q2 will be returned.
+
+ The nlerp() function is typically faster than slerp() and will
+ give approximate results to spherical interpolation that are
+ good enough for some applications.
+
+ \sa slerp()
+*/
+QQuaternion QQuaternion::nlerp
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t)
+{
+ // Handle the easy cases first.
+ if (t <= 0.0f)
+ return q1;
+ else if (t >= 1.0f)
+ return q2;
+
+ // Determine the angle between the two quaternions.
+ QQuaternion q2b;
+ qreal dot;
+ dot = q1.xp * q2.xp + q1.yp * q2.yp + q1.zp * q2.zp + q1.wp * q2.wp;
+ if (dot >= 0.0f)
+ q2b = q2;
+ else
+ q2b = -q2;
+
+ // Perform the linear interpolation.
+ return (q1 * (1.0f - t) + q2b * t).normalized();
+}
+
+/*!
+ Returns the quaternion as a QVariant.
+*/
+QQuaternion::operator QVariant() const
+{
+ return QVariant(QVariant::Quaternion, this);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QQuaternion &q)
+{
+ dbg.nospace() << "QQuaternion(scalar:" << q.scalar()
+ << ", vector:(" << q.x() << ", "
+ << q.y() << ", " << q.z() << "))";
+ return dbg.space();
+}
+
+#endif
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QQuaternion &quaternion)
+ \relates QQuaternion
+
+ Writes the given \a quaternion to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator<<(QDataStream &stream, const QQuaternion &quaternion)
+{
+ stream << double(quaternion.scalar()) << double(quaternion.x())
+ << double(quaternion.y()) << double(quaternion.z());
+ return stream;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QQuaternion &quaternion)
+ \relates QQuaternion
+
+ Reads a quaternion from the given \a stream into the given \a quaternion
+ and returns a reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator>>(QDataStream &stream, QQuaternion &quaternion)
+{
+ double scalar, x, y, z;
+ stream >> scalar;
+ stream >> x;
+ stream >> y;
+ stream >> z;
+ quaternion.setScalar(qreal(scalar));
+ quaternion.setX(qreal(x));
+ quaternion.setY(qreal(y));
+ quaternion.setZ(qreal(z));
+ return stream;
+}
+
+#endif // QT_NO_DATASTREAM
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h
new file mode 100644
index 0000000..af60b61
--- /dev/null
+++ b/src/gui/math3d/qquaternion.h
@@ -0,0 +1,334 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUATERNION_H
+#define QQUATERNION_H
+
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QUATERNION
+
+class QMatrix4x4;
+class QVariant;
+
+class Q_GUI_EXPORT QQuaternion
+{
+public:
+ QQuaternion();
+ QQuaternion(qreal scalar, qreal xpos, qreal ypos, qreal zpos);
+#ifndef QT_NO_VECTOR3D
+ QQuaternion(qreal scalar, const QVector3D& vector);
+#endif
+#ifndef QT_NO_VECTOR4D
+ explicit QQuaternion(const QVector4D& vector);
+#endif
+
+ bool isNull() const;
+ bool isIdentity() const;
+
+#ifndef QT_NO_VECTOR3D
+ QVector3D vector() const;
+ void setVector(const QVector3D& vector);
+#endif
+ void setVector(qreal x, qreal y, qreal z);
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ qreal scalar() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setZ(qreal z);
+ void setScalar(qreal scalar);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QQuaternion normalized() const;
+ void normalize();
+
+ QQuaternion conjugate() const;
+
+ QVector3D rotateVector(const QVector3D& vector) const;
+
+ QQuaternion &operator+=(const QQuaternion &quaternion);
+ QQuaternion &operator-=(const QQuaternion &quaternion);
+ QQuaternion &operator*=(qreal factor);
+ QQuaternion &operator*=(const QQuaternion &quaternion);
+ QQuaternion &operator/=(qreal divisor);
+
+ friend inline bool operator==(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline const QQuaternion operator*(qreal factor, const QQuaternion &quaternion);
+ friend inline const QQuaternion operator*(const QQuaternion &quaternion, qreal factor);
+ friend inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2);
+ friend inline const QQuaternion operator-(const QQuaternion &quaternion);
+ friend inline const QQuaternion operator/(const QQuaternion &quaternion, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2);
+
+#ifndef QT_NO_VECTOR4D
+ QVector4D toVector4D() const;
+#endif
+
+ operator QVariant() const;
+
+#ifndef QT_NO_VECTOR3D
+ static QQuaternion fromAxisAndAngle(const QVector3D& axis, qreal angle);
+#endif
+ static QQuaternion fromAxisAndAngle
+ (qreal x, qreal y, qreal z, qreal angle);
+
+ static QQuaternion slerp
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t);
+ static QQuaternion nlerp
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t);
+
+private:
+ float wp, xp, yp, zp;
+
+ friend class QMatrix4x4;
+
+ QQuaternion(float scalar, float xpos, float ypos, float zpos, int dummy);
+};
+
+inline QQuaternion::QQuaternion() : wp(1.0f), xp(0.0f), yp(0.0f), zp(0.0f) {}
+
+inline QQuaternion::QQuaternion(qreal scalar, qreal xpos, qreal ypos, qreal zpos) : wp(scalar), xp(xpos), yp(ypos), zp(zpos) {}
+
+
+inline QQuaternion::QQuaternion(float scalar, float xpos, float ypos, float zpos, int) : wp(scalar), xp(xpos), yp(ypos), zp(zpos) {}
+
+inline bool QQuaternion::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && qIsNull(wp);
+}
+
+inline bool QQuaternion::isIdentity() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && wp == 1.0f;
+}
+
+inline qreal QQuaternion::x() const { return qreal(xp); }
+inline qreal QQuaternion::y() const { return qreal(yp); }
+inline qreal QQuaternion::z() const { return qreal(zp); }
+inline qreal QQuaternion::scalar() const { return qreal(wp); }
+
+inline void QQuaternion::setX(qreal x) { xp = x; }
+inline void QQuaternion::setY(qreal y) { yp = y; }
+inline void QQuaternion::setZ(qreal z) { zp = z; }
+inline void QQuaternion::setScalar(qreal scalar) { wp = scalar; }
+
+inline QQuaternion QQuaternion::conjugate() const
+{
+ return QQuaternion(wp, -xp, -yp, -zp, 1);
+}
+
+inline QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
+{
+ xp += quaternion.xp;
+ yp += quaternion.yp;
+ zp += quaternion.zp;
+ wp += quaternion.wp;
+ return *this;
+}
+
+inline QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)
+{
+ xp -= quaternion.xp;
+ yp -= quaternion.yp;
+ zp -= quaternion.zp;
+ wp -= quaternion.wp;
+ return *this;
+}
+
+inline QQuaternion &QQuaternion::operator*=(qreal factor)
+{
+ xp *= factor;
+ yp *= factor;
+ zp *= factor;
+ wp *= factor;
+ return *this;
+}
+
+inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
+{
+ float ww = (q1.zp + q1.xp) * (q2.xp + q2.yp);
+ float yy = (q1.wp - q1.yp) * (q2.wp + q2.zp);
+ float zz = (q1.wp + q1.yp) * (q2.wp - q2.zp);
+ float xx = ww + yy + zz;
+ float qq = 0.5 * (xx + (q1.zp - q1.xp) * (q2.xp - q2.yp));
+
+ float w = qq - ww + (q1.zp - q1.yp) * (q2.yp - q2.zp);
+ float x = qq - xx + (q1.xp + q1.wp) * (q2.xp + q2.wp);
+ float y = qq - yy + (q1.wp - q1.xp) * (q2.yp + q2.zp);
+ float z = qq - zz + (q1.zp + q1.yp) * (q2.wp - q2.xp);
+
+ return QQuaternion(w, x, y, z, 1);
+}
+
+inline QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion)
+{
+ *this = *this * quaternion;
+ return *this;
+}
+
+inline QQuaternion &QQuaternion::operator/=(qreal divisor)
+{
+ xp /= divisor;
+ yp /= divisor;
+ zp /= divisor;
+ wp /= divisor;
+ return *this;
+}
+
+inline bool operator==(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return q1.xp == q2.xp && q1.yp == q2.yp && q1.zp == q2.zp && q1.wp == q2.wp;
+}
+
+inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return q1.xp != q2.xp || q1.yp != q2.yp || q1.zp != q2.zp || q1.wp != q2.wp;
+}
+
+inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return QQuaternion(q1.wp + q2.wp, q1.xp + q2.xp, q1.yp + q2.yp, q1.zp + q2.zp, 1);
+}
+
+inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return QQuaternion(q1.wp - q2.wp, q1.xp - q2.xp, q1.yp - q2.yp, q1.zp - q2.zp, 1);
+}
+
+inline const QQuaternion operator*(qreal factor, const QQuaternion &quaternion)
+{
+ return QQuaternion(quaternion.wp * factor, quaternion.xp * factor, quaternion.yp * factor, quaternion.zp * factor, 1);
+}
+
+inline const QQuaternion operator*(const QQuaternion &quaternion, qreal factor)
+{
+ return QQuaternion(quaternion.wp * factor, quaternion.xp * factor, quaternion.yp * factor, quaternion.zp * factor, 1);
+}
+
+inline const QQuaternion operator-(const QQuaternion &quaternion)
+{
+ return QQuaternion(-quaternion.wp, -quaternion.xp, -quaternion.yp, -quaternion.zp, 1);
+}
+
+inline const QQuaternion operator/(const QQuaternion &quaternion, qreal divisor)
+{
+ return QQuaternion(quaternion.wp / divisor, quaternion.xp / divisor, quaternion.yp / divisor, quaternion.zp / divisor, 1);
+}
+
+inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)
+{
+ return qFuzzyCompare(q1.xp, q2.xp) &&
+ qFuzzyCompare(q1.yp, q2.yp) &&
+ qFuzzyCompare(q1.zp, q2.zp) &&
+ qFuzzyCompare(q1.wp, q2.wp);
+}
+
+#ifndef QT_NO_VECTOR3D
+
+inline QQuaternion::QQuaternion(qreal scalar, const QVector3D& vector)
+ : wp(scalar), xp(vector.xp), yp(vector.yp), zp(vector.zp) {}
+
+inline void QQuaternion::setVector(const QVector3D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+}
+
+inline QVector3D QQuaternion::vector() const
+{
+ return QVector3D(xp, yp, zp, 1);
+}
+
+#endif
+
+inline void QQuaternion::setVector(qreal x, qreal y, qreal z)
+{
+ xp = x;
+ yp = y;
+ zp = z;
+}
+
+#ifndef QT_NO_VECTOR4D
+
+inline QQuaternion::QQuaternion(const QVector4D& vector)
+ : wp(vector.wp), xp(vector.xp), yp(vector.yp), zp(vector.zp) {}
+
+inline QVector4D QQuaternion::toVector4D() const
+{
+ return QVector4D(xp, yp, zp, wp, 1);
+}
+
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QQuaternion &q);
+#endif
+
+#ifndef QT_NO_DATASTREAM
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QQuaternion &);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QQuaternion &);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp
new file mode 100644
index 0000000..35c86a1
--- /dev/null
+++ b/src/gui/math3d/qvector2d.cpp
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector2d.h"
+#include "qvector3d.h"
+#include "qvector4d.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ \class QVector2D
+ \brief The QVector2D class represents a vector or vertex in 2D space.
+ \since 4.6
+ \ingroup painting
+ \ingroup painting-3D
+
+ The QVector2D class can also be used to represent vertices in 2D space.
+ We therefore do not need to provide a separate vertex class.
+
+ \sa QVector3D, QVector4D, QQuaternion
+*/
+
+/*!
+ \fn QVector2D::QVector2D()
+
+ Constructs a null vector, i.e. with coordinates (0, 0, 0).
+*/
+
+/*!
+ \fn QVector2D::QVector2D(qreal xpos, qreal ypos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos).
+*/
+
+/*!
+ \fn QVector2D::QVector2D(const QPoint& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point.
+*/
+
+/*!
+ \fn QVector2D::QVector2D(const QPointF& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Constructs a vector with x and y coordinates from a 3D \a vector.
+ The z coordinate of \a vector is dropped.
+
+ \sa toVector3D()
+*/
+QVector2D::QVector2D(const QVector3D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Constructs a vector with x and y coordinates from a 3D \a vector.
+ The z and w coordinates of \a vector are dropped.
+
+ \sa toVector4D()
+*/
+QVector2D::QVector2D(const QVector4D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+}
+
+#endif
+
+/*!
+ \fn bool QVector2D::isNull() const
+
+ Returns true if the x and y coordinates are set to 0.0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn qreal QVector2D::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), y()
+*/
+
+/*!
+ \fn qreal QVector2D::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), x()
+*/
+
+/*!
+ \fn void QVector2D::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x(), setY()
+*/
+
+/*!
+ \fn void QVector2D::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX()
+*/
+
+/*!
+ Returns the length of the vector from the origin.
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QVector2D::length() const
+{
+ return qSqrt(xp * xp + yp * yp);
+}
+
+/*!
+ Returns the squared length of the vector from the origin.
+ This is equivalent to the dot product of the vector with itself.
+
+ \sa length(), dotProduct()
+*/
+qreal QVector2D::lengthSquared() const
+{
+ return xp * xp + yp * yp;
+}
+
+/*!
+ Returns the normalized unit vector form of this vector.
+
+ If this vector is null, then a null vector is returned. If the length
+ of the vector is very close to 1, then the vector will be returned as-is.
+ Otherwise the normalized form of the vector of length 1 will be returned.
+
+ \sa length(), normalize()
+*/
+QVector2D QVector2D::normalized() const
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f))
+ return *this;
+ else if (!qFuzzyIsNull(len))
+ return *this / qSqrt(len);
+ else
+ return QVector2D();
+}
+
+/*!
+ Normalizes the currect vector in place. Nothing happens if this
+ vector is a null vector or the length of the vector is very close to 1.
+
+ \sa length(), normalized()
+*/
+void QVector2D::normalize()
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
+ return;
+
+ len = qSqrt(len);
+
+ xp /= len;
+ yp /= len;
+}
+
+/*!
+ \fn QVector2D &QVector2D::operator+=(const QVector2D &vector)
+
+ Adds the given \a vector to this vector and returns a reference to
+ this vector.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator-=(const QVector2D &vector)
+
+ Subtracts the given \a vector from this vector and returns a reference to
+ this vector.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator*=(qreal factor)
+
+ Multiplies this vector's coordinates by the given \a factor, and
+ returns a reference to this vector.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator*=(const QVector2D &vector)
+
+ Multiplies the components of this vector by the corresponding
+ components in \a vector.
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator/=(qreal divisor)
+
+ Divides this vector's coordinates by the given \a divisor, and
+ returns a reference to this vector.
+
+ \sa operator*=()
+*/
+
+/*!
+ Returns the dot product of \a v1 and \a v2.
+*/
+qreal QVector2D::dotProduct(const QVector2D& v1, const QVector2D& v2)
+{
+ return v1.xp * v2.xp + v1.yp * v2.yp;
+}
+
+/*!
+ \fn bool operator==(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns true if \a v1 is equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns true if \a v1 is not equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QVector2D operator+(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns a QVector2D object that is the sum of the given vectors, \a v1
+ and \a v2; each component is added separately.
+
+ \sa QVector2D::operator+=()
+*/
+
+/*!
+ \fn const QVector2D operator-(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns a QVector2D object that is formed by subtracting \a v2 from \a v1;
+ each component is subtracted separately.
+
+ \sa QVector2D::operator-=()
+*/
+
+/*!
+ \fn const QVector2D operator*(qreal factor, const QVector2D &vector)
+ \relates QVector2D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector2D::operator*=()
+*/
+
+/*!
+ \fn const QVector2D operator*(const QVector2D &vector, qreal factor)
+ \relates QVector2D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector2D::operator*=()
+*/
+
+/*!
+ \fn const QVector2D operator*(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Multiplies the components of \a v1 by the corresponding
+ components in \a v2.
+*/
+
+/*!
+ \fn const QVector2D operator-(const QVector2D &vector)
+ \relates QVector2D
+ \overload
+
+ Returns a QVector2D object that is formed by changing the sign of
+ the components of the given \a vector.
+
+ Equivalent to \c {QVector2D(0,0) - vector}.
+*/
+
+/*!
+ \fn const QVector2D operator/(const QVector2D &vector, qreal divisor)
+ \relates QVector2D
+
+ Returns the QVector2D object formed by dividing all three components of
+ the given \a vector by the given \a divisor.
+
+ \sa QVector2D::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2)
+ \relates QVector2D
+
+ Returns true if \a v1 and \a v2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Returns the 3D form of this 2D vector, with the z coordinate set to zero.
+
+ \sa toVector4D(), toPoint()
+*/
+QVector3D QVector2D::toVector3D() const
+{
+ return QVector3D(xp, yp, 0.0f, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Returns the 4D form of this 2D vector, with the z and w coordinates set to zero.
+
+ \sa toVector3D(), toPoint()
+*/
+QVector4D QVector2D::toVector4D() const
+{
+ return QVector4D(xp, yp, 0.0f, 0.0f, 1);
+}
+
+#endif
+
+/*!
+ \fn QPoint QVector2D::toPoint() const
+
+ Returns the QPoint form of this 2D vector.
+
+ \sa toPointF(), toVector3D()
+*/
+
+/*!
+ \fn QPointF QVector2D::toPointF() const
+
+ Returns the QPointF form of this 2D vector.
+
+ \sa toPoint(), toVector3D()
+*/
+
+/*!
+ Returns the 2D vector as a QVariant.
+*/
+QVector2D::operator QVariant() const
+{
+ return QVariant(QVariant::Vector2D, this);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QVector2D &vector)
+{
+ dbg.nospace() << "QVector2D(" << vector.x() << ", " << vector.y() << ')';
+ return dbg.space();
+}
+
+#endif
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QVector2D &vector)
+ \relates QVector2D
+
+ Writes the given \a vector to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator<<(QDataStream &stream, const QVector2D &vector)
+{
+ stream << double(vector.x()) << double(vector.y());
+ return stream;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QVector2D &vector)
+ \relates QVector2D
+
+ Reads a 2D vector from the given \a stream into the given \a vector
+ and returns a reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator>>(QDataStream &stream, QVector2D &vector)
+{
+ double x, y;
+ stream >> x;
+ stream >> y;
+ vector.setX(qreal(x));
+ vector.setY(qreal(y));
+ return stream;
+}
+
+#endif // QT_NO_DATASTREAM
+
+#endif // QT_NO_VECTOR2D
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h
new file mode 100644
index 0000000..d9727e2
--- /dev/null
+++ b/src/gui/math3d/qvector2d.h
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR2D_H
+#define QVECTOR2D_H
+
+#include <QtCore/qpoint.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QVector3D;
+class QVector4D;
+class QVariant;
+
+#ifndef QT_NO_VECTOR2D
+
+class Q_GUI_EXPORT QVector2D
+{
+public:
+ QVector2D();
+ QVector2D(qreal xpos, qreal ypos);
+ explicit QVector2D(const QPoint& point);
+ explicit QVector2D(const QPointF& point);
+#ifndef QT_NO_VECTOR3D
+ explicit QVector2D(const QVector3D& vector);
+#endif
+#ifndef QT_NO_VECTOR4D
+ explicit QVector2D(const QVector4D& vector);
+#endif
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QVector2D normalized() const;
+ void normalize();
+
+ QVector2D &operator+=(const QVector2D &vector);
+ QVector2D &operator-=(const QVector2D &vector);
+ QVector2D &operator*=(qreal factor);
+ QVector2D &operator*=(const QVector2D &vector);
+ QVector2D &operator/=(qreal divisor);
+
+ static qreal dotProduct(const QVector2D& v1, const QVector2D& v2);
+
+ friend inline bool operator==(const QVector2D &v1, const QVector2D &v2);
+ friend inline bool operator!=(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator+(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator-(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator*(qreal factor, const QVector2D &vector);
+ friend inline const QVector2D operator*(const QVector2D &vector, qreal factor);
+ friend inline const QVector2D operator*(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator-(const QVector2D &vector);
+ friend inline const QVector2D operator/(const QVector2D &vector, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2);
+
+#ifndef QT_NO_VECTOR3D
+ QVector3D toVector3D() const;
+#endif
+#ifndef QT_NO_VECTOR4D
+ QVector4D toVector4D() const;
+#endif
+
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+
+ operator QVariant() const;
+
+private:
+ float xp, yp;
+
+ QVector2D(float xpos, float ypos, int dummy);
+
+ friend class QVector3D;
+ friend class QVector4D;
+};
+
+inline QVector2D::QVector2D() : xp(0.0f), yp(0.0f) {}
+
+inline QVector2D::QVector2D(float xpos, float ypos, int) : xp(xpos), yp(ypos) {}
+
+inline QVector2D::QVector2D(qreal xpos, qreal ypos) : xp(xpos), yp(ypos) {}
+
+inline QVector2D::QVector2D(const QPoint& point) : xp(point.x()), yp(point.y()) {}
+
+inline QVector2D::QVector2D(const QPointF& point) : xp(point.x()), yp(point.y()) {}
+
+inline bool QVector2D::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp);
+}
+
+inline qreal QVector2D::x() const { return qreal(xp); }
+inline qreal QVector2D::y() const { return qreal(yp); }
+
+inline void QVector2D::setX(qreal x) { xp = x; }
+inline void QVector2D::setY(qreal y) { yp = y; }
+
+inline QVector2D &QVector2D::operator+=(const QVector2D &vector)
+{
+ xp += vector.xp;
+ yp += vector.yp;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator-=(const QVector2D &vector)
+{
+ xp -= vector.xp;
+ yp -= vector.yp;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator*=(qreal factor)
+{
+ xp *= factor;
+ yp *= factor;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator*=(const QVector2D &vector)
+{
+ xp *= vector.xp;
+ yp *= vector.yp;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator/=(qreal divisor)
+{
+ xp /= divisor;
+ yp /= divisor;
+ return *this;
+}
+
+inline bool operator==(const QVector2D &v1, const QVector2D &v2)
+{
+ return v1.xp == v2.xp && v1.yp == v2.yp;
+}
+
+inline bool operator!=(const QVector2D &v1, const QVector2D &v2)
+{
+ return v1.xp != v2.xp || v1.yp != v2.yp;
+}
+
+inline const QVector2D operator+(const QVector2D &v1, const QVector2D &v2)
+{
+ return QVector2D(v1.xp + v2.xp, v1.yp + v2.yp, 1);
+}
+
+inline const QVector2D operator-(const QVector2D &v1, const QVector2D &v2)
+{
+ return QVector2D(v1.xp - v2.xp, v1.yp - v2.yp, 1);
+}
+
+inline const QVector2D operator*(qreal factor, const QVector2D &vector)
+{
+ return QVector2D(vector.xp * factor, vector.yp * factor, 1);
+}
+
+inline const QVector2D operator*(const QVector2D &vector, qreal factor)
+{
+ return QVector2D(vector.xp * factor, vector.yp * factor, 1);
+}
+
+inline const QVector2D operator*(const QVector2D &v1, const QVector2D &v2)
+{
+ return QVector2D(v1.xp * v2.xp, v1.yp * v2.yp, 1);
+}
+
+inline const QVector2D operator-(const QVector2D &vector)
+{
+ return QVector2D(-vector.xp, -vector.yp, 1);
+}
+
+inline const QVector2D operator/(const QVector2D &vector, qreal divisor)
+{
+ return QVector2D(vector.xp / divisor, vector.yp / divisor, 1);
+}
+
+inline bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2)
+{
+ return qFuzzyCompare(v1.xp, v2.xp) && qFuzzyCompare(v1.yp, v2.yp);
+}
+
+inline QPoint QVector2D::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+inline QPointF QVector2D::toPointF() const
+{
+ return QPointF(qreal(xp), qreal(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector2D &vector);
+#endif
+
+#ifndef QT_NO_DATASTREAM
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QVector2D &);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector2D &);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp
new file mode 100644
index 0000000..5c96979
--- /dev/null
+++ b/src/gui/math3d/qvector3d.cpp
@@ -0,0 +1,618 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector3d.h"
+#include "qvector2d.h"
+#include "qvector4d.h"
+#include <QtCore/qmath.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \class QVector3D
+ \brief The QVector3D class represents a vector or vertex in 3D space.
+ \since 4.6
+ \ingroup painting-3D
+
+ Vectors are one of the main building blocks of 3D representation and
+ drawing. They consist of three coordinates, traditionally called
+ x, y, and z.
+
+ The QVector3D class can also be used to represent vertices in 3D space.
+ We therefore do not need to provide a separate vertex class.
+
+ \sa QVector2D, QVector4D, QQuaternion
+*/
+
+/*!
+ \fn QVector3D::QVector3D()
+
+ Constructs a null vector, i.e. with coordinates (0, 0, 0).
+*/
+
+/*!
+ \fn QVector3D::QVector3D(qreal xpos, qreal ypos, qreal zpos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos).
+*/
+
+/*!
+ \fn QVector3D::QVector3D(const QPoint& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and a
+ z coordinate of 0.
+*/
+
+/*!
+ \fn QVector3D::QVector3D(const QPointF& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and a
+ z coordinate of 0.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Constructs a 3D vector from the specified 2D \a vector. The z
+ coordinate is set to zero.
+
+ \sa toVector2D()
+*/
+QVector3D::QVector3D(const QVector2D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = 0.0f;
+}
+
+/*!
+ Constructs a 3D vector from the specified 2D \a vector. The z
+ coordinate is set to \a zpos.
+
+ \sa toVector2D()
+*/
+QVector3D::QVector3D(const QVector2D& vector, qreal zpos)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = zpos;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Constructs a 3D vector from the specified 4D \a vector. The w
+ coordinate is dropped.
+
+ \sa toVector4D()
+*/
+QVector3D::QVector3D(const QVector4D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+}
+
+#endif
+
+/*!
+ \fn bool QVector3D::isNull() const
+
+ Returns true if the x, y, and z coordinates are set to 0.0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn qreal QVector3D::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), y(), z()
+*/
+
+/*!
+ \fn qreal QVector3D::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), x(), z()
+*/
+
+/*!
+ \fn qreal QVector3D::z() const
+
+ Returns the z coordinate of this point.
+
+ \sa setZ(), x(), y()
+*/
+
+/*!
+ \fn void QVector3D::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x(), setY(), setZ()
+*/
+
+/*!
+ \fn void QVector3D::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX(), setZ()
+*/
+
+/*!
+ \fn void QVector3D::setZ(qreal z)
+
+ Sets the z coordinate of this point to the given \a z coordinate.
+
+ \sa z(), setX(), setY()
+*/
+
+/*!
+ Returns the normalized unit vector form of this vector.
+
+ If this vector is null, then a null vector is returned. If the length
+ of the vector is very close to 1, then the vector will be returned as-is.
+ Otherwise the normalized form of the vector of length 1 will be returned.
+
+ \sa length(), normalize()
+*/
+QVector3D QVector3D::normalized() const
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f))
+ return *this;
+ else if (!qFuzzyIsNull(len))
+ return *this / qSqrt(len);
+ else
+ return QVector3D();
+}
+
+/*!
+ Normalizes the currect vector in place. Nothing happens if this
+ vector is a null vector or the length of the vector is very close to 1.
+
+ \sa length(), normalized()
+*/
+void QVector3D::normalize()
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
+ return;
+
+ len = qSqrt(len);
+
+ xp /= len;
+ yp /= len;
+ zp /= len;
+}
+
+/*!
+ \fn QVector3D &QVector3D::operator+=(const QVector3D &vector)
+
+ Adds the given \a vector to this vector and returns a reference to
+ this vector.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator-=(const QVector3D &vector)
+
+ Subtracts the given \a vector from this vector and returns a reference to
+ this vector.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator*=(qreal factor)
+
+ Multiplies this vector's coordinates by the given \a factor, and
+ returns a reference to this vector.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator*=(const QVector3D& vector)
+ \overload
+
+ Multiplies the components of this vector by the corresponding
+ components in \a vector.
+
+ Note: this is not the same as the crossProduct() of this
+ vector and \a vector.
+
+ \sa crossProduct()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator/=(qreal divisor)
+
+ Divides this vector's coordinates by the given \a divisor, and
+ returns a reference to this vector.
+
+ \sa operator*=()
+*/
+
+/*!
+ Returns the dot product of \a v1 and \a v2.
+*/
+qreal QVector3D::dotProduct(const QVector3D& v1, const QVector3D& v2)
+{
+ return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp;
+}
+
+/*!
+ Returns the cross-product of vectors \a v1 and \a v2, which corresponds
+ to the normal vector of a plane defined by \a v1 and \a v2.
+
+ \sa normal()
+*/
+QVector3D QVector3D::crossProduct(const QVector3D& v1, const QVector3D& v2)
+{
+ return QVector3D(v1.yp * v2.zp - v1.zp * v2.yp,
+ v1.zp * v2.xp - v1.xp * v2.zp,
+ v1.xp * v2.yp - v1.yp * v2.xp, 1);
+}
+
+/*!
+ Returns the normal vector of a plane defined by vectors \a v1 and \a v2,
+ normalized to be a unit vector.
+
+ Use crossProduct() to compute the cross-product of \a v1 and \a v2 if you
+ do not need the result to be normalized to a unit vector.
+
+ \sa crossProduct(), distanceToPlane()
+*/
+QVector3D QVector3D::normal(const QVector3D& v1, const QVector3D& v2)
+{
+ return crossProduct(v1, v2).normalized();
+}
+
+/*!
+ \overload
+
+ Returns the normal vector of a plane defined by vectors
+ \a v2 - \a v1 and \a v3 - \a v1, normalized to be a unit vector.
+
+ Use crossProduct() to compute the cross-product of \a v2 - \a v1 and
+ \a v3 - \a v1 if you do not need the result to be normalized to a
+ unit vector.
+
+ \sa crossProduct(), distanceToPlane()
+*/
+QVector3D QVector3D::normal
+ (const QVector3D& v1, const QVector3D& v2, const QVector3D& v3)
+{
+ return crossProduct((v2 - v1), (v3 - v1)).normalized();
+}
+
+/*!
+ Returns the distance from this vertex to a plane defined by
+ the vertex \a plane and a \a normal unit vector. The \a normal
+ parameter is assumed to have been normalized to a unit vector.
+
+ The return value will be negative if the vertex is below the plane,
+ or zero if it is on the plane.
+
+ \sa normal(), distanceToLine()
+*/
+qreal QVector3D::distanceToPlane
+ (const QVector3D& plane, const QVector3D& normal) const
+{
+ return dotProduct(*this - plane, normal);
+}
+
+/*!
+ \overload
+
+ Returns the distance from this vertex a plane defined by
+ the vertices \a plane1, \a plane2 and \a plane3.
+
+ The return value will be negative if the vertex is below the plane,
+ or zero if it is on the plane.
+
+ The two vectors that define the plane are \a plane2 - \a plane1
+ and \a plane3 - \a plane1.
+
+ \sa normal(), distanceToLine()
+*/
+qreal QVector3D::distanceToPlane
+ (const QVector3D& plane1, const QVector3D& plane2, const QVector3D& plane3) const
+{
+ QVector3D n = normal(plane2 - plane1, plane3 - plane1);
+ return dotProduct(*this - plane1, n);
+}
+
+/*!
+ Returns the distance that this vertex is from a line defined
+ by \a point and the unit vector \a direction.
+
+ If \a direction is a null vector, then it does not define a line.
+ In that case, the distance from \a point to this vertex is returned.
+
+ \sa distanceToPlane()
+*/
+qreal QVector3D::distanceToLine
+ (const QVector3D& point, const QVector3D& direction) const
+{
+ if (direction.isNull())
+ return (*this - point).length();
+ QVector3D p = point + dotProduct(*this - point, direction) * direction;
+ return (*this - p).length();
+}
+
+/*!
+ \fn bool operator==(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns true if \a v1 is equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns true if \a v1 is not equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QVector3D operator+(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns a QVector3D object that is the sum of the given vectors, \a v1
+ and \a v2; each component is added separately.
+
+ \sa QVector3D::operator+=()
+*/
+
+/*!
+ \fn const QVector3D operator-(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns a QVector3D object that is formed by subtracting \a v2 from \a v1;
+ each component is subtracted separately.
+
+ \sa QVector3D::operator-=()
+*/
+
+/*!
+ \fn const QVector3D operator*(qreal factor, const QVector3D &vector)
+ \relates QVector3D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector3D::operator*=()
+*/
+
+/*!
+ \fn const QVector3D operator*(const QVector3D &vector, qreal factor)
+ \relates QVector3D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector3D::operator*=()
+*/
+
+/*!
+ \fn const QVector3D operator*(const QVector3D &v1, const QVector3D& v2)
+ \relates QVector3D
+
+ Multiplies the components of \a v1 by the corresponding components in \a v2.
+
+ Note: this is not the same as the crossProduct() of \a v1 and \a v2.
+
+ \sa QVector3D::crossProduct()
+*/
+
+/*!
+ \fn const QVector3D operator-(const QVector3D &vector)
+ \relates QVector3D
+ \overload
+
+ Returns a QVector3D object that is formed by changing the sign of
+ all three components of the given \a vector.
+
+ Equivalent to \c {QVector3D(0,0,0) - vector}.
+*/
+
+/*!
+ \fn const QVector3D operator/(const QVector3D &vector, qreal divisor)
+ \relates QVector3D
+
+ Returns the QVector3D object formed by dividing all three components of
+ the given \a vector by the given \a divisor.
+
+ \sa QVector3D::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2)
+ \relates QVector3D
+
+ Returns true if \a v1 and \a v2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Returns the 2D vector form of this 3D vector, dropping the z coordinate.
+
+ \sa toVector4D(), toPoint()
+*/
+QVector2D QVector3D::toVector2D() const
+{
+ return QVector2D(xp, yp, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Returns the 4D form of this 3D vector, with the w coordinate set to zero.
+
+ \sa toVector2D(), toPoint()
+*/
+QVector4D QVector3D::toVector4D() const
+{
+ return QVector4D(xp, yp, zp, 0.0f, 1);
+}
+
+#endif
+
+/*!
+ \fn QPoint QVector3D::toPoint() const
+
+ Returns the QPoint form of this 3D vector. The z coordinate
+ is dropped.
+
+ \sa toPointF(), toVector2D()
+*/
+
+/*!
+ \fn QPointF QVector3D::toPointF() const
+
+ Returns the QPointF form of this 3D vector. The z coordinate
+ is dropped.
+
+ \sa toPoint(), toVector2D()
+*/
+
+/*!
+ Returns the 3D vector as a QVariant.
+*/
+QVector3D::operator QVariant() const
+{
+ return QVariant(QVariant::Vector3D, this);
+}
+
+/*!
+ Returns the length of the vector from the origin.
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QVector3D::length() const
+{
+ return qSqrt(xp * xp + yp * yp + zp * zp);
+}
+
+/*!
+ Returns the squared length of the vector from the origin.
+ This is equivalent to the dot product of the vector with itself.
+
+ \sa length(), dotProduct()
+*/
+qreal QVector3D::lengthSquared() const
+{
+ return xp * xp + yp * yp + zp * zp;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QVector3D &vector)
+{
+ dbg.nospace() << "QVector3D("
+ << vector.x() << ", " << vector.y() << ", " << vector.z() << ')';
+ return dbg.space();
+}
+
+#endif
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QVector3D &vector)
+ \relates QVector3D
+
+ Writes the given \a vector to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator<<(QDataStream &stream, const QVector3D &vector)
+{
+ stream << double(vector.x()) << double(vector.y())
+ << double(vector.z());
+ return stream;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QVector3D &vector)
+ \relates QVector3D
+
+ Reads a 3D vector from the given \a stream into the given \a vector
+ and returns a reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator>>(QDataStream &stream, QVector3D &vector)
+{
+ double x, y, z;
+ stream >> x;
+ stream >> y;
+ stream >> z;
+ vector.setX(qreal(x));
+ vector.setY(qreal(y));
+ vector.setZ(qreal(z));
+ return stream;
+}
+
+#endif // QT_NO_DATASTREAM
+
+#endif // QT_NO_VECTOR3D
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h
new file mode 100644
index 0000000..d1370fb
--- /dev/null
+++ b/src/gui/math3d/qvector3d.h
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR3D_H
+#define QVECTOR3D_H
+
+#include <QtCore/qpoint.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QMatrix4x4;
+class QVector2D;
+class QVector4D;
+class QQuaternion;
+
+#ifndef QT_NO_VECTOR3D
+
+class Q_GUI_EXPORT QVector3D
+{
+public:
+ QVector3D();
+ QVector3D(qreal xpos, qreal ypos, qreal zpos);
+ explicit QVector3D(const QPoint& point);
+ explicit QVector3D(const QPointF& point);
+#ifndef QT_NO_VECTOR2D
+ QVector3D(const QVector2D& vector);
+ QVector3D(const QVector2D& vector, qreal zpos);
+#endif
+#ifndef QT_NO_VECTOR4D
+ explicit QVector3D(const QVector4D& vector);
+#endif
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setZ(qreal z);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QVector3D normalized() const;
+ void normalize();
+
+ QVector3D &operator+=(const QVector3D &vector);
+ QVector3D &operator-=(const QVector3D &vector);
+ QVector3D &operator*=(qreal factor);
+ QVector3D &operator*=(const QVector3D& vector);
+ QVector3D &operator/=(qreal divisor);
+
+ static qreal dotProduct(const QVector3D& v1, const QVector3D& v2);
+ static QVector3D crossProduct(const QVector3D& v1, const QVector3D& v2);
+ static QVector3D normal(const QVector3D& v1, const QVector3D& v2);
+ static QVector3D normal
+ (const QVector3D& v1, const QVector3D& v2, const QVector3D& v3);
+
+ qreal distanceToPlane(const QVector3D& plane, const QVector3D& normal) const;
+ qreal distanceToPlane(const QVector3D& plane1, const QVector3D& plane2, const QVector3D& plane3) const;
+ qreal distanceToLine(const QVector3D& point, const QVector3D& direction) const;
+
+ friend inline bool operator==(const QVector3D &v1, const QVector3D &v2);
+ friend inline bool operator!=(const QVector3D &v1, const QVector3D &v2);
+ friend inline const QVector3D operator+(const QVector3D &v1, const QVector3D &v2);
+ friend inline const QVector3D operator-(const QVector3D &v1, const QVector3D &v2);
+ friend inline const QVector3D operator*(qreal factor, const QVector3D &vector);
+ friend inline const QVector3D operator*(const QVector3D &vector, qreal factor);
+ friend const QVector3D operator*(const QVector3D &v1, const QVector3D& v2);
+ friend inline const QVector3D operator-(const QVector3D &vector);
+ friend inline const QVector3D operator/(const QVector3D &vector, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2);
+
+#ifndef QT_NO_VECTOR2D
+ QVector2D toVector2D() const;
+#endif
+#ifndef QT_NO_VECTOR4D
+ QVector4D toVector4D() const;
+#endif
+
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+
+ operator QVariant() const;
+
+private:
+ float xp, yp, zp;
+
+ QVector3D(float xpos, float ypos, float zpos, int dummy);
+
+ friend class QVector2D;
+ friend class QVector4D;
+ friend class QQuaternion;
+ friend class QMatrix4x4;
+#ifndef QT_NO_MATRIX4X4
+ friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
+ friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
+#endif
+};
+
+inline QVector3D::QVector3D() : xp(0.0f), yp(0.0f), zp(0.0f) {}
+
+inline QVector3D::QVector3D(qreal xpos, qreal ypos, qreal zpos) : xp(xpos), yp(ypos), zp(zpos) {}
+
+inline QVector3D::QVector3D(float xpos, float ypos, float zpos, int) : xp(xpos), yp(ypos), zp(zpos) {}
+
+inline QVector3D::QVector3D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f) {}
+
+inline QVector3D::QVector3D(const QPointF& point) : xp(point.x()), yp(point.y()), zp(0.0f) {}
+
+inline bool QVector3D::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp);
+}
+
+inline qreal QVector3D::x() const { return qreal(xp); }
+inline qreal QVector3D::y() const { return qreal(yp); }
+inline qreal QVector3D::z() const { return qreal(zp); }
+
+inline void QVector3D::setX(qreal x) { xp = x; }
+inline void QVector3D::setY(qreal y) { yp = y; }
+inline void QVector3D::setZ(qreal z) { zp = z; }
+
+inline QVector3D &QVector3D::operator+=(const QVector3D &vector)
+{
+ xp += vector.xp;
+ yp += vector.yp;
+ zp += vector.zp;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator-=(const QVector3D &vector)
+{
+ xp -= vector.xp;
+ yp -= vector.yp;
+ zp -= vector.zp;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator*=(qreal factor)
+{
+ xp *= factor;
+ yp *= factor;
+ zp *= factor;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator*=(const QVector3D& vector)
+{
+ xp *= vector.xp;
+ yp *= vector.yp;
+ zp *= vector.zp;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator/=(qreal divisor)
+{
+ xp /= divisor;
+ yp /= divisor;
+ zp /= divisor;
+ return *this;
+}
+
+inline bool operator==(const QVector3D &v1, const QVector3D &v2)
+{
+ return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp;
+}
+
+inline bool operator!=(const QVector3D &v1, const QVector3D &v2)
+{
+ return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp;
+}
+
+inline const QVector3D operator+(const QVector3D &v1, const QVector3D &v2)
+{
+ return QVector3D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp, 1);
+}
+
+inline const QVector3D operator-(const QVector3D &v1, const QVector3D &v2)
+{
+ return QVector3D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp, 1);
+}
+
+inline const QVector3D operator*(qreal factor, const QVector3D &vector)
+{
+ return QVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor, 1);
+}
+
+inline const QVector3D operator*(const QVector3D &vector, qreal factor)
+{
+ return QVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor, 1);
+}
+
+inline const QVector3D operator*(const QVector3D &v1, const QVector3D& v2)
+{
+ return QVector3D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp, 1);
+}
+
+inline const QVector3D operator-(const QVector3D &vector)
+{
+ return QVector3D(-vector.xp, -vector.yp, -vector.zp, 1);
+}
+
+inline const QVector3D operator/(const QVector3D &vector, qreal divisor)
+{
+ return QVector3D(vector.xp / divisor, vector.yp / divisor, vector.zp / divisor, 1);
+}
+
+inline bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2)
+{
+ return qFuzzyCompare(v1.xp, v2.xp) &&
+ qFuzzyCompare(v1.yp, v2.yp) &&
+ qFuzzyCompare(v1.zp, v2.zp);
+}
+
+inline QPoint QVector3D::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+inline QPointF QVector3D::toPointF() const
+{
+ return QPointF(qreal(xp), qreal(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector3D &vector);
+#endif
+
+#ifndef QT_NO_DATASTREAM
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QVector3D &);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector3D &);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp
new file mode 100644
index 0000000..11eb4c4
--- /dev/null
+++ b/src/gui/math3d/qvector4d.cpp
@@ -0,0 +1,571 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector4d.h"
+#include "qvector3d.h"
+#include "qvector2d.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \class QVector4D
+ \brief The QVector4D class represents a vector or vertex in 4D space.
+ \since 4.6
+ \ingroup painting-3D
+
+ The QVector4D class can also be used to represent vertices in 4D space.
+ We therefore do not need to provide a separate vertex class.
+
+ \sa QQuaternion, QVector2D, QVector3D
+*/
+
+/*!
+ \fn QVector4D::QVector4D()
+
+ Constructs a null vector, i.e. with coordinates (0, 0, 0, 0).
+*/
+
+/*!
+ \fn QVector4D::QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos, \a wpos).
+*/
+
+/*!
+ \fn QVector4D::QVector4D(const QPoint& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and
+ z and w coordinates of 0.
+*/
+
+/*!
+ \fn QVector4D::QVector4D(const QPointF& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and
+ z and w coordinates of 0.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Constructs a 4D vector from the specified 2D \a vector. The z
+ and w coordinates are set to zero.
+
+ \sa toVector2D()
+*/
+QVector4D::QVector4D(const QVector2D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = 0.0f;
+ wp = 0.0f;
+}
+
+/*!
+ Constructs a 4D vector from the specified 2D \a vector. The z
+ and w coordinates are set to \a zpos and \a wpos respectively.
+
+ \sa toVector2D()
+*/
+QVector4D::QVector4D(const QVector2D& vector, qreal zpos, qreal wpos)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = zpos;
+ wp = wpos;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Constructs a 4D vector from the specified 3D \a vector. The w
+ coordinate is set to zero.
+
+ \sa toVector3D()
+*/
+QVector4D::QVector4D(const QVector3D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+ wp = 0.0f;
+}
+
+/*!
+ Constructs a 4D vector from the specified 3D \a vector. The w
+ coordinate is set to \a wpos.
+
+ \sa toVector3D()
+*/
+QVector4D::QVector4D(const QVector3D& vector, qreal wpos)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+ wp = wpos;
+}
+
+#endif
+
+/*!
+ \fn bool QVector4D::isNull() const
+
+ Returns true if the x, y, z, and w coordinates are set to 0.0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn qreal QVector4D::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), y(), z(), w()
+*/
+
+/*!
+ \fn qreal QVector4D::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), x(), z(), w()
+*/
+
+/*!
+ \fn qreal QVector4D::z() const
+
+ Returns the z coordinate of this point.
+
+ \sa setZ(), x(), y(), w()
+*/
+
+/*!
+ \fn qreal QVector4D::w() const
+
+ Returns the w coordinate of this point.
+
+ \sa setW(), x(), y(), z()
+*/
+
+/*!
+ \fn void QVector4D::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x(), setY(), setZ(), setW()
+*/
+
+/*!
+ \fn void QVector4D::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX(), setZ(), setW()
+*/
+
+/*!
+ \fn void QVector4D::setZ(qreal z)
+
+ Sets the z coordinate of this point to the given \a z coordinate.
+
+ \sa z(), setX(), setY(), setW()
+*/
+
+/*!
+ \fn void QVector4D::setW(qreal w)
+
+ Sets the w coordinate of this point to the given \a w coordinate.
+
+ \sa w(), setX(), setY(), setZ()
+*/
+
+/*!
+ Returns the length of the vector from the origin.
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QVector4D::length() const
+{
+ return qSqrt(xp * xp + yp * yp + zp * zp + wp * wp);
+}
+
+/*!
+ Returns the squared length of the vector from the origin.
+ This is equivalent to the dot product of the vector with itself.
+
+ \sa length(), dotProduct()
+*/
+qreal QVector4D::lengthSquared() const
+{
+ return xp * xp + yp * yp + zp * zp + wp * wp;
+}
+
+/*!
+ Returns the normalized unit vector form of this vector.
+
+ If this vector is null, then a null vector is returned. If the length
+ of the vector is very close to 1, then the vector will be returned as-is.
+ Otherwise the normalized form of the vector of length 1 will be returned.
+
+ \sa length(), normalize()
+*/
+QVector4D QVector4D::normalized() const
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f))
+ return *this;
+ else if (!qFuzzyIsNull(len))
+ return *this / qSqrt(len);
+ else
+ return QVector4D();
+}
+
+/*!
+ Normalizes the currect vector in place. Nothing happens if this
+ vector is a null vector or the length of the vector is very close to 1.
+
+ \sa length(), normalized()
+*/
+void QVector4D::normalize()
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
+ return;
+
+ len = qSqrt(len);
+
+ xp /= len;
+ yp /= len;
+ zp /= len;
+ wp /= len;
+}
+
+/*!
+ \fn QVector4D &QVector4D::operator+=(const QVector4D &vector)
+
+ Adds the given \a vector to this vector and returns a reference to
+ this vector.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator-=(const QVector4D &vector)
+
+ Subtracts the given \a vector from this vector and returns a reference to
+ this vector.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator*=(qreal factor)
+
+ Multiplies this vector's coordinates by the given \a factor, and
+ returns a reference to this vector.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator*=(const QVector4D &vector)
+
+ Multiplies the components of this vector by the corresponding
+ components in \a vector.
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator/=(qreal divisor)
+
+ Divides this vector's coordinates by the given \a divisor, and
+ returns a reference to this vector.
+
+ \sa operator*=()
+*/
+
+/*!
+ Returns the dot product of \a v1 and \a v2.
+*/
+qreal QVector4D::dotProduct(const QVector4D& v1, const QVector4D& v2)
+{
+ return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp + v1.wp * v2.wp;
+}
+
+/*!
+ \fn bool operator==(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns true if \a v1 is equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns true if \a v1 is not equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QVector4D operator+(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns a QVector4D object that is the sum of the given vectors, \a v1
+ and \a v2; each component is added separately.
+
+ \sa QVector4D::operator+=()
+*/
+
+/*!
+ \fn const QVector4D operator-(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns a QVector4D object that is formed by subtracting \a v2 from \a v1;
+ each component is subtracted separately.
+
+ \sa QVector4D::operator-=()
+*/
+
+/*!
+ \fn const QVector4D operator*(qreal factor, const QVector4D &vector)
+ \relates QVector4D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector4D::operator*=()
+*/
+
+/*!
+ \fn const QVector4D operator*(const QVector4D &vector, qreal factor)
+ \relates QVector4D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector4D::operator*=()
+*/
+
+/*!
+ \fn const QVector4D operator*(const QVector4D &v1, const QVector4D& v2)
+ \relates QVector4D
+
+ Returns the vector consisting of the multiplication of the
+ components from \a v1 and \a v2.
+
+ \sa QVector4D::operator*=()
+*/
+
+/*!
+ \fn const QVector4D operator-(const QVector4D &vector)
+ \relates QVector4D
+ \overload
+
+ Returns a QVector4D object that is formed by changing the sign of
+ all three components of the given \a vector.
+
+ Equivalent to \c {QVector4D(0,0,0,0) - vector}.
+*/
+
+/*!
+ \fn const QVector4D operator/(const QVector4D &vector, qreal divisor)
+ \relates QVector4D
+
+ Returns the QVector4D object formed by dividing all four components of
+ the given \a vector by the given \a divisor.
+
+ \sa QVector4D::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2)
+ \relates QVector4D
+
+ Returns true if \a v1 and \a v2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Returns the 2D vector form of this 4D vector, dropping the z and w coordinates.
+
+ \sa toVector2DAffine(), toVector3D(), toPoint()
+*/
+QVector2D QVector4D::toVector2D() const
+{
+ return QVector2D(xp, yp, 1);
+}
+
+/*!
+ Returns the 2D vector form of this 4D vector, dividing the x and y
+ coordinates by the w coordinate and dropping the z coordinate.
+ Returns a null vector if w is zero.
+
+ \sa toVector2D(), toVector3DAffine(), toPoint()
+*/
+QVector2D QVector4D::toVector2DAffine() const
+{
+ if (qIsNull(wp))
+ return QVector2D();
+ return QVector2D(xp / wp, yp / wp, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Returns the 3D vector form of this 4D vector, dropping the w coordinate.
+
+ \sa toVector3DAffine(), toVector2D(), toPoint()
+*/
+QVector3D QVector4D::toVector3D() const
+{
+ return QVector3D(xp, yp, zp, 1);
+}
+
+/*!
+ Returns the 3D vector form of this 4D vector, dividing the x, y, and
+ z coordinates by the w coordinate. Returns a null vector if w is zero.
+
+ \sa toVector3D(), toVector2DAffine(), toPoint()
+*/
+QVector3D QVector4D::toVector3DAffine() const
+{
+ if (qIsNull(wp))
+ return QVector3D();
+ return QVector3D(xp / wp, yp / wp, zp / wp, 1);
+}
+
+#endif
+
+/*!
+ \fn QPoint QVector4D::toPoint() const
+
+ Returns the QPoint form of this 4D vector. The z and w coordinates
+ are dropped.
+
+ \sa toPointF(), toVector2D()
+*/
+
+/*!
+ \fn QPointF QVector4D::toPointF() const
+
+ Returns the QPointF form of this 4D vector. The z and w coordinates
+ are dropped.
+
+ \sa toPoint(), toVector2D()
+*/
+
+/*!
+ Returns the 4D vector as a QVariant.
+*/
+QVector4D::operator QVariant() const
+{
+ return QVariant(QVariant::Vector4D, this);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QVector4D &vector)
+{
+ dbg.nospace() << "QVector4D("
+ << vector.x() << ", " << vector.y() << ", "
+ << vector.z() << ", " << vector.w() << ')';
+ return dbg.space();
+}
+
+#endif
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QVector4D &vector)
+ \relates QVector4D
+
+ Writes the given \a vector to the given \a stream and returns a
+ reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator<<(QDataStream &stream, const QVector4D &vector)
+{
+ stream << double(vector.x()) << double(vector.y())
+ << double(vector.z()) << double(vector.w());
+ return stream;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QVector4D &vector)
+ \relates QVector4D
+
+ Reads a 4D vector from the given \a stream into the given \a vector
+ and returns a reference to the stream.
+
+ \sa {Format of the QDataStream Operators}
+*/
+
+QDataStream &operator>>(QDataStream &stream, QVector4D &vector)
+{
+ double x, y, z, w;
+ stream >> x;
+ stream >> y;
+ stream >> z;
+ stream >> w;
+ vector.setX(qreal(x));
+ vector.setY(qreal(y));
+ vector.setZ(qreal(z));
+ vector.setW(qreal(w));
+ return stream;
+}
+
+#endif // QT_NO_DATASTREAM
+
+#endif // QT_NO_VECTOR4D
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h
new file mode 100644
index 0000000..69ccd30
--- /dev/null
+++ b/src/gui/math3d/qvector4d.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR4D_H
+#define QVECTOR4D_H
+
+#include <QtCore/qpoint.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QMatrix4x4;
+class QVector2D;
+class QVector3D;
+class QQuaternion;
+
+#ifndef QT_NO_VECTOR4D
+
+class Q_GUI_EXPORT QVector4D
+{
+public:
+ QVector4D();
+ QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos);
+ explicit QVector4D(const QPoint& point);
+ explicit QVector4D(const QPointF& point);
+#ifndef QT_NO_VECTOR2D
+ QVector4D(const QVector2D& vector);
+ QVector4D(const QVector2D& vector, qreal zpos, qreal wpos);
+#endif
+#ifndef QT_NO_VECTOR3D
+ QVector4D(const QVector3D& vector);
+ QVector4D(const QVector3D& vector, qreal wpos);
+#endif
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ qreal w() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setZ(qreal z);
+ void setW(qreal w);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QVector4D normalized() const;
+ void normalize();
+
+ QVector4D &operator+=(const QVector4D &vector);
+ QVector4D &operator-=(const QVector4D &vector);
+ QVector4D &operator*=(qreal factor);
+ QVector4D &operator*=(const QVector4D &vector);
+ QVector4D &operator/=(qreal divisor);
+
+ static qreal dotProduct(const QVector4D& v1, const QVector4D& v2);
+
+ friend inline bool operator==(const QVector4D &v1, const QVector4D &v2);
+ friend inline bool operator!=(const QVector4D &v1, const QVector4D &v2);
+ friend inline const QVector4D operator+(const QVector4D &v1, const QVector4D &v2);
+ friend inline const QVector4D operator-(const QVector4D &v1, const QVector4D &v2);
+ friend inline const QVector4D operator*(qreal factor, const QVector4D &vector);
+ friend inline const QVector4D operator*(const QVector4D &vector, qreal factor);
+ friend inline const QVector4D operator*(const QVector4D &v1, const QVector4D& v2);
+ friend inline const QVector4D operator-(const QVector4D &vector);
+ friend inline const QVector4D operator/(const QVector4D &vector, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2);
+
+#ifndef QT_NO_VECTOR2D
+ QVector2D toVector2D() const;
+ QVector2D toVector2DAffine() const;
+#endif
+#ifndef QT_NO_VECTOR3D
+ QVector3D toVector3D() const;
+ QVector3D toVector3DAffine() const;
+#endif
+
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+
+ operator QVariant() const;
+
+private:
+ float xp, yp, zp, wp;
+
+ QVector4D(float xpos, float ypos, float zpos, float wpos, int dummy);
+
+ friend class QVector2D;
+ friend class QVector3D;
+ friend class QQuaternion;
+ friend class QMatrix4x4;
+#ifndef QT_NO_MATRIX4X4
+ friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
+ friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
+#endif
+};
+
+inline QVector4D::QVector4D() : xp(0.0f), yp(0.0f), zp(0.0f), wp(0.0f) {}
+
+inline QVector4D::QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos) : xp(xpos), yp(ypos), zp(zpos), wp(wpos) {}
+
+inline QVector4D::QVector4D(float xpos, float ypos, float zpos, float wpos, int) : xp(xpos), yp(ypos), zp(zpos), wp(wpos) {}
+
+inline QVector4D::QVector4D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f), wp(0.0f) {}
+
+inline QVector4D::QVector4D(const QPointF& point) : xp(point.x()), yp(point.y()), zp(0.0f), wp(0.0f) {}
+
+inline bool QVector4D::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && qIsNull(wp);
+}
+
+inline qreal QVector4D::x() const { return qreal(xp); }
+inline qreal QVector4D::y() const { return qreal(yp); }
+inline qreal QVector4D::z() const { return qreal(zp); }
+inline qreal QVector4D::w() const { return qreal(wp); }
+
+inline void QVector4D::setX(qreal x) { xp = x; }
+inline void QVector4D::setY(qreal y) { yp = y; }
+inline void QVector4D::setZ(qreal z) { zp = z; }
+inline void QVector4D::setW(qreal w) { wp = w; }
+
+inline QVector4D &QVector4D::operator+=(const QVector4D &vector)
+{
+ xp += vector.xp;
+ yp += vector.yp;
+ zp += vector.zp;
+ wp += vector.wp;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator-=(const QVector4D &vector)
+{
+ xp -= vector.xp;
+ yp -= vector.yp;
+ zp -= vector.zp;
+ wp -= vector.wp;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator*=(qreal factor)
+{
+ xp *= factor;
+ yp *= factor;
+ zp *= factor;
+ wp *= factor;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator*=(const QVector4D &vector)
+{
+ xp *= vector.xp;
+ yp *= vector.yp;
+ zp *= vector.zp;
+ wp *= vector.wp;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator/=(qreal divisor)
+{
+ xp /= divisor;
+ yp /= divisor;
+ zp /= divisor;
+ wp /= divisor;
+ return *this;
+}
+
+inline bool operator==(const QVector4D &v1, const QVector4D &v2)
+{
+ return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp && v1.wp == v2.wp;
+}
+
+inline bool operator!=(const QVector4D &v1, const QVector4D &v2)
+{
+ return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp || v1.wp != v2.wp;
+}
+
+inline const QVector4D operator+(const QVector4D &v1, const QVector4D &v2)
+{
+ return QVector4D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp, v1.wp + v2.wp, 1);
+}
+
+inline const QVector4D operator-(const QVector4D &v1, const QVector4D &v2)
+{
+ return QVector4D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp, v1.wp - v2.wp, 1);
+}
+
+inline const QVector4D operator*(qreal factor, const QVector4D &vector)
+{
+ return QVector4D(vector.xp * factor, vector.yp * factor, vector.zp * factor, vector.wp * factor, 1);
+}
+
+inline const QVector4D operator*(const QVector4D &vector, qreal factor)
+{
+ return QVector4D(vector.xp * factor, vector.yp * factor, vector.zp * factor, vector.wp * factor, 1);
+}
+
+inline const QVector4D operator*(const QVector4D &v1, const QVector4D& v2)
+{
+ return QVector4D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp, v1.wp * v2.wp, 1);
+}
+
+inline const QVector4D operator-(const QVector4D &vector)
+{
+ return QVector4D(-vector.xp, -vector.yp, -vector.zp, -vector.wp, 1);
+}
+
+inline const QVector4D operator/(const QVector4D &vector, qreal divisor)
+{
+ return QVector4D(vector.xp / divisor, vector.yp / divisor, vector.zp / divisor, vector.wp / divisor, 1);
+}
+
+inline bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2)
+{
+ return qFuzzyCompare(v1.xp, v2.xp) &&
+ qFuzzyCompare(v1.yp, v2.yp) &&
+ qFuzzyCompare(v1.zp, v2.zp) &&
+ qFuzzyCompare(v1.wp, v2.wp);
+}
+
+inline QPoint QVector4D::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+inline QPointF QVector4D::toPointF() const
+{
+ return QPointF(qreal(xp), qreal(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector4D &vector);
+#endif
+
+#ifndef QT_NO_DATASTREAM
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QVector4D &);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector4D &);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 528559c..feef15a 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -46,7 +46,7 @@ HEADERS += \
SOURCES += \
painting/qbezier.cpp \
- painting/qblendfunctions.cpp \
+ painting/qblendfunctions.cpp \
painting/qbrush.cpp \
painting/qcolor.cpp \
painting/qcolor_p.cpp \
@@ -57,6 +57,7 @@ SOURCES += \
painting/qmatrix.cpp \
painting/qmemrotate.cpp \
painting/qoutlinemapper.cpp \
+ painting/qpaintdevice.cpp \
painting/qpaintengine.cpp \
painting/qpaintengine_alpha.cpp \
painting/qpaintengine_preview.cpp \
@@ -75,13 +76,10 @@ SOURCES += \
painting/qstroker.cpp \
painting/qstylepainter.cpp \
painting/qtessellator.cpp \
- painting/qwindowsurface.cpp \
painting/qtextureglyphcache.cpp \
painting/qtransform.cpp \
+ painting/qwindowsurface.cpp \
- DEFINES += QT_RASTER_IMAGEENGINE
- win32:DEFINES += QT_RASTER_PAINTENGINE
- embedded:DEFINES += QT_RASTER_PAINTENGINE
SOURCES += \
painting/qpaintengine_raster.cpp \
painting/qdrawhelper.cpp \
@@ -100,15 +98,9 @@ win32 {
painting/qcolormap_win.cpp \
painting/qpaintdevice_win.cpp \
painting/qprintengine_win.cpp \
- painting/qprinterinfo_win.cpp \
- painting/qregion_win.cpp
+ painting/qprinterinfo_win.cpp
+
!win32-borland:!wince*:LIBS += -lmsimg32
- contains(QT_CONFIG, direct3d) {
- HEADERS += painting/qpaintengine_d3d_p.h
- SOURCES += painting/qpaintengine_d3d.cpp
- RESOURCES += painting/qpaintengine_d3d.qrc
- LIBS += -ldxguid
- }
}
embedded {
@@ -132,10 +124,6 @@ embedded {
painting/qwindowsurface_raster.cpp \
}
-wince* {
- SOURCES -= painting/qregion_win.cpp
-}
-
unix:x11 {
HEADERS += \
painting/qpaintengine_x11_p.h
@@ -162,14 +150,14 @@ unix:x11 {
painting/qprintengine_mac.mm \
}
-unix:!mac {
+unix:!mac:!symbian {
HEADERS += \
painting/qprinterinfo_unix_p.h
SOURCES += \
painting/qprinterinfo_unix.cpp
}
-win32|x11|mac|embedded {
+win32|x11|mac|embedded|symbian {
SOURCES += painting/qbackingstore.cpp
HEADERS += painting/qbackingstore_p.h
}
@@ -186,6 +174,12 @@ embedded {
painting/qpaintdevice_qws.cpp
}
+symbian {
+ SOURCES += \
+ painting/qregion_s60.cpp \
+ painting/qcolormap_s60.cpp
+}
+
x11|embedded {
contains(QT_CONFIG,qtopia) {
DEFINES += QT_NO_CUPS QT_NO_LPR
@@ -231,7 +225,7 @@ contains(QMAKE_MAC_XARCH, no) {
win32-g++|!win32:!*-icc* {
mmx {
- mmx_compiler.commands = $$QMAKE_CXX -c -Winline
+ mmx_compiler.commands = $$QMAKE_CXX -c -Winline
mac {
mmx_compiler.commands += -Xarch_i386 -mmmx
@@ -362,8 +356,27 @@ embedded {
SOURCES += painting/qwindowsurface_qws.cpp
}
-win32:contains(QT_CONFIG, direct3d) {
- HEADERS += painting/qwindowsurface_d3d_p.h
- SOURCES += painting/qwindowsurface_d3d.cpp
+
+
+symbian {
+ HEADERS += painting/qwindowsurface_s60_p.h
+ SOURCES += painting/qwindowsurface_s60.cpp
+ armccIfdefBlock = \
+ "$${LITERAL_HASH}if defined(ARMV6)" \
+ "MACRO QT_HAVE_ARMV6" \
+ "SOURCEPATH painting" \
+ "SOURCE qblendfunctions_armv6_rvct.s" \
+ "SOURCE qdrawhelper_armv6_rvct.s" \
+ "$${LITERAL_HASH}endif"
+
+ MMP_RULES += armccIfdefBlock
+ QMAKE_CXXFLAGS.ARMCC *= -O3
+}
+
+contains(QT_CONFIG, zlib) {
+ INCLUDEPATH += ../3rdparty/zlib
+} else:!contains(QT_CONFIG, no-zlib) {
+ unix:LIBS_PRIVATE += -lz
+# win32:LIBS += libz.lib
}
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index b428b1f..e82f36e 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -39,6 +39,9 @@
**
****************************************************************************/
+
+#include "qplatformdefs.h"
+
#include "qbackingstore_p.h"
#include <QtCore/qglobal.h>
@@ -556,7 +559,8 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
}
const QPoint offset = widget->mapTo(tlw, QPoint());
- if (qt_region_strictContains(dirty, widget->rect().translated(offset))) {
+ const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
+ if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
if (updateImmediately)
sendUpdateRequest(tlw, updateImmediately);
return; // Already dirty.
@@ -564,7 +568,10 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
if (invalidateBuffer) {
const bool eventAlreadyPosted = !dirty.isEmpty();
- dirty += rgn.translated(offset);
+ if (widget->d_func()->graphicsEffect)
+ dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset);
+ else
+ dirty += rgn.translated(offset);
if (!eventAlreadyPosted || updateImmediately)
sendUpdateRequest(tlw, updateImmediately);
return;
@@ -577,8 +584,12 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
}
if (widget->d_func()->inDirtyList) {
- if (!qt_region_strictContains(widget->d_func()->dirty, widget->rect()))
- widget->d_func()->dirty += rgn;
+ if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) {
+ if (widget->d_func()->graphicsEffect)
+ widget->d_func()->dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect());
+ else
+ widget->d_func()->dirty += rgn;
+ }
} else {
addDirtyWidget(widget, rgn);
}
@@ -622,7 +633,8 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd
return;
}
- const QRect translatedRect(rect.translated(widget->mapTo(tlw, QPoint())));
+ const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
+ const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
if (qt_region_strictContains(dirty, translatedRect)) {
if (updateImmediately)
sendUpdateRequest(tlw, updateImmediately);
@@ -644,8 +656,8 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd
}
if (widget->d_func()->inDirtyList) {
- if (!qt_region_strictContains(widget->d_func()->dirty, rect))
- widget->d_func()->dirty += rect;
+ if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect))
+ widget->d_func()->dirty += widgetRect;
} else {
addDirtyWidget(widget, rect);
}
@@ -761,7 +773,7 @@ void QWidgetBackingStore::paintWindowDecoration()
engine->setSystemClip(decorationRegion.translated(tlwOffset));
QPainter painter(windowSurface->paintDevice());
- painter.setFont(qApp->font());
+ painter.setFont(QApplication::font());
painter.translate(tlwOffset);
const int numDirty = managerPrivate->dirtyRegions.size();
@@ -829,6 +841,10 @@ QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
QWidgetBackingStore::~QWidgetBackingStore()
{
+ for (int c = 0; c < dirtyWidgets.size(); ++c) {
+ resetWidget(dirtyWidgets.at(c));
+ }
+
delete windowSurface;
windowSurface = 0;
delete dirtyOnScreenWidgets;
@@ -840,7 +856,7 @@ QWidgetBackingStore::~QWidgetBackingStore()
void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
{
Q_Q(QWidget);
- if (!q->isVisible())
+ if (!q->isVisible() || (dx == 0 && dy == 0))
return;
QWidget *tlw = q->window();
@@ -877,7 +893,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
&& !isOverlapped(sourceRect) && !isOverlapped(destRect);
if (!accelerateMove) {
- QRegion parentR(parentRect);
+ QRegion parentR(effectiveRectFor(parentRect));
if (!extra || !extra->hasMask) {
parentR -= newRect;
} else {
@@ -1350,7 +1366,7 @@ void QWidgetBackingStore::flush(QWidget *widget, QWindowSurface *surface)
static inline bool discardInvalidateBufferRequest(QWidget *widget, QTLWExtra *tlwExtra)
{
Q_ASSERT(widget);
- if (qApp && qApp->closingDown())
+ if (QApplication::closingDown())
return true;
if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore)
@@ -1381,7 +1397,7 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
const QRect newWidgetRect(q->rect());
const QRect oldWidgetRect(0, 0, oldSize.width(), oldSize.height());
- if (!staticContents) {
+ if (!staticContents || graphicsEffect) {
QRegion staticChildren;
QWidgetBackingStore *bs = 0;
if (offset.isNull() && (bs = maybeBackingStore()))
@@ -1401,19 +1417,19 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
return;
// Invalidate newly exposed area of the parent.
- if (extra && extra->hasMask) {
+ if (!graphicsEffect && extra && extra->hasMask) {
QRegion parentExpose(extra->mask.translated(oldPos));
parentExpose &= QRect(oldPos, oldSize);
if (hasStaticChildren)
parentExpose -= data.crect; // Offset is unchanged, safe to do this.
q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
} else {
- if (hasStaticChildren) {
+ if (hasStaticChildren && !graphicsEffect) {
QRegion parentExpose(QRect(oldPos, oldSize));
parentExpose -= data.crect; // Offset is unchanged, safe to do this.
q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
} else {
- q->parentWidget()->d_func()->invalidateBuffer(QRect(oldPos, oldSize));
+ q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(QRect(oldPos, oldSize)));
}
}
return;
@@ -1471,7 +1487,7 @@ void QWidgetPrivate::invalidateBuffer(const QRegion &rgn)
QRegion wrgn(rgn);
wrgn &= clipRect();
- if (extra && extra->hasMask)
+ if (!graphicsEffect && extra && extra->hasMask)
wrgn &= extra->mask;
if (wrgn.isEmpty())
return;
@@ -1499,7 +1515,7 @@ void QWidgetPrivate::invalidateBuffer(const QRect &rect)
if (wRect.isEmpty())
return;
- if (!extra || !extra->hasMask) {
+ if (graphicsEffect || !extra || !extra->hasMask) {
tlwExtra->backingStore->markDirty(wRect, q, false, true);
return;
}
@@ -1528,7 +1544,8 @@ void QWidgetPrivate::repaint_sys(const QRegion &rgn)
// QGLWidget does not support partial updates if:
// 1) The context is double buffered
// 2) The context is single buffered and auto-fill background is enabled.
- const bool noPartialUpdateSupport = (engine && engine->type() == QPaintEngine::OpenGL)
+ const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
+ || engine->type() == QPaintEngine::OpenGL2))
&& (usesDoubleBufferedGLContext || q->autoFillBackground());
QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
diff --git a/src/gui/painting/qbackingstore_p.h b/src/gui/painting/qbackingstore_p.h
index 9645303..f55cfcd 100644
--- a/src/gui/painting/qbackingstore_p.h
+++ b/src/gui/painting/qbackingstore_p.h
@@ -144,9 +144,13 @@ private:
inline void addDirtyWidget(QWidget *widget, const QRegion &rgn)
{
if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) {
- widget->d_func()->dirty = rgn;
+ QWidgetPrivate *widgetPrivate = widget->d_func();
+ if (widgetPrivate->graphicsEffect)
+ widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect());
+ else
+ widgetPrivate->dirty = rgn;
dirtyWidgets.append(widget);
- widget->d_func()->inDirtyList = true;
+ widgetPrivate->inDirtyList = true;
}
}
diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp
index 4ee54f4..fe1766e 100644
--- a/src/gui/painting/qbezier.cpp
+++ b/src/gui/painting/qbezier.cpp
@@ -127,13 +127,13 @@ static inline void flattenBezierWithoutInflections(QBezier &bez,
qreal dy = bez.y2 - bez.y1;
qreal normalized = qSqrt(dx * dx + dy * dy);
- if (qFuzzyCompare(normalized + 1, 1))
+ if (qFuzzyIsNull(normalized))
break;
qreal d = qAbs(dx * (bez.y3 - bez.y2) - dy * (bez.x3 - bez.x2));
qreal t = qSqrt(4. / 3. * normalized * flatness / d);
- if (t > 1 || qFuzzyCompare(t, (qreal)1.))
+ if (t > 1 || qFuzzyIsNull(t - (qreal)1.))
break;
bez.parameterSplitLeft(t, &left);
p->append(bez.pt1());
@@ -144,19 +144,19 @@ static inline void flattenBezierWithoutInflections(QBezier &bez,
static inline int quadraticRoots(qreal a, qreal b, qreal c,
qreal *x1, qreal *x2)
{
- if (qFuzzyCompare(a + 1, 1)) {
- if (qFuzzyCompare(b + 1, 1))
+ if (qFuzzyIsNull(a)) {
+ if (qFuzzyIsNull(b))
return 0;
*x1 = *x2 = (-c / b);
return 1;
} else {
const qreal det = b * b - 4 * a * c;
- if (qFuzzyCompare(det + 1, 1)) {
+ if (qFuzzyIsNull(det)) {
*x1 = *x2 = -b / (2 * a);
return 1;
}
if (det > 0) {
- if (qFuzzyCompare(b + 1, 1)) {
+ if (qFuzzyIsNull(b)) {
*x2 = qSqrt(-c / a);
*x1 = -(*x2);
return 2;
@@ -187,7 +187,7 @@ static inline bool findInflections(qreal a, qreal b, qreal c,
*t1 = r2;
*t2 = r1;
}
- if (!qFuzzyCompare(a + 1, 1))
+ if (!qFuzzyIsNull(a))
*tCups = 0.5 * (-b / a);
else
*tCups = 2;
@@ -243,7 +243,7 @@ void QBezier::addToPolygonMixed(QPolygonF *polygon) const
qreal b = 6 * (ay * cx - ax * cy);
qreal c = 2 * (by * cx - bx * cy);
- if ((qFuzzyCompare(a + 1, 1) && qFuzzyCompare(b + 1, 1)) ||
+ if ((qFuzzyIsNull(a) && qFuzzyIsNull(b)) ||
(b * b - 4 * a *c) < 0) {
QBezier bez(*this);
flattenBezierWithoutInflections(bez, polygon);
@@ -447,7 +447,7 @@ static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qr
qreal r = 1.0 + prev_normal.x() * next_normal.x()
+ prev_normal.y() * next_normal.y();
- if (qFuzzyCompare(r + 1, 1)) {
+ if (qFuzzyIsNull(r)) {
points_shifted[i] = points[i] + offset * prev_normal;
} else {
qreal k = offset / r;
@@ -477,12 +477,12 @@ static bool addCircle(const QBezier *b, qreal offset, QBezier *o)
normals[0] = QPointF(b->y2 - b->y1, b->x1 - b->x2);
qreal dist = qSqrt(normals[0].x()*normals[0].x() + normals[0].y()*normals[0].y());
- if (qFuzzyCompare(dist + 1, 1))
+ if (qFuzzyIsNull(dist))
return false;
normals[0] /= dist;
normals[2] = QPointF(b->y4 - b->y3, b->x3 - b->x4);
dist = qSqrt(normals[2].x()*normals[2].x() + normals[2].y()*normals[2].y());
- if (qFuzzyCompare(dist + 1, 1))
+ if (qFuzzyIsNull(dist))
return false;
normals[2] /= dist;
@@ -673,10 +673,10 @@ static int IntersectBB(const QBezier &a, const QBezier &b)
#ifdef QDEBUG_BEZIER
static QDebug operator<<(QDebug dbg, const QBezier &bz)
{
- dbg <<"["<<bz.x1<<", "<<bz.y1<<"], "
- <<"["<<bz.x2<<", "<<bz.y2<<"], "
- <<"["<<bz.x3<<", "<<bz.y3<<"], "
- <<"["<<bz.x4<<", "<<bz.y4<<"]";
+ dbg << '[' << bz.x1<< ", " << bz.y1 << "], "
+ << '[' << bz.x2 <<", " << bz.y2 << "], "
+ << '[' << bz.x3 <<", " << bz.y3 << "], "
+ << '[' << bz.x4 <<", " << bz.y4 << ']';
return dbg;
}
#endif
@@ -1022,7 +1022,7 @@ int QBezier::stationaryYPoints(qreal &t0, qreal &t1) const
QList<qreal> result;
- if (qFuzzyCompare(reciprocal + 1, 1)) {
+ if (qFuzzyIsNull(reciprocal)) {
t0 = -b / (2 * a);
return 1;
} else if (reciprocal > 0) {
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index 08f6783..8b25a91 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -104,6 +104,37 @@ struct Blend_RGB16_on_RGB16_ConstAlpha {
quint32 m_ialpha;
};
+struct Blend_ARGB24_on_RGB16_SourceAlpha {
+ inline void write(quint16 *dst, const qargb8565 &src) {
+ const uint alpha = src.alpha();
+ if (alpha) {
+ quint16 s = src.rawValue16();
+ if (alpha < 255)
+ s += BYTE_MUL_RGB16(*dst, 255 - alpha);
+ *dst = s;
+ }
+ }
+};
+
+struct Blend_ARGB24_on_RGB16_SourceAndConstAlpha {
+ inline Blend_ARGB24_on_RGB16_SourceAndConstAlpha(quint32 alpha) {
+ m_alpha = (alpha * 255) >> 8;
+ }
+
+ inline void write(quint16 *dst, qargb8565 src) {
+ src = src.byte_mul(src.alpha(m_alpha));
+ const uint alpha = src.alpha();
+ if (alpha) {
+ quint16 s = src.rawValue16();
+ if (alpha < 255)
+ s += BYTE_MUL_RGB16(*dst, 255 - alpha);
+ *dst = s;
+ }
+ }
+
+ quint32 m_alpha;
+};
+
struct Blend_ARGB32_on_RGB16_SourceAlpha {
inline void write(quint16 *dst, quint32 src) {
const quint8 alpha = qAlpha(src);
@@ -237,6 +268,32 @@ void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
}
}
+void qt_scale_image_argb24_on_rgb16(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha)
+{
+#ifdef QT_DEBUG_DRAW
+ printf("qt_scale_argb24_on_rgb16: dst=(%p, %d), src=(%p, %d), target=(%d, %d), [%d x %d], src=(%d, %d) [%d x %d] alpha=%d\n",
+ destPixels, dbpl, srcPixels, sbpl,
+ targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(),
+ sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height(),
+ const_alpha);
+#endif
+ if (const_alpha == 256) {
+ Blend_ARGB24_on_RGB16_SourceAlpha noAlpha;
+ qt_scale_image_16bit<qargb8565>(destPixels, dbpl, srcPixels, sbpl,
+ targetRect, sourceRect, clip, noAlpha);
+ } else {
+ Blend_ARGB24_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha);
+ qt_scale_image_16bit<qargb8565>(destPixels, dbpl, srcPixels, sbpl,
+ targetRect, sourceRect, clip, constAlpha);
+ }
+}
+
+
void qt_scale_image_argb32_on_rgb16(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
const QRectF &targetRect,
@@ -317,9 +374,9 @@ template <typename T> void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl,
const uchar *src = srcPixels + y * sbpl;
const uchar *srcEnd = src + srcOffset;
while (src < srcEnd) {
-#if defined(QT_ARCH_ARM) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_))
+#if defined(QT_ARCH_ARM) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_))
// non-16-bit aligned memory access is not possible on PowerPC,
- // ARM <v6 (QT_ARCH_ARMV6) & SH
+ // ARM <v6 (QT_ARCH_ARMV6) & SH & AVR32
quint16 spix = (quint16(src[2])<<8) + src[1];
#else
quint16 spix = *(quint16 *) (src + 1);
@@ -513,11 +570,10 @@ static void qt_blend_argb32_on_argb32(uchar *destPixels, int dbpl,
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
uint s = src[x];
- if ((s & 0xff000000) == 0xff000000)
+ if (s >= 0xff000000)
dst[x] = s;
- else {
+ else if (s != 0)
dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
- }
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
@@ -737,7 +793,350 @@ void qt_scale_image_argb32_on_argb32(uchar *destPixels, int dbpl,
}
}
+struct QTransformImageVertex
+{
+ qreal x, y, u, v; // destination coordinates (x, y) and source coordinates (u, v)
+};
+
+template <class SrcT, class DestT, class Blender>
+void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
+ const SrcT *srcPixels, int sbpl,
+ const QTransformImageVertex &topLeft, const QTransformImageVertex &bottomLeft,
+ const QTransformImageVertex &topRight, const QTransformImageVertex &bottomRight,
+ const QRect &sourceRect,
+ const QRect &clip,
+ qreal topY, qreal bottomY,
+ int dudx, int dvdx, int dudy, int dvdy, int u0, int v0,
+ Blender blender)
+{
+ int fromY = qMax(qRound(topY), clip.top());
+ int toY = qMin(qRound(bottomY), clip.top() + clip.height());
+ if (fromY >= toY)
+ return;
+
+ qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y);
+ qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y);
+ int dx_l = int(leftSlope * 0x10000);
+ int dx_r = int(rightSlope * 0x10000);
+ int x_l = int((topLeft.x + (0.5 + fromY - topLeft.y) * leftSlope + 0.5) * 0x10000);
+ int x_r = int((topRight.x + (0.5 + fromY - topRight.y) * rightSlope + 0.5) * 0x10000);
+
+ int fromX, toX, x1, x2, u, v, i, ii;
+ DestT *line;
+ for (int y = fromY; y < toY; ++y) {
+ line = reinterpret_cast<DestT *>(reinterpret_cast<uchar *>(destPixels) + y * dbpl);
+
+ fromX = qMax(x_l >> 16, clip.left());
+ toX = qMin(x_r >> 16, clip.left() + clip.width());
+ if (fromX < toX) {
+ // Because of rounding, we can get source coordinates outside the source image.
+ // Clamp these coordinates to the source rect to avoid segmentation fault and
+ // garbage on the screen.
+
+ // Find the first pixel on the current scan line where the source coordinates are within the source rect.
+ x1 = fromX;
+ u = x1 * dudx + y * dudy + u0;
+ v = x1 * dvdx + y * dvdy + v0;
+ for (; x1 < toX; ++x1) {
+ int uu = u >> 16;
+ int vv = v >> 16;
+ if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
+ && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
+ break;
+ }
+ u += dudx;
+ v += dvdx;
+ }
+
+ // Find the last pixel on the current scan line where the source coordinates are within the source rect.
+ x2 = toX;
+ u = (x2 - 1) * dudx + y * dudy + u0;
+ v = (x2 - 1) * dvdx + y * dvdy + v0;
+ for (; x2 > x1; --x2) {
+ int uu = u >> 16;
+ int vv = v >> 16;
+ if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
+ && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
+ break;
+ }
+ u -= dudx;
+ v -= dvdx;
+ }
+
+ // Set up values at the beginning of the scan line.
+ u = fromX * dudx + y * dudy + u0;
+ v = fromX * dvdx + y * dvdy + v0;
+ line += fromX;
+
+ // Beginning of the scan line, with per-pixel checks.
+ i = x1 - fromX;
+ while (i) {
+ int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
+ int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
+ blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
+ u += dudx;
+ v += dvdx;
+ ++line;
+ --i;
+ }
+
+ // Middle of the scan line, without checks.
+ // Manual loop unrolling.
+ i = x2 - x1;
+ ii = i >> 3;
+ while (ii) {
+ blender.write(&line[0], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[1], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[2], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[3], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[4], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[5], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[6], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[7], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ line += 8;
+ --ii;
+ }
+ switch (i & 7) {
+ case 7: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 6: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 5: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 4: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 3: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 2: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 1: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ }
+
+ // End of the scan line, with per-pixel checks.
+ i = toX - x2;
+ while (i) {
+ int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
+ int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
+ blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
+ u += dudx;
+ v += dvdx;
+ ++line;
+ --i;
+ }
+ }
+ x_l += dx_l;
+ x_r += dx_r;
+ }
+}
+
+template <class SrcT, class DestT, class Blender>
+void qt_transform_image(DestT *destPixels, int dbpl,
+ const SrcT *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ Blender blender)
+{
+ enum Corner
+ {
+ TopLeft,
+ TopRight,
+ BottomRight,
+ BottomLeft
+ };
+
+ // map source rectangle to destination.
+ QTransformImageVertex v[4];
+ v[TopLeft].u = v[BottomLeft].u = sourceRect.left();
+ v[TopLeft].v = v[TopRight].v = sourceRect.top();
+ v[TopRight].u = v[BottomRight].u = sourceRect.right();
+ v[BottomLeft].v = v[BottomRight].v = sourceRect.bottom();
+ targetRectTransform.map(targetRect.left(), targetRect.top(), &v[TopLeft].x, &v[TopLeft].y);
+ targetRectTransform.map(targetRect.right(), targetRect.top(), &v[TopRight].x, &v[TopRight].y);
+ targetRectTransform.map(targetRect.left(), targetRect.bottom(), &v[BottomLeft].x, &v[BottomLeft].y);
+ targetRectTransform.map(targetRect.right(), targetRect.bottom(), &v[BottomRight].x, &v[BottomRight].y);
+
+ // find topmost vertex.
+ int topmost = 0;
+ for (int i = 1; i < 4; ++i) {
+ if (v[i].y < v[topmost].y)
+ topmost = i;
+ }
+ // rearrange array such that topmost vertex is at index 0.
+ switch (topmost) {
+ case 1:
+ {
+ QTransformImageVertex t = v[0];
+ for (int i = 0; i < 3; ++i)
+ v[i] = v[i+1];
+ v[3] = t;
+ }
+ break;
+ case 2:
+ qSwap(v[0], v[2]);
+ qSwap(v[1], v[3]);
+ break;
+ case 3:
+ {
+ QTransformImageVertex t = v[3];
+ for (int i = 3; i > 0; --i)
+ v[i] = v[i-1];
+ v[0] = t;
+ }
+ break;
+ }
+
+ // if necessary, swap vertex 1 and 3 such that 1 is to the left of 3.
+ qreal dx1 = v[1].x - v[0].x;
+ qreal dy1 = v[1].y - v[0].y;
+ qreal dx2 = v[3].x - v[0].x;
+ qreal dy2 = v[3].y - v[0].y;
+ if (dx1 * dy2 - dx2 * dy1 > 0)
+ qSwap(v[1], v[3]);
+
+ QTransformImageVertex u = {v[1].x - v[0].x, v[1].y - v[0].y, v[1].u - v[0].u, v[1].v - v[0].v};
+ QTransformImageVertex w = {v[2].x - v[0].x, v[2].y - v[0].y, v[2].u - v[0].u, v[2].v - v[0].v};
+
+ qreal det = u.x * w.y - u.y * w.x;
+ if (det == 0)
+ return;
+
+ qreal invDet = 1.0 / det;
+ qreal m11, m12, m21, m22, mdx, mdy;
+
+ m11 = (u.u * w.y - u.y * w.u) * invDet;
+ m12 = (u.x * w.u - u.u * w.x) * invDet;
+ m21 = (u.v * w.y - u.y * w.v) * invDet;
+ m22 = (u.x * w.v - u.v * w.x) * invDet;
+ mdx = v[0].u - m11 * v[0].x - m12 * v[0].y;
+ mdy = v[0].v - m21 * v[0].x - m22 * v[0].y;
+
+ int dudx = int(m11 * 0x10000);
+ int dvdx = int(m21 * 0x10000);
+ int dudy = int(m12 * 0x10000);
+ int dvdy = int(m22 * 0x10000);
+ int u0 = qCeil((0.5 * m11 + 0.5 * m12 + mdx) * 0x10000) - 1;
+ int v0 = qCeil((0.5 * m21 + 0.5 * m22 + mdy) * 0x10000) - 1;
+
+ int x1 = qFloor(sourceRect.left());
+ int y1 = qFloor(sourceRect.top());
+ int x2 = qCeil(sourceRect.right());
+ int y2 = qCeil(sourceRect.bottom());
+ QRect sourceRectI(x1, y1, x2 - x1, y2 - y1);
+
+ // rasterize trapezoids.
+ if (v[1].y < v[3].y) {
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[0], v[3], sourceRectI, clip, v[1].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[3].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ } else {
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[3], v[2], sourceRectI, clip, v[3].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[1].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ }
+}
+
+void qt_transform_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha)
+{
+ if (const_alpha == 256) {
+ Blend_RGB16_on_RGB16_NoAlpha noAlpha;
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const quint16 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, noAlpha);
+ } else {
+ Blend_RGB16_on_RGB16_ConstAlpha constAlpha(const_alpha);
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const quint16 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, constAlpha);
+ }
+}
+
+void qt_transform_image_argb24_on_rgb16(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha)
+{
+ if (const_alpha == 256) {
+ Blend_ARGB24_on_RGB16_SourceAlpha noAlpha;
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const qargb8565 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, noAlpha);
+ } else {
+ Blend_ARGB24_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha);
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const qargb8565 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, constAlpha);
+ }
+}
+
+
+void qt_transform_image_argb32_on_rgb16(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha)
+{
+ if (const_alpha == 256) {
+ Blend_ARGB32_on_RGB16_SourceAlpha noAlpha;
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const quint32 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, noAlpha);
+ } else {
+ Blend_ARGB32_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha);
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const quint32 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, constAlpha);
+ }
+}
+
+
+void qt_transform_image_rgb32_on_rgb32(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha)
+{
+ if (const_alpha == 256) {
+ Blend_RGB32_on_RGB32_NoAlpha noAlpha;
+ qt_transform_image(reinterpret_cast<quint32 *>(destPixels), dbpl,
+ reinterpret_cast<const quint32 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, noAlpha);
+ } else {
+ Blend_RGB32_on_RGB32_ConstAlpha constAlpha(const_alpha);
+ qt_transform_image(reinterpret_cast<quint32 *>(destPixels), dbpl,
+ reinterpret_cast<const quint32 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, constAlpha);
+ }
+}
+void qt_transform_image_argb32_on_argb32(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha)
+{
+ if (const_alpha == 256) {
+ Blend_ARGB32_on_ARGB32_SourceAlpha sourceAlpha;
+ qt_transform_image(reinterpret_cast<quint32 *>(destPixels), dbpl,
+ reinterpret_cast<const quint32 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, sourceAlpha);
+ } else {
+ Blend_ARGB32_on_ARGB32_SourceAndConstAlpha constAlpha(const_alpha);
+ qt_transform_image(reinterpret_cast<quint32 *>(destPixels), dbpl,
+ reinterpret_cast<const quint32 *>(srcPixels), sbpl,
+ targetRect, sourceRect, clip, targetRectTransform, constAlpha);
+ }
+}
SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] = {
{ // Format_Invalid
@@ -875,7 +1274,7 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB32,
qt_scale_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied,
qt_scale_image_rgb16_on_rgb16, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
+ qt_scale_image_argb24_on_rgb16, // Format_ARGB8565_Premultiplied,
0, // Format_RGB666,
0, // Format_ARGB6666_Premultiplied,
0, // Format_RGB555,
@@ -1322,5 +1721,295 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] =
}
};
+SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats] = {
+ { // Format_Invalid
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_Mono
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_MonoLSB
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_Indexed8
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_RGB32
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ qt_transform_image_rgb32_on_rgb32, // Format_RGB32,
+ 0, // Format_ARGB32,
+ qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_ARGB32
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_ARGB32_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ qt_transform_image_rgb32_on_rgb32, // Format_RGB32,
+ 0, // Format_ARGB32,
+ qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_RGB16
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ qt_transform_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied,
+ qt_transform_image_rgb16_on_rgb16, // Format_RGB16,
+ qt_transform_image_argb24_on_rgb16, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_ARGB8565_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_RGB666
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_ARGB6666_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_RGB555
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_ARGB8555_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_RGB888
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_RGB444
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ },
+ { // Format_ARGB4444_Premultiplied
+ 0, // Format_Invalid,
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB,
+ 0, // Format_Indexed8,
+ 0, // Format_RGB32,
+ 0, // Format_ARGB32,
+ 0, // Format_ARGB32_Premultiplied,
+ 0, // Format_RGB16,
+ 0, // Format_ARGB8565_Premultiplied,
+ 0, // Format_RGB666,
+ 0, // Format_ARGB6666_Premultiplied,
+ 0, // Format_RGB555,
+ 0, // Format_ARGB8555_Premultiplied,
+ 0, // Format_RGB888,
+ 0, // Format_RGB444,
+ 0 // Format_ARGB4444_Premultiplied,
+ }
+};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qblendfunctions_armv6_rvct.s b/src/gui/painting/qblendfunctions_armv6_rvct.s
new file mode 100644
index 0000000..0d413cb
--- /dev/null
+++ b/src/gui/painting/qblendfunctions_armv6_rvct.s
@@ -0,0 +1,222 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;** Contact: Nokia Corporation (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module of the Qt Toolkit.
+;**
+;** $QT_BEGIN_LICENSE:LGPL$
+;** No Commercial Usage
+;** This file contains pre-release code and may not be distributed.
+;** You may use this file in accordance with the terms and conditions
+;** contained in the either Technology Preview License Agreement or the
+;** Beta Release License Agreement.
+;**
+;** GNU Lesser General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU Lesser
+;** General Public License version 2.1 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.LGPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU Lesser General Public License version 2.1 requirements
+;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;**
+;** In addition, as a special exception, Nokia gives you certain
+;** additional rights. These rights are described in the Nokia Qt LGPL
+;** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;** package.
+;**
+;** GNU General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU
+;** General Public License version 3.0 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.GPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU General Public License version 3.0 requirements will be
+;** met: http://www.gnu.org/copyleft/gpl.html.
+;**
+;** If you are unsure which license is appropriate for your use, please
+;** contact the sales department at http://qt.nokia.com/contact.
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+
+;
+; W A R N I N G
+; -------------
+;
+; This file is not part of the Qt API. It exists purely as an
+; implementation detail. This header file may change from version to
+; version without notice, or even be removed.
+;
+; We mean it.
+;
+
+
+ ARM
+ PRESERVE8
+
+ INCLUDE qdrawhelper_armv6_rvct.inc
+
+
+;-----------------------------------------------------------------------------
+; qt_blend_rgb32_on_rgb32_arm
+;
+; @brief
+;
+; @param dest Destination pixels (r0)
+; @param dbpl Destination bytes per line (r1)
+; @param src Source pixels (r2)
+; @param sbpl Source bytes per line (r3)
+; @param w Width (s0 -> r4)
+; @param h Height (s1 -> r5)
+; @param const_alpha Constant alpha (s2 -> r6)
+;
+;---------------------------------------------------------------------------
+qt_blend_rgb32_on_rgb32_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ ; read arguments off the stack
+ add r8, sp, #10 * 4
+ ldmia r8, {r9-r11}
+
+ ; Reorganize registers
+
+ mov r4, r10
+ mov r5, r1
+ mov r6, r3
+
+ mov r1, r2
+ mov r2, r9
+ mov r3, r11
+
+ ; Now we have registers
+ ; @param dest Destination pixels (r0)
+ ; @param src Source pixels (r1)
+ ; @param w Width (r2)
+ ; @param const_alpha Constant alpha (r3)
+ ; @param h Height (r4)
+ ; @param dbpl Destination bytes per line (r5)
+ ; @param sbpl Source bytes per line (r6)
+
+ cmp r3, #256 ; test if we have fully opaque constant alpha value
+ bne rgb32_blend_const_alpha ; branch if not
+
+rgb32_blend_loop
+
+ subs r4, r4, #1
+ bmi rgb32_blend_exit ; while(h--)
+
+rgb321 PixCpySafe r0, r1, r2
+
+ add r0, r0, r5 ; dest = dest + dbpl
+ add r1, r1, r6 ; src = src + sbpl
+
+ b rgb32_blend_loop
+
+
+rgb32_blend_const_alpha
+
+ ;ldr r14, =ComponentHalf ; load 0x800080 to r14
+ mov r14, #0x800000
+ add r14, r14, #0x80
+
+ sub r3, r3, #1 ; const_alpha -= 1;
+
+rgb32_blend_loop_const_alpha
+
+ subs r4, r4, #1
+ bmi rgb32_blend_exit ; while(h--)
+
+rgb322 BlendRowSafe PixelSourceOverConstAlpha
+
+ add r0, r0, r5 ; dest = dest + dbpl
+ add r1, r1, r6 ; src = src + sbpl
+
+ b rgb32_blend_loop_const_alpha
+
+rgb32_blend_exit
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+
+
+;-----------------------------------------------------------------------------
+; qt_blend_argb32_on_argb32_arm
+;
+; @brief
+;
+; @param dest Destination pixels (r0)
+; @param dbpl Destination bytes per line (r1)
+; @param src Source pixels (r2)
+; @param sbpl Source bytes per line (r3)
+; @param w Width (s0 -> r4)
+; @param h Height (s1 -> r5)
+; @param const_alpha Constant alpha (s2 -> r6)
+;
+;---------------------------------------------------------------------------
+qt_blend_argb32_on_argb32_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ ; read arguments off the stack
+ add r8, sp, #10 * 4
+ ldmia r8, {r9-r11}
+
+ ; Reorganize registers
+
+ mov r4, r10
+ mov r5, r1
+ mov r6, r3
+
+ mov r1, r2
+ mov r2, r9
+ mov r3, r11
+
+ ; Now we have registers
+ ; @param dest Destination pixels (r0)
+ ; @param src Source pixels (r1)
+ ; @param w Width (r2)
+ ; @param const_alpha Constant alpha (r3)
+ ; @param h Height (r4)
+ ; @param dbpl Destination bytes per line (r5)
+ ; @param sbpl Source bytes per line (r6)
+
+ ;ldr r14, =ComponentHalf ; load 0x800080 to r14
+ mov r14, #0x800000
+ add r14, r14, #0x80
+
+ cmp r3, #256 ; test if we have fully opaque constant alpha value
+ bne argb32_blend_const_alpha ; branch if not
+
+argb32_blend_loop
+
+ subs r4, r4, #1
+ bmi argb32_blend_exit ; while(h--)
+
+argb321 BlendRowSafe PixelSourceOver
+
+ add r0, r0, r5 ; dest = dest + dbpl
+ add r1, r1, r6 ; src = src + sbpl
+
+ b argb32_blend_loop
+
+argb32_blend_const_alpha
+
+ sub r3, r3, #1 ; const_alpha -= 1;
+
+argb32_blend_loop_const_alpha
+
+ subs r4, r4, #1
+ bmi argb32_blend_exit ; while(h--)
+
+argb322 BlendRowSafe PixelSourceOverConstAlpha
+
+ add r0, r0, r5 ; dest = dest + dbpl
+ add r1, r1, r6 ; src = src + sbpl
+
+ b argb32_blend_loop_const_alpha
+
+argb32_blend_exit
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+
+ END ; File end
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 5224dc3..1de641b 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -217,11 +217,11 @@ struct QTexturedBrushData : public QBrushData
// returns true if the brush has a pixmap (or bitmap) set as the
// brush texture, false otherwise
-bool qHasPixmapTexture(const QBrush& brush)
+bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush)
{
if (brush.style() != Qt::TexturePattern)
return false;
- QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d);
+ QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d.data());
return tx_data->m_has_pixmap_texture;
}
@@ -230,10 +230,35 @@ struct QGradientBrushData : public QBrushData
QGradient gradient;
};
+struct QBrushDataPointerDeleter
+{
+ static inline void deleteData(QBrushData *d)
+ {
+ switch (d->style) {
+ case Qt::TexturePattern:
+ delete static_cast<QTexturedBrushData*>(d);
+ break;
+ case Qt::LinearGradientPattern:
+ case Qt::RadialGradientPattern:
+ case Qt::ConicalGradientPattern:
+ delete static_cast<QGradientBrushData*>(d);
+ break;
+ default:
+ delete d;
+ }
+ }
+
+ static inline void cleanup(QBrushData *d)
+ {
+ if (d && !d->ref.deref()) {
+ deleteData(d);
+ }
+ }
+};
/*!
\class QBrush
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
\brief The QBrush class defines the fill pattern of shapes drawn
@@ -364,20 +389,20 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style)
{
switch(style) {
case Qt::NoBrush:
- d = nullBrushInstance();
+ d.reset(nullBrushInstance());
d->ref.ref();
if (d->color != color) setColor(color);
return;
case Qt::TexturePattern:
- d = new QTexturedBrushData;
+ d.reset(new QTexturedBrushData);
break;
case Qt::LinearGradientPattern:
case Qt::RadialGradientPattern:
case Qt::ConicalGradientPattern:
- d = new QGradientBrushData;
+ d.reset(new QGradientBrushData);
break;
default:
- d = new QBrushData;
+ d.reset(new QBrushData);
break;
}
d->ref = 1;
@@ -391,8 +416,8 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style)
*/
QBrush::QBrush()
+ : d(nullBrushInstance())
{
- d = nullBrushInstance();
Q_ASSERT(d);
d->ref.ref();
}
@@ -435,7 +460,7 @@ QBrush::QBrush(Qt::BrushStyle style)
if (qbrush_check_type(style))
init(Qt::black, style);
else {
- d = nullBrushInstance();
+ d.reset(nullBrushInstance());
d->ref.ref();
}
}
@@ -451,7 +476,7 @@ QBrush::QBrush(const QColor &color, Qt::BrushStyle style)
if (qbrush_check_type(style))
init(color, style);
else {
- d = nullBrushInstance();
+ d.reset(nullBrushInstance());
d->ref.ref();
}
}
@@ -468,7 +493,7 @@ QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style)
if (qbrush_check_type(style))
init(color, style);
else {
- d = nullBrushInstance();
+ d.reset(nullBrushInstance());
d->ref.ref();
}
}
@@ -510,8 +535,8 @@ QBrush::QBrush(Qt::GlobalColor color, const QPixmap &pixmap)
*/
QBrush::QBrush(const QBrush &other)
+ : d(other.d.data())
{
- d = other.d;
d->ref.ref();
}
@@ -535,7 +560,7 @@ QBrush::QBrush(const QGradient &gradient)
};
init(QColor(), enum_table[gradient.type()]);
- QGradientBrushData *grad = static_cast<QGradientBrushData *>(d);
+ QGradientBrushData *grad = static_cast<QGradientBrushData *>(d.data());
grad->gradient = gradient;
}
@@ -545,24 +570,11 @@ QBrush::QBrush(const QGradient &gradient)
QBrush::~QBrush()
{
- if (!d->ref.deref())
- cleanUp(d);
}
void QBrush::cleanUp(QBrushData *x)
{
- switch (x->style) {
- case Qt::TexturePattern:
- delete static_cast<QTexturedBrushData*>(x);
- break;
- case Qt::LinearGradientPattern:
- case Qt::RadialGradientPattern:
- case Qt::ConicalGradientPattern:
- delete static_cast<QGradientBrushData*>(x);
- break;
- default:
- delete x;
- }
+ QBrushDataPointerDeleter::deleteData(x);
}
@@ -571,38 +583,36 @@ void QBrush::detach(Qt::BrushStyle newStyle)
if (newStyle == d->style && d->ref == 1)
return;
- QBrushData *x;
+ QScopedPointer<QBrushData> x;
switch(newStyle) {
case Qt::TexturePattern: {
QTexturedBrushData *tbd = new QTexturedBrushData;
if (d->style == Qt::TexturePattern) {
- QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d);
+ QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
if (data->m_has_pixmap_texture)
tbd->setPixmap(data->pixmap());
else
tbd->setImage(data->image());
}
- x = tbd;
+ x.reset(tbd);
break;
}
case Qt::LinearGradientPattern:
case Qt::RadialGradientPattern:
case Qt::ConicalGradientPattern:
- x = new QGradientBrushData;
- static_cast<QGradientBrushData *>(x)->gradient =
- static_cast<QGradientBrushData *>(d)->gradient;
+ x.reset(new QGradientBrushData);
+ static_cast<QGradientBrushData *>(x.data())->gradient =
+ static_cast<QGradientBrushData *>(d.data())->gradient;
break;
default:
- x = new QBrushData;
+ x.reset(new QBrushData);
break;
}
x->ref = 1;
x->style = newStyle;
x->color = d->color;
x->transform = d->transform;
- if (!d->ref.deref())
- cleanUp(d);
- d = x;
+ d.reset(x.take());
}
@@ -615,10 +625,11 @@ void QBrush::detach(Qt::BrushStyle newStyle)
QBrush &QBrush::operator=(const QBrush &b)
{
+ if (d == b.d)
+ return *this;
+
b.d->ref.ref();
- if (!d->ref.deref())
- cleanUp(d);
- d = b.d;
+ d.reset(b.d.data());
return *this;
}
@@ -713,7 +724,7 @@ QPixmap *QBrush::pixmap() const
{
if (d->style != Qt::TexturePattern)
return 0;
- QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d);
+ QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d.data());
QPixmap &pixmap = data->pixmap();
return pixmap.isNull() ? 0 : &pixmap;
}
@@ -730,7 +741,7 @@ QPixmap *QBrush::pixmap() const
QPixmap QBrush::texture() const
{
return d->style == Qt::TexturePattern
- ? ((QTexturedBrushData*) d)->pixmap()
+ ? (static_cast<QTexturedBrushData *>(d.data()))->pixmap()
: QPixmap();
}
@@ -748,7 +759,7 @@ void QBrush::setTexture(const QPixmap &pixmap)
{
if (!pixmap.isNull()) {
detach(Qt::TexturePattern);
- QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d);
+ QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
data->setPixmap(pixmap);
} else {
detach(Qt::NoBrush);
@@ -771,7 +782,7 @@ void QBrush::setTexture(const QPixmap &pixmap)
QImage QBrush::textureImage() const
{
return d->style == Qt::TexturePattern
- ? ((QTexturedBrushData *) d)->image()
+ ? (static_cast<QTexturedBrushData *>(d.data()))->image()
: QImage();
}
@@ -796,7 +807,7 @@ void QBrush::setTextureImage(const QImage &image)
{
if (!image.isNull()) {
detach(Qt::TexturePattern);
- QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d);
+ QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
data->setImage(image);
} else {
detach(Qt::NoBrush);
@@ -812,7 +823,7 @@ const QGradient *QBrush::gradient() const
if (d->style == Qt::LinearGradientPattern
|| d->style == Qt::RadialGradientPattern
|| d->style == Qt::ConicalGradientPattern) {
- return &static_cast<const QGradientBrushData *>(d)->gradient;
+ return &static_cast<const QGradientBrushData *>(d.data())->gradient;
}
return 0;
}
@@ -846,7 +857,9 @@ bool QBrush::isOpaque() const
return false;
return true;
} else if (d->style == Qt::TexturePattern) {
- return !texture().hasAlpha();
+ return qHasPixmapTexture(*this)
+ ? !texture().hasAlphaChannel() && !texture().isQBitmap()
+ : !textureImage().hasAlphaChannel();
}
return false;
@@ -923,16 +936,16 @@ bool QBrush::operator==(const QBrush &b) const
if (b.d->style == d->style && b.d->color == d->color) {
switch (d->style) {
case Qt::TexturePattern: {
- QPixmap &us = ((QTexturedBrushData *) d)->pixmap();
- QPixmap &them = ((QTexturedBrushData *) b.d)->pixmap();
+ QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
+ QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
return ((us.isNull() && them.isNull()) || us.cacheKey() == them.cacheKey());
}
case Qt::LinearGradientPattern:
case Qt::RadialGradientPattern:
case Qt::ConicalGradientPattern:
{
- QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d);
- QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d);
+ QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
+ QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
return d1->gradient == d2->gradient;
}
default:
@@ -1151,7 +1164,7 @@ QDataStream &operator>>(QDataStream &s, QBrush &b)
/*!
\class QGradient
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
\brief The QGradient class is used in combination with QBrush to
@@ -1515,7 +1528,7 @@ bool QGradient::operator==(const QGradient &gradient)
/*!
\class QLinearGradient
- \ingroup multimedia
+ \ingroup painting
\brief The QLinearGradient class is used in combination with QBrush to
specify a linear gradient brush.
@@ -1694,7 +1707,7 @@ void QLinearGradient::setFinalStop(const QPointF &stop)
/*!
\class QRadialGradient
- \ingroup multimedia
+ \ingroup painting
\brief The QRadialGradient class is used in combination with QBrush to
specify a radial gradient brush.
@@ -1951,7 +1964,7 @@ void QRadialGradient::setFocalPoint(const QPointF &focalPoint)
/*!
\class QConicalGradient
- \ingroup multimedia
+ \ingroup painting
\brief The QConicalGradient class is used in combination with QBrush to
specify a conical gradient brush.
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index 264def3..2412ab7 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -45,12 +45,22 @@
#include <QtCore/qpair.h>
#include <QtCore/qpoint.h>
#include <QtCore/qvector.h>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qcolor.h>
#include <QtGui/qmatrix.h>
#include <QtGui/qtransform.h>
#include <QtGui/qimage.h>
#include <QtGui/qpixmap.h>
+#if defined(Q_OS_VXWORKS)
+# if defined(m_data)
+# undef m_data
+# endif
+# if defined(m_type)
+# undef m_type
+# endif
+#endif
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -61,6 +71,7 @@ struct QBrushData;
class QPixmap;
class QGradient;
class QVariant;
+struct QBrushDataPointerDeleter;
class Q_GUI_EXPORT QBrush
{
@@ -123,15 +134,15 @@ private:
friend class QRasterPaintEnginePrivate;
friend struct QSpanData;
friend class QPainter;
- friend bool qHasPixmapTexture(const QBrush& brush);
+ friend bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush);
void detach(Qt::BrushStyle newStyle);
void init(const QColor &color, Qt::BrushStyle bs);
- QBrushData *d;
+ QScopedPointer<QBrushData, QBrushDataPointerDeleter> d;
void cleanUp(QBrushData *x);
public:
inline bool isDetached() const;
- typedef QBrushData * DataPtr;
+ typedef QScopedPointer<QBrushData, QBrushDataPointerDeleter> DataPtr;
inline DataPtr &data_ptr() { return d; }
};
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 8cc8226..395995c 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -66,9 +66,9 @@ QT_BEGIN_NAMESPACE
\class QColor
\brief The QColor class provides colors based on RGB, HSV or CMYK values.
- \ingroup multimedia
+ \ingroup painting
\ingroup appearance
- \mainclass
+
A color is normally specified in terms of RGB (red, green, and
blue) components, but it is also possible to specify it in terms
@@ -237,6 +237,15 @@ QT_BEGIN_NAMESPACE
alpha-channel to feature \l {QColor#Alpha-Blended
Drawing}{alpha-blended drawing}.
+ \section1 The HSL Color Model
+
+ HSL is similar to HSV. Instead of value parameter from HSV,
+ HSL has the lightness parameter.
+ The lightness parameter goes from black to color and from color to white.
+ If you go outside at the night its black or dark gray. At day its colorful but
+ if you look in a really strong light a things they are going to white and
+ wash out.
+
\section1 The CMYK Color Model
While the RGB and HSV color models are used for display on
@@ -437,6 +446,9 @@ QColor::QColor(Spec spec)
case Cmyk:
setCmyk(0, 0, 0, 0);
break;
+ case Hsl:
+ setHsl(0, 0, 0, 0);
+ break;
}
}
@@ -678,6 +690,113 @@ void QColor::setHsv(int h, int s, int v, int a)
}
/*!
+ Sets the contents pointed to by \a h, \a s, \a l, and \a a, to the hue,
+ saturation, lightness, and alpha-channel (transparency) components of the
+ color's HSL value.
+
+ These components can be retrieved individually using the hueHslF(),
+ saturationHslF(), lightnessF() and alphaF() functions.
+
+ \sa setHsl()
+*/
+void QColor::getHslF(qreal *h, qreal *s, qreal *l, qreal *a) const
+{
+ if (!h || !s || !l)
+ return;
+
+ if (cspec != Invalid && cspec != Hsl) {
+ toHsl().getHslF(h, s, l, a);
+ return;
+ }
+
+ *h = ct.ahsl.hue == USHRT_MAX ? -1.0 : ct.ahsl.hue / 36000.0;
+ *s = ct.ahsl.saturation / qreal(USHRT_MAX);
+ *l = ct.ahsl.lightness / qreal(USHRT_MAX);
+
+ if (a)
+ *a = ct.ahsl.alpha / qreal(USHRT_MAX);
+}
+
+/*!
+ Sets the contents pointed to by \a h, \a s, \a l, and \a a, to the hue,
+ saturation, lightness, and alpha-channel (transparency) components of the
+ color's HSL value.
+
+ These components can be retrieved individually using the hueHsl(),
+ saturationHsl(), lightness() and alpha() functions.
+
+ \sa setHsl()
+*/
+void QColor::getHsl(int *h, int *s, int *l, int *a) const
+{
+ if (!h || !s || !l)
+ return;
+
+ if (cspec != Invalid && cspec != Hsl) {
+ toHsl().getHsl(h, s, l, a);
+ return;
+ }
+
+ *h = ct.ahsl.hue == USHRT_MAX ? -1 : ct.ahsl.hue / 100;
+ *s = ct.ahsl.saturation >> 8;
+ *l = ct.ahsl.lightness >> 8;
+
+ if (a)
+ *a = ct.ahsl.alpha >> 8;
+}
+
+/*!
+ Sets a HSL color lightness; \a h is the hue, \a s is the saturation, \a l is
+ the lightness and \a a is the alpha component of the HSL color.
+
+ All the values must be in the range 0.0-1.0.
+
+ \sa getHslF(), setHsl()
+*/
+void QColor::setHslF(qreal h, qreal s, qreal l, qreal a)
+{
+ if (((h < 0.0 || h > 1.0) && h != -1.0)
+ || (s < 0.0 || s > 1.0)
+ || (l < 0.0 || l > 1.0)
+ || (a < 0.0 || a > 1.0)) {
+ qWarning("QColor::setHsvF: HSV parameters out of range");
+ return;
+ }
+
+ cspec = Hsl;
+ ct.ahsl.alpha = qRound(a * USHRT_MAX);
+ ct.ahsl.hue = h == -1.0 ? USHRT_MAX : qRound(h * 36000);
+ ct.ahsl.saturation = qRound(s * USHRT_MAX);
+ ct.ahsl.lightness = qRound(l * USHRT_MAX);
+ ct.ahsl.pad = 0;
+}
+
+/*!
+ Sets a HSL color value; \a h is the hue, \a s is the saturation, \a l is
+ the lightness and \a a is the alpha component of the HSL color.
+
+ The saturation, value and alpha-channel values must be in the range 0-255,
+ and the hue value must be greater than -1.
+
+ \sa getHsl(), setHslF()
+*/
+void QColor::setHsl(int h, int s, int l, int a)
+{
+ if (h < -1 || (uint)s > 255 || (uint)l > 255 || (uint)a > 255) {
+ qWarning("QColor::setHsv: HSV parameters out of range");
+ invalidate();
+ return;
+ }
+
+ cspec = Hsl;
+ ct.ahsl.alpha = a * 0x101;
+ ct.ahsl.hue = h == -1 ? USHRT_MAX : (h % 360) * 100;
+ ct.ahsl.saturation = s * 0x101;
+ ct.ahsl.lightness = l * 0x101;
+ ct.ahsl.pad = 0;
+}
+
+/*!
Sets the contents pointed to by \a r, \a g, \a b, and \a a, to the red,
green, blue, and alpha-channel (transparency) components of the color's
RGB value.
@@ -1082,11 +1201,25 @@ void QColor::setBlueF(qreal blue)
/*!
Returns the hue color component of this color.
- \sa hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ The color is implicitly converted to HSV.
+
+ \sa hsvHue(), hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
+
int QColor::hue() const
{
+ return hsvHue();
+}
+
+/*!
+ Returns the hue color component of this color.
+
+ \sa hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+int QColor::hsvHue() const
+{
if (cspec != Invalid && cspec != Hsv)
return toHsv().hue();
return ct.ahsv.hue == USHRT_MAX ? -1 : ct.ahsv.hue / 100;
@@ -1095,11 +1228,25 @@ int QColor::hue() const
/*!
Returns the saturation color component of this color.
- \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ The color is implicitly converted to HSV.
+
+ \sa hsvSaturation(), saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
+
int QColor::saturation() const
{
+ return hsvSaturation();
+}
+
+/*!
+ Returns the saturation color component of this color.
+
+ \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+int QColor::hsvSaturation() const
+{
if (cspec != Invalid && cspec != Hsv)
return toHsv().saturation();
return ct.ahsv.saturation >> 8;
@@ -1121,11 +1268,24 @@ int QColor::value() const
/*!
Returns the hue color component of this color.
- \sa hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color
+ The color is implicitly converted to HSV.
+
+ \sa hsvHueF(), hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
qreal QColor::hueF() const
{
+ return hsvHueF();
+}
+
+/*!
+ Returns the hue color component of this color.
+
+ \sa hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+qreal QColor::hsvHueF() const
+{
if (cspec != Invalid && cspec != Hsv)
return toHsv().hueF();
return ct.ahsv.hue == USHRT_MAX ? -1.0 : ct.ahsv.hue / 36000.0;
@@ -1134,11 +1294,24 @@ qreal QColor::hueF() const
/*!
Returns the saturation color component of this color.
- \sa saturation() getHsvF(), {QColor#The HSV Color Model}{The HSV Color
+ The color is implicitly converted to HSV.
+
+ \sa hsvSaturationF(), saturation() getHsvF(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
qreal QColor::saturationF() const
{
+ return hsvSaturationF();
+}
+
+/*!
+ Returns the saturation color component of this color.
+
+ \sa saturation() getHsvF(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+qreal QColor::hsvSaturationF() const
+{
if (cspec != Invalid && cspec != Hsv)
return toHsv().saturationF();
return ct.ahsv.saturation / qreal(USHRT_MAX);
@@ -1158,6 +1331,79 @@ qreal QColor::valueF() const
}
/*!
+ Returns the hue color component of this color.
+
+ \sa hueHslF(), getHsl()
+*/
+int QColor::hslHue() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().hslHue();
+ return ct.ahsl.hue == USHRT_MAX ? -1 : ct.ahsl.hue / 100;
+}
+
+/*!
+ Returns the saturation color component of this color.
+
+ \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color
+ Model}
+*/
+int QColor::hslSaturation() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().hslSaturation();
+ return ct.ahsl.saturation >> 8;
+}
+
+/*!
+ Returns the lightness color component of this color.
+
+ \sa lightnessF(), getHsl()
+*/
+int QColor::lightness() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().lightness();
+ return ct.ahsl.lightness >> 8;
+}
+
+/*!
+ Returns the hue color component of this color.
+
+ \sa hue(), getHslF()
+*/
+qreal QColor::hslHueF() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().hslHueF();
+ return ct.ahsl.hue == USHRT_MAX ? -1.0 : ct.ahsl.hue / 36000.0;
+}
+
+/*!
+ Returns the saturation color component of this color.
+
+ \sa saturationHsl() getHslF()
+*/
+qreal QColor::hslSaturationF() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().hslSaturationF();
+ return ct.ahsl.saturation / qreal(USHRT_MAX);
+}
+
+/*!
+ Returns the lightness color component of this color.
+
+ \sa value() getHslF()
+*/
+qreal QColor::lightnessF() const
+{
+ if (cspec != Invalid && cspec != Hsl)
+ return toHsl().lightnessF();
+ return ct.ahsl.lightness / qreal(USHRT_MAX);
+}
+
+/*!
Returns the cyan color component of this color.
\sa cyanF(), getCmyk(), {QColor#The CMYK Color Model}{The CMYK
@@ -1337,6 +1583,53 @@ QColor QColor::toRgb() const
}
break;
}
+ case Hsl:
+ {
+ if (ct.ahsl.saturation == 0 || ct.ahsl.hue == USHRT_MAX) {
+ // achromatic case
+ color.ct.argb.red = color.ct.argb.green = color.ct.argb.blue = ct.ahsl.lightness;
+ } else if (ct.ahsl.lightness == 0) {
+ // lightness 0
+ color.ct.argb.red = color.ct.argb.green = color.ct.argb.blue = 0;
+ } else {
+ // chromatic case
+ const qreal h = ct.ahsl.hue == 36000 ? 0 : ct.ahsl.hue / 36000.;
+ const qreal s = ct.ahsl.saturation / qreal(USHRT_MAX);
+ const qreal l = ct.ahsl.lightness / qreal(USHRT_MAX);
+
+ qreal temp2;
+ if (l < qreal(0.5))
+ temp2 = l * (qreal(1.0) + s);
+ else
+ temp2 = l + s - (l * s);
+
+ const qreal temp1 = (qreal(2.0) * l) - temp2;
+ qreal temp3[3] = { h + (qreal(1.0) / qreal(3.0)),
+ h,
+ h - (qreal(1.0) / qreal(3.0)) };
+
+ for (int i = 0; i != 3; ++i) {
+ if (temp3[i] < qreal(0.0))
+ temp3[i] += qreal(1.0);
+ else if (temp3[i] > qreal(1.0))
+ temp3[i] -= qreal(1.0);
+
+ const qreal sixtemp3 = temp3[i] * qreal(6.0);
+ if (sixtemp3 < qreal(1.0))
+ color.ct.array[i+1] = qRound((temp1 + (temp2 - temp1) * sixtemp3) * USHRT_MAX);
+ else if ((temp3[i] * qreal(2.0)) < qreal(1.0))
+ color.ct.array[i+1] = qRound(temp2 * USHRT_MAX);
+ else if ((temp3[i] * qreal(3.0)) < qreal(2.0))
+ color.ct.array[i+1] = qRound((temp1 + (temp2 -temp1) * (qreal(2.0) /qreal(3.0) - temp3[i]) * qreal(6.0)) * USHRT_MAX);
+ else
+ color.ct.array[i+1] = qRound(temp1 * USHRT_MAX);
+ }
+ color.ct.argb.red = color.ct.argb.red == 1 ? 0 : color.ct.argb.red;
+ color.ct.argb.green = color.ct.argb.green == 1 ? 0 : color.ct.argb.green;
+ color.ct.argb.blue = color.ct.argb.blue == 1 ? 0 : color.ct.argb.blue;
+ }
+ break;
+ }
case Cmyk:
{
const qreal c = ct.acmyk.cyan / qreal(USHRT_MAX);
@@ -1387,7 +1680,7 @@ QColor QColor::toHsv() const
const qreal min = Q_MIN_3(r, g, b);
const qreal delta = max - min;
color.ct.ahsv.value = qRound(max * USHRT_MAX);
- if (qFuzzyCompare(delta + 1, 1)) {
+ if (qFuzzyIsNull(delta)) {
// achromatic case, hue is undefined
color.ct.ahsv.hue = USHRT_MAX;
color.ct.ahsv.saturation = 0;
@@ -1414,6 +1707,62 @@ QColor QColor::toHsv() const
}
/*!
+ Creates and returns an HSL QColor based on this color.
+
+ \sa fromHsl(), convertTo(), isValid()
+*/
+QColor QColor::toHsl() const
+{
+ if (!isValid() || cspec == Hsl)
+ return *this;
+
+ if (cspec != Rgb)
+ return toRgb().toHsl();
+
+ QColor color;
+ color.cspec = Hsl;
+ color.ct.ahsl.alpha = ct.argb.alpha;
+ color.ct.ahsl.pad = 0;
+
+ const qreal r = ct.argb.red / qreal(USHRT_MAX);
+ const qreal g = ct.argb.green / qreal(USHRT_MAX);
+ const qreal b = ct.argb.blue / qreal(USHRT_MAX);
+ const qreal max = Q_MAX_3(r, g, b);
+ const qreal min = Q_MIN_3(r, g, b);
+ const qreal delta = max - min;
+ const qreal delta2 = max + min;
+ const qreal lightness = qreal(0.5) * delta2;
+ color.ct.ahsl.lightness = qRound(lightness * USHRT_MAX);
+ if (qFuzzyIsNull(delta)) {
+ // achromatic case, hue is undefined
+ color.ct.ahsl.hue = 0;
+ color.ct.ahsl.saturation = 0;
+ } else {
+ // chromatic case
+ qreal hue = 0;
+ if (lightness < qreal(0.5))
+ color.ct.ahsl.saturation = qRound((delta / delta2) * USHRT_MAX);
+ else
+ color.ct.ahsl.saturation = qRound((delta / (qreal(2.0) - delta2)) * USHRT_MAX);
+ if (qFuzzyCompare(r, max)) {
+ hue = ((g - b) /delta);
+ } else if (qFuzzyCompare(g, max)) {
+ hue = (2.0 + (b - r) / delta);
+ } else if (qFuzzyCompare(b, max)) {
+ hue = (4.0 + (r - g) / delta);
+ } else {
+ Q_ASSERT_X(false, "QColor::toHsv", "internal error");
+ }
+ hue *= 60.0;
+ if (hue < 0.0)
+ hue += 360.0;
+ color.ct.ahsl.hue = qRound(hue * 100);
+ }
+
+ return color;
+}
+
+/*!
Creates and returns a CMYK QColor based on this color.
\sa fromCmyk(), convertTo(), isValid(), {QColor#The CMYK Color
@@ -1441,7 +1790,7 @@ QColor QColor::toCmyk() const
// cmy -> cmyk
const qreal k = qMin(c, qMin(m, y));
- if (!qFuzzyCompare(k,1)) {
+ if (!qFuzzyIsNull(k - 1)) {
c = (c - k) / (1.0 - k);
m = (m - k) / (1.0 - k);
y = (y - k) / (1.0 - k);
@@ -1466,6 +1815,8 @@ QColor QColor::convertTo(QColor::Spec colorSpec) const
return toHsv();
case Cmyk:
return toCmyk();
+ case Hsl:
+ return toHsl();
case Invalid:
break;
}
@@ -1627,6 +1978,70 @@ QColor QColor::fromHsvF(qreal h, qreal s, qreal v, qreal a)
}
/*!
+ Static convenience function that returns a QColor constructed from the HSV
+ color values, \a h (hue), \a s (saturation), \a l (lightness), and \a a
+ (alpha-channel, i.e. transparency).
+
+ The value of \a s, \a l, and \a a must all be in the range 0-255; the value
+ of \a h must be in the range 0-359.
+
+ \sa toHsl(), fromHslF(), isValid()
+*/
+QColor QColor::fromHsl(int h, int s, int l, int a)
+{
+ if (((h < 0 || h >= 360) && h != -1)
+ || s < 0 || s > 255
+ || l < 0 || l > 255
+ || a < 0 || a > 255) {
+ qWarning("QColor::fromHsv: HSV parameters out of range");
+ return QColor();
+ }
+
+ QColor color;
+ color.cspec = Hsl;
+ color.ct.ahsl.alpha = a * 0x101;
+ color.ct.ahsl.hue = h == -1 ? USHRT_MAX : (h % 360) * 100;
+ color.ct.ahsl.saturation = s * 0x101;
+ color.ct.ahsl.lightness = l * 0x101;
+ color.ct.ahsl.pad = 0;
+ return color;
+}
+
+/*!
+ \overload
+
+ Static convenience function that returns a QColor constructed from the HSV
+ color values, \a h (hue), \a s (saturation), \a l (lightness), and \a a
+ (alpha-channel, i.e. transparency).
+
+ All the values must be in the range 0.0-1.0.
+
+ \sa toHsl(), fromHsl(), isValid()
+*/
+QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a)
+{
+ if (((h < 0.0 || h > 1.0) && h != -1.0)
+ || (s < 0.0 || s > 1.0)
+ || (l < 0.0 || l > 1.0)
+ || (a < 0.0 || a > 1.0)) {
+ qWarning("QColor::fromHsvF: HSV parameters out of range");
+ return QColor();
+ }
+
+ QColor color;
+ color.cspec = Hsl;
+ color.ct.ahsl.alpha = qRound(a * USHRT_MAX);
+ color.ct.ahsl.hue = (h == -1.0) ? USHRT_MAX : qRound(h * 36000);
+ if (color.ct.ahsl.hue == 36000)
+ color.ct.ahsl.hue = 0;
+ color.ct.ahsl.saturation = qRound(s * USHRT_MAX);
+ color.ct.ahsl.lightness = qRound(l * USHRT_MAX);
+ color.ct.ahsl.pad = 0;
+ return color;
+}
+
+
+/*!
Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the
cyan, magenta, yellow, black, and alpha-channel (transparency) components
of the color's CMYK value.
@@ -1917,14 +2332,26 @@ QColor &QColor::operator=(Qt::GlobalColor color)
*/
bool QColor::operator==(const QColor &color) const
{
- return (cspec == color.cspec
- && ct.argb.alpha == color.ct.argb.alpha
- && ((cspec == QColor::Hsv
- && ((ct.argb.red % 36000) == (color.ct.argb.red % 36000)))
- || (ct.argb.red == color.ct.argb.red))
- && ct.argb.green == color.ct.argb.green
- && ct.argb.blue == color.ct.argb.blue
- && ct.argb.pad == color.ct.argb.pad);
+ if (cspec == Hsl && cspec == color.cspec) {
+ return (ct.argb.alpha == color.ct.argb.alpha
+ && ((((ct.ahsl.hue % 36000) == (color.ct.ahsl.hue % 36000)))
+ || (ct.ahsl.hue == color.ct.ahsl.hue))
+ && (qAbs(ct.ahsl.saturation - color.ct.ahsl.saturation) < 50
+ || ct.ahsl.lightness == 0
+ || color.ct.ahsl.lightness == 0
+ || ct.ahsl.lightness == USHRT_MAX
+ || color.ct.ahsl.lightness == USHRT_MAX)
+ && (qAbs(ct.ahsl.lightness - color.ct.ahsl.lightness)) < 50);
+ } else {
+ return (cspec == color.cspec
+ && ct.argb.alpha == color.ct.argb.alpha
+ && (((cspec == QColor::Hsv)
+ && ((ct.ahsv.hue % 36000) == (color.ct.ahsv.hue % 36000)))
+ || (ct.ahsv.hue == color.ct.ahsv.hue))
+ && ct.argb.green == color.ct.argb.green
+ && ct.argb.blue == color.ct.argb.blue
+ && ct.argb.pad == color.ct.argb.pad);
+ }
}
/*!
@@ -2022,12 +2449,14 @@ QDebug operator<<(QDebug dbg, const QColor &c)
if (!c.isValid())
dbg.nospace() << "QColor(Invalid)";
else if (c.spec() == QColor::Rgb)
- dbg.nospace() << "QColor(ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ")";
+ dbg.nospace() << "QColor(ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ')';
else if (c.spec() == QColor::Hsv)
- dbg.nospace() << "QColor(AHSV " << c.alphaF() << ", " << c.hueF() << ", " << c.saturationF() << ", " << c.valueF() << ")";
+ dbg.nospace() << "QColor(AHSV " << c.alphaF() << ", " << c.hueF() << ", " << c.saturationF() << ", " << c.valueF() << ')';
else if (c.spec() == QColor::Cmyk)
dbg.nospace() << "QColor(ACMYK " << c.alphaF() << ", " << c.cyanF() << ", " << c.magentaF() << ", " << c.yellowF() << ", "
- << c.blackF()<< ")";
+ << c.blackF()<< ')';
+ else if (c.spec() == QColor::Hsl)
+ dbg.nospace() << "QColor(AHSL " << c.alphaF() << ", " << c.hslHueF() << ", " << c.hslSaturationF() << ", " << c.lightnessF() << ')';
return dbg.space();
#else
@@ -2116,9 +2545,7 @@ QDataStream &operator>>(QDataStream &stream, QColor &color)
return stream;
}
-#endif
-
-
+#endif // QT_NO_DATASTREAM
/*****************************************************************************
diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h
index a95f721..92654c1 100644
--- a/src/gui/painting/qcolor.h
+++ b/src/gui/painting/qcolor.h
@@ -67,7 +67,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QColor &);
class Q_GUI_EXPORT QColor
{
public:
- enum Spec { Invalid, Rgb, Hsv, Cmyk };
+ enum Spec { Invalid, Rgb, Hsv, Cmyk, Hsl };
QColor();
QColor(Qt::GlobalColor color);
@@ -122,10 +122,14 @@ public:
int hue() const; // 0 <= hue < 360
int saturation() const;
+ int hsvHue() const; // 0 <= hue < 360
+ int hsvSaturation() const;
int value() const;
qreal hueF() const; // 0.0 <= hueF < 360.0
qreal saturationF() const;
+ qreal hsvHueF() const; // 0.0 <= hueF < 360.0
+ qreal hsvSaturationF() const;
qreal valueF() const;
void getHsv(int *h, int *s, int *v, int *a = 0) const;
@@ -150,9 +154,24 @@ public:
void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = 0);
void setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0);
+ int hslHue() const; // 0 <= hue < 360
+ int hslSaturation() const;
+ int lightness() const;
+
+ qreal hslHueF() const; // 0.0 <= hueF < 360.0
+ qreal hslSaturationF() const;
+ qreal lightnessF() const;
+
+ void getHsl(int *h, int *s, int *l, int *a = 0) const;
+ void setHsl(int h, int s, int l, int a = 255);
+
+ void getHslF(qreal *h, qreal *s, qreal *l, qreal *a = 0) const;
+ void setHslF(qreal h, qreal s, qreal l, qreal a = 1.0);
+
QColor toRgb() const;
QColor toHsv() const;
QColor toCmyk() const;
+ QColor toHsl() const;
QColor convertTo(Spec colorSpec) const;
@@ -168,6 +187,9 @@ public:
static QColor fromCmyk(int c, int m, int y, int k, int a = 255);
static QColor fromCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0);
+ static QColor fromHsl(int h, int s, int l, int a = 255);
+ static QColor fromHslF(qreal h, qreal s, qreal l, qreal a = 1.0);
+
QColor light(int f = 150) const;
QColor lighter(int f = 150) const;
QColor dark(int f = 200) const;
@@ -234,6 +256,14 @@ private:
ushort yellow;
ushort black;
} acmyk;
+ struct {
+ ushort alpha;
+ ushort hue;
+ ushort saturation;
+ ushort lightness;
+ ushort pad;
+ } ahsl;
+ ushort array[5];
} ct;
friend class QColormap;
diff --git a/src/gui/painting/qcolor_p.cpp b/src/gui/painting/qcolor_p.cpp
index 1fb32fe..fe014df 100644
--- a/src/gui/painting/qcolor_p.cpp
+++ b/src/gui/painting/qcolor_p.cpp
@@ -49,7 +49,7 @@
#include "qrgb.h"
#include "qstringlist.h"
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qguifunctions_wince.h"
#endif
QT_BEGIN_NAMESPACE
diff --git a/src/gui/painting/qcolormap.qdoc b/src/gui/painting/qcolormap.qdoc
new file mode 100644
index 0000000..b4cb2f3
--- /dev/null
+++ b/src/gui/painting/qcolormap.qdoc
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QColormap
+ \ingroup painting
+
+ \brief The QColormap class maps device independent QColors to device
+ dependent pixel values.
+*/
+
+/*! \enum QColormap::Mode
+
+ This enum describes how QColormap maps device independent RGB
+ values to device dependent pixel values.
+
+ \value Direct Pixel values are derived directly from the RGB
+ values, also known as "True Color."
+
+ \value Indexed Pixel values represent indexes into a vector of
+ available colors, i.e. QColormap uses the index of the color that
+ most closely matches an RGB value.
+
+ \value Gray Similar to \c Indexed, pixel values represent a vector
+ of available gray tones. QColormap uses the index of the gray
+ tone that most closely matches the computed gray tone of an RGB
+ value.
+*/
+
+/*!
+ \fn QColormap QColormap::instance(int screen)
+
+ Returns the colormap for the specified \a screen. If \a screen is
+ -1, this function returns the colormap for the default screen.
+*/
+
+/*!
+ \fn QColormap::QColormap(const QColormap &colormap)
+
+ Constructs a copy of another \a colormap.
+*/
+
+/*!
+ \fn QColormap::~QColormap()
+
+ Destroys the colormap.
+*/
+
+/*!
+ \fn int QColormap::size() const
+
+ Returns the size of the colormap for \c Indexed and \c Gray modes;
+ Returns -1 for \c Direct mode.
+
+ \sa colormap()
+*/
+
+/*!
+ \fn uint QColormap::pixel(const QColor &color) const
+
+ Returns a device dependent pixel value for the \a color.
+
+ \sa colorAt()
+*/
+
+/*!
+ \fn int QColormap::depth() const
+
+ Returns the depth of the device.
+
+ \sa size()
+*/
+
+/*!
+ \fn QColormap::Mode QColormap::mode() const
+
+ Returns the mode of this colormap.
+
+ \sa QColormap::Mode
+*/
+
+/*!
+ \fn const QColor QColormap::colorAt(uint pixel) const
+
+ Returns a QColor for the \a pixel.
+
+ \sa pixel()
+*/
+
+/*!
+ \fn const QVector<QColor> QColormap::colormap() const
+
+ Returns a vector of colors which represents the devices colormap
+ for \c Indexed and \c Gray modes. This function returns an empty
+ vector for \c Direct mode.
+
+ \sa size()
+*/
+
+/*! \fn HPALETTE QColormap::hPal()
+
+ This function is only available on Windows.
+
+ Returns an handle to the HPALETTE used by this colormap. If no
+ HPALETTE is being used, this function returns zero.
+*/
+
+/*! \since 4.2
+
+ \fn QColormap &QColormap::operator=(const QColormap &colormap)
+
+ Assigns the given \a colormap to \e this color map and returns
+ a reference to \e this color map.
+*/
diff --git a/src/gui/painting/qcolormap_s60.cpp b/src/gui/painting/qcolormap_s60.cpp
new file mode 100644
index 0000000..7a27c94
--- /dev/null
+++ b/src/gui/painting/qcolormap_s60.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcolormap.h"
+#include "qcolor.h"
+
+QT_BEGIN_NAMESPACE
+
+class QColormapPrivate
+{
+public:
+ inline QColormapPrivate()
+ : ref(1)
+ { }
+
+ QAtomicInt ref;
+};
+
+void QColormap::initialize()
+{
+}
+
+void QColormap::cleanup()
+{
+}
+
+QColormap QColormap::instance(int)
+{
+ return QColormap();
+}
+
+QColormap::QColormap() : d(new QColormapPrivate)
+{}
+
+QColormap::QColormap(const QColormap &colormap) :d (colormap.d)
+{ d->ref.ref(); }
+
+QColormap::~QColormap()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+QColormap::Mode QColormap::mode() const
+{ return QColormap::Direct; }
+
+int QColormap::depth() const
+{
+ return 32;
+}
+
+int QColormap::size() const
+{
+ return -1;
+}
+
+uint QColormap::pixel(const QColor &color) const
+{ return color.rgba(); }
+
+const QColor QColormap::colorAt(uint pixel) const
+{ return QColor(pixel); }
+
+const QVector<QColor> QColormap::colormap() const
+{ return QVector<QColor>(); }
+
+QColormap &QColormap::operator=(const QColormap &colormap)
+{ qAtomicAssign(d, colormap.d); return *this; }
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolormap_win.cpp b/src/gui/painting/qcolormap_win.cpp
index 13ad246..6052fc9 100644
--- a/src/gui/painting/qcolormap_win.cpp
+++ b/src/gui/painting/qcolormap_win.cpp
@@ -44,7 +44,7 @@
#include "qvector.h"
#include "qt_windows.h"
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qguifunctions_wince.h"
#endif
diff --git a/src/gui/painting/qcssutil.cpp b/src/gui/painting/qcssutil.cpp
index e83d750..7a541c5 100644
--- a/src/gui/painting/qcssutil.cpp
+++ b/src/gui/painting/qcssutil.cpp
@@ -353,7 +353,7 @@ void qDrawBorder(QPainter *p, const QRect &rect, const QCss::BorderStyle *styles
qNormalizeRadii(rect, radii, &tlr, &trr, &blr, &brr);
// Drawn in increasing order of precendence
- if (styles[BottomEdge] != BorderStyle_None) {
+ if (styles[BottomEdge] != BorderStyle_None && borders[BottomEdge] > 0) {
qreal dw1 = (blr.width() || paintsOver(styles, colors, BottomEdge, LeftEdge)) ? 0 : borders[LeftEdge];
qreal dw2 = (brr.width() || paintsOver(styles, colors, BottomEdge, RightEdge)) ? 0 : borders[RightEdge];
qreal x1 = br.x() + blr.width();
@@ -365,7 +365,7 @@ void qDrawBorder(QPainter *p, const QRect &rect, const QCss::BorderStyle *styles
if (blr.width() || brr.width())
qDrawRoundedCorners(p, x1, y1, x2, y2, blr, brr, BottomEdge, styles[BottomEdge], colors[BottomEdge]);
}
- if (styles[RightEdge] != BorderStyle_None) {
+ if (styles[RightEdge] != BorderStyle_None && borders[RightEdge] > 0) {
qreal dw1 = (trr.height() || paintsOver(styles, colors, RightEdge, TopEdge)) ? 0 : borders[TopEdge];
qreal dw2 = (brr.height() || paintsOver(styles, colors, RightEdge, BottomEdge)) ? 0 : borders[BottomEdge];
qreal x1 = br.x() + br.width() - borders[RightEdge];
@@ -377,7 +377,7 @@ void qDrawBorder(QPainter *p, const QRect &rect, const QCss::BorderStyle *styles
if (trr.height() || brr.height())
qDrawRoundedCorners(p, x1, y1, x2, y2, trr, brr, RightEdge, styles[RightEdge], colors[RightEdge]);
}
- if (styles[LeftEdge] != BorderStyle_None) {
+ if (styles[LeftEdge] != BorderStyle_None && borders[LeftEdge] > 0) {
qreal dw1 = (tlr.height() || paintsOver(styles, colors, LeftEdge, TopEdge)) ? 0 : borders[TopEdge];
qreal dw2 = (blr.height() || paintsOver(styles, colors, LeftEdge, BottomEdge)) ? 0 : borders[BottomEdge];
qreal x1 = br.x();
@@ -389,7 +389,7 @@ void qDrawBorder(QPainter *p, const QRect &rect, const QCss::BorderStyle *styles
if (tlr.height() || blr.height())
qDrawRoundedCorners(p, x1, y1, x2, y2, tlr, blr, LeftEdge, styles[LeftEdge], colors[LeftEdge]);
}
- if (styles[TopEdge] != BorderStyle_None) {
+ if (styles[TopEdge] != BorderStyle_None && borders[TopEdge] > 0) {
qreal dw1 = (tlr.width() || paintsOver(styles, colors, TopEdge, LeftEdge)) ? 0 : borders[LeftEdge];
qreal dw2 = (trr.width() || paintsOver(styles, colors, TopEdge, RightEdge)) ? 0 : borders[RightEdge];
qreal x1 = br.x() + tlr.width();
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 1f0280e..ab192c5 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -38,15 +38,18 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
#include <private/qdrawhelper_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qpainter_p.h>
#include <private/qdrawhelper_x86_p.h>
+#include <private/qdrawhelper_armv6_p.h>
#include <private/qmath_p.h>
#include <qmath.h>
QT_BEGIN_NAMESPACE
+
#define MASK(src, a) src = BYTE_MUL(src, a)
#if defined(Q_OS_IRIX) && defined(Q_CC_GNU) && __GNUC__ == 3 && __GNUC__ < 4 && QT_POINTER_SIZE == 8
@@ -157,46 +160,9 @@ static uint * QT_FASTCALL destFetchRGB16(uint *buffer, QRasterBuffer *rasterBuff
return buffer;
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-template <typename EnumType, int value>
-class QEnumToType
-{
-public:
- inline EnumType operator()() const
- {
- return EnumType(value);
- }
-};
-template <QImage::Format format>
-class QImageFormatToType
-{
-public:
- inline QImage::Format operator()() const
- {
- return format;
- }
-};
-// Would have used QEnumToType instead of creating a specialized version for QImageFormatToType,
-// but that causes internal compiler error on VC6
-#define Q_TEMPLATE_IMAGEFORMAT_FIX(format) , const QImageFormatToType<format> &imageFormatType
-#define Q_TEMPLATE_IMAGEFORMAT_CALL(format) , QImageFormatToType<format>()
-#define Q_TEMPLATE_ENUM_FIX(Type, Value) , const QEnumToType<Type, Value> &enumTemplateType
-#define Q_TEMPLATE_ENUM_CALL(Type, Value) , QEnumToType<Type, Value>()
-#define Q_TEMPLATE_FIX(Type) , const QTypeInfo<Type> &templateType
-#define Q_TEMPLATE_CALL(Type) , QTypeInfo<Type>()
-#else
-#define Q_TEMPLATE_IMAGEFORMAT_FIX(format)
-#define Q_TEMPLATE_IMAGEFORMAT_CALL(format)
-#define Q_TEMPLATE_ENUM_FIX(Type, Value)
-#define Q_TEMPLATE_ENUM_CALL(Type, Value)
-#define Q_TEMPLATE_FIX(Type)
-#define Q_TEMPLATE_CALL(Type)
-#endif
-
template <class DST>
Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer,
- int x, int y, int length
- Q_TEMPLATE_FIX(DST))
+ int x, int y, int length)
{
const DST *src = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x;
quint32 *dest = reinterpret_cast<quint32*>(buffer);
@@ -205,28 +171,7 @@ Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuf
return buffer;
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-#define DEST_FETCH_DECL(DST) \
- static uint * QT_FASTCALL destFetch_##DST(uint *buffer, \
- QRasterBuffer *rasterBuffer, \
- int x, int y, int length) \
- { \
- return destFetch<DST>(buffer, rasterBuffer, x, y, length Q_TEMPLATE_CALL(DST)); \
- }
-
-DEST_FETCH_DECL(qargb8565)
-DEST_FETCH_DECL(qrgb666)
-DEST_FETCH_DECL(qargb6666)
-DEST_FETCH_DECL(qrgb555)
-DEST_FETCH_DECL(qrgb888)
-DEST_FETCH_DECL(qargb8555)
-DEST_FETCH_DECL(qrgb444)
-DEST_FETCH_DECL(qargb4444)
-#undef DEST_FETCH_DECL
-# define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch_##Arg
-#else // !VC6 && !VC2002
# define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg>
-#endif
static const DestFetchProc destFetchProc[QImage::NImageFormats] =
{
@@ -366,8 +311,7 @@ static void QT_FASTCALL destStoreRGB16(QRasterBuffer *rasterBuffer, int x, int y
template <class DST>
Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer,
int x, int y,
- const uint *buffer, int length
- Q_TEMPLATE_FIX(DST))
+ const uint *buffer, int length)
{
DST *dest = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x;
const quint32p *src = reinterpret_cast<const quint32p*>(buffer);
@@ -375,28 +319,7 @@ Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffe
*dest++ = DST(*src++);
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-# define DEST_STORE_DECL(DST) \
- static void QT_FASTCALL destStore_##DST(QRasterBuffer *rasterBuffer, \
- int x, int y, \
- const uint *buffer, int length) \
- { \
- destStore<DST>(rasterBuffer, x, y, buffer, length Q_TEMPLATE_CALL(DST)); \
- }
-
-DEST_STORE_DECL(qargb8565)
-DEST_STORE_DECL(qrgb555)
-DEST_STORE_DECL(qrgb666)
-DEST_STORE_DECL(qargb6666)
-DEST_STORE_DECL(qargb8555)
-DEST_STORE_DECL(qrgb888)
-DEST_STORE_DECL(qrgb444)
-DEST_STORE_DECL(qargb4444)
-# undef DEST_FETCH_DECL
-# define SPANFUNC_POINTER_DESTSTORE(DEST) destStore_##DEST
-#else // !VC6 && !VC2002
# define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST>
-#endif
static const DestStoreProc destStoreProc[QImage::NImageFormats] =
{
@@ -425,10 +348,8 @@ static const DestStoreProc destStoreProc[QImage::NImageFormats] =
We need 5 fetch methods per surface type:
untransformed
- transformed
- transformed tiled
- transformed bilinear
- transformed bilinear tiled
+ transformed (tiled and not tiled)
+ transformed bilinear (tiled and not tiled)
We don't need bounds checks for untransformed, but we need them for the other ones.
@@ -436,14 +357,12 @@ static const DestStoreProc destStoreProc[QImage::NImageFormats] =
*/
template <QImage::Format format>
-Q_STATIC_TEMPLATE_FUNCTION uint QT_FASTCALL qt_fetchPixel(const uchar *scanLine, int x, const QVector<QRgb> *rgb
- Q_TEMPLATE_IMAGEFORMAT_FIX(format));
+Q_STATIC_TEMPLATE_FUNCTION uint QT_FASTCALL qt_fetchPixel(const uchar *scanLine, int x, const QVector<QRgb> *rgb);
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_Mono>(const uchar *scanLine,
- int x, const QVector<QRgb> *rgb
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_Mono))
+ int x, const QVector<QRgb> *rgb)
{
bool pixel = scanLine[x>>3] & (0x80 >> (x & 7));
if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0));
@@ -453,8 +372,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_Mono>(const uchar *scanLine,
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_MonoLSB>(const uchar *scanLine,
- int x, const QVector<QRgb> *rgb
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_MonoLSB))
+ int x, const QVector<QRgb> *rgb)
{
bool pixel = scanLine[x>>3] & (0x1 << (x & 7));
if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0));
@@ -464,8 +382,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_MonoLSB>(const uchar *scanLine,
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_Indexed8>(const uchar *scanLine,
- int x, const QVector<QRgb> *rgb
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_Indexed8))
+ int x, const QVector<QRgb> *rgb)
{
return PREMUL(rgb->at(scanLine[x]));
}
@@ -473,8 +390,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_Indexed8>(const uchar *scanLine,
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32>(const uchar *scanLine,
- int x, const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB32))
+ int x, const QVector<QRgb> *)
{
return PREMUL(((const uint *)scanLine)[x]);
}
@@ -482,8 +398,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32>(const uchar *scanLine,
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32_Premultiplied>(const uchar *scanLine,
- int x, const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB32_Premultiplied))
+ int x, const QVector<QRgb> *)
{
return ((const uint *)scanLine)[x];
}
@@ -491,8 +406,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32_Premultiplied>(const uchar
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB16>(const uchar *scanLine,
- int x, const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB16))
+ int x, const QVector<QRgb> *)
{
return qConvertRgb16To32(((const ushort *)scanLine)[x]);
}
@@ -501,8 +415,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8565_Premultiplied>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB8565_Premultiplied))
+ const QVector<QRgb> *)
{
const qargb8565 color = reinterpret_cast<const qargb8565*>(scanLine)[x];
return qt_colorConvert<quint32, qargb8565>(color, 0);
@@ -512,8 +425,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB666>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB666))
+ const QVector<QRgb> *)
{
const qrgb666 color = reinterpret_cast<const qrgb666*>(scanLine)[x];
return qt_colorConvert<quint32, qrgb666>(color, 0);
@@ -523,8 +435,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB6666_Premultiplied>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB6666_Premultiplied))
+ const QVector<QRgb> *)
{
const qargb6666 color = reinterpret_cast<const qargb6666*>(scanLine)[x];
return qt_colorConvert<quint32, qargb6666>(color, 0);
@@ -534,8 +445,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB555>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB555))
+ const QVector<QRgb> *)
{
const qrgb555 color = reinterpret_cast<const qrgb555*>(scanLine)[x];
return qt_colorConvert<quint32, qrgb555>(color, 0);
@@ -545,8 +455,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8555_Premultiplied>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB8555_Premultiplied))
+ const QVector<QRgb> *)
{
const qargb8555 color = reinterpret_cast<const qargb8555*>(scanLine)[x];
return qt_colorConvert<quint32, qargb8555>(color, 0);
@@ -556,8 +465,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB888>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB888))
+ const QVector<QRgb> *)
{
const qrgb888 color = reinterpret_cast<const qrgb888*>(scanLine)[x];
return qt_colorConvert<quint32, qrgb888>(color, 0);
@@ -567,8 +475,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB444>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB444))
+ const QVector<QRgb> *)
{
const qrgb444 color = reinterpret_cast<const qrgb444*>(scanLine)[x];
return qt_colorConvert<quint32, qrgb444>(color, 0);
@@ -578,47 +485,24 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB4444_Premultiplied>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB4444_Premultiplied))
+ const QVector<QRgb> *)
{
const qargb4444 color = reinterpret_cast<const qargb4444*>(scanLine)[x];
return qt_colorConvert<quint32, qargb4444>(color, 0);
}
-typedef uint (QT_FASTCALL *FetchPixelProc)(const uchar *scanLine, int x, const QVector<QRgb> *);
-
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-
-// explicit template instantiations needed to compile with VC6 and VC2002
-
-#define SPANFUNC_INSTANTIATION_FETCHPIXEL(Arg) \
- static inline uint fetchPixel_##Arg(const uchar * scanLine, int x, const QVector<QRgb> * rgb) \
-{ \
- return qt_fetchPixel<QImage::Arg>(scanLine, x, rgb Q_TEMPLATE_IMAGEFORMAT_CALL(QImage::Arg)); \
+template<>
+Q_STATIC_TEMPLATE_SPECIALIZATION
+uint QT_FASTCALL qt_fetchPixel<QImage::Format_Invalid>(const uchar *,
+ int ,
+ const QVector<QRgb> *)
+{
+ return 0;
}
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_Mono);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_MonoLSB);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_Indexed8);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB32_Premultiplied);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB32);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB16);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB8565_Premultiplied);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB666);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB6666_Premultiplied);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB555);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB8555_Premultiplied);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB888);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB444);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB4444_Premultiplied);
-
-#undef SPANFUNC_INSTANTIATION_FETCHPIXEL
-
-#define SPANFUNC_POINTER_FETCHPIXEL(Arg) fetchPixel_##Arg
+typedef uint (QT_FASTCALL *FetchPixelProc)(const uchar *scanLine, int x, const QVector<QRgb> *);
-#else // !VC6 && !VC2002
-# define SPANFUNC_POINTER_FETCHPIXEL(Arg) qt_fetchPixel<QImage::Arg>
-#endif
+#define SPANFUNC_POINTER_FETCHPIXEL(Arg) qt_fetchPixel<QImage::Arg>
static const FetchPixelProc fetchPixelProc[QImage::NImageFormats] =
@@ -653,11 +537,11 @@ enum TextureBlendType {
template <QImage::Format format>
Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL qt_fetchUntransformed(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length Q_TEMPLATE_IMAGEFORMAT_FIX(format))
+ int y, int x, int length)
{
const uchar *scanLine = data->texture.scanLine(y);
for (int i = 0; i < length; ++i)
- buffer[i] = qt_fetchPixel<format>(scanLine, x + i, data->texture.colorTable Q_TEMPLATE_IMAGEFORMAT_CALL(format));
+ buffer[i] = qt_fetchPixel<format>(scanLine, x + i, data->texture.colorTable);
return buffer;
}
@@ -665,13 +549,15 @@ template <>
Q_STATIC_TEMPLATE_SPECIALIZATION const uint * QT_FASTCALL
qt_fetchUntransformed<QImage::Format_ARGB32_Premultiplied>(uint *, const Operator *,
const QSpanData *data,
- int y, int x, int Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB32_Premultiplied))
+ int y, int x, int)
{
const uchar *scanLine = data->texture.scanLine(y);
return ((const uint *)scanLine) + x;
}
-static const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data,
+template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */
+Q_STATIC_TEMPLATE_FUNCTION
+const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data,
int y, int x, int length)
{
FetchPixelProc fetch = fetchPixelProc[data->texture.format];
@@ -698,84 +584,23 @@ static const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *,
int px = fx >> 16;
int py = fy >> 16;
- bool out = (px < 0) || (px >= image_width)
- || (py < 0) || (py >= image_height);
-
- const uchar *scanLine = data->texture.scanLine(py);
- *b = out ? uint(0) : fetch(scanLine, px, data->texture.colorTable);
- fx += fdx;
- fy += fdy;
- ++b;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
+ if (blendType == BlendTransformedTiled) {
+ px %= image_width;
+ py %= image_height;
+ if (px < 0) px += image_width;
+ if (py < 0) py += image_height;
- qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
- qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
- qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
-
- while (b < end) {
- const qreal iw = fw == 0 ? 1 : 1 / fw;
- const qreal tx = fx * iw;
- const qreal ty = fy * iw;
- const int px = int(tx) - (tx < 0);
- const int py = int(ty) - (ty < 0);
-
- bool out = (px < 0) || (px >= image_width)
- || (py < 0) || (py >= image_height);
-
- const uchar *scanLine = data->texture.scanLine(py);
- *b = out ? uint(0) : fetch(scanLine, px, data->texture.colorTable);
- fx += fdx;
- fy += fdy;
- fw += fdw;
- //force increment to avoid /0
- if (!fw) {
- fw += fdw;
+ const uchar *scanLine = data->texture.scanLine(py);
+ *b = fetch(scanLine, px, data->texture.colorTable);
+ } else {
+ if ((px < 0) || (px >= image_width)
+ || (py < 0) || (py >= image_height)) {
+ *b = uint(0);
+ } else {
+ const uchar *scanLine = data->texture.scanLine(py);
+ *b = fetch(scanLine, px, data->texture.colorTable);
+ }
}
- ++b;
- }
- }
-
- return buffer;
-}
-
-static const uint * QT_FASTCALL fetchTransformedTiled(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
-{
- FetchPixelProc fetch = fetchPixelProc[data->texture.format];
-
- int image_width = data->texture.width;
- int image_height = data->texture.height;
-
- const qreal cx = x + 0.5;
- const qreal cy = y + 0.5;
-
- const uint *end = buffer + length;
- uint *b = buffer;
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- int fdx = (int)(data->m11 * fixed_scale);
- int fdy = (int)(data->m12 * fixed_scale);
-
- int fx = int((data->m21 * cy
- + data->m11 * cx + data->dx) * fixed_scale);
- int fy = int((data->m22 * cy
- + data->m12 * cx + data->dy) * fixed_scale);
-
- while (b < end) {
- int px = fx >> 16;
- int py = fy >> 16;
-
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
-
- const uchar *scanLine = data->texture.scanLine(py);
- *b = fetch(scanLine, px, data->texture.colorTable);
fx += fdx;
fy += fdy;
++b;
@@ -796,13 +621,23 @@ static const uint * QT_FASTCALL fetchTransformedTiled(uint *buffer, const Operat
int px = int(tx) - (tx < 0);
int py = int(ty) - (ty < 0);
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
+ if (blendType == BlendTransformedTiled) {
+ px %= image_width;
+ py %= image_height;
+ if (px < 0) px += image_width;
+ if (py < 0) py += image_height;
- const uchar *scanLine = data->texture.scanLine(py);
- *b = fetch(scanLine, px, data->texture.colorTable);
+ const uchar *scanLine = data->texture.scanLine(py);
+ *b = fetch(scanLine, px, data->texture.colorTable);
+ } else {
+ if ((px < 0) || (px >= image_width)
+ || (py < 0) || (py >= image_height)) {
+ *b = uint(0);
+ } else {
+ const uchar *scanLine = data->texture.scanLine(py);
+ *b = fetch(scanLine, px, data->texture.colorTable);
+ }
+ }
fx += fdx;
fy += fdy;
fw += fdw;
@@ -817,10 +652,20 @@ static const uint * QT_FASTCALL fetchTransformedTiled(uint *buffer, const Operat
return buffer;
}
-static const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
+template<TextureBlendType blendType, QImage::Format format> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */
+Q_STATIC_TEMPLATE_FUNCTION
+const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
{
- FetchPixelProc fetch = fetchPixelProc[data->texture.format];
+#ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2
+ FetchPixelProc fetch;
+ if (format != QImage::Format_Invalid)
+ fetch = qt_fetchPixel<format>;
+ else
+ fetch = fetchPixelProc[data->texture.format];
+#else
+ FetchPixelProc fetch = (format != QImage::Format_Invalid) ? FetchPixelProc(qt_fetchPixel<format>) : fetchPixelProc[data->texture.format];
+#endif
int image_width = data->texture.width;
int image_height = data->texture.height;
@@ -853,130 +698,27 @@ static const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Ope
int idistx = 256 - distx;
int idisty = 256 - disty;
- x1 = qBound(0, x1, image_width - 1);
- x2 = qBound(0, x2, image_width - 1);
- y1 = qBound(0, y1, image_height - 1);
- y2 = qBound(0, y2, image_height - 1);
-
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
-
- uint tl = fetch(s1, x1, data->texture.colorTable);
- uint tr = fetch(s1, x2, data->texture.colorTable);
- uint bl = fetch(s2, x1, data->texture.colorTable);
- uint br = fetch(s2, x2, data->texture.colorTable);
-
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
-
- fx += fdx;
- fy += fdy;
- ++b;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
-
- qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
- qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
- qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
-
- while (b < end) {
- const qreal iw = fw == 0 ? 1 : 1 / fw;
- const qreal px = fx * iw - 0.5;
- const qreal py = fy * iw - 0.5;
-
- int x1 = int(px) - (px < 0);
- int x2 = x1 + 1;
- int y1 = int(py) - (py < 0);
- int y2 = y1 + 1;
-
- int distx = int((px - x1) * 256);
- int disty = int((py - y1) * 256);
- int idistx = 256 - distx;
- int idisty = 256 - disty;
-
- x1 = qBound(0, x1, image_width - 1);
- x2 = qBound(0, x2, image_width - 1);
- y1 = qBound(0, y1, image_height - 1);
- y2 = qBound(0, y2, image_height - 1);
-
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
-
- uint tl = fetch(s1, x1, data->texture.colorTable);
- uint tr = fetch(s1, x2, data->texture.colorTable);
- uint bl = fetch(s2, x1, data->texture.colorTable);
- uint br = fetch(s2, x2, data->texture.colorTable);
-
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
-
- fx += fdx;
- fy += fdy;
- fw += fdw;
- //force increment to avoid /0
- if (!fw) {
- fw += fdw;
+ if (blendType == BlendTransformedBilinearTiled) {
+ x1 %= image_width;
+ x2 %= image_width;
+ y1 %= image_height;
+ y2 %= image_height;
+
+ if (x1 < 0) x1 += image_width;
+ if (x2 < 0) x2 += image_width;
+ if (y1 < 0) y1 += image_height;
+ if (y2 < 0) y2 += image_height;
+
+ Q_ASSERT(x1 >= 0 && x1 < image_width);
+ Q_ASSERT(x2 >= 0 && x2 < image_width);
+ Q_ASSERT(y1 >= 0 && y1 < image_height);
+ Q_ASSERT(y2 >= 0 && y2 < image_height);
+ } else {
+ x1 = qBound(0, x1, image_width - 1);
+ x2 = qBound(0, x2, image_width - 1);
+ y1 = qBound(0, y1, image_height - 1);
+ y2 = qBound(0, y2, image_height - 1);
}
- ++b;
- }
- }
-
- return buffer;
-}
-
-static const uint * QT_FASTCALL fetchTransformedBilinearTiled(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
-{
- FetchPixelProc fetch = fetchPixelProc[data->texture.format];
-
- int image_width = data->texture.width;
- int image_height = data->texture.height;
-
- const qreal cx = x + 0.5;
- const qreal cy = y + 0.5;
-
- const uint *end = buffer + length;
- uint *b = buffer;
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- int fdx = (int)(data->m11 * fixed_scale);
- int fdy = (int)(data->m12 * fixed_scale);
-
- int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
- int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
-
- fx -= half_point;
- fy -= half_point;
- while (b < end) {
- int x1 = (fx >> 16);
- int x2 = x1 + 1;
- int y1 = (fy >> 16);
- int y2 = y1 + 1;
-
- int distx = ((fx - (x1 << 16)) >> 8);
- int disty = ((fy - (y1 << 16)) >> 8);
- int idistx = 256 - distx;
- int idisty = 256 - disty;
-
- x1 %= image_width;
- x2 %= image_width;
- y1 %= image_height;
- y2 %= image_height;
-
- if (x1 < 0) x1 += image_width;
- if (x2 < 0) x2 += image_width;
- if (y1 < 0) y1 += image_height;
- if (y2 < 0) y2 += image_height;
-
- Q_ASSERT(x1 >= 0 && x1 < image_width);
- Q_ASSERT(x2 >= 0 && x2 < image_width);
- Q_ASSERT(y1 >= 0 && y1 < image_height);
- Q_ASSERT(y2 >= 0 && y2 < image_height);
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
@@ -1018,20 +760,27 @@ static const uint * QT_FASTCALL fetchTransformedBilinearTiled(uint *buffer, cons
int idistx = 256 - distx;
int idisty = 256 - disty;
- x1 %= image_width;
- x2 %= image_width;
- y1 %= image_height;
- y2 %= image_height;
-
- if (x1 < 0) x1 += image_width;
- if (x2 < 0) x2 += image_width;
- if (y1 < 0) y1 += image_height;
- if (y2 < 0) y2 += image_height;
-
- Q_ASSERT(x1 >= 0 && x1 < image_width);
- Q_ASSERT(x2 >= 0 && x2 < image_width);
- Q_ASSERT(y1 >= 0 && y1 < image_height);
- Q_ASSERT(y2 >= 0 && y2 < image_height);
+ if (blendType == BlendTransformedBilinearTiled) {
+ x1 %= image_width;
+ x2 %= image_width;
+ y1 %= image_height;
+ y2 %= image_height;
+
+ if (x1 < 0) x1 += image_width;
+ if (x2 < 0) x2 += image_width;
+ if (y1 < 0) y1 += image_height;
+ if (y2 < 0) y2 += image_height;
+
+ Q_ASSERT(x1 >= 0 && x1 < image_width);
+ Q_ASSERT(x2 >= 0 && x2 < image_width);
+ Q_ASSERT(y1 >= 0 && y1 < image_height);
+ Q_ASSERT(y2 >= 0 && y2 < image_height);
+ } else {
+ x1 = qBound(0, x1, image_width - 1);
+ x2 = qBound(0, x2, image_width - 1);
+ y1 = qBound(0, y1, image_height - 1);
+ y2 = qBound(0, y2, image_height - 1);
+ }
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
@@ -1059,39 +808,7 @@ static const uint * QT_FASTCALL fetchTransformedBilinearTiled(uint *buffer, cons
return buffer;
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-
-// explicit template instantiations needed to compile with VC6 and VC2002
-
-#define SPANFUNC_POINTER_FETCHUNTRANSFORMED(Arg) \
- const uint *qt_fetchUntransformed_##Arg(uint *buffer, const Operator *op, const QSpanData *data, \
- int y, int x, int length) \
-{ \
- return qt_fetchUntransformed<QImage::Arg>(buffer, op, data, y, x, length Q_TEMPLATE_IMAGEFORMAT_CALL(QImage::Arg)); \
-}
-
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_Mono);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_MonoLSB);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_Indexed8);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB32_Premultiplied);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB32);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB16);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB8565_Premultiplied);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB666);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB6666_Premultiplied);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB555);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB8555_Premultiplied);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB888);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB444);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB4444_Premultiplied);
-
-#undef SPANFUNC_POINTER_FETCHUNTRANSFORMED
-
-#define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed_##Arg
-
-#else // !VC6 && !VC2002
-# define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed<QImage::Arg>
-#endif
+#define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed<QImage::Arg>
static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
// Untransformed
@@ -1135,75 +852,75 @@ static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
// Transformed
{
0, // Invalid
- fetchTransformed, // Mono
- fetchTransformed, // MonoLsb
- fetchTransformed, // Indexed8
- fetchTransformed, // RGB32
- fetchTransformed, // ARGB32
- fetchTransformed, // ARGB32_Premultiplied
- fetchTransformed, // RGB16
- fetchTransformed, // ARGB8565_Premultiplied
- fetchTransformed, // RGB666
- fetchTransformed, // ARGB6666_Premultiplied
- fetchTransformed, // RGB555
- fetchTransformed, // ARGB8555_Premultiplied
- fetchTransformed, // RGB888
- fetchTransformed, // RGB444
- fetchTransformed, // ARGB4444_Premultiplied
+ fetchTransformed<BlendTransformed>, // Mono
+ fetchTransformed<BlendTransformed>, // MonoLsb
+ fetchTransformed<BlendTransformed>, // Indexed8
+ fetchTransformed<BlendTransformed>, // RGB32
+ fetchTransformed<BlendTransformed>, // ARGB32
+ fetchTransformed<BlendTransformed>, // ARGB32_Premultiplied
+ fetchTransformed<BlendTransformed>, // RGB16
+ fetchTransformed<BlendTransformed>, // ARGB8565_Premultiplied
+ fetchTransformed<BlendTransformed>, // RGB666
+ fetchTransformed<BlendTransformed>, // ARGB6666_Premultiplied
+ fetchTransformed<BlendTransformed>, // RGB555
+ fetchTransformed<BlendTransformed>, // ARGB8555_Premultiplied
+ fetchTransformed<BlendTransformed>, // RGB888
+ fetchTransformed<BlendTransformed>, // RGB444
+ fetchTransformed<BlendTransformed>, // ARGB4444_Premultiplied
},
{
0, // TransformedTiled
- fetchTransformedTiled, // Mono
- fetchTransformedTiled, // MonoLsb
- fetchTransformedTiled, // Indexed8
- fetchTransformedTiled, // RGB32
- fetchTransformedTiled, // ARGB32
- fetchTransformedTiled, // ARGB32_Premultiplied
- fetchTransformedTiled, // RGB16
- fetchTransformedTiled, // ARGB8565_Premultiplied
- fetchTransformedTiled, // RGB666
- fetchTransformedTiled, // ARGB6666_Premultiplied
- fetchTransformedTiled, // RGB555
- fetchTransformedTiled, // ARGB8555_Premultiplied
- fetchTransformedTiled, // RGB888
- fetchTransformedTiled, // RGB444
- fetchTransformedTiled, // ARGB4444_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // Mono
+ fetchTransformed<BlendTransformedTiled>, // MonoLsb
+ fetchTransformed<BlendTransformedTiled>, // Indexed8
+ fetchTransformed<BlendTransformedTiled>, // RGB32
+ fetchTransformed<BlendTransformedTiled>, // ARGB32
+ fetchTransformed<BlendTransformedTiled>, // ARGB32_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // RGB16
+ fetchTransformed<BlendTransformedTiled>, // ARGB8565_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // RGB666
+ fetchTransformed<BlendTransformedTiled>, // ARGB6666_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // RGB555
+ fetchTransformed<BlendTransformedTiled>, // ARGB8555_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // RGB888
+ fetchTransformed<BlendTransformedTiled>, // RGB444
+ fetchTransformed<BlendTransformedTiled>, // ARGB4444_Premultiplied
},
{
0, // Bilinear
- fetchTransformedBilinear, // Mono
- fetchTransformedBilinear, // MonoLsb
- fetchTransformedBilinear, // Indexed8
- fetchTransformedBilinear, // RGB32
- fetchTransformedBilinear, // ARGB32
- fetchTransformedBilinear, // ARGB32_Premultiplied
- fetchTransformedBilinear, // RGB16
- fetchTransformedBilinear, // ARGB8565_Premultiplied
- fetchTransformedBilinear, // RGB666
- fetchTransformedBilinear, // ARGB6666_Premultiplied
- fetchTransformedBilinear, // RGB555
- fetchTransformedBilinear, // ARGB8555_Premultiplied
- fetchTransformedBilinear, // RGB888
- fetchTransformedBilinear, // RGB444
- fetchTransformedBilinear // ARGB4444_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Mono
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // MonoLsb
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Indexed8
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // RGB32
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32>, // ARGB32
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB16
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8565_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB666
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB6666_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB555
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8555_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB888
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB444
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid> // ARGB4444_Premultiplied
},
{
0, // BilinearTiled
- fetchTransformedBilinearTiled, // Mono
- fetchTransformedBilinearTiled, // MonoLsb
- fetchTransformedBilinearTiled, // Indexed8
- fetchTransformedBilinearTiled, // RGB32
- fetchTransformedBilinearTiled, // ARGB32
- fetchTransformedBilinearTiled, // ARGB32_Premultiplied
- fetchTransformedBilinearTiled, // RGB16
- fetchTransformedBilinearTiled, // ARGB8565_Premultiplied
- fetchTransformedBilinearTiled, // RGB666
- fetchTransformedBilinearTiled, // ARGB6666_Premultiplied
- fetchTransformedBilinearTiled, // RGB555
- fetchTransformedBilinearTiled, // ARGB8555_Premultiplied
- fetchTransformedBilinearTiled, // RGB888
- fetchTransformedBilinearTiled, // RGB444
- fetchTransformedBilinearTiled // ARGB4444_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Mono
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // MonoLsb
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Indexed8
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // RGB32
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32>, // ARGB32
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB16
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8565_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB666
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB6666_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB555
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8555_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB888
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB444
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid> // ARGB4444_Premultiplied
},
};
@@ -1497,7 +1214,32 @@ static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operato
return b;
}
-
+#if defined(Q_CC_RVCT)
+// Force ARM code generation for comp_func_* -methods
+# pragma push
+# pragma arm
+# if defined(QT_HAVE_ARMV6)
+static __forceinline void preload(const uint *start)
+{
+ asm( "pld [start]" );
+}
+static const uint L2CacheLineLength = 32;
+static const uint L2CacheLineLengthInInts = L2CacheLineLength/sizeof(uint);
+# define PRELOAD_INIT(x) preload(x);
+# define PRELOAD_INIT2(x,y) PRELOAD_INIT(x) PRELOAD_INIT(y)
+# define PRELOAD_COND(x) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts);
+// Two consecutive preloads stall, so space them out a bit by using different modulus.
+# define PRELOAD_COND2(x,y) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); \
+ if (((uint)&y[i])%L2CacheLineLength == 16) preload(&y[i] + L2CacheLineLengthInInts);
+# endif // QT_HAVE_ARMV6
+#endif // Q_CC_RVCT
+
+#if !defined(Q_CC_RVCT) || !defined(QT_HAVE_ARMV6)
+# define PRELOAD_INIT(x)
+# define PRELOAD_INIT2(x,y)
+# define PRELOAD_COND(x)
+# define PRELOAD_COND2(x,y)
+#endif
/* The constant alpha factor describes an alpha factor that gets applied
to the result of the composition operation combining it with the destination.
@@ -1530,8 +1272,11 @@ static void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint
QT_MEMFILL_UINT(dest, length, 0);
} else {
int ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(dest[i], ialpha);
+ }
}
}
@@ -1541,8 +1286,11 @@ static void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, ui
QT_MEMFILL_UINT(dest, length, 0);
} else {
int ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(dest[i], ialpha);
+ }
}
}
@@ -1557,8 +1305,11 @@ static void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint colo
} else {
int ialpha = 255 - const_alpha;
color = BYTE_MUL(color, const_alpha);
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = color + BYTE_MUL(dest[i], ialpha);
+ }
}
}
@@ -1568,8 +1319,11 @@ static void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length
::memcpy(dest, src, length * sizeof(uint));
} else {
int ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha);
+ }
}
}
@@ -1594,20 +1348,26 @@ static void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint
} else {
if (const_alpha != 255)
color = BYTE_MUL(color, const_alpha);
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color));
+ }
}
}
static void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = src[i];
dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
}
} else {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = BYTE_MUL(src[i], const_alpha);
dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
}
@@ -1623,7 +1383,9 @@ static void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length,
{
if (const_alpha != 255)
color = BYTE_MUL(color, const_alpha);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = d + BYTE_MUL(color, qAlpha(~d));
}
@@ -1631,13 +1393,16 @@ static void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length,
static void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
dest[i] = d + BYTE_MUL(src[i], qAlpha(~d));
}
} else {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = BYTE_MUL(src[i], const_alpha);
dest[i] = d + BYTE_MUL(s, qAlpha(~d));
@@ -1651,13 +1416,17 @@ static void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, i
*/
static void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
{
+ PRELOAD_INIT(dest)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(color, qAlpha(dest[i]));
+ }
} else {
color = BYTE_MUL(color, const_alpha);
uint cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia);
}
@@ -1666,12 +1435,16 @@ static void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint co
static void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = BYTE_MUL(src[i], qAlpha(dest[i]));
+ }
} else {
uint cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = BYTE_MUL(src[i], const_alpha);
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia);
@@ -1690,19 +1463,25 @@ static void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, ui
if (const_alpha != 255) {
a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
}
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(dest[i], a);
}
}
static void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = BYTE_MUL(dest[i], qAlpha(src[i]));
+ }
} else {
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia;
dest[i] = BYTE_MUL(dest[i], a);
}
@@ -1716,13 +1495,17 @@ static void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int
static void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
{
+ PRELOAD_INIT(dest)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(color, qAlpha(~dest[i]));
+ }
} else {
color = BYTE_MUL(color, const_alpha);
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia);
}
@@ -1731,12 +1514,16 @@ static void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint c
static void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i]));
+ }
} else {
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = BYTE_MUL(src[i], const_alpha);
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia);
@@ -1754,18 +1541,25 @@ static void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, u
uint a = qAlpha(~color);
if (const_alpha != 255)
a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(dest[i], a);
+ }
}
static void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i]));
+ }
} else {
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia;
dest[i] = BYTE_MUL(dest[i], sia);
}
@@ -1784,20 +1578,26 @@ static void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint
color = BYTE_MUL(color, const_alpha);
}
uint sia = qAlpha(~color);
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia);
+ }
}
static void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = src[i];
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
}
} else {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = BYTE_MUL(src[i], const_alpha);
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
@@ -1817,7 +1617,9 @@ static void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length,
color = BYTE_MUL(color, const_alpha);
a = qAlpha(color) + 255 - const_alpha;
}
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d));
}
@@ -1825,8 +1627,10 @@ static void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length,
static void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = src[i];
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d));
@@ -1834,6 +1638,7 @@ static void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, i
} else {
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = BYTE_MUL(src[i], const_alpha);
uint d = dest[i];
uint a = qAlpha(s) + cia;
@@ -1854,7 +1659,9 @@ static void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color,
color = BYTE_MUL(color, const_alpha);
uint sia = qAlpha(~color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia);
}
@@ -1862,14 +1669,17 @@ static void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color,
static void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
}
} else {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = BYTE_MUL(src[i], const_alpha);
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
@@ -1920,7 +1730,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int
{
uint s = color;
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
#define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
d = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK));
@@ -1940,7 +1752,9 @@ static void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color,
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -1976,7 +1790,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest,
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2002,7 +1818,9 @@ static void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint co
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2040,7 +1858,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, i
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2066,7 +1886,9 @@ static void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint colo
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2115,7 +1937,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest,
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2141,7 +1965,9 @@ static void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint col
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2184,7 +2010,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, i
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2210,7 +2038,9 @@ static void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint colo
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2253,7 +2083,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest,
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2279,7 +2111,9 @@ static void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint col
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2332,7 +2166,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *des
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2358,7 +2194,9 @@ static void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2411,7 +2249,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2437,7 +2277,9 @@ static void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint c
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2487,7 +2329,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2513,7 +2357,9 @@ static void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint c
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2572,7 +2418,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2598,7 +2446,9 @@ static void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint c
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2641,7 +2491,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *des
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2667,7 +2519,9 @@ static void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2704,7 +2558,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_imp
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2730,7 +2586,9 @@ static void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint c
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2756,6 +2614,11 @@ static void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int len
comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#if defined(Q_CC_RVCT)
+// Restore pragma state from previous #pragma arm
+# pragma pop
+#endif
+
static void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
int length,
uint color,
@@ -3219,8 +3082,7 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
}
template <class T>
-Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_FIX(T))
+Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
Operator op = getOperator(data, spans, count);
@@ -3266,28 +3128,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *
blend_color_generic(count, spans, userData);
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-#define BLEND_COLOR_DECL(DST) \
- static void blendColor_##DST(int count, \
- const QSpan *spans, \
- void *userData) \
- { \
- blendColor<DST>(count, spans, userData Q_TEMPLATE_CALL(DST)); \
- }
-
-BLEND_COLOR_DECL(qargb8565)
-BLEND_COLOR_DECL(qrgb666)
-BLEND_COLOR_DECL(qargb6666)
-BLEND_COLOR_DECL(qrgb555)
-BLEND_COLOR_DECL(qargb8555)
-BLEND_COLOR_DECL(qrgb888)
-BLEND_COLOR_DECL(qrgb444)
-BLEND_COLOR_DECL(qargb4444)
-#undef DEST_FETCH_DECL
-#define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor_##DST
-#else // !VC6 && !VC2002
-# define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor<DST>
-#endif
+#define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor<DST>
static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
{
@@ -3365,45 +3206,117 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
blend_color_generic(count, spans, userData);
}
-template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+template <typename T>
+void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handler)
{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
-
- uint buffer[buffer_size];
- uint src_buffer[buffer_size];
- Operator op = getOperator(data, spans, count);
-
uint const_alpha = 256;
if (data->type == QSpanData::Texture)
const_alpha = data->texture.const_alpha;
- while (count--) {
+ int coverage = 0;
+ while (count) {
int x = spans->x;
- int length = spans->len;
- const int coverage = (spans->coverage * const_alpha) >> 8;
+ const int y = spans->y;
+ int right = x + spans->len;
+
+ // compute length of adjacent spans
+ for (int i = 1; i < count && spans[i].y == y && spans[i].x == right; ++i)
+ right += spans[i].len;
+ int length = right - x;
+
while (length) {
int l = qMin(buffer_size, length);
- const uint *src = op.src_fetch(src_buffer, &op, data, spans->y, x, l);
- if (spanMethod == RegularSpans) {
- uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
- op.func(dest, src, l, coverage);
- if (op.dest_store)
- op.dest_store(data->rasterBuffer, x, spans->y, dest, l);
- } else {
- drawBufferSpan(data, src, l, x, spans->y, l, coverage);
- }
- x += l;
length -= l;
+
+ int process_length = l;
+ int process_x = x;
+
+ const uint *src = handler.fetch(process_x, y, process_length);
+ int offset = 0;
+ while (l > 0) {
+ if (x == spans->x) // new span?
+ coverage = (spans->coverage * const_alpha) >> 8;
+
+ int right = spans->x + spans->len;
+ int len = qMin(l, right - x);
+
+ handler.process(x, y, len, coverage, src, offset);
+
+ l -= len;
+ x += len;
+ offset += len;
+
+ if (x == right) { // done with current span?
+ ++spans;
+ --count;
+ }
+ }
+ handler.store(process_x, y, process_length);
}
- ++spans;
}
}
+struct QBlendBase
+{
+ QBlendBase(QSpanData *d, Operator o)
+ : data(d)
+ , op(o)
+ , dest(0)
+ {
+ }
+
+ QSpanData *data;
+ Operator op;
+
+ uint *dest;
+
+ uint buffer[buffer_size];
+ uint src_buffer[buffer_size];
+};
+
+template <SpanMethod spanMethod>
+class BlendSrcGeneric : public QBlendBase
+{
+public:
+ BlendSrcGeneric(QSpanData *d, Operator o)
+ : QBlendBase(d, o)
+ {
+ }
+
+ const uint *fetch(int x, int y, int len)
+ {
+ if (spanMethod == RegularSpans)
+ dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, y, len) : buffer;
+
+ return op.src_fetch(src_buffer, &op, data, y, x, len);
+ }
+
+ void process(int x, int y, int len, int coverage, const uint *src, int offset)
+ {
+ if (spanMethod == RegularSpans)
+ op.func(dest + offset, src + offset, len, coverage);
+ else
+ drawBufferSpan(data, src + offset, len, x, y, len, coverage);
+ }
+
+ void store(int x, int y, int len)
+ {
+ if (spanMethod == RegularSpans && op.dest_store) {
+ op.dest_store(data->rasterBuffer, x, y, dest, len);
+ }
+ }
+};
+
+template <SpanMethod spanMethod>
+Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+ BlendSrcGeneric<spanMethod> blend(data, getOperator(data, spans, count));
+ handleSpans(count, spans, data, blend);
+}
+
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -3454,13 +3367,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSp
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_untransformed_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_untransformed_generic<spanMethod>(count, spans, userData);
return;
}
@@ -4706,8 +4618,7 @@ void QT_FASTCALL blendUntransformed(int count, const QSpan *spans, void *userDat
if (mode != QPainter::CompositionMode_SourceOver &&
mode != QPainter::CompositionMode_Source)
{
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -4769,8 +4680,7 @@ static void blend_untransformed_rgb888(int count, const QSpan *spans,
blendUntransformed<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_argb6666(int count, const QSpan *spans,
@@ -4785,8 +4695,7 @@ static void blend_untransformed_argb6666(int count, const QSpan *spans,
blendUntransformed<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_rgb666(int count, const QSpan *spans,
@@ -4801,8 +4710,7 @@ static void blend_untransformed_rgb666(int count, const QSpan *spans,
blendUntransformed<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_argb8565(int count, const QSpan *spans,
@@ -4817,8 +4725,7 @@ static void blend_untransformed_argb8565(int count, const QSpan *spans,
blendUntransformed<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_rgb565(int count, const QSpan *spans,
@@ -4833,8 +4740,7 @@ static void blend_untransformed_rgb565(int count, const QSpan *spans,
blendUntransformed<qrgb565, qrgb565>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_argb8555(int count, const QSpan *spans,
@@ -4849,8 +4755,7 @@ static void blend_untransformed_argb8555(int count, const QSpan *spans,
blendUntransformed<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_rgb555(int count, const QSpan *spans,
@@ -4865,8 +4770,7 @@ static void blend_untransformed_rgb555(int count, const QSpan *spans,
blendUntransformed<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_argb4444(int count, const QSpan *spans,
@@ -4881,8 +4785,7 @@ static void blend_untransformed_argb4444(int count, const QSpan *spans,
blendUntransformed<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_rgb444(int count, const QSpan *spans,
@@ -4897,13 +4800,11 @@ static void blend_untransformed_rgb444(int count, const QSpan *spans,
blendUntransformed<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -4957,13 +4858,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *span
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_tiled_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_tiled_generic<spanMethod>(count, spans, userData);
return;
}
@@ -5019,8 +4919,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void *
if (mode != QPainter::CompositionMode_SourceOver &&
mode != QPainter::CompositionMode_Source)
{
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -5052,30 +4951,60 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void *
if (sy < 0)
sy += image_height;
- while (length) {
- int l = qMin(image_width - sx, length);
- if (buffer_size < l)
- l = buffer_size;
-
- DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x;
- const SRC *src = (SRC*)data->texture.scanLine(sy) + sx;
- if (modeSource && coverage == 255) {
+ if (modeSource && coverage == 255) {
+ // Copy the first texture block
+ length = image_width;
+ while (length) {
+ int l = qMin(image_width - sx, length);
+ if (buffer_size < l)
+ l = buffer_size;
+ DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x;
+ const SRC *src = (SRC*)data->texture.scanLine(sy) + sx;
qt_memconvert<DST, SRC>(dest, src, l);
- } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 &&
- (quintptr(dest) & 3) == (quintptr(src) & 3))
- {
- blendUntransformed_dest24(dest, src, coverage, l);
- } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 &&
- (quintptr(dest) & 3) == (quintptr(src) & 3))
- {
- blendUntransformed_dest16(dest, src, coverage, l);
- } else {
- blendUntransformed_unaligned(dest, src, coverage, l);
+ length -= l;
+ sx = 0;
}
- x += l;
- length -= l;
- sx = 0;
+ // Now use the rasterBuffer as the source of the texture,
+ // We can now progressively copy larger blocks
+ // - Less cpu time in code figuring out what to copy
+ // We are dealing with one block of data
+ // - More likely to fit in the cache
+ // - can use memcpy
+ int copy_image_width = image_width;
+ length = spans->len - image_width;
+ DST *src = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x;
+ DST *dest = src + copy_image_width;
+ while (copy_image_width < length) {
+ qt_memconvert(dest, src, copy_image_width);
+ dest += copy_image_width;
+ length -= copy_image_width;
+ copy_image_width *= 2;
+ }
+ qt_memconvert(dest, src, length);
+ } else {
+ while (length) {
+ int l = qMin(image_width - sx, length);
+ if (buffer_size < l)
+ l = buffer_size;
+ DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x;
+ const SRC *src = (SRC*)data->texture.scanLine(sy) + sx;
+ if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 &&
+ (quintptr(dest) & 3) == (quintptr(src) & 3))
+ {
+ blendUntransformed_dest24(dest, src, coverage, l);
+ } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 &&
+ (quintptr(dest) & 3) == (quintptr(src) & 3))
+ {
+ blendUntransformed_dest16(dest, src, coverage, l);
+ } else {
+ blendUntransformed_unaligned(dest, src, coverage, l);
+ }
+
+ x += l;
+ length -= l;
+ sx = 0;
+ }
}
++spans;
}
@@ -5090,8 +5019,7 @@ static void blend_tiled_rgb888(int count, const QSpan *spans, void *userData)
blendTiled<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_argb6666(int count, const QSpan *spans, void *userData)
@@ -5105,8 +5033,7 @@ static void blend_tiled_argb6666(int count, const QSpan *spans, void *userData)
blendTiled<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_rgb666(int count, const QSpan *spans, void *userData)
@@ -5120,8 +5047,7 @@ static void blend_tiled_rgb666(int count, const QSpan *spans, void *userData)
blendTiled<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData)
@@ -5135,8 +5061,7 @@ static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData)
blendTiled<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
@@ -5150,8 +5075,7 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
blendTiled<qrgb565, qrgb565>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_argb8555(int count, const QSpan *spans, void *userData)
@@ -5165,8 +5089,7 @@ static void blend_tiled_argb8555(int count, const QSpan *spans, void *userData)
blendTiled<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_rgb555(int count, const QSpan *spans, void *userData)
@@ -5180,8 +5103,7 @@ static void blend_tiled_rgb555(int count, const QSpan *spans, void *userData)
blendTiled<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_argb4444(int count, const QSpan *spans, void *userData)
@@ -5195,8 +5117,7 @@ static void blend_tiled_argb4444(int count, const QSpan *spans, void *userData)
blendTiled<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData)
@@ -5210,19 +5131,17 @@ static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData)
blendTiled<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_src_generic<spanMethod>(count, spans, userData);
return;
}
@@ -5401,8 +5320,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan
if (mode != QPainter::CompositionMode_SourceOver) {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -5605,8 +5523,7 @@ static void blend_transformed_bilinear_rgb888(int count, const QSpan *spans, voi
blendTransformedBilinear<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_argb6666(int count, const QSpan *spans, void *userData)
@@ -5620,8 +5537,7 @@ static void blend_transformed_bilinear_argb6666(int count, const QSpan *spans, v
blendTransformedBilinear<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_rgb666(int count, const QSpan *spans, void *userData)
@@ -5635,8 +5551,7 @@ static void blend_transformed_bilinear_rgb666(int count, const QSpan *spans, voi
blendTransformedBilinear<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, void *userData)
@@ -5650,8 +5565,7 @@ static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, v
blendTransformedBilinear<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans,
@@ -5666,8 +5580,7 @@ static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans,
blendTransformedBilinear<qrgb565, qargb8565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_argb8555(int count, const QSpan *spans, void *userData)
@@ -5681,8 +5594,7 @@ static void blend_transformed_bilinear_argb8555(int count, const QSpan *spans, v
blendTransformedBilinear<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_rgb555(int count, const QSpan *spans, void *userData)
@@ -5696,8 +5608,7 @@ static void blend_transformed_bilinear_rgb555(int count, const QSpan *spans, voi
blendTransformedBilinear<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_argb4444(int count, const QSpan *spans, void *userData)
@@ -5711,8 +5622,7 @@ static void blend_transformed_bilinear_argb4444(int count, const QSpan *spans, v
blendTransformedBilinear<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, void *userData)
@@ -5726,18 +5636,16 @@ static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, voi
blendTransformedBilinear<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_src_generic<spanMethod>(count, spans, userData);
return;
}
@@ -5923,13 +5831,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count,
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_src_generic<spanMethod>(count, spans, userData);
return;
}
@@ -6051,8 +5958,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans,
QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
if (mode != QPainter::CompositionMode_SourceOver) {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -6201,8 +6107,7 @@ static void blend_transformed_rgb888(int count, const QSpan *spans,
blendTransformed<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_argb6666(int count, const QSpan *spans,
@@ -6217,8 +6122,7 @@ static void blend_transformed_argb6666(int count, const QSpan *spans,
blendTransformed<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_rgb666(int count, const QSpan *spans,
@@ -6233,8 +6137,7 @@ static void blend_transformed_rgb666(int count, const QSpan *spans,
blendTransformed<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_argb8565(int count, const QSpan *spans,
@@ -6249,8 +6152,7 @@ static void blend_transformed_argb8565(int count, const QSpan *spans,
blendTransformed<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_rgb565(int count, const QSpan *spans,
@@ -6265,8 +6167,7 @@ static void blend_transformed_rgb565(int count, const QSpan *spans,
blendTransformed<qrgb565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_argb8555(int count, const QSpan *spans,
@@ -6281,8 +6182,7 @@ static void blend_transformed_argb8555(int count, const QSpan *spans,
blendTransformed<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_rgb555(int count, const QSpan *spans,
@@ -6297,8 +6197,7 @@ static void blend_transformed_rgb555(int count, const QSpan *spans,
blendTransformed<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_argb4444(int count, const QSpan *spans,
@@ -6313,8 +6212,7 @@ static void blend_transformed_argb4444(int count, const QSpan *spans,
blendTransformed<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_rgb444(int count, const QSpan *spans,
@@ -6329,18 +6227,16 @@ static void blend_transformed_rgb444(int count, const QSpan *spans,
blendTransformed<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_src_generic<spanMethod>(count, spans, userData);
return;
}
@@ -6474,8 +6370,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp
QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
if (mode != QPainter::CompositionMode_SourceOver) {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -6625,8 +6520,7 @@ static void blend_transformed_tiled_rgb888(int count, const QSpan *spans,
blendTransformedTiled<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_argb6666(int count, const QSpan *spans,
@@ -6641,8 +6535,7 @@ static void blend_transformed_tiled_argb6666(int count, const QSpan *spans,
blendTransformedTiled<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_rgb666(int count, const QSpan *spans,
@@ -6657,8 +6550,7 @@ static void blend_transformed_tiled_rgb666(int count, const QSpan *spans,
blendTransformedTiled<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_argb8565(int count, const QSpan *spans,
@@ -6673,8 +6565,7 @@ static void blend_transformed_tiled_argb8565(int count, const QSpan *spans,
blendTransformedTiled<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_rgb565(int count, const QSpan *spans,
@@ -6689,8 +6580,7 @@ static void blend_transformed_tiled_rgb565(int count, const QSpan *spans,
blendTransformedTiled<qrgb565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_argb8555(int count, const QSpan *spans,
@@ -6705,8 +6595,7 @@ static void blend_transformed_tiled_argb8555(int count, const QSpan *spans,
blendTransformedTiled<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_rgb555(int count, const QSpan *spans,
@@ -6721,8 +6610,7 @@ static void blend_transformed_tiled_rgb555(int count, const QSpan *spans,
blendTransformedTiled<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_argb4444(int count, const QSpan *spans,
@@ -6737,8 +6625,7 @@ static void blend_transformed_tiled_argb4444(int count, const QSpan *spans,
blendTransformedTiled<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_rgb444(int count, const QSpan *spans,
@@ -6753,36 +6640,10 @@ static void blend_transformed_tiled_rgb444(int count, const QSpan *spans,
blendTransformedTiled<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-
-// explicit template instantiations needed to compile with VC6 and VC2002
-
-#define SPANFUNC_INSTANTIATION(Name, Arg) \
-static inline void Name##_##Arg(int count, const QSpan *spans, void *userData) \
-{ \
- Name<Arg>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, Arg)); \
-}
-
-SPANFUNC_INSTANTIATION(blend_untransformed_generic, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_untransformed_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_tiled_generic, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_tiled_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_src_generic, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_transformed_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_transformed_tiled_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_transformed_bilinear_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_transformed_bilinear_tiled_argb, RegularSpans);
-#undef SPANFUNC_INSTANTIATION
-
-#define SPANFUNC_POINTER(Name, Arg) Name##_##Arg
-
-#else // !VC6 && !VC2002
# define SPANFUNC_POINTER(Name, Arg) Name<Arg>
-#endif
/* Image formats here are target formats */
@@ -7149,8 +7010,7 @@ static void qt_gradient_quint32(int count, const QSpan *spans, void *userData)
}
} else {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
}
@@ -7198,8 +7058,7 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData)
data->solid.color = oldColor;
} else {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
}
@@ -7258,7 +7117,13 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
}
void qt_build_pow_tables() {
- qreal smoothing = 1.7;
+ qreal smoothing = qreal(1.7);
+
+#ifdef Q_WS_MAC
+ // decided by testing a few things on an iMac, should probably get this from the
+ // system...
+ smoothing = 2.0;
+#endif
#ifdef Q_WS_WIN
int winSmooth;
@@ -7274,15 +7139,15 @@ void qt_build_pow_tables() {
}
#else
for (int i=0; i<256; ++i) {
- qt_pow_rgb_gamma[i] = uchar(qRound(pow(i / 255.0, smoothing) * 255));
- qt_pow_rgb_invgamma[i] = uchar(qRound(pow(i / 255.0, 1 / smoothing) * 255));
+ qt_pow_rgb_gamma[i] = uchar(qRound(pow(i / qreal(255.0), smoothing) * 255));
+ qt_pow_rgb_invgamma[i] = uchar(qRound(pow(i / qreal(255.), 1 / smoothing) * 255));
}
#endif
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
const qreal gray_gamma = 2.31;
for (int i=0; i<256; ++i)
- qt_pow_gamma[i] = uint(qRound(pow(i / 255.0, gray_gamma) * 2047));
+ qt_pow_gamma[i] = uint(qRound(pow(i / qreal(255.), gray_gamma) * 2047));
for (int i=0; i<2048; ++i)
qt_pow_invgamma[i] = uchar(qRound(pow(i / 2047.0, 1 / gray_gamma) * 255));
#endif
@@ -7404,7 +7269,7 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer,
#endif
{
int ialpha = 255 - coverage;
- dest[i] = BYTE_MUL(c, uint(coverage)) + BYTE_MUL(dest[i], ialpha);
+ dest[i] = INTERPOLATE_PIXEL_255(c, coverage, dest[i], ialpha);
}
}
}
@@ -7445,7 +7310,7 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer,
#endif
{
int ialpha = 255 - coverage;
- dest[xp] = BYTE_MUL(c, uint(coverage)) + BYTE_MUL(dest[xp], ialpha);
+ dest[xp] = INTERPOLATE_PIXEL_255(c, coverage, dest[xp], ialpha);
}
}
@@ -7547,13 +7412,13 @@ inline void qt_rectfill_template(QRasterBuffer *rasterBuffer,
QT_RECTFILL(quint32)
QT_RECTFILL(quint16)
QT_RECTFILL(qargb8565)
-QT_RECTFILL(qrgb666);
-QT_RECTFILL(qargb6666);
+QT_RECTFILL(qrgb666)
+QT_RECTFILL(qargb6666)
QT_RECTFILL(qrgb555)
QT_RECTFILL(qargb8555)
QT_RECTFILL(qrgb888)
-QT_RECTFILL(qrgb444);
-QT_RECTFILL(qargb4444);
+QT_RECTFILL(qrgb444)
+QT_RECTFILL(qargb4444)
#undef QT_RECTFILL
@@ -8031,6 +7896,96 @@ static uint detectCPUFeatures()
#endif
}
+#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
+// Move these to qdrawhelper_arm.c when all
+// functions are implemented using arm assembly.
+static CompositionFunctionSolid qt_functionForModeSolid_ARMv6[numCompositionFunctions] = {
+ comp_func_solid_SourceOver,
+ comp_func_solid_DestinationOver,
+ comp_func_solid_Clear,
+ comp_func_solid_Source,
+ comp_func_solid_Destination,
+ comp_func_solid_SourceIn,
+ comp_func_solid_DestinationIn,
+ comp_func_solid_SourceOut,
+ comp_func_solid_DestinationOut,
+ comp_func_solid_SourceAtop,
+ comp_func_solid_DestinationAtop,
+ comp_func_solid_XOR,
+ comp_func_solid_Plus,
+ comp_func_solid_Multiply,
+ comp_func_solid_Screen,
+ comp_func_solid_Overlay,
+ comp_func_solid_Darken,
+ comp_func_solid_Lighten,
+ comp_func_solid_ColorDodge,
+ comp_func_solid_ColorBurn,
+ comp_func_solid_HardLight,
+ comp_func_solid_SoftLight,
+ comp_func_solid_Difference,
+ comp_func_solid_Exclusion,
+ rasterop_solid_SourceOrDestination,
+ rasterop_solid_SourceAndDestination,
+ rasterop_solid_SourceXorDestination,
+ rasterop_solid_NotSourceAndNotDestination,
+ rasterop_solid_NotSourceOrNotDestination,
+ rasterop_solid_NotSourceXorDestination,
+ rasterop_solid_NotSource,
+ rasterop_solid_NotSourceAndDestination,
+ rasterop_solid_SourceAndNotDestination
+};
+
+static CompositionFunction qt_functionForMode_ARMv6[numCompositionFunctions] = {
+ comp_func_SourceOver_armv6,
+ comp_func_DestinationOver,
+ comp_func_Clear,
+ comp_func_Source_armv6,
+ comp_func_Destination,
+ comp_func_SourceIn,
+ comp_func_DestinationIn,
+ comp_func_SourceOut,
+ comp_func_DestinationOut,
+ comp_func_SourceAtop,
+ comp_func_DestinationAtop,
+ comp_func_XOR,
+ comp_func_Plus,
+ comp_func_Multiply,
+ comp_func_Screen,
+ comp_func_Overlay,
+ comp_func_Darken,
+ comp_func_Lighten,
+ comp_func_ColorDodge,
+ comp_func_ColorBurn,
+ comp_func_HardLight,
+ comp_func_SoftLight,
+ comp_func_Difference,
+ comp_func_Exclusion,
+ rasterop_SourceOrDestination,
+ rasterop_SourceAndDestination,
+ rasterop_SourceXorDestination,
+ rasterop_NotSourceAndNotDestination,
+ rasterop_NotSourceOrNotDestination,
+ rasterop_NotSourceXorDestination,
+ rasterop_NotSource,
+ rasterop_NotSourceAndDestination,
+ rasterop_SourceAndNotDestination
+};
+
+static void qt_blend_color_argb_armv6(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+
+ CompositionFunctionSolid func = qt_functionForModeSolid_ARMv6[data->rasterBuffer->compositionMode];
+ while (count--) {
+ uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
+ func(target, spans->len, data->solid.color, spans->coverage);
+ ++spans;
+ }
+}
+
+#endif // Q_CC_RVCT && QT_HAVE_ARMV6
+
+
void qInitDrawhelperAsm()
{
static uint features = 0xffffffff;
@@ -8146,6 +8101,20 @@ void qInitDrawhelperAsm()
#endif // QT_NO_DEBUG
+#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
+ functionForModeAsm = qt_functionForMode_ARMv6;
+ functionForModeSolidAsm = qt_functionForModeSolid_ARMv6;
+
+ qt_memfill32 = qt_memfill32_armv6;
+
+ qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_armv6;
+
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
+#endif // Q_CC_RVCT && QT_HAVE_ARMV6
+
if (functionForModeSolidAsm) {
const int destinationMode = QPainter::CompositionMode_Destination;
functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode];
diff --git a/src/gui/painting/qdrawhelper_armv6_p.h b/src/gui/painting/qdrawhelper_armv6_p.h
new file mode 100644
index 0000000..9f3e062
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_armv6_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDRAWHELPER_ARMV6_P_H
+#define QDRAWHELPER_ARMV6_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 <private/qdrawhelper_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
+
+extern "C" void qt_blend_rgb32_on_rgb32_armv6(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+extern "C" void qt_blend_argb32_on_argb32_armv6(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+extern "C" void qt_memfill32_armv6(quint32 *dest, quint32 value, int count);
+
+extern "C" void comp_func_Source_armv6(uint *dest, const uint *src, int length, uint const_alpha);
+extern "C" void comp_func_SourceOver_armv6(uint *dest, const uint *src, int length, uint const_alpha);
+
+#endif // QT_HAVE_ARMV6
+
+QT_END_NAMESPACE
+
+#endif // QDRAWHELPER_ARMV6_P_H
diff --git a/src/gui/painting/qdrawhelper_armv6_rvct.inc b/src/gui/painting/qdrawhelper_armv6_rvct.inc
new file mode 100644
index 0000000..1aabbf5
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_armv6_rvct.inc
@@ -0,0 +1,496 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;** Contact: Nokia Corporation (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module of the Qt Toolkit.
+;**
+;** $QT_BEGIN_LICENSE:LGPL$
+;** No Commercial Usage
+;** This file contains pre-release code and may not be distributed.
+;** You may use this file in accordance with the terms and conditions
+;** contained in the either Technology Preview License Agreement or the
+;** Beta Release License Agreement.
+;**
+;** GNU Lesser General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU Lesser
+;** General Public License version 2.1 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.LGPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU Lesser General Public License version 2.1 requirements
+;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;**
+;** In addition, as a special exception, Nokia gives you certain
+;** additional rights. These rights are described in the Nokia Qt LGPL
+;** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;** package.
+;**
+;** GNU General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU
+;** General Public License version 3.0 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.GPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU General Public License version 3.0 requirements will be
+;** met: http://www.gnu.org/copyleft/gpl.html.
+;**
+;** If you are unsure which license is appropriate for your use, please
+;** contact the sales department at http://qt.nokia.com/contact.
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+
+;
+; W A R N I N G
+; -------------
+;
+; This file is not part of the Qt API. It exists purely as an
+; implementation detail. This header file may change from version to
+; version without notice, or even be removed.
+;
+; We mean it.
+;
+
+;-----------------------------------------------------------------------------
+; Globals.
+; Earch marcro expects that caller has loaded 0x800080 to r14.
+;-----------------------------------------------------------------------------
+
+ComponentHalf EQU 0x800080
+
+;-----------------------------------------------------------------------------
+; ARM assembly implementations of accelerated graphics operations.
+;
+; Conventions:
+;
+; - r0 = Target buffer pointer
+; - r1 = Source buffer pointer
+; - r2 = Length of the buffer to blend
+; - r3 = Constant alpha for source buffer
+;
+;-----------------------------------------------------------------------------
+
+; A macro for transparently defining ARM functions
+ MACRO
+$func Function
+ AREA Function_$func, CODE
+ GLOBAL $func
+ ALIGN 4
+ CODE32
+$func
+ MEND
+
+
+;-----------------------------------------------------------------------------
+; Armv6 boosted implementation of BYTE_MUL(...) function found in qdrawhelper_p.h.
+;
+; @param dst Destination register where to store the result
+; @param x Value to multiply
+; @param a Multiplicator byte
+; @param r14 Component half 0x800080
+;
+; @note Trashes x, r8
+;-----------------------------------------------------------------------------
+ MACRO
+ ByteMul $dst, $x, $a
+
+ ; static inline uint BYTE_MUL(uint x, uint a)
+
+ ; uint r8 = (x & 0xff00ff) * a + 0x800080
+ uxtb16 r8, $x ; r8 = r8 & 0x00FF00FF
+ mla r8, r8, $a, r14
+
+ ; x = ((r >> 8) & 0xff00ff) * a + 0x800080
+ uxtb16 $x, $x, ror #8
+ mla $x, $x, $a, r14
+
+
+ ; r8 = (r8 + ((r8 >> 8) & 0xff00ff) ) >> 8
+ ; r8 &= 0xff00ff
+ uxtab16 r8, r8, r8, ror #8
+ uxtb16 r8, r8, ror #8
+
+ ; x = x + ((x >>8) & 0xff00ff)
+ uxtab16 $x, $x, $x, ror #8
+
+ ; x &= 0xff00ff00
+ ; x |= r8
+ uxtb16 $x, $x, ror #8
+ orr $dst, r8, $x, lsl #8
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; Armv6 boosted implementation of INTERPOLATE_PIXEL_255(...) function found in
+; qdrawhelper_p.h.
+;
+; @param dst Destination register where to store the result
+; @param x First value to multiply
+; @param a Multiplicator byte for first value
+; @param y Second value to multiply
+; @param b Multiplicator byte for second value
+; @param r14 Component half 0x800080
+;
+;
+; @note Trashes x, r8, r14
+;-----------------------------------------------------------------------------
+ MACRO
+ InterpolatePixel255 $dst, $x, $a, $y, $b
+
+ ; static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b)
+
+ ; First calculate the parts where we need 0x800080
+
+ ; uint r8 = (((x & 0xff00ff) * a) + 0x800080)
+ uxtb16 r8, $x ; r8 = r8 & 0x00FF00FF
+ mla r8, r8, $a, r14
+
+ ; x = ((((x >> 8) & 0xff00ff) * a) + 0x800080)
+ uxtb16 $x, $x, ror #8
+ mla $x, $x, $a, r14
+
+ ; Now we are trashing r14 to free it for other purposes
+
+ ; uint r14 = (y & 0xff00ff) * b
+ uxtb16 r14, $y ; r14 = y & 0x00FF00FF
+ mul r14, r14, $b
+
+ ; r8 = r8 + r14
+ add r8, r8, r14
+
+ ; r8 = (r8 + ((r8 >> 8) & 0xff00ff) ) >> 8
+ ; r8 &= 0xff00ff
+ uxtab16 r8, r8, r8, ror #8
+ uxtb16 r8, r8, ror #8
+
+ ; r14 = ((y >> 8) & 0xff00ff) * b
+ uxtb16 r14, $y, ror #8 ; r14 = ((y >> 8) & 0xFF00FF)
+ mul r14, r14, $b
+
+ ; x = x + r14
+ add $x, $x, r14
+
+ ; x = x + ((x >>8) & 0xff00ff)
+ uxtab16 $x, $x, $x, ror #8
+
+ ; x &= 0xff00ff00
+ ; x |= r8
+ uxtb16 $x, $x, ror #8
+ orr $dst, r8, $x, lsl #8
+
+ MEND
+
+;-----------------------------------------------------------------------------
+;
+;-----------------------------------------------------------------------------
+ MACRO
+$label Blend4Pixels $BlendPixel
+
+ ; Blend first 4 pixels
+
+ ldmia r1!, {r4-r7}
+ ldm r0, {r9-r12}
+
+b4p1_$label $BlendPixel r9, r4, r3
+b4p2_$label $BlendPixel r10, r5, r3
+b4p3_$label $BlendPixel r11, r6, r3
+b4p4_$label $BlendPixel r12, r7, r3
+
+ stmia r0!, {r9-r12}
+
+ MEND
+
+;-----------------------------------------------------------------------------
+;
+;-----------------------------------------------------------------------------
+ MACRO
+$label Blend8Pixels $BlendPixel
+
+b8p1_$label Blend4Pixels $BlendPixel
+b8p2_$label Blend4Pixels $BlendPixel
+
+ MEND
+
+;-----------------------------------------------------------------------------
+;
+;-----------------------------------------------------------------------------
+ MACRO
+$label Blend16Pixels $BlendPixel
+
+b16p1_$label Blend8Pixels $BlendPixel
+b16p2_$label Blend8Pixels $BlendPixel
+
+ MEND
+
+;-----------------------------------------------------------------------------
+;
+;-----------------------------------------------------------------------------
+ MACRO
+$label Blend32Pixels $BlendPixel
+
+b32p1_$label Blend16Pixels $BlendPixel
+b32p2_$label Blend16Pixels $BlendPixel
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one row of pixels and saving the results
+; to destination buffer.
+;
+; @param dest Destination buffer (r0)
+; @param src Source buffer (r1)
+; @param length Length (r2)
+; @param const_alpha Constant alpha (r3)
+; @param r14 Component Half (0x800080) (r14)
+;
+; @note Advances r0, r1
+; @note Trashes r2, r4-r12
+;-----------------------------------------------------------------------------
+ MACRO
+$label BlendRow $BlendPixel
+
+ pld [r1]
+
+bloop_$label
+ ; Blend 32 pixels per loop iteration
+ subs r2, r2, #32
+ bmi b_remaining_$label
+
+brp1_$label Blend32Pixels $BlendPixel
+
+ b bloop_$label
+
+b_remaining_$label
+
+ ; Remaining 31 pixels
+
+ addmi r2, r2, #32
+
+ ; Blend 16 pixels
+ tst r2, #16
+ beq b_remaining8_$label
+
+brp2_$label Blend16Pixels $BlendPixel
+
+b_remaining8_$label
+
+ ; Blend 8 pixels
+ tst r2, #8
+ beq b_remaining4_$label
+
+brp3_$label Blend8Pixels $BlendPixel
+
+b_remaining4_$label
+
+ ; Blend 4 pixels
+ tst r2, #4
+ beq b_remaining3_$label
+
+brp4_$label Blend4Pixels $BlendPixel
+
+b_remaining3_$label
+
+ ; Remaining 3 pixels
+
+ tst r2, #2
+ beq b_last_$label
+
+ ldmia r1!, {r4-r5}
+ ldm r0, {r9-r10}
+
+brp5_$label $BlendPixel r9, r4, r3
+brp6_$label $BlendPixel r10, r5, r3
+
+ stmia r0!, {r9-r10}
+
+b_last_$label
+
+ tst r2, #1
+ beq bexit_$label
+
+ ldr r4, [r1]
+ ldr r9, [r0]
+
+bpl_$label $BlendPixel r9, r4, r3
+
+ str r9, [r0]
+
+bexit_$label
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one row of pixels and saving the results
+; to destination buffer. Restores all registers.
+;
+; @param dest Destination buffer (r0)
+; @param src Source buffer (r1)
+; @param length Length (r2)
+; @param const_alpha Constant alpha (r3)
+; @param r14 Component Half (0x800080) (r14)
+;
+; @note Advances r0, r1
+; @note Trashes r2, r4-r12
+;-----------------------------------------------------------------------------
+ MACRO
+$label BlendRowSafe $BlendPixel
+
+ stmfd sp!, {r0-r6} ; Preserves registers only up to r6
+
+brs_$label BlendRow $BlendPixel
+
+ ldmfd sp!, {r0-r6}
+
+ MEND
+
+
+;-----------------------------------------------------------------------------
+; Pix Copy.
+; NOTE! Cache line size of ARM1136JF-S and ARM1136J-S is 32 bytes (8 pixels).
+;
+; @param dst Destination pixels (r0)
+; @param src Source pixels (r1)
+; @param len Length (r2)
+;
+; @note Trashes r3-r10
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixCpy $dst, $src, $len
+
+ pld [$src]
+
+pcpy_loop_$label
+ ; Copy 8 pixels per loop iteration
+ pld [$src, #96]
+ subs $len, $len, #8
+ ldmgeia $src!, {r3-r10}
+ stmgeia $dst!, {r3-r10}
+ bgt pcpy_loop_$label
+
+pcpy_remaining_$label
+
+ ; Copy up to 7 remaining pixels
+
+ ; Copy 4 pixels
+ tst $len, #4
+ ldmneia $src!, {r3-r6}
+ stmneia $dst!, {r3-r6}
+
+ tst $len, #2
+ ldmneia $src!, {r3-r4}
+ stmneia $dst!, {r3-r4}
+
+ tst $len, #1
+ ldrne r3, [$src]
+ strne r3, [$dst]
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; General Pix Copy. Maximum 8 pixels at time. Restores all registers.
+;
+; @param dst Destination pixels (r0)
+; @param src Source pixels (r1)
+; @param len Length (r2)
+;
+; @note Trashes r3-r10
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixCpySafe $dst, $src, $len
+
+ stmfd sp!, {r0-r6} ; Preserves registers only up to r6
+
+pcs_$label PixCpy $dst, $src, $len
+
+ ldmfd sp!, {r0-r6} ; pop
+
+ MEND
+
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one pixel and saving the result to
+; dst register.
+;
+; @param dst Destination register, must contain destination pixel upon entry
+; @param src Source register, must contain source pixel upon entry
+; @param const_alpha Constant source alpha
+; @param r14 Component half 0x800080
+;
+; @note Trashes const_alpha, r8
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixelSourceOver $dst, $src, $const_alpha
+
+ ; Negate src and extract alpha
+ mvn $const_alpha, $src ; bitwise not
+ uxtb $const_alpha, $const_alpha, ror #24 ; r3 = ((r3 & 0xFF000000) >> 24);
+
+ ;cmp $const_alpha, #255 ; test for full transparency ( negated )
+ ;beq exit_$label
+ cmp $const_alpha, #0 ; test for full opacity ( negated )
+ moveq $dst, $src
+ beq exit_$label
+
+ ByteMul $dst, $dst, $const_alpha
+ add $dst, $src, $dst
+
+exit_$label
+ MEND
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one pixel and saving the result to
+; dst register.
+;
+; @param dst Destination register, must contain destination pixel upon entry
+; @param src Source register, must contain source pixel upon entry
+; @param const_alpha Constant source alpha
+; @param r14 Component half 0x800080
+;
+; @note Trashes src, const_alpha, r8
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixelSourceOverConstAlpha $dst, $src, $const_alpha
+
+ ; store alpha because we are going to trash it
+ stmfd sp!, {$const_alpha}
+
+ ByteMul $src, $src, $const_alpha
+
+ ; Negate src and extract alpha
+ mvn $const_alpha, $src ; bitwise not
+ uxtb $const_alpha, $const_alpha, ror #24 ; r3 = ((r3 & 0xFF000000) >> 24);
+
+ ByteMul $dst, $dst, $const_alpha
+
+ add $dst, $src, $dst
+
+ ; recover alpha
+ ldmfd sp!, {$const_alpha}
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one pixel and saving the result to
+; a register.
+;
+; @param dst Destination register, must contain destination pixel upon entry
+; @param src Source register, must contain source pixel upon entry
+; @param const_alpha Constant source alpha
+; @param r14 Component half 0x800080
+;
+; @note Trashes src, r8
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixelSourceConstAlpha $dst, $src, $const_alpha
+
+ ; store r2 and r14 because we are going to trash them
+ stmfd sp!, {r2, r14}
+
+ rsb r2, $const_alpha, #255
+ InterpolatePixel255 $dst, $src, $const_alpha, $dst, r2
+
+ ; recover r2 and r14
+ ldmfd sp!, {r2, r14}
+
+ MEND
+
+ END ; File end
diff --git a/src/gui/painting/qdrawhelper_armv6_rvct.s b/src/gui/painting/qdrawhelper_armv6_rvct.s
new file mode 100644
index 0000000..51b67a4
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_armv6_rvct.s
@@ -0,0 +1,177 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;** Contact: Nokia Corporation (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module of the Qt Toolkit.
+;**
+;** $QT_BEGIN_LICENSE:LGPL$
+;** No Commercial Usage
+;** This file contains pre-release code and may not be distributed.
+;** You may use this file in accordance with the terms and conditions
+;** contained in the either Technology Preview License Agreement or the
+;** Beta Release License Agreement.
+;**
+;** GNU Lesser General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU Lesser
+;** General Public License version 2.1 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.LGPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU Lesser General Public License version 2.1 requirements
+;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;**
+;** In addition, as a special exception, Nokia gives you certain
+;** additional rights. These rights are described in the Nokia Qt LGPL
+;** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;** package.
+;**
+;** GNU General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU
+;** General Public License version 3.0 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.GPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU General Public License version 3.0 requirements will be
+;** met: http://www.gnu.org/copyleft/gpl.html.
+;**
+;** If you are unsure which license is appropriate for your use, please
+;** contact the sales department at http://qt.nokia.com/contact.
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+
+;
+; W A R N I N G
+; -------------
+;
+; This file is not part of the Qt API. It exists purely as an
+; implementation detail. This header file may change from version to
+; version without notice, or even be removed.
+;
+; We mean it.
+;
+
+ ARM
+ PRESERVE8
+
+ INCLUDE qdrawhelper_armv6_rvct.inc
+
+;-----------------------------------------------------------------------------
+; qt_memfill32_armv6
+;
+; @brief Not yet in use!
+;
+; @param dest Destination buffer (r0)
+; @param value Value (r1)
+; @param count Count (r2)
+;
+;---------------------------------------------------------------------------
+qt_memfill32_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ mov r3, r1
+ mov r4, r1
+ mov r5, r1
+ mov r6, r1
+ mov r7, r1
+ mov r8, r1
+ mov r9, r1
+
+mfill_loop
+ ; Fill 32 pixels per loop iteration
+ subs r2, r2, #32
+ stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ bgt mfill_loop
+
+mfill_remaining
+
+ ; Fill up to 31 remaining pixels
+
+ ; Fill 16 pixels
+ tst r2, #16
+ stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+
+ ; Fill 8 pixels
+ tst r2, #8
+ stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+
+ ; Fill 4 pixels
+ tst r2, #4
+ stmneia r0!, {r1, r3, r4, r5}
+
+ ; Fill 2 pixels
+ tst r2, #2
+ stmneia r0!, {r1, r3}
+
+ ; Fill last one
+ tst r2, #1
+ strne r1, [r0]
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+;-----------------------------------------------------------------------------
+; comp_func_Source_arm
+;
+; @brief
+;
+; @param dest Destination buffer (r0)
+; @param src Source buffer (r1)
+; @param length Length (r2)
+; @param const_alpha Constant alpha (r3)
+;
+;---------------------------------------------------------------------------
+comp_func_Source_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ cmp r3, #255 ; if(r3 == 255)
+ bne src2 ; branch if not
+
+src1 PixCpy r0, r1, r2
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+src2
+ ;ldr r14, =ComponentHalf ; load 0x800080 to r14
+ mov r14, #0x800000
+ add r14, r14, #0x80
+
+src22 BlendRow PixelSourceConstAlpha
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+;-----------------------------------------------------------------------------
+; comp_func_SourceOver_arm
+;
+; @brief
+;
+; @param dest Destination buffer (r0)
+; @param src Source buffer (r1)
+; @param length Length (r2)
+; @param const_alpha Constant alpha (r3)
+;
+;---------------------------------------------------------------------------
+comp_func_SourceOver_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ ;ldr r14, =ComponentHalf ; load 0x800080 to r14
+ mov r14, #0x800000
+ add r14, r14, #0x80
+
+ cmp r3, #255 ; if(r3 == 255)
+ bne srcovr2 ; branch if not
+
+srcovr1 BlendRow PixelSourceOver
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+srcovr2
+
+srcovr22 BlendRow PixelSourceOverConstAlpha
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+
+ END ; File end
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 71378ec..45a5440 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -87,7 +87,7 @@ QT_BEGIN_NAMESPACE
#if defined(Q_CC_RVCT)
// RVCT doesn't like static template functions
# define Q_STATIC_TEMPLATE_FUNCTION
-# define Q_STATIC_INLINE_FUNCTION inline
+# define Q_STATIC_INLINE_FUNCTION static __forceinline
#else
# define Q_STATIC_TEMPLATE_FUNCTION static
# define Q_STATIC_INLINE_FUNCTION static inline
@@ -110,6 +110,7 @@ struct QSpanData;
class QGradient;
class QRasterBuffer;
class QClipData;
+class QRasterPaintEngineState;
typedef QT_FT_SpanFunc ProcessSpans;
typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer,
@@ -145,6 +146,14 @@ typedef void (*SrcOverScaleFunc)(uchar *destPixels, int dbpl,
const QRect &clipRect,
int const_alpha);
+typedef void (*SrcOverTransformFunc)(uchar *destPixels, int dbpl,
+ const uchar *src, int spbl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clipRect,
+ const QTransform &targetRectTransform,
+ int const_alpha);
+
struct DrawHelper {
ProcessSpans blendColor;
@@ -157,6 +166,7 @@ struct DrawHelper {
extern SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats];
extern SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats];
+extern SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats];
extern DrawHelper qDrawHelper[QImage::NImageFormats];
@@ -293,26 +303,30 @@ struct QSpanData
};
void init(QRasterBuffer *rb, const QRasterPaintEngine *pe);
- void setup(const QBrush &brush, int alpha);
+ void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode);
void setupMatrix(const QTransform &matrix, int bilinear);
void initTexture(const QImage *image, int alpha, QTextureData::Type = QTextureData::Plain, const QRect &sourceRect = QRect());
void adjustSpanMethods();
};
-static inline uint BYTE_MUL_RGB16(uint x, uint a) {
+Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) {
a += 1;
uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0;
t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f;
return t;
}
-static inline uint BYTE_MUL_RGB16_32(uint x, uint a) {
+Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) {
uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0;
t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f;
return t;
}
+#if defined(Q_CC_RVCT)
+# pragma push
+# pragma arm
+#endif
Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
uint t = (x & 0xff00ff) * a;
t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
@@ -324,8 +338,11 @@ Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
x |= t;
return x;
}
+#if defined(Q_CC_RVCT)
+# pragma pop
+#endif
-static inline uint PREMUL(uint x) {
+Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
uint a = x >> 24;
uint t = (x & 0xff00ff) * a;
t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
@@ -390,7 +407,7 @@ public:
return qt_colorConvert<quint16, quint32>(data, 0);
}
- static inline quint32p fromRawData(quint32 v)
+ Q_STATIC_INLINE_FUNCTION quint32p fromRawData(quint32 v)
{
quint32p p;
p.data = v;
@@ -421,7 +438,7 @@ class qrgb565;
class qargb8565
{
public:
- static inline bool hasAlpha() { return true; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; }
inline qargb8565() {}
inline qargb8565(quint32 v);
@@ -438,14 +455,15 @@ public:
data[1] &= 0xdf;
return *this;
}
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; }
- static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
inline qargb8565 byte_mul(quint8 a) const;
inline qargb8565 operator+(qargb8565 v) const;
inline bool operator==(const qargb8565 &v) const;
inline quint32 rawValue() const;
+ inline quint16 rawValue16() const;
private:
friend class qrgb565;
@@ -456,13 +474,13 @@ private:
class qrgb565
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
qrgb565(int v = 0) : data(v) {}
inline explicit qrgb565(quint32p v);
inline explicit qrgb565(quint32 v);
- inline explicit qrgb565(qargb8565 v);
+ inline explicit qrgb565(const qargb8565 &v);
inline operator quint32() const;
inline operator quint16() const;
@@ -471,8 +489,8 @@ public:
inline quint8 alpha() const { return 0xff; }
inline qrgb565 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; }
- static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
inline qrgb565 byte_mul(quint8 a) const;
@@ -568,6 +586,11 @@ quint32 qargb8565::rawValue() const
return (data[2] << 16) | (data[1] << 8) | data[0];
}
+quint16 qargb8565::rawValue16() const
+{
+ return (data[2] << 8) | data[1];
+}
+
qrgb565::qrgb565(quint32p v)
{
*this = qrgb565(quint32(v));
@@ -582,7 +605,7 @@ qrgb565::qrgb565(quint32 v)
data = (r & 0xf800) | (g & 0x07e0)| (b & 0x001f);
}
-qrgb565::qrgb565(qargb8565 v)
+qrgb565::qrgb565(const qargb8565 &v)
{
data = (v.data[2] << 8) | v.data[1];
}
@@ -647,7 +670,7 @@ class qrgb555;
class qargb8555
{
public:
- static inline bool hasAlpha() { return true; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; }
qargb8555() {}
inline qargb8555(quint32 v);
@@ -659,8 +682,8 @@ public:
inline quint8 alpha() const { return data[0]; }
inline qargb8555 truncedAlpha() { data[0] &= 0xf8; return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; }
- static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
inline qargb8555 operator+(qargb8555 v) const;
inline qargb8555 byte_mul(quint8 a) const;
@@ -677,7 +700,7 @@ private:
class qrgb555
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
inline qrgb555(int v = 0) : data(v) {}
@@ -726,8 +749,8 @@ public:
inline quint8 alpha() const { return 0xff; }
inline qrgb555 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; }
- static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
inline bool operator==(const qrgb555 &v) const { return v.data == data; }
inline bool operator!=(const qrgb555 &v) const { return v.data != data; }
@@ -875,7 +898,7 @@ class qrgb666;
class qargb6666
{
public:
- static inline bool hasAlpha() { return true; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; }
inline qargb6666() {}
inline qargb6666(quint32 v) { *this = qargb6666(quint32p(v)); }
@@ -887,8 +910,8 @@ public:
inline quint8 alpha() const;
inline qargb6666 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 2; }
- static inline quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; }
inline qargb6666 byte_mul(quint8 a) const;
inline qargb6666 operator+(qargb6666 v) const;
@@ -905,7 +928,7 @@ private:
class qrgb666
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
inline qrgb666() {}
inline qrgb666(quint32 v);
@@ -915,8 +938,8 @@ public:
inline quint8 alpha() const { return 0xff; }
inline qrgb666 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 2; }
- static inline quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; }
inline qrgb666 operator+(qrgb666 v) const;
inline qrgb666 byte_mul(quint8 a) const;
@@ -1073,7 +1096,7 @@ quint32 qargb6666::rawValue() const
class qrgb888
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
inline qrgb888() {}
inline qrgb888(quint32 v);
@@ -1082,8 +1105,8 @@ public:
inline quint8 alpha() const { return 0xff; }
inline qrgb888 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return a; }
- static inline quint8 ialpha(quint8 a) { return 255 - a; }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return a; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 255 - a; }
inline qrgb888 byte_mul(quint8 a) const;
inline qrgb888 operator+(qrgb888 v) const;
@@ -1262,7 +1285,7 @@ class qrgb444;
class qargb4444
{
public:
- static inline bool hasAlpha() { return true; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; }
inline qargb4444() {}
inline qargb4444(quint32 v) { *this = qargb4444(quint32p(v)); }
@@ -1276,8 +1299,8 @@ public:
inline quint8 alpha() const { return ((data & 0xf000) >> 8) | ((data & 0xf000) >> 12); }
inline qargb4444 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 4; }
- static inline quint8 ialpha(quint8 a) { return 0x10 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); }
inline qargb4444 byte_mul(quint8 a) const;
inline bool operator==(const qargb4444 &v) const { return data == v.data; }
@@ -1293,7 +1316,7 @@ private:
class qrgb444
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
inline qrgb444() {}
inline qrgb444(quint32 v);
@@ -1305,8 +1328,8 @@ public:
inline qrgb444 operator+(qrgb444 v) const;
inline quint8 alpha() const { return 0xff; }
inline qrgb444 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 4; }
- static inline quint8 ialpha(quint8 a) { return 0x10 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); }
inline qrgb444 byte_mul(quint8 a) const;
inline bool operator==(const qrgb444 &v) const { return data == v.data; }
@@ -1767,7 +1790,14 @@ do { \
} \
} while (0)
+#if defined(Q_CC_RVCT)
+# pragma push
+# pragma arm
+#endif
Q_STATIC_INLINE_FUNCTION int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
+#if defined(Q_CC_RVCT)
+# pragma pop
+#endif
inline ushort qConvertRgb32To16(uint c)
{
@@ -1810,7 +1840,7 @@ inline int qBlue565(quint16 rgb) {
}
#if 1
-static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
+Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
t >>= 8;
t &= 0xff00ff;
@@ -1821,7 +1851,11 @@ static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
return x;
}
-static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
+#if defined(Q_CC_RVCT)
+# pragma push
+# pragma arm
+#endif
+Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
t &= 0xff00ff;
@@ -1832,9 +1866,12 @@ static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
x |= t;
return x;
}
+#if defined(Q_CC_RVCT)
+# pragma pop
+#endif
#else
// possible implementation for 64 bit
-static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
+Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b;
t >>= 8;
@@ -1842,7 +1879,7 @@ static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
return (uint(t)) | (uint(t >> 24));
}
-static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
+Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b;
t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080);
@@ -1857,7 +1894,7 @@ Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
return (uint(t)) | (uint(t >> 24));
}
-static inline uint PREMUL(uint x) {
+Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
uint a = x >> 24;
ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080);
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index a9c1f6f..59a5063 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1008,8 +1008,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
;
#ifndef QT_NO_IMAGE_HEURISTIC_MASK
} else { // color pixmap, no mask
- QString k;
- k.sprintf("$qt-drawitem-%llx", pm.cacheKey());
+ QString k = QString::fromLatin1("$qt-drawitem-%1").arg(pm.cacheKey());
if (!QPixmapCache::find(k, pm)) {
pm = pm.createHeuristicMask();
pm.setMask((QBitmap&)pm);
@@ -1038,4 +1037,328 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
#endif
+/*!
+ \class QMargins
+ \since 4.6
+
+ Holds the borders used to split a pixmap into nine segments in order to
+ draw it, similar to \l{http://www.w3.org/TR/css3-background/}
+ {CSS3 border-images}.
+
+ \sa Qt::TileRule, QTileRules
+*/
+
+/*! \fn QMargins::QMargins(int margin)
+ Constructs a QMargins with the top, left, bottom, and
+ right margins set to \a margin.
+*/
+
+/*! \fn QMargins::QMargins(int topMargin, int leftMargin, int bottomMargin, int rightMargin)
+ Constructs a QMargins with the given \a topMargin, \a leftMargin,
+ \a bottomMargin, and \a rightMargin.
+ */
+
+/*!
+ \class QTileRules
+ \since 4.6
+
+ Holds the rules used to draw a pixmap or image split into nine segments,
+ similar to \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}.
+
+ \sa Qt::TileRule, QMargins
+*/
+
+/*! \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule)
+ Constructs a QTileRules with the given \a horizontalRule and
+ \a verticalRule.
+ */
+
+/*! \fn QTileRules::QTileRules(Qt::TileRule rule)
+ Constructs a QTileRules with the given \a rule used for both
+ the horizontal rule and the vertical rule.
+ */
+
+/*!
+ \fn void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)
+ \since 4.6
+ \relates QMargins
+
+ Draws the given \a pixmap into the given \a target rectangle, using the
+ given \a painter. The pixmap will be split into nine segments and drawn
+ according to the \a margins structure.
+*/
+
+static inline void qVerticalRepeat(QPainter *painter,
+ const QRect &target,
+ const QPixmap &pixmap,
+ const QRect &source,
+ void (*drawPixmap)(QPainter*,
+ const QRect&,
+ const QPixmap&,
+ const QRect&))
+{
+ const int x = target.x();
+ const int width = target.width();
+ const int height = source.height();
+ const int bottom = target.bottom() - height;
+ int y = target.y();
+ for (; y < bottom; y += height)
+ (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source);
+ const QRect remaining(source.x(), source.y(), source.width(), target.bottom() - y + 1);
+ (*drawPixmap)(painter, QRect(x, y, width, remaining.height()), pixmap, remaining);
+}
+
+static inline void qHorizontalRepeat(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ const int y = target.y();
+ const int width = source.width();
+ const int height = target.height();
+ const int right = target.right() - width;
+ int x = target.x();
+ for (; x < right; x += width)
+ (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source);
+ const QRect remaining(source.x(), source.y(), target.right() - x + 1, source.height());
+ (*drawPixmap)(painter, QRect(x, y, remaining.width(), height), pixmap, remaining);
+}
+
+static inline void qVerticalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ // qreal based - slow on non-fpu devices
+ const qreal x = target.x();
+ const qreal width = target.width();
+ const qreal verticalFactor = static_cast<qreal>(target.height()) / static_cast<qreal>(source.height());
+ const qreal verticalIncrement = static_cast<qreal>(target.height()) / static_cast<int>(verticalFactor + 0.5);
+ const qreal bottom = target.bottom();
+ for (qreal y = static_cast<qreal>(target.y()); y < bottom; y += verticalIncrement)
+ (*drawPixmap)(painter, QRectF(x, y, width, verticalIncrement).toRect(), pixmap, source);
+
+}
+
+static inline void qHorizontalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ // qreal based - slow on non-fpu devices
+ const qreal y = target.y();
+ const qreal height = target.height();
+ const qreal horizontalFactor = static_cast<qreal>(target.width()) / static_cast<qreal>(source.width());
+ const qreal horizontalIncrement = static_cast<qreal>(target.width()) / static_cast<int>(horizontalFactor + 0.5);
+ const qreal right = target.right();
+ for (qreal x = target.x(); x < right; x += horizontalIncrement)
+ (*drawPixmap)(painter, QRectF(x, y, horizontalIncrement, height).toRect(), pixmap, source);
+}
+
+static inline void qDrawPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ painter->drawPixmap(target, pixmap, source);
+}
+
+static inline void qDrawVerticallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qVerticalRepeat(painter, target, pixmap, source, qDrawPixmap);
+}
+
+static inline void qDrawHorizontallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qHorizontalRepeat(painter, target, pixmap, source, qDrawPixmap);
+}
+
+static inline void qDrawVerticallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qVerticalRound(painter, target, pixmap, source, qDrawPixmap);
+}
+
+static inline void qDrawHorizontallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qHorizontalRound(painter, target, pixmap, source, qDrawPixmap);
+}
+
+/*!
+ \since 4.6
+
+ Draws the indicated \a sourceRect rectangle from the given \a pixmap into
+ the given \a targetRect rectangle, using the given \a painter. The pixmap
+ will be split into nine segments according to the given \a targetMargins
+ and \a sourceMargins structures. Finally, the pixmap will be drawn
+ according to the given \a rules.
+
+ This function is used to draw a scaled pixmap, similar to
+ \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}
+
+ \sa Qt::TileRule, QTileRules, QMargins
+*/
+
+void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, const QPixmap &pixmap,
+ const QRect &sourceRect, const QMargins &sourceMargins, const QTileRules &rules)
+{
+ // source center
+ const int sourceTop = sourceRect.top();
+ const int sourceLeft = sourceRect.left();
+ const int sourceCenterTop = sourceTop + sourceMargins.top;
+ const int sourceCenterLeft = sourceLeft + sourceMargins.left;
+ const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom + 1;
+ const int sourceCenterRight = sourceRect.right() - sourceMargins.right + 1;
+ const int sourceCenterWidth = sourceCenterRight - sourceMargins.left;
+ const int sourceCenterHeight = sourceCenterBottom - sourceMargins.top;
+ // target center
+ const int targetTop = targetRect.top();
+ const int targetLeft = targetRect.left();
+ const int targetCenterTop = targetTop + targetMargins.top;
+ const int targetCenterLeft = targetLeft + targetMargins.left;
+ const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom + 1;
+ const int targetCenterRight = targetRect.right() - targetMargins.right + 1;
+ const int targetCenterWidth = targetCenterRight - targetCenterLeft;
+ const int targetCenterHeight = targetCenterBottom - targetCenterTop;
+
+ // corners
+ if (targetMargins.top > 0 && targetMargins.left > 0 && sourceMargins.top > 0 && sourceMargins.left > 0) { // top left
+ const QRect targetTopLeftRect(targetLeft, targetTop, targetMargins.left, targetMargins.top);
+ const QRect sourceTopLeftRect(sourceLeft, sourceTop, sourceMargins.left, sourceMargins.top);
+ qDrawPixmap(painter, targetTopLeftRect, pixmap, sourceTopLeftRect);
+ }
+ if (targetMargins.top > 0 && targetMargins.right > 0 && sourceMargins.top > 0 && sourceMargins.right > 0) { // top right
+ const QRect targetTopRightRect(targetCenterRight, targetTop, targetMargins.right, targetMargins.top);
+ const QRect sourceTopRightRect(sourceCenterRight, sourceTop, sourceMargins.right, sourceMargins.top);
+ qDrawPixmap(painter, targetTopRightRect, pixmap, sourceTopRightRect);
+ }
+ if (targetMargins.bottom > 0 && targetMargins.left > 0 && sourceMargins.bottom > 0 && sourceMargins.left > 0) { // bottom left
+ const QRect targetBottomLeftRect(targetLeft, targetCenterBottom, targetMargins.left, targetMargins.bottom);
+ const QRect sourceBottomLeftRect(sourceLeft, sourceCenterBottom, sourceMargins.left, sourceMargins.bottom);
+ qDrawPixmap(painter, targetBottomLeftRect, pixmap, sourceBottomLeftRect);
+ }
+ if (targetMargins.bottom > 0 && targetMargins.right > 0 && sourceMargins.bottom > 0 && sourceMargins.right > 0) { // bottom right
+ const QRect targetBottomRightRect(targetCenterRight, targetCenterBottom, targetMargins.right, targetMargins.bottom);
+ const QRect sourceBottomRightRect(sourceCenterRight, sourceCenterBottom, sourceMargins.right, sourceMargins.bottom);
+ qDrawPixmap(painter, targetBottomRightRect, pixmap, sourceBottomRightRect);
+ }
+
+ // horizontal edges
+ switch (rules.horizontal) {
+ case Qt::Stretch:
+ if (targetMargins.top > 0 && sourceMargins.top > 0) { // top
+ const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top);
+ const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top);
+ qDrawPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ }
+ if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom
+ const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom);
+ const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom);
+ qDrawPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ }
+ break;
+ case Qt::Repeat:
+ if (targetMargins.top > 0 && sourceMargins.top > 0) { // top
+ const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top);
+ const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top);
+ qDrawHorizontallyRepeatedPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ }
+ if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom
+ const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom);
+ const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom);
+ qDrawHorizontallyRepeatedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ }
+ break;
+ case Qt::Round:
+ if (targetMargins.top > 0 && sourceMargins.top > 0) { // top
+ const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top);
+ const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top);
+ qDrawHorizontallyRoundedPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ }
+ if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom
+ const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom);
+ const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom);
+ qDrawHorizontallyRoundedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ }
+ break;
+ }
+
+ // vertical edges
+ switch (rules.vertical) {
+ case Qt::Stretch:
+ if (targetMargins.left > 0 && sourceMargins.left > 0) { // left
+ const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight);
+ const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight);
+ qDrawPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ }
+ if (targetMargins.right > 0 && sourceMargins.right > 0) { // right
+ const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight);
+ const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight);
+ qDrawPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ }
+ break;
+ case Qt::Repeat:
+ if (targetMargins.left > 0 && sourceMargins.left > 0) { // left
+ const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight);
+ const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight);
+ qDrawVerticallyRepeatedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ }
+ if (targetMargins.right > 0 && sourceMargins.right > 0) { // right
+ const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight);
+ const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight);
+ qDrawVerticallyRepeatedPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ }
+ break;
+ case Qt::Round:
+ if (targetMargins.left > 0 && sourceMargins.left > 0) { // left
+ const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight);
+ const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight);
+ qDrawVerticallyRoundedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ }
+ if (targetMargins.right > 0 && sourceMargins.right > 0) { // right
+ const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight);
+ const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight);
+ qDrawVerticallyRoundedPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ }
+ break;
+ }
+
+ // center
+ if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
+ const QRect targetCenterRect(targetCenterLeft, targetCenterTop, targetCenterWidth, targetCenterHeight);
+ const QRect sourceCenterRect(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
+ switch (rules.horizontal) {
+ case Qt::Stretch:
+ switch (rules.vertical) {
+ case Qt::Stretch: // stretch stretch
+ qDrawPixmap(painter, targetCenterRect, pixmap, sourceCenterRect);
+ break;
+ case Qt::Repeat: // stretch repeat
+ qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ case Qt::Round: // stretch round
+ qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ }
+ break;
+ case Qt::Repeat:
+ switch (rules.vertical) {
+ case Qt::Stretch: // repeat stretch
+ qHorizontalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ case Qt::Repeat: // repeat repeat
+ qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap);
+ break;
+ case Qt::Round: // repeat round
+ qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap);
+ break;
+ }
+ break;
+ case Qt::Round:
+ switch (rules.vertical) {
+ case Qt::Stretch: // round stretch
+ qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ case Qt::Repeat: // round repeat
+ qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRepeatedPixmap);
+ break;
+ case Qt::Round: // round round
+ qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRoundedPixmap);
+ break;
+ }
+ break;
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawutil.h b/src/gui/painting/qdrawutil.h
index 02b71a9..4135c19 100644
--- a/src/gui/painting/qdrawutil.h
+++ b/src/gui/painting/qdrawutil.h
@@ -44,6 +44,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qstring.h> // char*->QString conversion
+#include <QtGui/qpixmap.h>
QT_BEGIN_HEADER
@@ -60,7 +61,6 @@ class QPoint;
class QColor;
class QBrush;
class QRect;
-class QPixmap;
//
// Standard shade drawing
@@ -133,6 +133,49 @@ Q_GUI_EXPORT QT3_SUPPORT void qDrawArrow(QPainter *p, Qt::ArrowType type, Qt::GU
const QPalette &pal, bool enabled);
#endif
+struct QMargins
+{
+ inline QMargins(int margin = 0)
+ : top(margin),
+ left(margin),
+ bottom(margin),
+ right(margin) {}
+ inline QMargins(int topMargin, int leftMargin, int bottomMargin, int rightMargin)
+ : top(topMargin),
+ left(leftMargin),
+ bottom(bottomMargin),
+ right(rightMargin) {}
+ int top;
+ int left;
+ int bottom;
+ int right;
+};
+
+struct QTileRules
+{
+ inline QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule = Qt::Stretch)
+ : horizontal(horizontalRule), vertical(verticalRule) {}
+ inline QTileRules(Qt::TileRule rule = Qt::Stretch)
+ : horizontal(rule), vertical(rule) {}
+ Qt::TileRule horizontal;
+ Qt::TileRule vertical;
+};
+
+Q_GUI_EXPORT void qDrawBorderPixmap(QPainter *painter,
+ const QRect &targetRect,
+ const QMargins &targetMargins,
+ const QPixmap &pixmap,
+ const QRect &sourceRect,
+ const QMargins &sourceMargins,
+ const QTileRules &rules = QTileRules());
+inline void qDrawBorderPixmap(QPainter *painter,
+ const QRect &target,
+ const QMargins &margins,
+ const QPixmap &pixmap)
+{
+ qDrawBorderPixmap(painter, target, margins, pixmap, pixmap.rect(), margins);
+}
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp
index 26bc3c0..ea4595a 100644
--- a/src/gui/painting/qemulationpaintengine.cpp
+++ b/src/gui/painting/qemulationpaintengine.cpp
@@ -99,9 +99,9 @@ void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
} else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
QBrush copy = brush;
QTransform mat = copy.transform();
- QRealRect r = path.controlPointRect();
- mat.translate(r.x1, r.y1);
- mat.scale(r.x2 - r.x1, r.y2 - r.y1);
+ QRectF r = path.controlPointRect();
+ mat.translate(r.x(), r.y());
+ mat.scale(r.width(), r.height());
copy.setTransform(mat);
real_engine->fill(path, copy);
return;
@@ -139,9 +139,9 @@ void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
return;
} else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
QTransform mat = brush.transform();
- QRealRect r = path.controlPointRect();
- mat.translate(r.x1, r.y1);
- mat.scale(r.x2 - r.x1, r.y2 - r.y1);
+ QRectF r = path.controlPointRect();
+ mat.translate(r.x(), r.y());
+ mat.scale(r.width(), r.height());
brush.setTransform(mat);
copy.setBrush(brush);
real_engine->stroke(path, copy);
diff --git a/src/gui/painting/qfixed_p.h b/src/gui/painting/qfixed_p.h
index 3e5635b..70a92ab 100644
--- a/src/gui/painting/qfixed_p.h
+++ b/src/gui/painting/qfixed_p.h
@@ -181,8 +181,10 @@ inline bool operator<(int i, const QFixed &f) { return (i<<6) < f.value(); }
inline bool operator>(const QFixed &f, int i) { return f.value() > (i<<6); }
inline bool operator>(int i, const QFixed &f) { return (i<<6) > f.value(); }
+#ifndef QT_NO_DEBUG_STREAM
inline QDebug &operator<<(QDebug &dbg, const QFixed &f)
{ return dbg << f.toReal(); }
+#endif
struct QFixedPoint {
QFixed x;
diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp
index 38197e0..a7f5efb 100644
--- a/src/gui/painting/qgraphicssystem.cpp
+++ b/src/gui/painting/qgraphicssystem.cpp
@@ -44,7 +44,7 @@
#ifdef Q_WS_X11
# include <private/qpixmap_x11_p.h>
#endif
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
# include <private/qpixmap_raster_p.h>
#endif
#ifdef Q_WS_MAC
@@ -64,7 +64,7 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ
#endif
#if defined(Q_WS_X11)
return new QX11PixmapData(type);
-#elif defined(Q_WS_WIN)
+#elif defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
return new QRasterPixmapData(type);
#elif defined(Q_WS_MAC)
return new QMacPixmapData(type);
diff --git a/src/gui/painting/qgraphicssystemfactory.cpp b/src/gui/painting/qgraphicssystemfactory.cpp
index 2a886ca..979456a 100644
--- a/src/gui/painting/qgraphicssystemfactory.cpp
+++ b/src/gui/painting/qgraphicssystemfactory.cpp
@@ -64,7 +64,11 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key)
if (system.isEmpty()) {
system = QLatin1String("opengl");
}
-#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN)
+#elif defined (QT_GRAPHICSSYSTEM_OPENVG)
+ if (system.isEmpty()) {
+ system = QLatin1String("openvg");
+ }
+#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN)
if (system.isEmpty()) {
system = QLatin1String("raster");
}
diff --git a/src/gui/painting/qgraphicssystemfactory_p.h b/src/gui/painting/qgraphicssystemfactory_p.h
index 31a05a5..128230d 100644
--- a/src/gui/painting/qgraphicssystemfactory_p.h
+++ b/src/gui/painting/qgraphicssystemfactory_p.h
@@ -63,7 +63,7 @@ QT_MODULE(Gui)
class QGraphicsSystem;
-class Q_GUI_EXPORT QGraphicsSystemFactory
+class QGraphicsSystemFactory
{
public:
static QStringList keys();
diff --git a/src/gui/painting/qgraphicssystemplugin_p.h b/src/gui/painting/qgraphicssystemplugin_p.h
index 10479e4..528dafd 100644
--- a/src/gui/painting/qgraphicssystemplugin_p.h
+++ b/src/gui/painting/qgraphicssystemplugin_p.h
@@ -64,7 +64,7 @@ QT_MODULE(Gui)
class QGraphicsSystem;
-struct Q_GUI_EXPORT QGraphicsSystemFactoryInterface : public QFactoryInterface
+struct QGraphicsSystemFactoryInterface : public QFactoryInterface
{
virtual QGraphicsSystem *create(const QString &key) = 0;
};
diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c
index be3f18f..83f1cb9 100644
--- a/src/gui/painting/qgrayraster.c
+++ b/src/gui/painting/qgrayraster.c
@@ -134,7 +134,9 @@
#define ErrRaster_MemoryOverflow -4
-
+#if defined(VXWORKS)
+# include <vxWorksCommon.h> /* needed for setjmp.h */
+#endif
#include <string.h> /* for qt_ft_memcpy() */
#include <setjmp.h>
#include <limits.h>
@@ -1875,6 +1877,10 @@
if (memory)
fprintf(stderr, "gray_raster_new(), memory ignored");
memory = malloc(sizeof(TRaster));
+ if (!memory) {
+ *araster = 0;
+ return ErrRaster_Memory_Overflow;
+ }
QT_FT_MEM_ZERO(memory, sizeof(TRaster));
*araster = (QT_FT_Raster) memory;
diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp
index 166e9f1..c8a3499 100644
--- a/src/gui/painting/qmatrix.cpp
+++ b/src/gui/painting/qmatrix.cpp
@@ -55,11 +55,15 @@ QT_BEGIN_NAMESPACE
\class QMatrix
\brief The QMatrix class specifies 2D transformations of a
coordinate system.
+ \obsolete
- \ingroup multimedia
+ \ingroup painting
A matrix specifies how to translate, scale, shear or rotate the
coordinate system, and is typically used when rendering graphics.
+ QMatrix, in contrast to QTransform, does not allow perspective
+ transformations. QTransform is the recommended transformation
+ class in Qt.
A QMatrix object can be built using the setMatrix(), scale(),
rotate(), translate() and shear() functions. Alternatively, it
@@ -172,8 +176,8 @@ QT_BEGIN_NAMESPACE
\snippet doc/src/snippets/matrix/matrix.cpp 2
\endtable
- \sa QPainter, {The Coordinate System}, {demos/affine}{Affine
- Transformations Demo}, {Transformations Example}
+ \sa QPainter, QTransform, {The Coordinate System},
+ {demos/affine}{Affine Transformations Demo}, {Transformations Example}
*/
@@ -197,6 +201,10 @@ QT_BEGIN_NAMESPACE
/*****************************************************************************
QMatrix member functions
*****************************************************************************/
+/*!
+ \fn QMatrix::QMatrix(Qt::Initialization)
+ \internal
+*/
/*!
Constructs an identity matrix.
@@ -208,9 +216,13 @@ QT_BEGIN_NAMESPACE
*/
QMatrix::QMatrix()
+ : _m11(1.)
+ , _m12(0.)
+ , _m21(0.)
+ , _m22(1.)
+ , _dx(0.)
+ , _dy(0.)
{
- _m11 = _m22 = 1.0;
- _m12 = _m21 = _dx = _dy = 0.0;
}
/*!
@@ -220,12 +232,14 @@ QMatrix::QMatrix()
\sa setMatrix()
*/
-QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22,
- qreal dx, qreal dy)
+QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
+ : _m11(m11)
+ , _m12(m12)
+ , _m21(m21)
+ , _m22(m22)
+ , _dx(dx)
+ , _dy(dy)
{
- _m11 = m11; _m12 = m12;
- _m21 = m21; _m22 = m22;
- _dx = dx; _dy = dy;
}
@@ -233,8 +247,13 @@ QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22,
Constructs a matrix that is a copy of the given \a matrix.
*/
QMatrix::QMatrix(const QMatrix &matrix)
+ : _m11(matrix._m11)
+ , _m12(matrix._m12)
+ , _m21(matrix._m21)
+ , _m22(matrix._m22)
+ , _dx(matrix._dx)
+ , _dy(matrix._dy)
{
- *this = matrix;
}
/*!
@@ -249,12 +268,14 @@ QMatrix::QMatrix(const QMatrix &matrix)
\sa QMatrix()
*/
-void QMatrix::setMatrix(qreal m11, qreal m12, qreal m21, qreal m22,
- qreal dx, qreal dy)
+void QMatrix::setMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
{
- _m11 = m11; _m12 = m12;
- _m21 = m21; _m22 = m22;
- _dx = dx; _dy = dy;
+ _m11 = m11;
+ _m12 = m12;
+ _m21 = m21;
+ _m22 = m22;
+ _dx = dx;
+ _dy = dy;
}
@@ -968,18 +989,17 @@ QMatrix QMatrix::inverted(bool *invertible) const
if (determinant == 0.0) {
if (invertible)
*invertible = false; // singular matrix
- QMatrix defaultMatrix;
- return defaultMatrix;
+ return QMatrix(true);
}
else { // invertible matrix
if (invertible)
*invertible = true;
qreal dinv = 1.0/determinant;
- QMatrix imatrix((_m22*dinv), (-_m12*dinv),
- (-_m21*dinv), (_m11*dinv),
- ((_m21*_dy - _m22*_dx)*dinv),
- ((_m12*_dx - _m11*_dy)*dinv));
- return imatrix;
+ return QMatrix((_m22*dinv), (-_m12*dinv),
+ (-_m21*dinv), (_m11*dinv),
+ ((_m21*_dy - _m22*_dx)*dinv),
+ ((_m12*_dx - _m11*_dy)*dinv),
+ true);
}
}
@@ -1054,9 +1074,14 @@ QMatrix &QMatrix::operator *=(const QMatrix &m)
QMatrix QMatrix::operator *(const QMatrix &m) const
{
- QMatrix result = *this;
- result *= m;
- return result;
+ qreal tm11 = _m11*m._m11 + _m12*m._m21;
+ qreal tm12 = _m11*m._m12 + _m12*m._m22;
+ qreal tm21 = _m21*m._m11 + _m22*m._m21;
+ qreal tm22 = _m21*m._m12 + _m22*m._m22;
+
+ qreal tdx = _dx*m._m11 + _dy*m._m21 + m._dx;
+ qreal tdy = _dx*m._m12 + _dy*m._m22 + m._dy;
+ return QMatrix(tm11, tm12, tm21, tm22, tdx, tdy, true);
}
/*!
@@ -1161,7 +1186,7 @@ QDebug operator<<(QDebug dbg, const QMatrix &m)
<< " 22=" << m.m22()
<< " dx=" << m.dx()
<< " dy=" << m.dy()
- << ")";
+ << ')';
return dbg.space();
}
#endif
@@ -1177,4 +1202,15 @@ QDebug operator<<(QDebug dbg, const QMatrix &m)
Use the mapRect() function instead.
*/
+
+/*!
+ \fn bool qFuzzyCompare(const QMatrix& m1, const QMatrix& m2)
+
+ \relates QMatrix
+ \since 4.6
+
+ Returns true if \a m1 and \a m2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h
index d8f809c..cd003f6 100644
--- a/src/gui/painting/qmatrix.h
+++ b/src/gui/painting/qmatrix.h
@@ -61,6 +61,7 @@ class QVariant;
class Q_GUI_EXPORT QMatrix // 2D transform matrix
{
public:
+ inline explicit QMatrix(Qt::Initialization) {}
QMatrix();
QMatrix(qreal m11, qreal m12, qreal m21, qreal m22,
qreal dx, qreal dy);
@@ -99,7 +100,7 @@ public:
QMatrix &shear(qreal sh, qreal sv);
QMatrix &rotate(qreal a);
- bool isInvertible() const { return !qFuzzyCompare(_m11*_m22 - _m12*_m21 + 1, 1); }
+ bool isInvertible() const { return !qFuzzyIsNull(_m11*_m22 - _m12*_m21); }
qreal det() const { return _m11*_m22 - _m12*_m21; }
QMatrix inverted(bool *invertible = 0) const;
@@ -121,6 +122,20 @@ public:
#endif
private:
+ inline QMatrix(bool)
+ : _m11(1.)
+ , _m12(0.)
+ , _m21(0.)
+ , _m22(1.)
+ , _dx(0.)
+ , _dy(0.) {}
+ inline QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy, bool)
+ : _m11(m11)
+ , _m12(m12)
+ , _m21(m21)
+ , _m22(m22)
+ , _dx(dx)
+ , _dy(dy) {}
friend class QTransform;
qreal _m11, _m12;
qreal _m21, _m22;
@@ -147,16 +162,29 @@ Q_GUI_EXPORT QPainterPath operator *(const QPainterPath &p, const QMatrix &m);
inline bool QMatrix::isIdentity() const
{
- return qFuzzyCompare(_m11, 1) && qFuzzyCompare(_m22, 1) && qFuzzyCompare(_m12 + 1, 1)
- && qFuzzyCompare(_m21 + 1, 1) && qFuzzyCompare(_dx + 1, 1) && qFuzzyCompare(_dy + 1, 1);
+ return qFuzzyIsNull(_m11 - 1) && qFuzzyIsNull(_m22 - 1) && qFuzzyIsNull(_m12)
+ && qFuzzyIsNull(_m21) && qFuzzyIsNull(_dx) && qFuzzyIsNull(_dy);
}
+inline bool qFuzzyCompare(const QMatrix& m1, const QMatrix& m2)
+{
+ return qFuzzyCompare(m1.m11(), m2.m11())
+ && qFuzzyCompare(m1.m12(), m2.m12())
+ && qFuzzyCompare(m1.m21(), m2.m21())
+ && qFuzzyCompare(m1.m22(), m2.m22())
+ && qFuzzyCompare(m1.dx(), m2.dx())
+ && qFuzzyCompare(m1.dy(), m2.dy());
+}
+
+
/*****************************************************************************
QMatrix stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix &);
+#endif
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QMatrix &);
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index e90ba55..216b8c6 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -198,32 +198,8 @@ void QOutlineMapper::endOutline()
m_m22 * e.y() + m_m12 * e.x() + m_dy);
}
} else {
- // ## TODO: this case needs to be plain code polygonal paths
- QPainterPath path;
- if (m_element_types.isEmpty()) {
- if (!m_elements.isEmpty())
- path.moveTo(m_elements.at(0));
- for (int i=1; i<m_elements.size(); ++i)
- path.lineTo(m_elements.at(i));
- } else {
- for (int i=0; i<m_elements.size(); ++i) {
- switch (m_element_types.at(i)) {
- case QPainterPath::MoveToElement:
- path.moveTo(m_elements.at(i));
- break;
- case QPainterPath::LineToElement:
- path.lineTo(m_elements.at(i));
- break;
- case QPainterPath::CurveToElement:
- path.cubicTo(m_elements.at(i), m_elements.at(i+1), m_elements.at(i+2));
- i += 2;
- break;
- default:
- Q_ASSERT(false);
- break;
- }
- }
- }
+ const QVectorPath vp((qreal *)m_elements.data(), m_elements.size(), m_element_types.data());
+ QPainterPath path = vp.convertToPainterPath();
path = QTransform(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33).map(path);
if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL))
path.setFillRule(Qt::WindingFill);
diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp
new file mode 100644
index 0000000..6a2a4c4
--- /dev/null
+++ b/src/gui/painting/qpaintdevice.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpaintdevice.h"
+
+QT_BEGIN_NAMESPACE
+
+extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp
+
+QPaintDevice::QPaintDevice()
+{
+ painters = 0;
+}
+
+QPaintDevice::~QPaintDevice()
+{
+ if (paintingActive())
+ qWarning("QPaintDevice: Cannot destroy paint device that is being "
+ "painted");
+ qt_painter_removePaintDevice(this);
+}
+
+
+int QPaintDevice::metric(PaintDeviceMetric) const
+{
+ qWarning("QPaintDevice::metrics: Device has no metric information");
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintdevice.qdoc b/src/gui/painting/qpaintdevice.qdoc
new file mode 100644
index 0000000..2d6f273
--- /dev/null
+++ b/src/gui/painting/qpaintdevice.qdoc
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPaintDevice
+ \brief The QPaintDevice class is the base class of objects that
+ can be painted.
+
+ \ingroup painting
+
+ A paint device is an abstraction of a two-dimensional space that
+ can be drawn using a QPainter. Its default coordinate system has
+ its origin located at the top-left position. X increases to the
+ right and Y increases downwards. The unit is one pixel.
+
+ The drawing capabilities of QPaintDevice are currently implemented
+ by the QWidget, QImage, QPixmap, QGLPixelBuffer, QPicture, and
+ QPrinter subclasses.
+
+ To implement support for a new backend, you must derive from
+ QPaintDevice and reimplement the virtual paintEngine() function to
+ tell QPainter which paint engine should be used to draw on this
+ particular device. Note that you also must create a corresponding
+ paint engine to be able to draw on the device, i.e derive from
+ QPaintEngine and reimplement its virtual functions.
+
+ \warning Qt requires that a QApplication object exists before
+ any paint devices can be created. Paint devices access window
+ system resources, and these resources are not initialized before
+ an application object is created.
+
+ The QPaintDevice class provides several functions returning the
+ various device metrics: The depth() function returns its bit depth
+ (number of bit planes). The height() function returns its height
+ in default coordinate system units (e.g. pixels for QPixmap and
+ QWidget) while heightMM() returns the height of the device in
+ millimeters. Similiarily, the width() and widthMM() functions
+ return the width of the device in default coordinate system units
+ and in millimeters, respectively. Alternatively, the protected
+ metric() function can be used to retrieve the metric information
+ by specifying the desired PaintDeviceMetric as argument.
+
+ The logicalDpiX() and logicalDpiY() functions return the
+ horizontal and vertical resolution of the device in dots per
+ inch. The physicalDpiX() and physicalDpiY() functions also return
+ the resolution of the device in dots per inch, but note that if
+ the logical and vertical resolution differ, the corresponding
+ QPaintEngine must handle the mapping. Finally, the numColors()
+ function returns the number of different colors available for the
+ paint device.
+
+ \sa QPaintEngine, QPainter, {The Coordinate System}, {The Paint
+ System}
+*/
+
+/*!
+ \enum QPaintDevice::PaintDeviceMetric
+
+ Describes the various metrics of a paint device.
+
+ \value PdmWidth The width of the paint device in default
+ coordinate system units (e.g. pixels for QPixmap and QWidget). See
+ also width().
+
+ \value PdmHeight The height of the paint device in default
+ coordinate system units (e.g. pixels for QPixmap and QWidget). See
+ also height().
+
+ \value PdmWidthMM The width of the paint device in millimeters. See
+ also widthMM().
+
+ \value PdmHeightMM The height of the paint device in millimeters. See
+ also heightMM().
+
+ \value PdmNumColors The number of different colors available for
+ the paint device. See also numColors().
+
+ \value PdmDepth The bit depth (number of bit planes) of the paint
+ device. See also depth().
+
+ \value PdmDpiX The horizontal resolution of the device in dots per
+ inch. See also logicalDpiX().
+
+ \value PdmDpiY The vertical resolution of the device in dots per inch. See
+ also logicalDpiY().
+
+ \value PdmPhysicalDpiX The horizontal resolution of the device in
+ dots per inch. See also physicalDpiX().
+
+ \value PdmPhysicalDpiY The vertical resolution of the device in
+ dots per inch. See also physicalDpiY().
+
+ \sa metric()
+*/
+
+/*!
+ \fn QPaintDevice::QPaintDevice()
+
+ Constructs a paint device. This constructor can be invoked only from
+ subclasses of QPaintDevice.
+*/
+
+/*!
+ \fn QPaintDevice::~QPaintDevice()
+
+ Destroys the paint device and frees window system resources.
+*/
+
+/*!
+ \fn int QPaintDevice::devType() const
+
+ \internal
+
+ Returns the device type identifier, which is QInternal::Widget
+ if the device is a QWidget, QInternal::Pixmap if it's a
+ QPixmap, QInternal::Printer if it's a QPrinter,
+ QInternal::Picture if it's a QPicture, or
+ QInternal::UnknownDevice in other cases.
+*/
+
+/*!
+ \fn bool QPaintDevice::paintingActive() const
+
+ Returns true if the device is currently being painted on, i.e. someone has
+ called QPainter::begin() but not yet called QPainter::end() for
+ this device; otherwise returns false.
+
+ \sa QPainter::isActive()
+*/
+
+/*!
+ \fn QPaintEngine *QPaintDevice::paintEngine() const
+
+ Returns a pointer to the paint engine used for drawing on the
+ device.
+*/
+
+/*!
+ \fn int QPaintDevice::metric(PaintDeviceMetric metric) const
+
+ Returns the metric information for the given paint device \a metric.
+
+ \sa PaintDeviceMetric
+*/
+
+/*!
+ \fn int QPaintDevice::width() const
+
+ Returns the width of the paint device in default coordinate system
+ units (e.g. pixels for QPixmap and QWidget).
+
+ \sa widthMM()
+*/
+
+/*!
+ \fn int QPaintDevice::height() const
+
+ Returns the height of the paint device in default coordinate
+ system units (e.g. pixels for QPixmap and QWidget).
+
+ \sa heightMM()
+*/
+
+/*!
+ \fn int QPaintDevice::widthMM() const
+
+ Returns the width of the paint device in millimeters. Due to platform
+ limitations it may not be possible to use this function to determine
+ the actual physical size of a widget on the screen.
+
+ \sa width()
+*/
+
+/*!
+ \fn int QPaintDevice::heightMM() const
+
+ Returns the height of the paint device in millimeters. Due to platform
+ limitations it may not be possible to use this function to determine
+ the actual physical size of a widget on the screen.
+
+ \sa height()
+*/
+
+/*!
+ \fn int QPaintDevice::numColors() const
+
+ Returns the number of different colors available for the paint
+ device. Since this value is an int, it will not be sufficient to represent
+ the number of colors on 32 bit displays, in this case INT_MAX is
+ returned instead.
+*/
+
+/*!
+ \fn int QPaintDevice::depth() const
+
+ Returns the bit depth (number of bit planes) of the paint device.
+*/
+
+/*!
+ \fn int QPaintDevice::logicalDpiX() const
+
+ Returns the horizontal resolution of the device in dots per inch,
+ which is used when computing font sizes. For X11, this is usually
+ the same as could be computed from widthMM().
+
+ Note that if the logicalDpiX() doesn't equal the physicalDpiX(),
+ the corresponding QPaintEngine must handle the resolution mapping.
+
+ \sa logicalDpiY(), physicalDpiX()
+*/
+
+/*!
+ \fn int QPaintDevice::logicalDpiY() const
+
+ Returns the vertical resolution of the device in dots per inch,
+ which is used when computing font sizes. For X11, this is usually
+ the same as could be computed from heightMM().
+
+ Note that if the logicalDpiY() doesn't equal the physicalDpiY(),
+ the corresponding QPaintEngine must handle the resolution mapping.
+
+ \sa logicalDpiX(), physicalDpiY()
+*/
+
+/*!
+ \fn int QPaintDevice::physicalDpiX() const
+
+ Returns the horizontal resolution of the device in dots per inch.
+ For example, when printing, this resolution refers to the physical
+ printer's resolution. The logical DPI on the other hand, refers to
+ the resolution used by the actual paint engine.
+
+ Note that if the physicalDpiX() doesn't equal the logicalDpiX(),
+ the corresponding QPaintEngine must handle the resolution mapping.
+
+ \sa physicalDpiY(), logicalDpiX()
+*/
+
+/*!
+ \fn int QPaintDevice::physicalDpiY() const
+
+ Returns the horizontal resolution of the device in dots per inch.
+ For example, when printing, this resolution refers to the physical
+ printer's resolution. The logical DPI on the other hand, refers to
+ the resolution used by the actual paint engine.
+
+ Note that if the physicalDpiY() doesn't equal the logicalDpiY(),
+ the corresponding QPaintEngine must handle the resolution mapping.
+
+ \sa physicalDpiX(), logicalDpiY()
+*/
diff --git a/src/gui/painting/qpaintdevice_mac.cpp b/src/gui/painting/qpaintdevice_mac.cpp
index da68091..24b6b61 100644
--- a/src/gui/painting/qpaintdevice_mac.cpp
+++ b/src/gui/painting/qpaintdevice_mac.cpp
@@ -57,34 +57,6 @@ QT_BEGIN_NAMESPACE
Internal variables and functions
*****************************************************************************/
-
-/*****************************************************************************
- External functions
- *****************************************************************************/
-
-extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp
-
-/*****************************************************************************
- QPaintDevice member functions
- *****************************************************************************/
-QPaintDevice::QPaintDevice()
-{
- painters = 0;
-}
-
-QPaintDevice::~QPaintDevice()
-{
- if(paintingActive())
- qWarning("QPaintDevice: Cannot destroy paint device that is being "
- "painted, be sure to QPainter::end() painters");
- qt_painter_removePaintDevice(this);
-}
-
-int QPaintDevice::metric(PaintDeviceMetric) const
-{
- return 0;
-}
-
/*! \internal */
float qt_mac_defaultDpi_x()
{
@@ -142,21 +114,16 @@ Q_GUI_EXPORT CGContextRef qt_mac_cg_context(const QPaintDevice *pdev)
if (pdev->devType() == QInternal::Pixmap) {
const QPixmap *pm = static_cast<const QPixmap*>(pdev);
CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev);
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
uint flags = kCGImageAlphaPremultipliedFirst;
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
- if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- flags |= kCGBitmapByteOrder32Host;
-#endif
-#else
- CGImageAlphaInfo flags = kCGImageAlphaPremultipliedFirst;
+ flags |= kCGBitmapByteOrder32Host;
#endif
CGContextRef ret = 0;
// It would make sense to put this into a mac #ifdef'ed
// virtual function in the QPixmapData at some point
if (pm->data->classId() == QPixmapData::MacClass) {
- const QMacPixmapData *pmData = static_cast<const QMacPixmapData*>(pm->data);
+ const QMacPixmapData *pmData = static_cast<const QMacPixmapData*>(pm->data.data());
ret = CGBitmapContextCreate(pmData->pixels, pmData->w, pmData->h,
8, pmData->bytesPerRow, colorspace,
flags);
diff --git a/src/gui/painting/qpaintdevice_qws.cpp b/src/gui/painting/qpaintdevice_qws.cpp
index f302304..8438f46 100644
--- a/src/gui/painting/qpaintdevice_qws.cpp
+++ b/src/gui/painting/qpaintdevice_qws.cpp
@@ -48,39 +48,6 @@
QT_BEGIN_NAMESPACE
-QPaintDevice::QPaintDevice()
-{
- painters = 0;
-}
-
-extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp
-
-
-QPaintDevice::~QPaintDevice()
-{
- if (paintingActive())
- qWarning("QPaintDevice: Cannot destroy paint device that is being "
- "painted");
- qt_painter_removePaintDevice(this);
-}
-
-
-int QPaintDevice::metric(PaintDeviceMetric m) const
-{
- qWarning("QPaintDevice::metrics: Device has no metric information");
- if (m == PdmDpiX) {
- return 72;
- } else if (m == PdmDpiY) {
- return 72;
- } else if (m == PdmNumColors) {
- // FIXME: does this need to be a real value?
- return 256;
- } else {
- qDebug("Unrecognised metric %d!",m);
- return 0;
- }
-}
-
QWSDisplay *QPaintDevice::qwsDisplay()
{
return qt_fbdpy;
diff --git a/src/gui/painting/qpaintdevice_win.cpp b/src/gui/painting/qpaintdevice_win.cpp
index 8779a96..453b561 100644
--- a/src/gui/painting/qpaintdevice_win.cpp
+++ b/src/gui/painting/qpaintdevice_win.cpp
@@ -50,27 +50,6 @@
QT_BEGIN_NAMESPACE
-QPaintDevice::QPaintDevice()
-{
- painters = 0;
-}
-
-extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp
-
-QPaintDevice::~QPaintDevice()
-{
- if (paintingActive())
- qWarning("QPaintDevice: Cannot destroy paint device that is being "
- "painted. Be sure to QPainter::end() painters!");
- qt_painter_removePaintDevice(this);
-}
-
-int QPaintDevice::metric(PaintDeviceMetric) const
-{
- qWarning("QPaintDevice::metrics: Device has no metric information");
- return 0;
-}
-
HDC QPaintDevice::getDC() const
{
return 0;
diff --git a/src/gui/painting/qpaintdevice_x11.cpp b/src/gui/painting/qpaintdevice_x11.cpp
index ea8463b..4b6bcb5 100644
--- a/src/gui/painting/qpaintdevice_x11.cpp
+++ b/src/gui/painting/qpaintdevice_x11.cpp
@@ -49,21 +49,6 @@
QT_BEGIN_NAMESPACE
-QPaintDevice::QPaintDevice()
-{
- painters = 0;
-}
-
-extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp
-
-QPaintDevice::~QPaintDevice()
-{
- if (paintingActive())
- qWarning("QPaintDevice: Cannot destroy paint device that is being "
- "painted");
- qt_painter_removePaintDevice(this);
-}
-
/*! \internal
Returns the X11 Drawable of the paint device. 0 is returned if it
@@ -96,12 +81,6 @@ const Q_GUI_EXPORT QX11Info *qt_x11Info(const QPaintDevice *pd)
return 0;
}
-int QPaintDevice::metric(PaintDeviceMetric) const
-{
- qWarning("QPaintDevice::metrics: Device has no metric information");
- return 0;
-}
-
#ifdef QT3_SUPPORT
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index 993757b..525959b 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -49,6 +49,7 @@
#include <private/qtextengine_p.h>
#include <qvarlengtharray.h>
#include <private/qfontengine_p.h>
+#include <private/qpaintengineex_p.h>
QT_BEGIN_NAMESPACE
@@ -144,7 +145,7 @@ QFont QTextItem::font() const
/*!
\class QPaintEngine
- \ingroup multimedia
+ \ingroup painting
\brief The QPaintEngine class provides an abstract definition of how
QPainter draws to a given device on a given platform.
@@ -302,6 +303,9 @@ void QPaintEngine::syncState()
{
Q_ASSERT(state);
updateState(*state);
+
+ if (isExtended())
+ static_cast<QPaintEngineEx *>(this)->sync();
}
static QPaintEngine *qt_polygon_recursion = 0;
@@ -713,7 +717,6 @@ QPaintEngine::QPaintEngine(QPaintEnginePrivate &dptr, PaintEngineFeatures caps)
*/
QPaintEngine::~QPaintEngine()
{
- delete d_ptr;
}
/*!
@@ -1004,8 +1007,7 @@ void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt &
const int size = qRound(ti.fontEngine->ascent());
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> glyphs;
- QTransform matrix;
- matrix.translate(p.x(), p.y() - size);
+ QTransform matrix = QTransform::fromTranslate(p.x(), p.y() - size);
ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
if (glyphs.size() == 0)
return;
diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h
index 96074e7..5cd17fe 100644
--- a/src/gui/painting/qpaintengine.h
+++ b/src/gui/painting/qpaintengine.h
@@ -44,6 +44,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qobjectdefs.h>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qpainter.h>
QT_BEGIN_HEADER
@@ -210,6 +211,7 @@ public:
Direct3D,
Pdf,
OpenVG,
+ OpenGL2,
User = 50, // first user type id
MaxUser = 100 // last user type id
@@ -239,7 +241,7 @@ protected:
uint selfDestruct : 1;
uint extended : 1;
- QPaintEnginePrivate *d_ptr;
+ QScopedPointer<QPaintEnginePrivate> d_ptr;
private:
void setAutoDestruct(bool autoDestr) { selfDestruct = autoDestr; }
diff --git a/src/gui/painting/qpaintengine_d3d.cpp b/src/gui/painting/qpaintengine_d3d.cpp
deleted file mode 100644
index 6fd94cf..0000000
--- a/src/gui/painting/qpaintengine_d3d.cpp
+++ /dev/null
@@ -1,4576 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qdebug.h>
-#include "qpaintengine_d3d_p.h"
-
-#include "private/qdrawhelper_p.h"
-#include "private/qfont_p.h"
-#include "private/qfontengine_p.h"
-#include "private/qpaintengine_p.h"
-#include "private/qtessellator_p.h"
-#include <private/qbezier_p.h>
-#include <private/qpainter_p.h>
-#include <private/qpixmap_raster_p.h>
-#include <private/qpolygonclipper_p.h>
-#include <qbuffer.h>
-#include <qcache.h>
-#include <qdir.h>
-#include <qfileinfo.h>
-#include <qlibrary.h>
-#include <qlibraryinfo.h>
-#include <qmath.h>
-#include <qpaintdevice.h>
-#include <qpixmapcache.h>
-
-#include <qwidget.h>
-#include <d3d9.h>
-#include <d3dx9.h>
-
-#include <mmintrin.h>
-#include <xmmintrin.h>
-
-QT_BEGIN_NAMESPACE
-
-#ifndef M_PI
- #define M_PI 3.14159265358979323846
-#endif
-
-#define QD3D_MASK_MARGIN 1
-#define QD3D_BATCH_SIZE 256
-
-// for the ClearType detection stuff..
-#ifndef SPI_GETFONTSMOOTHINGTYPE
-#define SPI_GETFONTSMOOTHINGTYPE 0x200A
-#endif
-
-#ifndef FE_FONTSMOOTHINGCLEARTYPE
-#define FE_FONTSMOOTHINGCLEARTYPE 0x0002
-#endif
-
-//#include <performance.h>
-#define PM_INIT
-#define PM_MEASURE(A)
-#define PM_DISPLAY
-
-//debugging
-//#define QT_DEBUG_VERTEXBUFFER_ACCESS
-//#define QT_DEBUG_D3D
-//#define QT_DEBUG_D3D_CALLS
-
-#define QD3D_SET_MARK(output) \
- D3DPERF_SetMarker(0, QString(output).utf16());
-
-#define QT_VERTEX_RESET_LIMIT 24576
-#define QT_VERTEX_BUF_SIZE 32768
-#define QD3DFVF_CSVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEXCOORDSIZE4(1))
-
-// this is a different usage of the effect framework than intended,
-// but it's convenient for us to use (See effect file)
-#define PASS_STENCIL_ODDEVEN 0
-#define PASS_STENCIL_WINDING 1
-#define PASS_STENCIL_DRAW 2
-#define PASS_STENCIL_DRAW_DIRECT 3
-#define PASS_STENCIL_CLIP 4
-#define PASS_STENCIL_NOSTENCILCHECK 5
-#define PASS_STENCIL_NOSTENCILCHECK_DIRECT 6
-#define PASS_TEXT 7
-#define PASS_CLEARTYPE_TEXT 8
-#define PASS_ALIASED_LINES 9
-#define PASS_ALIASED_LINES_DIRECT 10
-
-#define PASS_AA_CREATEMASK 0
-#define PASS_AA_DRAW 1
-#define PASS_AA_DRAW_DIRECT 2
-
-#define D3D_STAGE_COUNT 2
-#define D3D_RENDER_STATES 210
-#define D3D_TEXTURE_STATES 33
-#define D3D_SAMPLE_STATES 14
-
-
-typedef HRESULT (APIENTRY *PFND3DXCREATEBUFFER)(DWORD, LPD3DXBUFFER *);
-typedef HRESULT (APIENTRY *PFND3DXCREATEEFFECT)(LPDIRECT3DDEVICE9, LPCVOID, UINT, CONST D3DXMACRO *,
- LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL,
- LPD3DXEFFECT *, LPD3DXBUFFER *);
-typedef D3DXMATRIX *(APIENTRY *PFND3DXMATRIXORTHOOFFCENTERLH)(D3DMATRIX *, FLOAT, FLOAT,
- FLOAT, FLOAT, FLOAT, FLOAT);
-typedef IDirect3D9 *(APIENTRY *PFNDIRECT3DCREATE9)(uint);
-
-static PFNDIRECT3DCREATE9 pDirect3DCreate9 = 0;
-static PFND3DXCREATEBUFFER pD3DXCreateBuffer = 0;
-static PFND3DXCREATEEFFECT pD3DXCreateEffect = 0;
-static PFND3DXMATRIXORTHOOFFCENTERLH pD3DXMatrixOrthoOffCenterLH = 0;
-
-
-class QD3DSurfaceManager : public QObject {
- Q_OBJECT
-
-public:
- enum QD3DSurfaceManagerStatus {
- NoStatus = 0,
- NeedsResetting = 0x01,
- MaxSizeChanged = 0x02
- };
-
- QD3DSurfaceManager();
- ~QD3DSurfaceManager();
-
- void init(LPDIRECT3D9 object);
-
- void setPaintDevice(QPaintDevice *pd);
-
- int status() const;
- void reset();
-
- LPDIRECT3DSURFACE9 renderTarget();
-
- LPDIRECT3DSURFACE9 surface(QPaintDevice *pd);
- LPDIRECT3DSWAPCHAIN9 swapChain(QPaintDevice *pd);
- void releasePaintDevice(QPaintDevice *pd);
-
- LPDIRECT3DDEVICE9 device();
- void cleanup();
-
- QSize maxSize() const;
-
-private:
- struct D3DSwapChain {
- QSize size;
- LPDIRECT3DSWAPCHAIN9 swapchain;
- LPDIRECT3DSURFACE9 surface;
- };
-
- void updateMaxSize();
- void initPresentParameters(D3DPRESENT_PARAMETERS *params);
- D3DSwapChain *createSwapChain(QWidget *w);
-
- QSize m_max_size;
- int m_status;
- QMap<QPaintDevice *, D3DSwapChain *> m_swapchains;
-
- LPDIRECT3DDEVICE9 m_device;
- QPaintDevice *m_pd;
- HWND m_dummy;
- D3DSwapChain *m_current;
-
-private Q_SLOTS:
- void cleanupPaintDevice(QObject *);
-};
-
-struct vertex {
- D3DVECTOR pos;
- DWORD color;
- FLOAT s0, t0, r0, q0;
- FLOAT s1, t1, r1, q1;
-};
-
-struct QD3DMaskPosition {
- int x, y, channel;
-};
-
-
-struct QD3DBatchItem {
- enum QD3DBatchInfo {
- BI_WINDING = 0x0001,
- BI_AA = 0x0002,
- BI_BRECT = 0x0004,
- BI_MASKFULL = 0x0008,
- BI_TEXT = 0x0010,
- BI_MASK = 0x0020,
- BI_CLIP = 0x0040,
- BI_SCISSOR = 0x0080,
-
- BI_PIXMAP = 0x0100,
- BI_IMAGE = 0x0200,
- BI_COMPLEXBRUSH = 0x0400,
-
- BI_CLEARCLIP = 0x0800, // clip nothing (filling the clip mask with 0)
- BI_TRANSFORM = 0x1000,
- BI_MASKSCISSOR = 0x2000,
- BI_FASTLINE = 0x4000,
- BI_COSMETICPEN = 0x8000
- };
-
- int m_info;
-
- int m_count;
- int m_offset;
-
- QD3DMaskPosition m_maskpos;
- qreal m_xoffset;
- qreal m_yoffset;
- qreal m_opacity;
-
- QPixmap m_pixmap;
- QRectF m_brect;
- QBrush m_brush;
-
- IDirect3DTexture9 *m_texture;
-
- qreal m_width;
- qreal m_distance;
-
- QTransform m_matrix;
- QPainter::CompositionMode m_cmode;
-
- QVector<int> m_pointstops;
-};
-
-struct QD3DBatch {
- int m_item_index;
- QD3DBatchItem items[QD3D_BATCH_SIZE];
-};
-
-class QD3DStateManager;
-class QD3DFontCache;
-class QD3DDrawHelper;
-class QD3DGradientCache;
-
-class QDirect3DPaintEnginePrivate : public QPaintEnginePrivate
-{
- Q_DECLARE_PUBLIC(QDirect3DPaintEngine)
-
-public:
- enum RenderTechnique {
- RT_NoTechnique,
- RT_Antialiased,
- RT_Aliased,
- };
-
- QDirect3DPaintEnginePrivate()
- : m_d3d_object(0)
- , m_d3d_device(0)
- , m_txop(QTransform::TxNone)
- , m_effect(0)
- , m_flush_on_end(0)
- { init(); }
-
- ~QDirect3DPaintEnginePrivate();
-
- bool init();
- void initDevice();
-
- inline QD3DBatchItem *nextBatchItem();
-
- QPolygonF brushCoordinates(const QRectF &r, bool stroke, qreal *fp) const;
- void fillAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform);
- void fillAntialiasedPath(const QPainterPath &path, const QRectF &brect,
- const QTransform &txform, bool stroke);
- void fillPath(const QPainterPath &path, QRectF brect);
-
- void strokePath(const QPainterPath &path, QRectF brect, bool simple = false);
- QPainterPath strokePathFastPen(const QPainterPath &path);
- void strokeAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform);
-
- void flushBatch();
- int flushAntialiased(int offset);
- void flushAliased(QD3DBatchItem *item, int offset);
- void flushText(QD3DBatchItem *item, int offset);
- void flushLines(QD3DBatchItem *item, int offset);
-
- void updateTransform(const QTransform &matrix);
- void updatePen(const QPen &pen);
- void updateBrush(const QBrush &pen);
- void updateClipRegion(const QRegion &clipregion, Qt::ClipOperation op = Qt::ReplaceClip);
- void updateClipPath(const QPainterPath &clipregion, Qt::ClipOperation op = Qt::ReplaceClip);
- void updateFont(const QFont &font);
-
- void setRenderTechnique(RenderTechnique technique);
-
- QPointF transformPoint(const QPointF &p, qreal *w) const;
-
- bool prepareBatch(QD3DBatchItem *item, int offset);
- void prepareItem(QD3DBatchItem *item);
- void cleanupItem(QD3DBatchItem *item);
- void setCompositionMode(QPainter::CompositionMode mode);
-
- void verifyTexture(const QPixmap &pixmap);
-
- bool isFastRect(const QRectF &rect);
-
- void releaseDC();
-
- void cleanup();
- bool testCaps();
-
- QPixmap getPattern(Qt::BrushStyle style) const;
-
- // clipping
- QPainterPath m_sysclip_path;
- QPainterPath m_clip_path;
- QRegion m_sysclip_region;
- QRegion m_clip_region;
-
- qreal m_opacity;
- D3DCOLOR m_opacity_color;
-
- int m_current_state;
-
- ID3DXEffect* m_effect;
-
- RenderTechnique m_current_technique;
-
- QTransform m_matrix;
- qreal m_inv_scale;
-
- QPen m_pen;
- Qt::BrushStyle m_pen_brush_style;
- QTransform m_inv_pen_matrix;
- D3DCOLOR m_pen_color;
- qreal m_pen_width;
-
- QBrush m_brush;
- Qt::BrushStyle m_brush_style;
- QTransform m_inv_brush_matrix;
- D3DCOLOR m_brush_color;
- QTransform m_brush_origin;
-
- uint m_clipping_enabled : 1;
- uint m_has_complex_clipping : 1;
- uint m_cleartype_text: 1;
- uint m_has_pen : 1;
- uint m_has_cosmetic_pen : 1;
- uint m_has_brush : 1;
- uint m_has_fast_pen : 1;
- uint m_has_aa_fast_pen : 1;
- uint m_flush_on_end : 1;
- uint m_supports_d3d : 1;
-
- QTransform::TransformationType m_txop;
-
- QPainter::CompositionMode m_cmode;
-
- QD3DSurfaceManager m_surface_manager;
- QSize m_surface_size;
-
- LPDIRECT3D9 m_d3d_object;
- LPDIRECT3DDEVICE9 m_d3d_device;
- IDirect3DSurface9 *m_current_surface;
- bool m_in_scene;
-
- QD3DGradientCache *m_gradient_cache;
- QD3DDrawHelper *m_draw_helper;
- QD3DBatch m_batch;
- QD3DStateManager *m_statemanager;
-
- HDC m_dc;
- IDirect3DSurface9 *m_dcsurface;
-
- QMap<Qt::BrushStyle, QPixmap> m_patterns;
-};
-
-
-class QD3DStateManager : public ID3DXEffectStateManager {
-public:
- QD3DStateManager(LPDIRECT3DDEVICE9 pDevice, ID3DXEffect *effect);
- void reset();
-
- inline void startStateBlock();
- inline void endStateBlock();
-
- inline void setCosmeticPen(bool enabled);
- inline void setBrushMode(int mode);
- inline void setTexture(LPDIRECT3DBASETEXTURE9 pTexture);
- inline void setTexture(LPDIRECT3DBASETEXTURE9 pTexture, QGradient::Spread spread);
- inline void setTransformation(const QTransform *matrix = 0);
- inline void setProjection(const D3DXMATRIX *pMatrix);
- inline void setMaskChannel(int channel);
- inline void setMaskOffset(qreal x, qreal y);
- inline void setFocalDistance(const qreal &fd);
-
- inline void beginPass(int pass);
- inline void endPass();
-
- STDMETHOD(QueryInterface)(REFIID iid, LPVOID *ppv);
- STDMETHOD_(ULONG, AddRef)();
- STDMETHOD_(ULONG, Release)();
-
- STDMETHOD(SetTransform)(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix);
- STDMETHOD(SetMaterial)(CONST D3DMATERIAL9 *pMaterial);
- STDMETHOD(SetLight)(DWORD Index, CONST D3DLIGHT9 *pLight);
- STDMETHOD(LightEnable)(DWORD Index, BOOL Enable);
- STDMETHOD(SetRenderState)(D3DRENDERSTATETYPE State, DWORD Value);
- STDMETHOD(SetTexture)(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture);
- STDMETHOD(SetTextureStageState)(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
- STDMETHOD(SetSamplerState)(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
- STDMETHOD(SetNPatchMode)(FLOAT NumSegments);
- STDMETHOD(SetFVF)(DWORD FVF);
- STDMETHOD(SetVertexShader)(LPDIRECT3DVERTEXSHADER9 pShader);
- STDMETHOD(SetVertexShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount);
- STDMETHOD(SetVertexShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount);
- STDMETHOD(SetVertexShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount);
- STDMETHOD(SetPixelShader)(LPDIRECT3DPIXELSHADER9 pShader);
- STDMETHOD(SetPixelShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount);
- STDMETHOD(SetPixelShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount);
- STDMETHOD(SetPixelShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount);
-private:
- LPDIRECT3DVERTEXSHADER9 m_vertexshader;
- LPDIRECT3DPIXELSHADER9 m_pixelshader;
-
- LPDIRECT3DBASETEXTURE9 m_textures[D3D_STAGE_COUNT];
- DWORD m_texturestates[D3D_STAGE_COUNT][D3D_TEXTURE_STATES];
- DWORD m_samplerstates[D3D_STAGE_COUNT][D3D_SAMPLE_STATES];
- DWORD m_renderstate[D3D_RENDER_STATES];
-
- qreal m_radgradfd;
-
- bool m_cosmetic_pen;
- int m_pass;
- int m_maskchannel;
- int m_brushmode;
- LPDIRECT3DBASETEXTURE9 m_texture;
- D3DXMATRIX m_projection;
-
- D3DXMATRIX m_d3dIdentityMatrix;
- bool m_isIdentity;
- QTransform m_transformation;
-
- LPDIRECT3DDEVICE9 m_pDevice;
- ID3DXEffect *m_effect;
-
- LONG m_refs;
- bool m_changed;
- qreal m_xoffset, m_yoffset;
- static int m_mask_channels[4][4];
-};
-
-//
-// font cache stuff
-//
-
-struct QD3DGlyphCoord {
- // stores the offset and size of a glyph texture
- qreal x;
- qreal y;
- qreal width;
- qreal height;
- qreal log_width;
- qreal log_height;
- QFixed x_offset;
- QFixed y_offset;
-};
-
-struct QD3DFontTexture {
- int x_offset; // current glyph offset within the texture
- int y_offset;
- int width;
- int height;
- IDirect3DTexture9 *texture;
-};
-
-typedef QHash<glyph_t, QD3DGlyphCoord*> QD3DGlyphHash;
-typedef QHash<QFontEngine*, QD3DGlyphHash*> QD3DFontGlyphHash;
-typedef QHash<quint64, QD3DFontTexture*> QD3DFontTexHash;
-
-class QD3DGlyphCache : public QObject
-{
- Q_OBJECT
-public:
- QD3DGlyphCache()
- : QObject(0)
- , current_cache(0) {}
- ~QD3DGlyphCache();
- QD3DGlyphCoord *lookup(QFontEngine *, glyph_t);
- void cacheGlyphs(QDirect3DPaintEngine *, const QTextItemInt &, const QVarLengthArray<glyph_t> &,
- bool);
- void cleanCache();
- inline QD3DFontTexture *fontTexture(QFontEngine *engine) {
- return font_textures.constFind(reinterpret_cast<quint64>(engine)).value();
- }
-
-public slots:
- void fontEngineDestroyed(QObject *);
-
-private:
- QImage clearTypeGlyph(QFontEngine *, glyph_t glyph);
- QD3DGlyphHash *current_cache;
- QD3DFontTexHash font_textures;
- QD3DFontGlyphHash font_cache;
-};
-
-QD3DGlyphCache::~QD3DGlyphCache()
-{
-}
-
-QD3DGlyphCoord *QD3DGlyphCache::lookup(QFontEngine *, glyph_t g)
-{
- Q_ASSERT(current_cache != 0);
- QD3DGlyphHash::const_iterator it = current_cache->constFind(g);
- if (it == current_cache->constEnd())
- return 0;
- return it.value();
-}
-
-void QD3DGlyphCache::cleanCache()
-{
- QList<quint64> keys = font_textures.keys();
- for (int i=0; i<keys.size(); ++i)
- font_textures.value(keys.at(i))->texture->Release();
-
- qDeleteAll(font_textures);
- qDeleteAll(font_cache);
- font_textures.clear();
- font_cache.clear();
- current_cache = 0;
-}
-
-void QD3DGlyphCache::fontEngineDestroyed(QObject *object)
-{
-// qDebug() << "=> font engine destroyed: " << object;
- QFontEngine *engine = static_cast<QFontEngine *>(object);
-
- QD3DFontGlyphHash::iterator cache_it = font_cache.find(engine);
- if (cache_it != font_cache.end()) {
- QD3DGlyphHash *cache = font_cache.take(engine);
- delete cache;
- }
-
- quint64 font_key = reinterpret_cast<quint64>(engine);
- QD3DFontTexture *tex = font_textures.take(font_key);
- if (tex) {
- tex->texture->Release();
- delete tex;
- }
-}
-
-QImage QD3DGlyphCache::clearTypeGlyph(QFontEngine *engine, glyph_t glyph)
-{
- glyph_metrics_t gm = engine->boundingBox(glyph);
- int glyph_x = qFloor(gm.x.toReal());
- int glyph_y = qFloor(gm.y.toReal());
- int glyph_width = qCeil((gm.x + gm.width).toReal()) - glyph_x + 2;
- int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y + 2;
-
- if (glyph_width + glyph_x <= 0 || glyph_height <= 0)
- return QImage();
- QImage im(glyph_width + glyph_x, glyph_height, QImage::Format_ARGB32_Premultiplied);
- im.fill(0xff000000); // solid black
- QPainter p(&im);
-
- p.setPen(Qt::white);
- p.setBrush(Qt::NoBrush);
-
- QTextItemInt ti;
- ti.ascent = engine->ascent();
- ti.descent = engine->descent();
- ti.width = glyph_width;
- ti.fontEngine = engine;
-
- QGlyphLayoutArray<1> glyphLayout;
- ti.glyphs = glyphLayout;
- ti.glyphs.glyphs[0] = glyph;
- ti.glyphs.advances_x[0] = glyph_width;
- p.drawTextItem(QPointF(-glyph_x, -glyph_y), ti);
- p.end();
- return im;
-}
-
-#if 0
-static void dump_font_texture(QD3DFontTexture *tex)
-{
- QColor color(Qt::red);
- D3DLOCKED_RECT rect;
- if (FAILED(tex->texture->LockRect(0, &rect, 0, 0))) {
- qDebug() << "debug: unable to lock texture rect.";
- return;
- }
-
-// cleartype version
-// uint *tex_data = (uint *) rect.pBits;
-// QImage im(tex->width, tex->height, QImage::Format_ARGB32);
-// for (int y=0; y<tex->height; ++y) {
-// for (int x=0; x<tex->width; ++x) {
-// im.setPixel(x, y, ((*(tex_data+x+y*tex->width))));
-// }
-// }
- uchar *tex_data = (uchar *) rect.pBits;
- QImage im(rect.Pitch, tex->height, QImage::Format_ARGB32);
- for (int y=0; y<tex->height; ++y) {
- for (int x=0; x<rect.Pitch; ++x) {
- uchar val = ((*(tex_data+x+y*rect.Pitch)));
- im.setPixel(x, y, 0xff000000 | (val << 16) | (val << 8) | val);
- }
- }
- tex->texture->UnlockRect(0);
- static int i= 0;
- im.save(QString("tx%1.png").arg(i++));
-}
-#endif
-
-void QD3DGlyphCache::cacheGlyphs(QDirect3DPaintEngine *engine, const QTextItemInt &ti,
- const QVarLengthArray<glyph_t> &glyphs, bool clearType)
-{
- IDirect3DDevice9 *device = engine->d_func()->m_d3d_device;
- QD3DFontGlyphHash::const_iterator cache_it = font_cache.constFind(ti.fontEngine);
- QD3DGlyphHash *cache = 0;
- if (cache_it == font_cache.constEnd()) {
- cache = new QD3DGlyphHash;
- font_cache.insert(ti.fontEngine, cache);
- connect(ti.fontEngine, SIGNAL(destroyed(QObject *)), SLOT(fontEngineDestroyed(QObject *)));
- } else {
- cache = cache_it.value();
- }
-
- current_cache = cache;
-
- D3DFORMAT tex_format = clearType ? D3DFMT_A8R8G8B8 : D3DFMT_A8;
- quint64 font_key = reinterpret_cast<quint64>(ti.fontEngine);
- QD3DFontTexHash::const_iterator it = font_textures.constFind(font_key);
- QD3DFontTexture *font_tex = 0;
- if (it == font_textures.constEnd()) {
- // alloc a new texture, put it into the cache
- int tex_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5;
- int tex_width = tex_height * 30; // ###
- IDirect3DTexture9 *tex;
- if (FAILED(device->CreateTexture(tex_width, tex_height, 1, 0,
- tex_format, D3DPOOL_MANAGED, &tex, NULL)))
- {
- qWarning("QD3DGlyphCache::cacheGlyphs(): can't allocate font texture (%dx%d).",
- tex_width, tex_height);
- return;
- } else {
-// qDebug() << "=> new font texture: " << QSize(tex_width,tex_height);
- font_tex = new QD3DFontTexture;
- font_tex->texture = tex;
- font_tex->x_offset = 0;
- font_tex->y_offset = 0;
- font_tex->width = tex_width;
- font_tex->height = tex_height;
- font_textures.insert(font_key, font_tex);
- }
- } else {
- font_tex = it.value();
- // make it current render target..
- }
-
- // cache each glyph
- for (int i=0; i<glyphs.size(); ++i) {
- QD3DGlyphHash::const_iterator it = cache->constFind(glyphs[i]);
- if (it == cache->constEnd()) {
- glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]);
- int glyph_width = qCeil(metrics.width.toReal()) + 5;
- int glyph_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5;
- if (font_tex->x_offset + glyph_width > font_tex->width) {
- // no room on the current line, start new glyph strip
- int strip_height = glyph_height;
- font_tex->x_offset = 0;
- font_tex->y_offset += strip_height;
- if (font_tex->y_offset >= font_tex->height) {
- // if no room in the current texture - realloc a larger texture
- int old_tex_height = font_tex->height;
- font_tex->height += strip_height;
-
- IDirect3DTexture9 *new_tex;
- if (FAILED(device->CreateTexture(font_tex->width, font_tex->height, 1, 0,
- tex_format, D3DPOOL_MANAGED, &new_tex, NULL)))
- {
- qWarning("QD3DGlyphCache(): can't re-allocate font texture.");
- return;
- } else {
-// qDebug() << " -> new glyph strip added:" << QSize(font_tex->width,font_tex->height);
-
- D3DLOCKED_RECT new_rect, old_rect;
- if (FAILED(font_tex->texture->LockRect(0, &old_rect, 0, D3DLOCK_READONLY))) {
- qDebug() << "QD3DGlyphCache: unable to lock texture rect.";
- return;
- }
- if (FAILED(new_tex->LockRect(0, &new_rect, 0, 0))) {
- qDebug() << "QD3DGlyphCache: unable to lock texture rect.";
- return;
- }
- memcpy(new_rect.pBits, old_rect.pBits, new_rect.Pitch * old_tex_height);
- font_tex->texture->UnlockRect(0);
- new_tex->UnlockRect(0);
- engine->d_func()->flushBatch();
- font_tex->texture->Release();
- font_tex->texture = new_tex;
- }
-
- // update the texture coords and the y offset for the existing glyphs in
- // the cache, because of the texture size change
- QD3DGlyphHash::iterator it = cache->begin();
- while (it != cache->end()) {
- it.value()->height = (it.value()->height * old_tex_height) / font_tex->height;
- it.value()->y = (it.value()->y * old_tex_height) / font_tex->height;
- ++it;
- }
- }
- }
- QD3DGlyphCoord *d3d_glyph = new QD3DGlyphCoord;
- d3d_glyph->x = qreal(font_tex->x_offset) / font_tex->width;
- d3d_glyph->y = qreal(font_tex->y_offset) / font_tex->height;
- d3d_glyph->width = qreal(glyph_width) / font_tex->width;
- d3d_glyph->height = qreal(glyph_height) / font_tex->height;
- d3d_glyph->log_width = d3d_glyph->width * font_tex->width;
- d3d_glyph->log_height = d3d_glyph->height * font_tex->height;
- d3d_glyph->x_offset = -metrics.x;
- d3d_glyph->y_offset = metrics.y;
-
- QImage glyph_im;
- if (clearType)
- glyph_im = clearTypeGlyph(ti.fontEngine, glyphs[i]);
- else
- glyph_im = ti.fontEngine->alphaMapForGlyph(glyphs[i]).convertToFormat(QImage::Format_Indexed8);
-
- // write glyph to texture
- D3DLOCKED_RECT rect;
- RECT glyph_rect = { font_tex->x_offset, font_tex->y_offset,
- font_tex->x_offset + glyph_im.width(),
- font_tex->y_offset + glyph_im.height() };
-
-// qDebug() << " > new glyph char added:" << QSize(glyph_im.width(), glyph_im.height());
- if (FAILED(font_tex->texture->LockRect(0, &rect, &glyph_rect, 0))) {
- qDebug() << "QD3DGlyphCache: unable to lock texture rect.";
- return;
- }
-
- // ### unify these loops
- if (clearType) {
- int ppl = rect.Pitch / 4;
- uint *tex_data = (uint *) rect.pBits;
- for (int y=0; y<glyph_im.height(); ++y) {
- uint *s = (uint *) glyph_im.scanLine(y);
- for (int x=0; x<glyph_im.width(); ++x) {
- tex_data[ppl*y + x] = *s;
- ++s;
- }
- }
- } else {
- int ppl = rect.Pitch;
- uchar *tex_data = (uchar *) rect.pBits;
- for (int y=0; y<glyph_im.height(); ++y) {
- uchar *s = (uchar *) glyph_im.scanLine(y);
- for (int x=0; x<glyph_im.width(); ++x) {
- tex_data[ppl*y + x] = *s;
- ++s;
- }
- }
- }
- font_tex->texture->UnlockRect(0);
-
- // debug
-// dump_font_texture(font_tex);
-
- if (font_tex->x_offset + glyph_width > font_tex->width) {
- font_tex->x_offset = 0;
- font_tex->y_offset += glyph_height;
- } else {
- font_tex->x_offset += glyph_width;
- }
-
- cache->insert(glyphs[i], d3d_glyph);
- }
- }
-}
-
-Q_GLOBAL_STATIC(QD3DGlyphCache, qd3d_glyph_cache)
-
-//
-// end font caching stuff
-//
-
-
-//
-// D3D image cache stuff
-//
-
-// ### keep the GL stuff in mind..
-typedef void (*_qt_image_cleanup_hook_64)(qint64);
-extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
-
-static void qd3d_image_cleanup(qint64 key);
-
-class QD3DImage
-{
-public:
- QD3DImage(IDirect3DDevice9 *device, const QImage &image);
- ~QD3DImage();
-
- IDirect3DTexture9 *texture;
-};
-
-static QList<IDirect3DTexture9 *> qd3d_release_list;
-
-QD3DImage::QD3DImage(IDirect3DDevice9 *device, const QImage &image)
-{
- texture = 0;
- Q_ASSERT(device);
- QImage im = image.convertToFormat(QImage::Format_ARGB32);
- if (FAILED(device->CreateTexture(im.width(), im.height(), 1, 0,
- D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, 0))) {
- qWarning("QD3DImage(): unable to create Direct3D texture.");
- return;
- }
-// qDebug(" -> created image texture: %p - 0x%08x%08x",texture,uint (image.cacheKey() >> 32),uint (image.cacheKey() & 0xffffffff));
- D3DLOCKED_RECT rect;
- if (FAILED(texture->LockRect(0, &rect, 0, 0))) {
- qDebug() << "QD3DImage: unable to lock texture rect.";
- return;
- }
- DWORD *dst = (DWORD *) rect.pBits;
- DWORD *src = (DWORD *) im.scanLine(0);
-
- Q_ASSERT((rect.Pitch/4) == (im.bytesPerLine()/4));
- memcpy(dst, src, rect.Pitch*im.height());
- texture->UnlockRect(0);
-}
-
-QD3DImage::~QD3DImage()
-{
- if (texture)
- qd3d_release_list.append(texture);
-}
-
-static int qd3d_cache_limit = 64*1024; // cache ~64 MB worth of textures
-typedef QCache<quint64, QD3DImage> QD3DImageCache;
-
-class QD3DImageManager
-{
-public:
- QD3DImageManager() {
- // ### GL does the same!
- qt_image_cleanup_hook_64 = qd3d_image_cleanup;
- cache.setMaxCost(qd3d_cache_limit);
- }
- ~QD3DImageManager() {
-// qDebug() << "unhooking d3d image cache";
- qt_image_cleanup_hook_64 = 0;
- cache.clear();
- }
-
- IDirect3DTexture9 *lookup(IDirect3DDevice9 *device, const QImage &image);
- void remove(quint64 key);
-
-private:
- QD3DImageCache cache;
-};
-
-IDirect3DTexture9 *QD3DImageManager::lookup(IDirect3DDevice9 *device, const QImage &image)
-{
- QD3DImage *tex_image = 0;
-
- tex_image = cache.object(image.cacheKey());
- if (!tex_image) {
- // to avoid cache thrashing we remove images from the cache
- // that have the same serial no as the cached image, since
- // that image is most likely destoyed already, and we got a
- // stale cache entry
- uint serial = (uint) (image.cacheKey() >> 32);
- QList<quint64> keys = cache.keys();
- for (int i=0; i<keys.size(); ++i) {
- if ((uint)(keys.at(i) >> 32) == serial) {
- cache.remove(keys.at(i));
- break;
- }
- }
-// qDebug(" => cached: %d, adding cache image: 0x%08x%08x",cache.size(), uint (image.cacheKey() >> 32),uint (image.cacheKey() & 0xffffffff));
- // add cache entry
- int cost = image.width()*image.height()*4/1024;
- if (cache.totalCost() + cost > cache.maxCost()) {
- // no room for new entries? kick out half the cached images
- int old_max_cost = cache.maxCost();
- cache.setMaxCost(old_max_cost/2);
- cache.setMaxCost(old_max_cost);
- }
- tex_image = new QD3DImage(device, image);
- cache.insert(image.cacheKey(), tex_image, cost);
-// qDebug() << "==> total cache cost: " << cache.totalCost() << cost;
- }
-
- return tex_image->texture;
-}
-
-void QD3DImageManager::remove(quint64 key)
-{
-// QList<quint64> keys = cache.keys();
-// if (keys.contains(key))
-// qDebug() << "entery removed from cache";
- cache.remove(key);
-}
-
-Q_GLOBAL_STATIC(QD3DImageManager, qd3d_image_cache)
-
-static void qd3d_image_cleanup(qint64 key)
-{
-// qDebug() << "qd3d_image_cleanup:";
-// qDebug(" => key: 0x%08x%08x", (uint) (key >> 32), (uint)(key & 0xffffffff));
- qd3d_image_cache()->remove(key);
-}
-
-//
-// end D3D image cache stuff
-//
-
-class QD3DDrawHelper : public QTessellator
-{
-public:
- QD3DDrawHelper(QDirect3DPaintEnginePrivate *pe);
- ~QD3DDrawHelper();
-
- bool needsFlushing() const;
- QD3DMaskPosition allocateMaskPosition(const QRectF &brect, bool *breakbatch);
-
- void setClipPath(const QPainterPath &path, QD3DBatchItem **item);
-
- void queueAntialiasedMask(const QPolygonF &poly, QD3DBatchItem **item, const QRectF &brect);
- QRectF queueAliasedMask(const QPainterPath &path, QD3DBatchItem **item, D3DCOLOR color);
-
- void queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color, const QPolygonF &trect);
- void queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color);
-
- void queueTextGlyph(const QRectF &rect, const qreal *tex_coords, QD3DBatchItem *item,
- D3DCOLOR color);
-
- void queueAntialiasedLines(const QPainterPath &path, QD3DBatchItem **item, const QRectF &brect);
- void queueAliasedLines(const QLineF *lines, int lineCount, QD3DBatchItem **item);
-
- int drawAntialiasedMask(int offset, int maxoffset);
- void drawAliasedMask(int offset);
- void drawAntialiasedBoundingRect(QD3DBatchItem *item);
- void drawAliasedBoundingRect(QD3DBatchItem *item);
- void drawTextItem(QD3DBatchItem *item);
- void drawAliasedLines(QD3DBatchItem *item);
-
- void setMaskSize(QSize size);
-
- void beforeReset();
- void afterReset();
-
- IDirect3DSurface9 *freeMaskSurface();
-
- inline void lockVertexBuffer();
- inline void unlockVertexBuffer();
-
- inline int index() { return m_index; }
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- enum VertexBufferAccess {
- CLEAR = 0x00,
- READ = 0x01,
- WRITE = 0x02
- };
- int accesscontrol[QT_VERTEX_BUF_SIZE];
-#endif
-
-private:
- void addTrap(const Trapezoid &trap);
- void tessellate(const QPolygonF &poly);
- inline void lineToStencil(qreal x, qreal y);
- inline void curveToStencil(const QPointF &cp1, const QPointF &cp2, const QPointF &ep);
- QRectF pathToVertexArrays(const QPainterPath &path);
- void resetMask();
-
- QDirect3DPaintEnginePrivate *m_pe;
-
- qreal m_xoffset, m_yoffset;
- int m_startindex;
- int m_index;
- int m_height, m_width;
- LPDIRECT3DVERTEXBUFFER9 m_d3dvbuff;
- vertex *m_vbuff;
- QD3DBatchItem *m_item;
- QRectF m_boundingRect;
-
- qreal max_x;
- qreal max_y;
- qreal min_x;
- qreal min_y;
- qreal firstx;
- qreal firsty;
-
- QPointF tess_lastpoint;
- int tess_index;
-
- bool m_locked;
- IDirect3DTexture9 *m_mask;
- IDirect3DSurface9 *m_maskSurface;
- IDirect3DSurface9 *m_depthStencilSurface;
-
- D3DCOLOR m_color;
- bool m_clearmask;
- bool m_isLine;
- bool m_firstPoint;
-
- QD3DMaskPosition m_mask_position;
- int m_mask_offsetX2;
- int m_mask_offsetY2;
-};
-
-QD3DStateManager::QD3DStateManager(LPDIRECT3DDEVICE9 pDevice, ID3DXEffect *effect)
- : m_pDevice(pDevice), m_effect(effect), m_refs(0)
-{
- if (FAILED(D3DXMatrixIdentity(&m_d3dIdentityMatrix))) {
- qWarning("QDirect3DPaintEngine: D3DXMatrixIdentity failed");
- }
- reset();
-}
-
-void QD3DStateManager::reset()
-{
- m_radgradfd = -1;
-
- m_cosmetic_pen = false;
- m_pass = -1;
- m_maskchannel = -1;
- m_brushmode = -1;
- m_texture = 0;
- m_xoffset = INT_MAX;
- m_yoffset = INT_MAX;
-
- m_vertexshader = 0;
- m_pixelshader = 0;
-
- m_isIdentity = true;
- m_transformation = QTransform();
- m_effect->SetMatrix("g_mTransformation", &m_d3dIdentityMatrix);
-
- ZeroMemory(&m_projection, sizeof(D3DMATRIX));
- ZeroMemory(m_textures, sizeof(LPDIRECT3DBASETEXTURE9) * D3D_STAGE_COUNT);
- FillMemory(m_samplerstates, sizeof(DWORD) * D3D_SAMPLE_STATES * D3D_STAGE_COUNT, 0xFFFFFFFE);
- FillMemory(m_texturestates, sizeof(DWORD) * D3D_TEXTURE_STATES * D3D_STAGE_COUNT, 0xFFFFFFFE);
- FillMemory(m_renderstate, sizeof(DWORD) * D3D_RENDER_STATES, 0xFFFFFFFE);
-}
-
-inline void QD3DStateManager::beginPass(int pass)
-{
- if (pass != m_pass) {
- if (m_pass != -1)
- m_effect->EndPass();
- m_effect->BeginPass(pass);
- m_pass = pass;
- }
-}
-
-inline void QD3DStateManager::endPass()
-{
- if (m_pass != -1) {
- m_pass = -1;
- m_effect->EndPass();
- }
-}
-
-inline void QD3DStateManager::startStateBlock() {
- m_changed = false;
-}
-
-inline void QD3DStateManager::setCosmeticPen(bool enabled)
-{
- if (enabled != m_cosmetic_pen) {
- m_effect->SetBool("g_mCosmeticPen", enabled);
- m_cosmetic_pen = enabled;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setBrushMode(int mode)
-{
- if (mode != m_brushmode) {
- m_effect->SetInt("g_mBrushMode", mode);
- m_brushmode = mode;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setTexture(LPDIRECT3DBASETEXTURE9 pTexture)
-{
- SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
- SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
-
- if (pTexture != m_texture) {
- m_texture = pTexture;
- m_effect->SetTexture("g_mTexture", pTexture);
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setTexture(LPDIRECT3DBASETEXTURE9 pTexture, QGradient::Spread spread)
-{
- switch(spread) {
- case QGradient::RepeatSpread:
- SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
- SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
- break;
- case QGradient::ReflectSpread:
- SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
- SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
- break;
- default:
- SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
- SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
- break;
- };
-
- if (pTexture != m_texture) {
- m_texture = pTexture;
- m_effect->SetTexture("g_mTexture", pTexture);
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setTransformation(const QTransform *matrix)
-{
- if (matrix) {
- if (*matrix != m_transformation) {
- D3DXMATRIX dxmatrix(matrix->m11(), matrix->m12(), 0, matrix->m13(),
- matrix->m21(), matrix->m22(), 0, matrix->m23(),
- 0, 0, 1, 0,
- matrix->dx(), matrix->dy(), 0, 1);
- m_effect->SetMatrix("g_mTransformation", &dxmatrix);
- m_transformation = *matrix;
- m_changed = true;
- m_isIdentity = false;
- }
- } else if (!m_isIdentity) {
- m_effect->SetMatrix("g_mTransformation", &m_d3dIdentityMatrix);
- m_transformation = QTransform();
- m_changed = true;
- m_isIdentity = true;
- }
-}
-
-inline void QD3DStateManager::setProjection(const D3DXMATRIX *pMatrix)
-{
- if (*pMatrix != m_projection) {
- m_effect->SetMatrix("g_mViewProjection", pMatrix);
- m_projection = *pMatrix;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setFocalDistance(const qreal &fd)
-{
- if (fd != m_radgradfd) {
- m_effect->SetFloat("g_mFocalDist", fd);
- m_changed = true;
- m_radgradfd = fd;
- }
-}
-
-inline void QD3DStateManager::setMaskOffset(qreal x, qreal y)
-{
- if (x != m_xoffset || y != m_yoffset) {
- float offset[2] = {x, y};
- m_effect->SetFloatArray("g_mMaskOffset", offset, 2);
- m_xoffset = x;
- m_yoffset = y;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setMaskChannel(int channel)
-{
- if (m_maskchannel != channel) {
- m_effect->SetIntArray("g_mChannel", m_mask_channels[channel], 4);
- m_maskchannel = channel;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::endStateBlock()
-{
- if (m_changed) {
- m_effect->CommitChanges();
- m_changed = false;
- }
-}
-
-STDMETHODIMP QD3DStateManager::QueryInterface(REFIID iid, LPVOID *ppv)
-{
- if(iid == IID_IUnknown || iid == IID_ID3DXEffectStateManager)
- {
- *ppv = this;
- ++m_refs;
- return NOERROR;
- }
- *ppv = NULL;
- return ResultFromScode(E_NOINTERFACE);
-}
-
-STDMETHODIMP_(ULONG) QD3DStateManager::AddRef(void)
-{
- return (ULONG)InterlockedIncrement( &m_refs );
-}
-
-
-STDMETHODIMP_(ULONG) QD3DStateManager::Release(void)
-{
- if( 0L == InterlockedDecrement( &m_refs ) ) {
- delete this;
- return 0L;
- }
-
- return m_refs;
-}
-STDMETHODIMP QD3DStateManager::SetTransform(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix)
-{
- return m_pDevice->SetTransform(State, pMatrix);
-}
-
-STDMETHODIMP QD3DStateManager::SetMaterial(CONST D3DMATERIAL9 *pMaterial)
-{
- return m_pDevice->SetMaterial(pMaterial);
-}
-
-STDMETHODIMP QD3DStateManager::SetLight(DWORD Index, CONST D3DLIGHT9 *pLight)
-{
- return m_pDevice->SetLight(Index, pLight);
-}
-
-STDMETHODIMP QD3DStateManager::LightEnable(DWORD Index, BOOL Enable)
-{
- return m_pDevice->LightEnable(Index, Enable);
-}
-
-STDMETHODIMP QD3DStateManager::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value)
-{
- if (State < D3D_RENDER_STATES) {
- if (m_renderstate[State] == Value)
- return S_OK;
- m_renderstate[State] = Value;
- }
- return m_pDevice->SetRenderState(State, Value);
-}
-
-STDMETHODIMP QD3DStateManager::SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
-{
- if (Stage < D3D_STAGE_COUNT) {
- if (m_textures[Stage] == pTexture)
- return S_OK;
- m_textures[Stage] = pTexture;
- }
- return m_pDevice->SetTexture(Stage, pTexture);
-}
-
-STDMETHODIMP QD3DStateManager::SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
-{
- if (Stage < D3D_STAGE_COUNT && Type < D3D_TEXTURE_STATES) {
- if (m_texturestates[Stage][Type] == Value)
- return S_OK;
- m_texturestates[Stage][Type] = Value;
- }
- return m_pDevice->SetTextureStageState(Stage, Type, Value);
-}
-
-STDMETHODIMP QD3DStateManager::SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
-{
- if (Sampler < D3D_STAGE_COUNT && Type < D3D_SAMPLE_STATES) {
- if (m_samplerstates[Sampler][Type] == Value)
- return S_OK;
- m_samplerstates[Sampler][Type] = Value;
- }
- return m_pDevice->SetSamplerState(Sampler, Type, Value);
-}
-
-STDMETHODIMP QD3DStateManager::SetNPatchMode(FLOAT NumSegments)
-{
- return m_pDevice->SetNPatchMode(NumSegments);
-}
-
-STDMETHODIMP QD3DStateManager::SetFVF(DWORD FVF)
-{
- return m_pDevice->SetFVF(FVF);
-}
-
-STDMETHODIMP QD3DStateManager::SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader)
-{
- if (m_vertexshader == pShader)
- return S_OK;
- m_vertexshader = pShader;
- return m_pDevice->SetVertexShader(pShader);
-}
-
-STDMETHODIMP QD3DStateManager::SetVertexShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetVertexShaderConstantF(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetVertexShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetVertexShaderConstantI(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetVertexShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetVertexShaderConstantB(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader)
-{
- if (m_pixelshader == pShader)
- return S_OK;
- m_pixelshader = pShader;
- return m_pDevice->SetPixelShader(pShader);
-}
-
-STDMETHODIMP QD3DStateManager::SetPixelShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetPixelShaderConstantF(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetPixelShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetPixelShaderConstantI(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetPixelShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetPixelShaderConstantB(RegisterIndex, pConstantData, RegisterCount);
-}
-
-#define QD3D_GRADIENT_CACHE_SIZE 60
-#define QD3D_GRADIENT_PALETTE_SIZE 1024
-
-class QD3DGradientCache
-{
- struct CacheInfo
- {
- inline CacheInfo(QGradientStops s, qreal op) :
- stops(s), opacity(op) {}
-
- IDirect3DTexture9 *texture;
- QGradientStops stops;
- qreal opacity;
- };
-
- typedef QMultiHash<quint64, CacheInfo> QD3DGradientColorTableHash;
-
-public:
- QD3DGradientCache(LPDIRECT3DDEVICE9 device);
- ~QD3DGradientCache();
-
- inline IDirect3DTexture9 *getBuffer(const QGradientStops &stops, qreal opacity);
-
-protected:
- inline void generateGradientColorTable(const QGradientStops& s,
- uint *colorTable,
- int size, qreal opacity) const;
- IDirect3DTexture9 *addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity);
- void cleanCache();
-
- QD3DGradientColorTableHash cache;
- LPDIRECT3DDEVICE9 m_device;
-};
-
-QD3DGradientCache::QD3DGradientCache(LPDIRECT3DDEVICE9 device)
- : m_device(device)
-{
-
-}
-
-QD3DGradientCache::~QD3DGradientCache()
-{
- cleanCache();
-}
-
-inline IDirect3DTexture9 *QD3DGradientCache::getBuffer(const QGradientStops &stops, qreal opacity)
-{
- quint64 hash_val = 0;
-
- for (int i = 0; i < stops.size() && i <= 2; i++)
- hash_val += stops[i].second.rgba();
-
- QD3DGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
-
- if (it == cache.constEnd())
- return addCacheElement(hash_val, stops, opacity);
- else {
- do {
- const CacheInfo &cache_info = it.value();
- if (cache_info.stops == stops && cache_info.opacity == opacity) {
- return cache_info.texture;
- }
- ++it;
- } while (it != cache.constEnd() && it.key() == hash_val);
- // an exact match for these stops and opacity was not found, create new cache
- return addCacheElement(hash_val, stops, opacity);
- }
-}
-
-void QD3DGradientCache::generateGradientColorTable(const QGradientStops& s, uint *colorTable, int size, qreal opacity) const
-{
- int pos = 0;
- qreal fpos = 0.0;
- qreal incr = 1.0 / qreal(size);
- QVector<uint> colors(s.size());
-
- for (int i = 0; i < s.size(); ++i)
- colors[i] = s[i].second.rgba();
-
- uint alpha = qRound(opacity * 255);
- while (fpos < s.first().first) {
- colorTable[pos] = ARGB_COMBINE_ALPHA(colors[0], alpha);
- pos++;
- fpos += incr;
- }
-
- for (int i = 0; i < s.size() - 1; ++i) {
- qreal delta = 1/(s[i+1].first - s[i].first);
- while (fpos < s[i+1].first && pos < size) {
- int dist = int(256 * ((fpos - s[i].first) * delta));
- int idist = 256 - dist;
- uint current_color = ARGB_COMBINE_ALPHA(colors[i], alpha);
- uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha);
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
-#else
- uint c = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
- colorTable[pos] = ( (c << 24) & 0xff000000)
- | ((c >> 24) & 0x000000ff)
- | ((c << 8) & 0x00ff0000)
- | ((c >> 8) & 0x0000ff00);
-#endif // Q_BYTE_ORDER
- ++pos;
- fpos += incr;
- }
- }
- for (;pos < size; ++pos)
- colorTable[pos] = colors[s.size() - 1];
-}
-
-IDirect3DTexture9 *QD3DGradientCache::addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity)
-{
- if (cache.size() == QD3D_GRADIENT_CACHE_SIZE) {
- int elem_to_remove = qrand() % QD3D_GRADIENT_CACHE_SIZE;
- uint key = cache.keys()[elem_to_remove];
-
- // need to call release on each removed cache entry:
- QD3DGradientColorTableHash::const_iterator it = cache.constFind(key);
- do {
- it.value().texture->Release();
- } while (++it != cache.constEnd() && it.key() == key);
-
- cache.remove(key); // may remove more than 1, but OK
- }
-
- CacheInfo cache_entry(stops, opacity);
- uint buffer[QD3D_GRADIENT_PALETTE_SIZE];
- generateGradientColorTable(stops, buffer, QD3D_GRADIENT_PALETTE_SIZE, opacity);
-
- if (FAILED(m_device->CreateTexture(QD3D_GRADIENT_PALETTE_SIZE, 1, 1, 0,
- D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &cache_entry.texture, 0))) {
- qWarning("QD3DGradientCache::addCacheElement(): unable to create Direct3D texture.");
- return 0;
- }
-
- D3DLOCKED_RECT rect;
- if (FAILED(cache_entry.texture->LockRect(0, &rect, 0, 0))) {
- qDebug() << "QD3DGradientCache::addCacheElement(): unable to lock texture rect.";
- return 0;
- }
- memcpy(rect.pBits, buffer, rect.Pitch);
- cache_entry.texture->UnlockRect(0);
-
- return cache.insert(hash_val, cache_entry).value().texture;
-}
-
-void QD3DGradientCache::cleanCache()
-{
- QD3DGradientColorTableHash::const_iterator it = cache.constBegin();
- for (; it != cache.constEnd(); ++it) {
- const CacheInfo &cache_info = it.value();
- cache_info.texture->Release();
- }
- cache.clear();
-}
-
-QD3DSurfaceManager::QD3DSurfaceManager() :
- m_status(NoStatus), m_dummy(0), m_device(0), m_pd(0), m_current(0)
-{
-
-}
-
-QD3DSurfaceManager::~QD3DSurfaceManager()
-{
-}
-
-void QD3DSurfaceManager::setPaintDevice(QPaintDevice *pd)
-{
- m_status = NoStatus;
- m_pd = pd;
- m_current = 0;
-
- if (m_device->TestCooperativeLevel() != D3D_OK) {
- m_status = NeedsResetting;
- return;
- }
-
- m_current = m_swapchains.value(pd, 0);
- QWidget *w = static_cast<QWidget*>(pd);
-
- if (m_current) {
- if (m_current->size != w->size()) {
- m_swapchains.remove(pd);
- m_current->surface->Release();
- m_current->swapchain->Release();
- delete m_current;
- m_current = 0;
- }
- }
-
- if (!m_current) {
- m_current = createSwapChain(w);
- updateMaxSize();
- }
-}
-
-int QD3DSurfaceManager::status() const
-{
- return m_status;
-}
-
-void QD3DSurfaceManager::reset()
-{
- QList<QPaintDevice *> pds = m_swapchains.keys();
-
- QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin();
- while (i != m_swapchains.constEnd()) {
- i.value()->surface->Release();
- i.value()->swapchain->Release();
- ++i;
- }
- qDeleteAll(m_swapchains.values());
- m_swapchains.clear();
-
- D3DPRESENT_PARAMETERS params;
- initPresentParameters(&params);
- params.hDeviceWindow = m_dummy;
-
- HRESULT res = m_device->Reset(&params);
- if (FAILED(res)) {
- switch (res) {
- case D3DERR_DEVICELOST:
- qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DEVICELOST)");
- break;
- case D3DERR_DRIVERINTERNALERROR:
- qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DRIVERINTERNALERROR)");
- break;
- case D3DERR_OUTOFVIDEOMEMORY:
- qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_OUTOFVIDEOMEMORY)");
- break;
- default:
- qWarning("QDirect3DPaintEngine: Reset failed");
- };
- }
-
- for (int i=0; i<pds.count(); ++i) {
- QWidget *w = static_cast<QWidget*>(pds.at(i));
- createSwapChain(w);
- }
-
- // reset the mask as well
- m_status = MaxSizeChanged;
-
- setPaintDevice(m_pd);
- updateMaxSize();
-}
-
-LPDIRECT3DSURFACE9 QD3DSurfaceManager::renderTarget()
-{
- return m_current ? m_current->surface : 0;
-}
-
-LPDIRECT3DSURFACE9 QD3DSurfaceManager::surface(QPaintDevice *pd)
-{
- D3DSwapChain *swapchain = m_swapchains.value(pd, 0);
- return swapchain ? swapchain->surface : 0;
-}
-
-LPDIRECT3DSWAPCHAIN9 QD3DSurfaceManager::swapChain(QPaintDevice *pd)
-{
- D3DSwapChain *swapchain = m_swapchains.value(pd, 0);
- return swapchain ? swapchain->swapchain : 0;
-}
-
-void QD3DSurfaceManager::releasePaintDevice(QPaintDevice *pd)
-{
- D3DSwapChain *swapchain = m_swapchains.take(pd);
-
- if (swapchain) {
- swapchain->surface->Release();
- swapchain->swapchain->Release();
- delete swapchain;
- if (swapchain == m_current)
- m_current = 0;
- }
-}
-
-LPDIRECT3DDEVICE9 QD3DSurfaceManager::device()
-{
- return m_device;
-}
-
-void QD3DSurfaceManager::cleanup()
-{
- QPixmapCache::clear();
- qd3d_glyph_cache()->cleanCache();
-
- // release doomed textures
- for (int k=0; k<qd3d_release_list.size(); ++k)
- qd3d_release_list.at(k)->Release();
- qd3d_release_list.clear();
-
- QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin();
- while (i != m_swapchains.constEnd()) {
- i.value()->surface->Release();
- i.value()->swapchain->Release();
- ++i;
- }
- qDeleteAll(m_swapchains.values());
-
- if (m_device)
- m_device->Release();
-
- DestroyWindow(m_dummy);
- QString cname(QLatin1String("qt_d3d_dummy"));
- QT_WA({
- UnregisterClass((TCHAR*)cname.utf16(), (HINSTANCE)qWinAppInst());
- } , {
- UnregisterClassA(cname.toLatin1(), (HINSTANCE)qWinAppInst());
- });
-}
-
-QSize QD3DSurfaceManager::maxSize() const
-{
- return m_max_size;
-}
-
-extern "C" {
- LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
-};
-
-void QD3DSurfaceManager::init(LPDIRECT3D9 object)
-{
- QString cname(QLatin1String("qt_d3d_dummy"));
- uint style = CS_DBLCLKS | CS_SAVEBITS;
- ATOM atom;
- QT_WA({
- WNDCLASS wc;
- wc.style = style;
- wc.lpfnWndProc = (WNDPROC)QtWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
- wc.hIcon = 0;
- wc.hCursor = 0;
- wc.hbrBackground = 0;
- wc.lpszMenuName = 0;
- wc.lpszClassName = (TCHAR*)cname.utf16();
- atom = RegisterClass(&wc);
- } , {
- WNDCLASSA wc;
- wc.style = style;
- wc.lpfnWndProc = (WNDPROC)QtWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
- wc.hIcon = 0;
- wc.hCursor = 0;
- wc.hbrBackground = 0;
- wc.lpszMenuName = 0;
- QByteArray tempArray = cname.toLatin1();
- wc.lpszClassName = tempArray;
- atom = RegisterClassA(&wc);
- });
-
- QT_WA({
- const TCHAR *className = (TCHAR*)cname.utf16();
- m_dummy = CreateWindow(className, className, 0,
- 0, 0, 1, 1,
- 0, 0, qWinAppInst(), 0);
- } , {
- m_dummy = CreateWindowA(cname.toLatin1(), cname.toLatin1(), 0,
- 0, 0, 1, 1,
- 0, 0, qWinAppInst(), 0);
- });
-
- D3DPRESENT_PARAMETERS params;
- initPresentParameters(&params);
- params.hDeviceWindow = m_dummy;
-
- HRESULT res = object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 0,
- D3DCREATE_PUREDEVICE|D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_NOWINDOWCHANGES|D3DCREATE_FPU_PRESERVE,
- &params, &m_device);
-
- if (FAILED(res) || m_device == 0)
- qWarning("QDirect3DPaintEngine: failed to create Direct3D device (error=0x%x).", res);
-}
-
-void QD3DSurfaceManager::updateMaxSize()
-{
- int w = 0, h = 0;
- QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin();
- while (i != m_swapchains.constEnd()) {
-
- int nw = i.key()->width();
- if (nw > w)
- w = nw;
-
- int nh = i.key()->height();
- if (nh > h)
- h = nh;
-
- ++i;
- }
-
- QSize newsize = QSize(w, h);
- if (newsize != m_max_size) {
- m_status |= MaxSizeChanged;
- m_max_size = newsize;
- }
-}
-
-void QD3DSurfaceManager::initPresentParameters(D3DPRESENT_PARAMETERS *params)
-{
- ZeroMemory(params, sizeof(D3DPRESENT_PARAMETERS));
- params->Windowed = true;
- params->SwapEffect = D3DSWAPEFFECT_COPY;
- params->BackBufferFormat = D3DFMT_UNKNOWN;
- params->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
- params->Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
-}
-
-QD3DSurfaceManager::D3DSwapChain *QD3DSurfaceManager::createSwapChain(QWidget *w)
-{
- D3DPRESENT_PARAMETERS params;
- initPresentParameters(&params);
- params.hDeviceWindow = w->winId();
- D3DSwapChain *swapchain = new D3DSwapChain();
- swapchain->size = w->size();
- if (FAILED(m_device->CreateAdditionalSwapChain(&params, &swapchain->swapchain)))
- qWarning("QDirect3DPaintEngine: CreateAdditionalSwapChain failed");
- if (FAILED(swapchain->swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &swapchain->surface)))
- qWarning("QDirect3DPaintEngine: GetBackBuffer failed");
- m_swapchains.insert(w, swapchain);
- connect(w, SIGNAL(destroyed(QObject *)), SLOT(cleanupPaintDevice(QObject *)));
-
- // init with background color
- QColor bg = w->palette().color(QPalette::Background);
- m_device->ColorFill(swapchain->surface, 0, D3DCOLOR_ARGB(bg.alpha(), bg.red(),bg.green(),bg.blue()));
-
- return swapchain;
-}
-
-void QD3DSurfaceManager::cleanupPaintDevice(QObject *object)
-{
- QWidget *w = static_cast<QWidget *>(object);
- releasePaintDevice(w);
-}
-
-int QD3DStateManager::m_mask_channels[4][4] =
- {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
-
-QD3DDrawHelper::QD3DDrawHelper(QDirect3DPaintEnginePrivate *pe)
- : m_pe(pe), m_d3dvbuff(0), m_maskSurface(0), m_depthStencilSurface(0),
- m_locked(false), m_mask(0), m_startindex(0), m_index(0), m_vbuff(0), m_clearmask(true),
- m_isLine(false), m_firstPoint(true)
-{
- resetMask();
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess));
-#endif
-
- // create vertex buffer
- afterReset();
-}
-
-QD3DDrawHelper::~QD3DDrawHelper()
-{
- if (m_maskSurface)
- m_maskSurface->Release();
-
- if (m_mask)
- m_mask->Release();
-
- if (m_depthStencilSurface)
- m_depthStencilSurface->Release();
-
- if (m_d3dvbuff)
- m_d3dvbuff->Release();
-}
-
-inline void QD3DDrawHelper::lockVertexBuffer()
-{
- if (!m_locked) {
- DWORD lockflags = D3DLOCK_NOOVERWRITE;
- if (m_startindex >= QT_VERTEX_RESET_LIMIT) {
- m_startindex = 0;
- m_index = 0;
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=0; i<QT_VERTEX_BUF_SIZE; ++i) {
- if (accesscontrol[i] != (WRITE|READ) && accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- }
- memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess));
-#endif
-
- lockflags = D3DLOCK_DISCARD;
- }
-
- if (FAILED(m_d3dvbuff->Lock(0, 0, (void**)&m_vbuff, lockflags))) {
- qWarning() << "QDirect3DPaintEngine: unable to lock vertex buffer.";
- }
- m_locked = true;
- }
-}
-
-inline void QD3DDrawHelper::unlockVertexBuffer()
-{
- if (m_locked) {
- if (FAILED(m_d3dvbuff->Unlock())) {
- qWarning() << "QDirect3DPaintEngine: unable to unlock vertex buffer.";
- }
- m_locked = false;
- }
-}
-
-void QD3DDrawHelper::setClipPath(const QPainterPath &path, QD3DBatchItem **item)
-{
- lockVertexBuffer();
-
- m_item = *item;
- m_item->m_maskpos.x = m_item->m_maskpos.y = 0;
- m_item->m_maskpos.channel = 3;
- m_item->m_info |= QD3DBatchItem::BI_CLIP;
-
- bool winding = (path.fillRule() == Qt::WindingFill);
- if (winding)
- m_item->m_info |= QD3DBatchItem::BI_WINDING;
-
- if (!path.isEmpty()) {
- m_item->m_info |= QD3DBatchItem::BI_MASK;
- m_item->m_info &= ~QD3DBatchItem::BI_AA;
- m_color = 0;
- QRectF brect = pathToVertexArrays(path);
- queueRect(brect, m_item, 0);
- }
-
- *item = m_item;
-}
-
-
-
-void QD3DDrawHelper::queueAntialiasedMask(const QPolygonF &poly, QD3DBatchItem **item, const QRectF &brect)
-{
- lockVertexBuffer();
-
- m_item = *item;
- m_item->m_info |= QD3DBatchItem::BI_MASK;
- setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING);
-
- int xoffset = m_item->m_maskpos.x;
- int yoffset = m_item->m_maskpos.y;
-
- int x = brect.left();
- int y = brect.top();
-
- m_item->m_xoffset = (xoffset - x) + 1;
- m_item->m_yoffset = (yoffset - y) + 1;
-
- m_boundingRect = brect;
- tessellate(poly);
-
- *item = m_item;
-}
-
-QRectF QD3DDrawHelper::queueAliasedMask(const QPainterPath &path, QD3DBatchItem **item, D3DCOLOR color)
-{
- lockVertexBuffer();
-
- m_color = color;
- m_item = *item;
- m_item->m_info |= QD3DBatchItem::BI_MASK;
-
- bool winding = (path.fillRule() == Qt::WindingFill);
- if (winding)
- m_item->m_info |= QD3DBatchItem::BI_WINDING;
-
- QRectF result = pathToVertexArrays(path);
- *item = m_item;
- return result;
-}
-
-// used for drawing aliased transformed rects directly
-// don't use for antialiased or masked drawing
-void QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color, const QPolygonF &trect)
-{
- lockVertexBuffer();
-
- qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f;
- item->m_info |= QD3DBatchItem::BI_BRECT;
-
- // if the item does not have a mask, the offset is different
- if (!(item->m_info & QD3DBatchItem::BI_MASK)) {
- item->m_offset = m_index;
- item->m_count = (item->m_info & QD3DBatchItem::BI_AA) ? 0 : -2;
- }
-
- qreal x1 = rect.left();
- qreal y1 = rect.top();
- qreal x2 = rect.right();
- qreal y2 = rect.bottom();
-
- QPointF tc = trect.at(0);
- vertex v1 = { {x1, y1, zval} , color,
- tc.x(), tc.y(), 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f };
-
- tc = trect.at(1);
- vertex v2 = { {x2, y1, zval} , color,
- tc.x(), tc.y(), 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
-
- tc = trect.at(2);
- vertex v3 = { {x2, y2, zval} , color,
- tc.x(), tc.y(), 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};;
-
- tc = trect.at(3);
- vertex v4 = { {x1, y2, zval} , color,
- tc.x(), tc.y(), 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=m_index; i<(m_index + 4); ++i) {
- if ((m_index + 4) > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= WRITE;
- }
-#endif
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- m_vbuff[m_index++] = v4;
-
- m_startindex = m_index;
-}
-
-
-QD3DMaskPosition QD3DDrawHelper::allocateMaskPosition(const QRectF &brect, bool *breakbatch)
-{
- int w = brect.width();
- int h = brect.height();
-
- w += 3;
- h += 3;
-
- if (w > m_width)
- w = m_width;
- if (h > m_height)
- h = m_height;
-
- *breakbatch = false;
-
- if ((m_height - m_mask_offsetY2) >= h && (m_width - m_mask_position.x) >= w) {
- m_mask_position.y = m_mask_offsetY2;
- } else if ((m_width - m_mask_offsetX2) >= w) {
- m_mask_position.y = QD3D_MASK_MARGIN;
- m_mask_position.x = m_mask_offsetX2;
- } else if (m_mask_position.channel < 3) {
- ++m_mask_position.channel;
- m_mask_position.x = m_mask_position.y = QD3D_MASK_MARGIN;
- m_mask_offsetX2 = m_mask_offsetY2 = QD3D_MASK_MARGIN;
- } else {
- resetMask();
- *breakbatch = true;
- }
-
- int newoffset = m_mask_position.x + w;
- if (m_mask_offsetX2 < newoffset)
- m_mask_offsetX2 = newoffset;
- m_mask_offsetY2 = (m_mask_position.y + h);
-
- return m_mask_position;
-
-}
-
-void QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color)
-{
- lockVertexBuffer();
-
- QRectF brect;
- item->m_info |= QD3DBatchItem::BI_BRECT;
- qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f;
-
- if (item->m_info & QD3DBatchItem::BI_AA) {
- int xoffset = item->m_maskpos.x;
- int yoffset = item->m_maskpos.y;
-
- int x = rect.left();
- int y = rect.top();
-
- brect = QRectF(x, y, rect.width() + 1, rect.height() + 1);
-
- item->m_xoffset = (xoffset - x) + 1;
- item->m_yoffset = (yoffset - y) + 1;
-
- // if the item does not have a mask, the offset is different
- if (!(item->m_info & QD3DBatchItem::BI_MASK)) {
- item->m_offset = m_index;
- item->m_count = 0;
- }
- } else {
- brect = rect;
-
- if (!(item->m_info & QD3DBatchItem::BI_MASK)) {
- item->m_offset = m_index;
- item->m_count = -2;
- }
- }
-
- qreal left = brect.left();
- qreal right = brect.right();
- qreal top = brect.top();
- qreal bottom = brect.bottom();
-
- vertex v1 = { {left, bottom, zval}, color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
- vertex v2 = { {left, top, zval}, color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
- vertex v3 = { {right, top, zval}, color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
- vertex v4 = { {right, bottom, zval}, color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=m_index; i<(m_index + 4); ++i) {
- if ((m_index + 4) > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= WRITE;
- }
-#endif
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- m_vbuff[m_index++] = v4;
-
- m_startindex = m_index;
-}
-
-void QD3DDrawHelper::queueAntialiasedLines(const QPainterPath &path, QD3DBatchItem **item, const QRectF &brect)
-{
- lockVertexBuffer();
-
- m_item = *item;
- m_item->m_info |= QD3DBatchItem::BI_MASK;
- setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING);
-
- int xoffset = m_item->m_maskpos.x;
- int yoffset = m_item->m_maskpos.y;
- int x = brect.left();
- int y = brect.top();
-
- m_item->m_xoffset = (xoffset - x) + 1;
- m_item->m_yoffset = (yoffset - y) + 1;
-
- m_boundingRect = brect;
-
- m_xoffset = (x - xoffset) + 0.5f;
- m_yoffset = (y - yoffset) + 0.5f;
-
- QPointF last;
- for (int i = 0; i < path.elementCount(); ++i) {
- QPainterPath::Element element = path.elementAt(i);
-
- //Q_ASSERT(!element.isCurveTo());
-
- if (element.isLineTo())
- QTessellator::tessellateRect(last, element, m_item->m_width);
-
- last = element;
- }
-
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) / 3;
- m_startindex = m_index;
-
- *item = m_item;
-}
-
-void QD3DDrawHelper::queueAliasedLines(const QLineF *lines, int lineCount, QD3DBatchItem **item)
-{
- lockVertexBuffer();
-
- m_item = *item;
- m_item->m_info |= QD3DBatchItem::BI_FASTLINE;
-
- for (int i=0; i<lineCount; ++i) {
- const QLineF line = lines[i];
- qreal p1x = line.p1().x();
- qreal p1y = line.p1().y();
- qreal p2x = line.p2().x();
- qreal p2y = line.p2().y();
-
- vertex v1 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color,
- -1.f, -1.f, p2x, p2y,
- 0.f, 0.f, 0.f, 0.f };
- vertex v2 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color,
- 1.f, -1.f, p2x, p2y,
- 0.f, 0.f, 0.f, 0.f };
- vertex v3 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color,
- 1.f, 1.f, p2x, p2y,
- 0.f, 0.f, 0.f, 0.f };
- vertex v4 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color,
- -1.f, 1.f, p2x, p2y,
- 0.f, 0.f, 0.f, 0.f };
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
-
- if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) {
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) / 2;
- m_startindex = m_index;
-
- QD3DBatchItem itemcopy = *m_item;
- m_item = m_pe->nextBatchItem();
- *m_item = itemcopy;
-
- lockVertexBuffer();
- }
- }
-
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) - 2;
- m_startindex = m_index;
-
- *item = m_item;
-}
-
-void QD3DDrawHelper::queueTextGlyph(const QRectF &rect, const qreal *tex_coords,
- QD3DBatchItem *item, D3DCOLOR color)
-{
- lockVertexBuffer();
-
- qreal x1 = rect.left();
- qreal y1 = rect.top();
- qreal x2 = rect.right();
- qreal y2 = rect.bottom();
-
- vertex v1 = { {x1, y1, 0.5f}, color,
- tex_coords[0], tex_coords[1], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v2 = { {x2, y1, 0.5f}, color,
- tex_coords[2], tex_coords[1], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v3 = { {x2, y2, 0.5f}, color,
- tex_coords[2], tex_coords[3], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v4 = { {x1, y1, 0.5f}, color,
- tex_coords[0], tex_coords[1], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v5 = { {x2, y2, 0.5f}, color,
- tex_coords[2], tex_coords[3], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v6 = { {x1, y2, 0.5f}, color,
- tex_coords[0], tex_coords[3], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=m_index; i<(m_index + 6); ++i) {
- if ((m_index + 6) > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= WRITE;
- }
-#endif
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v5;
- m_vbuff[m_index++] = v6;
-
- m_startindex = m_index;
- ++item->m_count;
-}
-
-bool QD3DDrawHelper::needsFlushing() const
-{
- return (m_pe->m_batch.m_item_index >= QD3D_BATCH_SIZE || m_startindex >= QT_VERTEX_RESET_LIMIT);
-}
-
-void QD3DDrawHelper::setMaskSize(QSize size)
-{
- m_width = size.width();
- m_height = size.height();
-
- if (m_maskSurface)
- m_maskSurface->Release();
-
- if (m_mask)
- m_mask->Release();
-
- if (FAILED(m_pe->m_d3d_device->CreateTexture(m_width, m_height, 1, D3DUSAGE_RENDERTARGET,
- D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_mask, NULL))) {
- qWarning() << "QDirect3DPaintEngine: CreateTexture() failed.";
- }
-
- if (m_depthStencilSurface)
- m_depthStencilSurface->Release();
-
- if (FAILED(m_pe->m_d3d_device->CreateDepthStencilSurface(m_width, m_height, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0,
- TRUE, &m_depthStencilSurface, NULL))) {
- qWarning() << "QDirect3DPaintEngine: CreateDepthStencilSurface() failed.";
- }
-
- m_pe->m_d3d_device->SetDepthStencilSurface(m_depthStencilSurface);
- m_pe->m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0, 0.0f, 0);
-
- if (FAILED(m_mask->GetSurfaceLevel(0, &m_maskSurface))) {
- qWarning() << "QDirect3DPaintEngine: GetSurfaceLevel() failed.";
- }
-
- m_pe->m_d3d_device->ColorFill(m_maskSurface, 0, D3DCOLOR_ARGB(0,0,0,0));
- D3DXMATRIX projMatrix;
- pD3DXMatrixOrthoOffCenterLH(&projMatrix, 0, m_width, m_height, 0, 0, 1);
- m_pe->m_effect->SetMatrix("g_mMaskProjection", &projMatrix);
- m_pe->m_effect->SetTexture("g_mAAMask", m_mask);
-}
-
-void QD3DDrawHelper::beforeReset()
-{
- resetMask();
- m_clearmask = true;
-
- if (m_maskSurface) {
- m_maskSurface->Release();
- m_maskSurface = 0;
- }
-
- if (m_mask) {
- m_mask->Release();
- m_mask = 0;
- }
-
- if (m_depthStencilSurface) {
- m_depthStencilSurface->Release();
- m_depthStencilSurface = 0;
- }
-
- if (m_d3dvbuff)
- m_d3dvbuff->Release();
-}
-
-void QD3DDrawHelper::afterReset()
-{
- if (FAILED(m_pe->m_d3d_device->CreateVertexBuffer(QT_VERTEX_BUF_SIZE*sizeof(vertex), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
- QD3DFVF_CSVERTEX,
- D3DPOOL_DEFAULT, &m_d3dvbuff, NULL))) {
- qWarning() << "QDirect3DPaintEngine: failed to create vertex buffer.";
- }
-
- m_pe->m_d3d_device->SetStreamSource(0, m_d3dvbuff, 0, sizeof(vertex));
- m_pe->m_d3d_device->SetFVF(QD3DFVF_CSVERTEX);
-
- m_startindex = 0;
- m_index = 0;
-}
-
-IDirect3DSurface9 *QD3DDrawHelper::freeMaskSurface()
-{
- // we need to make sure the mask is cleared when it's used for something else
- resetMask();
- m_clearmask = true;
-
- return m_maskSurface;
-}
-
-int QD3DDrawHelper::drawAntialiasedMask(int offset, int maxoffset)
-{
- int newoffset = offset;
- QD3DBatchItem *item = &(m_pe->m_batch.items[offset]);
-
- // set mask as render target
- if (FAILED(m_pe->m_d3d_device->SetRenderTarget(0, m_maskSurface)))
- qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!";
-
- if (m_clearmask) {
- m_pe->m_d3d_device->Clear(0, 0, D3DCLEAR_TARGET,D3DCOLOR_ARGB(0,0,0,0), 0, 0);
- m_clearmask = false;
- }
-
- // fill the mask
- m_pe->m_statemanager->beginPass(PASS_AA_CREATEMASK);
- for (; newoffset<maxoffset; ++newoffset) {
- item = &(m_pe->m_batch.items[newoffset]);
- if (!(item->m_info & QD3DBatchItem::BI_AA) || !(item->m_info & QD3DBatchItem::BI_MASK)) {
- break;
- } else if (item->m_info & QD3DBatchItem::BI_MASKFULL) {
- item->m_info &= ~QD3DBatchItem::BI_MASKFULL;
- m_clearmask = true;
- break;
- }
-
- m_pe->m_statemanager->startStateBlock();
- if (item->m_info & QD3DBatchItem::BI_MASKSCISSOR) {
- RECT rect;
- QRectF srect = item->m_brect.adjusted(item->m_xoffset, item->m_yoffset,
- item->m_xoffset, item->m_yoffset);
- rect.left = qMax(qRound(srect.left()), 0);
- rect.top = qMax(qRound(srect.top()), 0);
- rect.bottom = qMin(m_height, qRound(srect.bottom()));
- rect.right = qMin(m_width, qRound(srect.right()));
- m_pe->m_d3d_device->SetScissorRect(&rect);
- m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
- }
- m_pe->m_statemanager->setMaskChannel(item->m_maskpos.channel);
- m_pe->m_statemanager->endStateBlock();
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = item->m_offset;
- for (int i=vbstart; i<(vbstart + (item->m_count * 3)); ++i) {
- if (accesscontrol[i] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= READ;
- }
-#endif
-
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, item->m_count);
-
- if (item->m_info & QD3DBatchItem::BI_MASKSCISSOR) {
- m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
- }
- }
- m_pe->m_statemanager->endPass();
-
- return newoffset;
-}
-
-void QD3DDrawHelper::drawAliasedMask(int offset)
-{
- QD3DBatchItem *item = &(m_pe->m_batch.items[offset]);
- if (item->m_info & QD3DBatchItem::BI_MASK) {
- m_pe->m_statemanager->beginPass( (item->m_info & QD3DBatchItem::BI_WINDING) ? PASS_STENCIL_WINDING : PASS_STENCIL_ODDEVEN );
- int prev_stop = 0;
- for (int i=0; i<item->m_pointstops.count(); ++i) {
- int stop = item->m_pointstops.at(i);
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = (item->m_offset + prev_stop);
- for (int j=vbstart; j<(vbstart+(stop - prev_stop)); ++j) {
- if (accesscontrol[j] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[j] |= READ;
- }
-#endif
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + prev_stop, (stop - prev_stop) - 2);
- prev_stop = stop;
- }
- m_pe->m_statemanager->endPass();
- }
-}
-
-void QD3DDrawHelper::drawTextItem(QD3DBatchItem *item)
-{
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = item->m_offset;
- for (int j=vbstart; j<(vbstart + ((item->m_count * 2) * 3)); ++j) {
- if (accesscontrol[j] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[j] |= READ;
- }
-#endif
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, item->m_count*2);
-}
-
-void QD3DDrawHelper::drawAliasedLines(QD3DBatchItem *item)
-{
- m_pe->m_statemanager->setCosmeticPen(item->m_info & QD3DBatchItem::BI_COSMETICPEN);
- if (item->m_info & QD3DBatchItem::BI_TRANSFORM) {
- m_pe->m_statemanager->setTransformation(&item->m_matrix);
- } else {
- m_pe->m_statemanager->setTransformation();
- }
- int pass = (item->m_info & QD3DBatchItem::BI_MASK)
- ? PASS_ALIASED_LINES
- : PASS_ALIASED_LINES_DIRECT;
- m_pe->m_statemanager->beginPass(pass);
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, (item->m_count + 2) / 3);
- m_pe->m_statemanager->endPass();
-}
-
-void QD3DDrawHelper::drawAntialiasedBoundingRect(QD3DBatchItem *item)
-{
- if (item->m_info & QD3DBatchItem::BI_SCISSOR) {
- RECT rect;
- rect.left = qMax(qRound(item->m_brect.left()), 0);
- rect.top = qMax(qRound(item->m_brect.top()), 0);
- rect.bottom = qMin(m_height, qRound(item->m_brect.bottom()));
- rect.right = qMin(m_width, qRound(item->m_brect.right()));
- m_pe->m_d3d_device->SetScissorRect(&rect);
- m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
- }
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = item->m_offset + (item->m_count * 3);
- for (int j=vbstart; j<(vbstart + 4); ++j) {
- if (accesscontrol[j] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[j] |= READ;
- }
-#endif
-
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + (item->m_count * 3), 2);
-
- if (item->m_info & QD3DBatchItem::BI_SCISSOR) {
- m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
- }
-}
-
-void QD3DDrawHelper::drawAliasedBoundingRect(QD3DBatchItem *item)
-{
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = (item->m_offset + item->m_count + 2);
- for (int j=vbstart; j<(vbstart + 4); ++j) {
- if (accesscontrol[j] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[j] |= READ;
- }
-#endif
-
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + item->m_count + 2, 2);
-}
-
-void QD3DDrawHelper::addTrap(const Trapezoid &trap)
-{
- qreal topLeftY = Q27Dot5ToDouble(trap.topLeft->y) - m_yoffset;
- qreal topLeftX = Q27Dot5ToDouble(trap.topLeft->x) - m_xoffset;
- qreal topRightY = Q27Dot5ToDouble(trap.topRight->y) - m_yoffset;
- qreal topRightX = Q27Dot5ToDouble(trap.topRight->x) - m_xoffset;
- qreal top = Q27Dot5ToDouble(trap.top) - m_yoffset;
- qreal bottom = Q27Dot5ToDouble(trap.bottom) - m_yoffset;
-
- Q27Dot5 _h = trap.topLeft->y - trap.bottomLeft->y;
- Q27Dot5 _w = trap.topLeft->x - trap.bottomLeft->x;
- qreal _leftA = (qreal)_w/_h;
- qreal _leftB = topLeftX - _leftA * topLeftY;
-
- _h = trap.topRight->y - trap.bottomRight->y;
- _w = trap.topRight->x - trap.bottomRight->x;
- qreal _rightA = (qreal)_w/_h;
- qreal _rightB = topRightX - _rightA * topRightY;
-
- qreal invLeftA = qFuzzyCompare(_leftA + 1, 1) ? 0.0 : 1.0 / _leftA;
- qreal invRightA = qFuzzyCompare(_rightA + 1, 1) ? 0.0 : 1.0 / _rightA;
-
- vertex v1 = { {1.f, top - 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
- vertex v2 = { {0.f, top - 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
- vertex v3 = { {0.f, bottom + 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
-
- vertex v4 = { {1.f, top - 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
- vertex v5 = { {0.f, bottom + 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
- vertex v6 = { {1.f, bottom + 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=m_index; i<(m_index + 6); ++i) {
- if ((m_index + 6) > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= WRITE;
- }
-#endif
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v5;
- m_vbuff[m_index++] = v6;
-
- // check if buffer is full
- if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) {
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) / 3;
- m_startindex = m_index;
-
- QD3DBatchItem itemcopy = *m_item;
- m_item = m_pe->nextBatchItem();
- *m_item = itemcopy;
- m_item->m_info &= ~QD3DBatchItem::BI_MASKFULL;
-
- lockVertexBuffer();
- }
-}
-
-void QD3DDrawHelper::tessellate(const QPolygonF &poly) {
- int xoffset = m_item->m_maskpos.x;
- int yoffset = m_item->m_maskpos.y;
-
- int x = m_boundingRect.left();
- int y = m_boundingRect.top();
- m_xoffset = (x - xoffset) + 0.5f;
- m_yoffset = (y - yoffset) + 0.5f;
-
- QTessellator::tessellate(poly.data(), poly.count());
-
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) / 3;
- m_startindex = m_index;
-}
-
-inline void QD3DDrawHelper::lineToStencil(qreal x, qreal y)
-{
- QPointF lastPt = tess_lastpoint;
- tess_lastpoint = QPointF(x, y);
-
- if (m_isLine && m_firstPoint)
- return;
-
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- if (m_index > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[m_index] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[m_index] |= WRITE;
-#endif
-
- vertex v;
- if (m_isLine) {
- vertex v1 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color,
- -1.f, -1.f, x, y,
- 0.f, 0.f, 0.f, 0.f};
- vertex v2 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color,
- 1.f, -1.f, x, y,
- 0.f, 0.f, 0.f, 0.f};
- vertex v3 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color,
- 1.f, 1.f, x, y,
- 0.f, 0.f, 0.f, 0.f};
- vertex v4 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color,
- -1.f, 1.f, x, y,
- 0.f, 0.f, 0.f, 0.f};
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- } else {
- vertex v1 = { {x, y, 0.5f}, m_color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
- m_vbuff[m_index++] = v1;
- v = v1;
- }
- ++tess_index;
-
- // check if buffer is full
- if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) {
- int firstindex = m_startindex;
- if (!m_item->m_pointstops.isEmpty())
- firstindex = m_item->m_pointstops.last();
-
- vertex first = m_vbuff[firstindex];
-
- // finish current polygon
- m_item->m_pointstops.append(tess_index);
- m_item->m_offset = m_startindex;
- m_startindex = m_index;
-
- // copy item
- QD3DBatchItem itemcopy = *m_item;
- m_item = m_pe->nextBatchItem();
- *m_item = itemcopy;
-
- // start new polygon
- lockVertexBuffer();
- m_item->m_pointstops.clear();
- if (!m_isLine) {
- tess_index = 2;
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- if (accesscontrol[m_index] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[m_index] |= WRITE;
-#endif
-
- m_vbuff[m_index++] = first;
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- if (accesscontrol[m_index] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[m_index] |= WRITE;
-#endif
-
- m_vbuff[m_index++] = v;
- } else {
- tess_index = 0;
- }
- }
-
- if (x > max_x)
- max_x = x;
- else if (x < min_x)
- min_x = x;
- if (y > max_y)
- max_y = y;
- else if (y < min_y)
- min_y = y;
-}
-
-inline void QD3DDrawHelper::curveToStencil(const QPointF &cp1, const QPointF &cp2,
- const QPointF &ep)
-{
- qreal inverseScale = 0.5f;
- qreal inverseScaleHalf = inverseScale / 2;
-
- QBezier beziers[32];
- beziers[0] = QBezier::fromPoints(tess_lastpoint, cp1, cp2, ep);
- QBezier *b = beziers;
- while (b >= beziers) {
- // check if we can pop the top bezier curve from the stack
- qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1);
- qreal d;
- if (l > inverseScale) {
- d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - (b->y4 - b->y1)*(b->x1 - b->x2) )
- + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - (b->y4 - b->y1)*(b->x1 - b->x3) );
- d /= l;
- } else {
- d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) +
- qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
- }
- if (d < inverseScaleHalf || b == beziers + 31) {
- // good enough, we pop it off and add the endpoint
- lineToStencil(b->x4, b->y4);
- --b;
- } else {
- // split, second half of the polygon goes lower into the stack
- b->split(b+1, b);
- ++b;
- }
- }
-}
-
-QRectF QD3DDrawHelper::pathToVertexArrays(const QPainterPath &path)
-{
- m_isLine = (m_item->m_info & QD3DBatchItem::BI_FASTLINE);
- const QPainterPath::Element &first = path.elementAt(0);
- firstx = first.x;
- firsty = first.y;
- min_x = max_x = firstx;
- min_y = max_y = firsty;
-
- m_firstPoint = true;
- tess_index = 0;
- m_item->m_pointstops.clear();
- lineToStencil(firstx, firsty);
- m_firstPoint = false;
-
- for (int i=1; i<path.elementCount(); ++i) {
- const QPainterPath::Element &e = path.elementAt(i);
- switch (e.type) {
- case QPainterPath::MoveToElement:
- m_item->m_pointstops.append(tess_index);
- m_firstPoint = true;
- lineToStencil(e.x, e.y);
- m_firstPoint = false;
- break;
- case QPainterPath::LineToElement:
- lineToStencil(e.x, e.y);
- break;
- case QPainterPath::CurveToElement:
- curveToStencil(e, path.elementAt(i+1), path.elementAt(i+2));
- i+=2;
- break;
- default:
- break;
- }
- }
-
- if (!m_isLine)
- lineToStencil(firstx, firsty);
-
- m_item->m_pointstops.append(tess_index);
-
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) - 2;
- m_startindex = m_index;
-
- QRectF result;
- result.setLeft(min_x);
- result.setRight(max_x);
- result.setTop(min_y);
- result.setBottom(max_y);
-
- if (m_isLine)
- result.adjust(0,0,1,1);
-
- return result;
-}
-
-void QD3DDrawHelper::resetMask()
-{
- m_mask_position.x = m_mask_position.y = QD3D_MASK_MARGIN;
- m_mask_position.channel = 0;
- m_mask_offsetX2 = m_mask_offsetY2 = QD3D_MASK_MARGIN;
-}
-
-
-static inline QPainterPath strokeForPath(const QPainterPath &path, const QPen &cpen) {
- QPainterPathStroker stroker;
- if (cpen.style() == Qt::CustomDashLine)
- stroker.setDashPattern(cpen.dashPattern());
- else
- stroker.setDashPattern(cpen.style());
-
- stroker.setCapStyle(cpen.capStyle());
- stroker.setJoinStyle(cpen.joinStyle());
- stroker.setMiterLimit(cpen.miterLimit());
- stroker.setWidth(cpen.widthF());
-
- QPainterPath stroke = stroker.createStroke(path);
- stroke.setFillRule(Qt::WindingFill);
- return stroke;
-}
-
-
-QDirect3DPaintEnginePrivate::~QDirect3DPaintEnginePrivate()
-{
-
-}
-
-void QDirect3DPaintEnginePrivate::updateClipPath(const QPainterPath &path, Qt::ClipOperation op)
-{
- //#### remove me
- QRegion r(path.toFillPolygon().toPolygon(), path.fillRule());
- updateClipRegion(r, op);
-
-/* if (m_draw_helper->needsFlushing())
- flushBatch();
-
- if (op == Qt::IntersectClip && !has_clipping)
- op = Qt::ReplaceClip;
-
- // switch to paths
- if (!m_has_complex_clipping) {
- m_clip_path = QPainterPath();
- m_clip_path.addRegion(m_clip_region);
- m_clip_region = QRegion();
- m_sysclip_path = QPainterPath();
- m_sysclip_path.addRegion(m_sysclip_region);
- m_sysclip_region = QRegion();
- m_has_complex_clipping = true;
- }
-
- QPainterPath cpath = m_matrix.map(path);
-
- QD3DBatchItem *item = &m_batch.items[m_batch.m_item_index++];
- item->m_info = QD3DBatchItem::BI_COMPLEXCLIP;
-
- switch (op) {
- case Qt::UniteClip:
- has_clipping = true;
- m_clip_path = m_clip_path.united(cpath);
- break;
- case Qt::ReplaceClip:
- has_clipping = true;
- m_clip_path = cpath;
- break;
- case Qt::NoClip:
- m_has_complex_clipping = false;
- has_clipping = false;
- item->m_info |= QD3DBatchItem::BI_CLEARCLIP;
- break;
- default: // intersect clip
- has_clipping = true;
- m_clip_path = m_clip_path.intersected(cpath);
- break;
- }
-
- if (!m_sysclip_path.isEmpty()) {
- item->m_info &= ~QD3DBatchItem::BI_CLEARCLIP;
- if (has_clipping)
- m_clip_path = m_clip_path.intersected(m_sysclip_path);
- else
- m_clip_path = m_sysclip_path;
- }
-
- // update the aliased clipping mask
- m_draw_helper->setClipPath(m_clip_path, item);
-
- // update the antialiased clipping mask
- if (m_draw_helper->needsFlushing())
- flushBatch();
-
- QD3DBatchItem *aaitem = &m_batch.items[m_batch.m_item_index++];
- aaitem->m_info = item->m_info|QD3DBatchItem::BI_AA;
- m_draw_helper->setClipPath(m_clip_path, aaitem); */
-}
-
-extern QPainterPath qt_regionToPath(const QRegion &region);
-
-void QDirect3DPaintEnginePrivate::updateClipRegion(const QRegion &clipregion, Qt::ClipOperation op)
-{
- if (m_draw_helper->needsFlushing())
- flushBatch();
- if (m_has_complex_clipping) {
- QPainterPath path = qt_regionToPath(clipregion);
- updateClipPath(path, op);
- return;
- }
-
- if (op == Qt::IntersectClip && m_clip_region.isEmpty())
- op = Qt::ReplaceClip;
-
- QRegion cregion = m_matrix.map(clipregion);
-
- QD3DBatchItem *item = nextBatchItem();
- item->m_info &= ~QD3DBatchItem::BI_AA;
-
- switch (op) {
- case Qt::UniteClip:
- m_clip_region = m_clip_region.united(cregion);
- break;
- case Qt::ReplaceClip:
- m_clip_region = cregion;
- break;
- case Qt::NoClip:
- m_clip_region = QRegion();
- item->m_info |= QD3DBatchItem::BI_CLEARCLIP;
- break;
- default: // intersect clip
- m_clip_region = m_clip_region.intersected(cregion);
- break;
- }
-
- QRegion crgn = m_clip_region;
- if (!m_sysclip_region.isEmpty()) {
- item->m_info &= ~QD3DBatchItem::BI_CLEARCLIP;
- if (!crgn.isEmpty())
- crgn = crgn.intersected(m_sysclip_region);
- else
- crgn = m_sysclip_region;
- }
-
- QPainterPath path = qt_regionToPath(crgn);
- m_draw_helper->setClipPath(path, &item);
-}
-
-void QDirect3DPaintEnginePrivate::updateFont(const QFont &)
-{
-}
-
-void QDirect3DPaintEnginePrivate::setRenderTechnique(RenderTechnique technique)
-{
- if (m_current_technique != technique) {
- if (m_current_technique != RT_NoTechnique)
- m_effect->End();
-
- if (technique == RT_Aliased) {
- m_effect->SetTechnique("Aliased");
- m_effect->Begin(0,D3DXFX_DONOTSAVESTATE);
- } else if (technique == RT_Antialiased) {
- m_effect->SetTechnique("Antialiased");
- m_effect->Begin(0,D3DXFX_DONOTSAVESTATE);
- }
- }
-
- m_current_technique = technique;
-}
-
-/*QPolygonF QDirect3DPaintEnginePrivate::transformedRect(const QRectF &brect) const
-{
- QPolygonF poly(brect);
- return m_matrix.map(poly);
-}
-
-QPolygonF QDirect3DPaintEnginePrivate::calcTextureCoords(const QPolygonF &trect) const
-{
- QPolygonF result(4);
- QRectF brect = trect.boundingRect();
- qreal angle = atan(trect.at(0).x() -
-}
-
-QPolygonF QDirect3DPaintEnginePrivate::offsetTextureCoords(const QRectF &brect, const QPolygonF &trect) const
-{
-
-}*/
-
-inline QD3DBatchItem *QDirect3DPaintEnginePrivate::nextBatchItem()
-{
- if (m_draw_helper->needsFlushing())
- flushBatch();
-
- QD3DBatchItem *item = &m_batch.items[m_batch.m_item_index++];
- item->m_info = m_current_state;
- item->m_cmode = m_cmode;
- return item;
-}
-
-qreal calculateAngle(qreal dx, qreal dy)
-{
- qreal angle;
-
- if (qFuzzyCompare(dx + 1, 1)) {
- angle = (dy < 0) ? -M_PI/2 : M_PI/2;
- } else {
- angle = atanf(dy/dx);
- if (dx < 0)
- angle += M_PI;
- }
-
- return angle;
-}
-
-QPolygonF QDirect3DPaintEnginePrivate::brushCoordinates(const QRectF &r, bool stroke, qreal *fd) const
-{
- QBrush brush;
- QTransform matrix;
- Qt::BrushStyle style;
-
- if (stroke) {
- brush = m_pen.brush();
- matrix = m_inv_pen_matrix;
- style = m_pen_brush_style;
- } else {
- brush = m_brush;
- matrix = m_inv_brush_matrix;
- style = m_brush_style;
- }
-
- QPolygonF bpoly;
- switch(style) {
- case Qt::TexturePattern: {
- QTransform totxcoords;
- QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f);
- totxcoords.scale(1.0f/brush.texture().width(),
- 1.0f/brush.texture().height());
- bpoly = matrix.map(QPolygonF(adj_brect));
- bpoly = totxcoords.map(bpoly);
- break; }
- case Qt::LinearGradientPattern: {
- const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient());
- QPointF start = g->start();
- QPointF stop = g->finalStop();
- qreal dx = stop.x() - start.x();
- qreal dy = stop.y() - start.y();
- qreal length = sqrt(dx * dx + dy * dy);
- qreal angle = calculateAngle(dx, dy);
- QTransform totxcoords;
- QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f);
- totxcoords.scale(1.0f/length, 1.0f/length);
- totxcoords.rotateRadians(-angle);
- totxcoords.translate(-start.x(), -start.y());
- bpoly = matrix.map(QPolygonF(adj_brect));
- bpoly = totxcoords.map(bpoly);
- break; }
- case Qt::ConicalGradientPattern: {
- const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient());
- QPointF center = g->center();
- qreal angle = g->angle();
- QTransform totxcoords;
- totxcoords.rotate(angle);
- totxcoords.translate(-center.x(), -center.y());
- bpoly = matrix.map(QPolygonF(r));
- bpoly = totxcoords.map(bpoly);
- break; }
- case Qt::RadialGradientPattern: {
- const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient());
- QPointF center = g->center();
- QPointF focalpoint = g->focalPoint();
- qreal dx = focalpoint.x() - center.x();
- qreal dy = focalpoint.y() - center.y();
- qreal radius = g->radius();
- *fd = sqrt(dx * dx + dy * dy) / radius;
- qreal angle = calculateAngle(dx, dy);
- QTransform totxcoords;
- totxcoords.scale(1.0f/radius, 1.0f/radius);
- totxcoords.rotateRadians(-angle);
- totxcoords.translate(-center.x(), -center.y());
- bpoly = matrix.map(QPolygonF(r));
- bpoly = totxcoords.map(bpoly);
- break; }
- default: {
- QTransform totxcoords;
- QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f);
- QPixmap pat = getPattern(style);
- totxcoords.scale(1.0f/pat.width(),
- 1.0f/pat.height());
- bpoly = matrix.map(QPolygonF(adj_brect));
- bpoly = totxcoords.map(bpoly); }
- };
-
- return bpoly;
-}
-
-void QDirect3DPaintEnginePrivate::strokeAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform)
-{
- D3DCOLOR solid_color;
- QD3DBatchItem *item = nextBatchItem();
-
- if (!txform.isIdentity())
- path = txform.map(path);
-
- QRectF trect;
- QPolygonF txcoord;
-
- solid_color = m_pen_color;
- bool has_complex_brush = false;
- if (m_pen_brush_style != Qt::SolidPattern) {
- has_complex_brush = true;
- item->m_brush = m_pen.brush();
- item->m_info |= QD3DBatchItem::BI_COMPLEXBRUSH;
- item->m_opacity = m_opacity;
- }
-
- if (m_has_fast_pen) {
- item->m_info |= QD3DBatchItem::BI_FASTLINE;
- if (m_pen_brush_style == Qt::SolidPattern) {
- m_draw_helper->queueAliasedMask(path, &item, solid_color);
- item->m_info &= ~QD3DBatchItem::BI_MASK; // bypass stencil buffer
- return;
- }
- }
-
- QRectF txrect = m_draw_helper->queueAliasedMask(path, &item, 0);
-
- if (has_complex_brush) {
- trect = brect;
- txcoord = brushCoordinates(brect, true, &item->m_distance);
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_matrix = m_matrix;
- } else {
- trect = txrect;
- static const QPolygonF empty_poly(4);
- txcoord = empty_poly;
- }
-
- m_draw_helper->queueRect(trect, item, solid_color, txcoord);
-}
-
-void QDirect3DPaintEnginePrivate::fillAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform)
-{
- D3DCOLOR solid_color;
- QD3DBatchItem *item = nextBatchItem();
-
- if (!txform.isIdentity())
- path = txform.map(path);
-
- QRectF trect;
- QPolygonF txcoord;
-
- solid_color = m_brush_color;
- bool has_complex_brush = false;
- if (m_brush_style != Qt::SolidPattern) {
- has_complex_brush = true;
- item->m_brush = m_brush;
- item->m_info |= QD3DBatchItem::BI_COMPLEXBRUSH;
- item->m_opacity = m_opacity;
- }
-
- QRectF txrect = m_draw_helper->queueAliasedMask(path, &item, 0);
-
- if (has_complex_brush) {
- trect = brect;
- txcoord = brushCoordinates(brect, false, &item->m_distance);
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_matrix = m_matrix;
- } else {
- trect = txrect;
- static const QPolygonF empty_poly(4);
- txcoord = empty_poly;
- }
-
- m_draw_helper->queueRect(trect, item, solid_color, txcoord);
-}
-
-void QDirect3DPaintEnginePrivate::fillAntialiasedPath(const QPainterPath &path, const QRectF &brect,
- const QTransform &txform, bool stroke)
-{
- D3DCOLOR solid_color;
- bool winding = (path.fillRule() == Qt::WindingFill);
- QPolygonF poly;
- QRectF txrect;
- QPainterPath tpath;
-
- if (m_has_aa_fast_pen && stroke) {
- tpath = txform.map(path);
- txrect = tpath.controlPointRect();
- txrect.adjust(-(m_pen_width/2),-(m_pen_width/2), m_pen_width, m_pen_width);
- } else {
- poly = path.toFillPolygon(txform);
- txrect = poly.boundingRect();
- }
-
- // brect = approx. bounding rect before transformation
- // txrect = exact bounding rect after transformation
- // trect = the rectangle to be drawn
- // txcoord = the texture coordinates
- // adj_txrect = adjusted rect to include aliased outline
-
- bool use_scissor = false;
- if (txrect.left() < 0) {
- txrect.adjust(-txrect.left(),0,0,0);
- use_scissor = true;
- }
- if (txrect.top() < 0) {
- txrect.adjust(0,-txrect.top(),0,0);
- use_scissor = true;
- }
-
- if (!txrect.isValid())
- return;
-
- QD3DBatchItem *item = nextBatchItem();
-
- QRectF adj_txrect = txrect.adjusted(-1,-1,1,1);
- QRectF trect;
- QPolygonF txcoord;
-
- bool has_complex_brush = false;
- if (stroke) {
- solid_color = m_pen_color;
- if (m_pen_brush_style != Qt::SolidPattern) {
- has_complex_brush = true;
- item->m_brush = m_pen.brush();
- }
- item->m_width = m_pen_width;
- } else {
- solid_color = m_brush_color;
- if (m_brush_style != Qt::SolidPattern) {
- has_complex_brush = true;
- item->m_brush = m_brush;
- }
- }
-
- qreal focaldist = 0;
- if (has_complex_brush) {
- trect = brect;
- txcoord = brushCoordinates(brect, stroke, &focaldist);
- } else {
- trect = adj_txrect;
- static const QPolygonF empty_poly(4);
- txcoord = empty_poly;
- }
-
- bool maskfull;
- item->m_maskpos = m_draw_helper->allocateMaskPosition(txrect, &maskfull);
- if (maskfull)
- item->m_info |= QD3DBatchItem::BI_MASKFULL;
- item->m_distance = focaldist;
-
- if (winding)
- item->m_info |= QD3DBatchItem::BI_WINDING;
-
- if (has_complex_brush) {
- item->m_info |= QD3DBatchItem::BI_SCISSOR|QD3DBatchItem::BI_COMPLEXBRUSH|
- QD3DBatchItem::BI_TRANSFORM;
- item->m_brect = adj_txrect;
- item->m_matrix = m_matrix;
- item->m_opacity = m_opacity;
- }
- if (use_scissor) {
- item->m_info |= QD3DBatchItem::BI_MASKSCISSOR;
- item->m_brect = adj_txrect;
- }
-
- if (m_has_aa_fast_pen && stroke) {
- m_draw_helper->queueAntialiasedLines(tpath, &item, txrect);
- } else {
- m_draw_helper->queueAntialiasedMask(poly, &item, txrect);
- }
-
- m_draw_helper->queueRect(trect, item, solid_color, txcoord);
-}
-
-QPainterPath QDirect3DPaintEnginePrivate::strokePathFastPen(const QPainterPath &path)
-{
- QPainterPath result;
- QBezier beziers[32];
- for (int i=0; i<path.elementCount(); ++i) {
- const QPainterPath::Element &e = path.elementAt(i);
- switch (e.type) {
- case QPainterPath::MoveToElement:
- result.moveTo(e.x, e.y);
- break;
- case QPainterPath::LineToElement:
- result.lineTo(e.x, e.y);
- break;
-
- case QPainterPath::CurveToElement:
- {
- QPointF sp = path.elementAt(i-1);
- QPointF cp2 = path.elementAt(i+1);
- QPointF ep = path.elementAt(i+2);
- i+=2;
-
- qreal inverseScaleHalf = m_inv_scale / 2;
- beziers[0] = QBezier::fromPoints(sp, e, cp2, ep);
- QBezier *b = beziers;
- while (b >= beziers) {
- // check if we can pop the top bezier curve from the stack
- qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1);
- qreal d;
- if (l > m_inv_scale) {
- d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2)
- - (b->y4 - b->y1)*(b->x1 - b->x2) )
- + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3)
- - (b->y4 - b->y1)*(b->x1 - b->x3) );
- d /= l;
- } else {
- d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) +
- qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
- }
- if (d < inverseScaleHalf || b == beziers + 31) {
- // good enough, we pop it off and add the endpoint
- result.lineTo(b->x4, b->y4);
- --b;
- } else {
- // split, second half of the polygon goes lower into the stack
- b->split(b+1, b);
- ++b;
- }
- }
- } // case CurveToElement
- default:
- break;
- } // end of switch
- }
- return result;
-}
-
-void QDirect3DPaintEnginePrivate::strokePath(const QPainterPath &path, QRectF brect, bool simple)
-{
- QTransform txform;
- QPainterPath tpath;
-
- if (m_has_fast_pen || m_has_aa_fast_pen) {
- if (!simple)
- tpath = strokePathFastPen(path);
- else
- tpath = path; //already only lines
- } else {
- tpath = strokeForPath(path, m_pen);
- }
-
- if (tpath.isEmpty())
- return;
-
- //brect is null if the path is not transformed
- if (brect.isNull())
- txform = m_matrix;
-
- if (!brect.isNull()) {
- // brect is set when the path is transformed already,
- // this is the case when we have a cosmetic pen.
- brect.adjust(-(m_pen_width/2),-(m_pen_width/2), m_pen_width, m_pen_width);
- }
-
- if (brect.isNull())
- brect = tpath.controlPointRect();
- brect.adjust(-m_inv_scale,-m_inv_scale,m_inv_scale,m_inv_scale); //adjust for antialiasing
-
- if (m_current_state & QD3DBatchItem::BI_AA) {
- fillAntialiasedPath(tpath, brect, txform, true);
- } else {
- strokeAliasedPath(tpath, brect, txform);
- }
-}
-
-void QDirect3DPaintEnginePrivate::fillPath(const QPainterPath &path, QRectF brect)
-{
- QTransform txform;
-
- //brect is null if the path is not transformed
- if (brect.isNull())
- txform = m_matrix;
-
- if (brect.isNull())
- brect = path.controlPointRect();
- brect.adjust(-m_inv_scale,-m_inv_scale,m_inv_scale,m_inv_scale); //adjust for antialiasing
-
- if (m_current_state & QD3DBatchItem::BI_AA) {
- fillAntialiasedPath(path, brect, txform, false);
- } else {
- fillAliasedPath(path, brect, txform);
- }
-}
-
-
-bool QDirect3DPaintEnginePrivate::init()
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEnginePrivate::init()";
-#endif
-
- m_draw_helper = 0;
- m_gradient_cache = 0;
- m_dc = 0;
- m_dcsurface = 0;
-
- m_supports_d3d = false;
- m_current_state = 0;
- m_in_scene = false;
- m_has_fast_pen = false;
- m_has_aa_fast_pen = false;
- m_has_pen = false;
- m_has_brush = false;
- m_pen_color = 0;
- m_brush_color = 0;
- m_current_surface = 0;
- m_batch.m_item_index = 0;
- m_current_technique = RT_NoTechnique;
-
- if (!pDirect3DCreate9) {
- QLibrary d3d_lib(QLatin1String("d3d9.dll"));
- pDirect3DCreate9 = (PFNDIRECT3DCREATE9) d3d_lib.resolve("Direct3DCreate9");
- if (!pDirect3DCreate9) {
- qWarning("QDirect3DPaintEngine: failed to resolve symbols from d3d9.dll.\n"
- "Make sure you have the DirectX run-time installed.");
- return false;
- }
- }
-
- if (!pD3DXCreateBuffer || !pD3DXCreateEffect || !pD3DXMatrixOrthoOffCenterLH) {
- QLibrary d3dx_lib(QLatin1String("d3dx9_32.dll"));
- pD3DXCreateBuffer = (PFND3DXCREATEBUFFER) d3dx_lib.resolve("D3DXCreateBuffer");
- pD3DXCreateEffect = (PFND3DXCREATEEFFECT) d3dx_lib.resolve("D3DXCreateEffect");
- pD3DXMatrixOrthoOffCenterLH = (PFND3DXMATRIXORTHOOFFCENTERLH)
- d3dx_lib.resolve("D3DXMatrixOrthoOffCenterLH");
- if (!(pD3DXCreateBuffer && pD3DXCreateEffect && pD3DXMatrixOrthoOffCenterLH)) {
- qWarning("QDirect3DPaintEngine: failed to resolve symbols from d3dx9_32.dll.\n"
- "Make sure you have the DirectX run-time installed.");
- return false;
- }
- }
-
- if (!m_d3d_object) {
- m_d3d_object = pDirect3DCreate9(D3D_SDK_VERSION);
- if (!m_d3d_object) {
- qWarning("QDirect3DPaintEngine: failed to create Direct3D object.\n"
- "Direct3D support in Qt will be disabled.");
- return false;
- }
- }
-
- m_supports_d3d = testCaps();
- if (!m_supports_d3d)
- return false;
-
- m_surface_manager.init(m_d3d_object);
- m_d3d_device = m_surface_manager.device();
-
- if (!m_d3d_device)
- return false;
-
- /* load shaders */
- QFile file(QLatin1String(":/qpaintengine_d3d.fx"));
- QByteArray fxFile;
- if (file.open(QFile::ReadOnly))
- fxFile = file.readAll();
-
- if (fxFile.size() > 0) {
- LPD3DXBUFFER compout;
- pD3DXCreateBuffer(4096, &compout);
- DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE|D3DXFX_DONOTSAVESTATE|D3DXSHADER_OPTIMIZATION_LEVEL3;
- if(FAILED(pD3DXCreateEffect(m_d3d_device, fxFile.constData(), fxFile.size(),
- NULL, NULL, dwShaderFlags, NULL, &m_effect, &compout))) {
- qWarning("QDirect3DPaintEngine: failed to compile effect file");
- if (compout)
- qWarning((char *)compout->GetBufferPointer());
- m_supports_d3d = false;
- return false;
- }
- if (m_effect) {
- m_statemanager = new QD3DStateManager(m_d3d_device, m_effect);
- m_effect->SetStateManager(m_statemanager);
- m_draw_helper = new QD3DDrawHelper(this);
- initDevice();
- m_gradient_cache = new QD3DGradientCache(m_d3d_device);
- }
- } else {
- return false;
- }
-
- return true;
-}
-
-QPixmap QDirect3DPaintEnginePrivate::getPattern(Qt::BrushStyle style) const
-{
- if (!m_patterns.contains(style)) {
- QImage img(16,16,QImage::Format_ARGB32);
- img.fill(0);
- QPainter p(&img);
- p.setBrush(QBrush(Qt::white, style));
- p.setPen(Qt::NoPen);
- p.drawRect(0,0,16,16);
- p.end();
- QPixmap pattern(QPixmap::fromImage(img));
- QDirect3DPaintEnginePrivate *ct = const_cast<QDirect3DPaintEnginePrivate *>(this);
- ct->verifyTexture(pattern);
- ct->m_patterns.insert(style, pattern);
- }
-
- return m_patterns.value(style);
-}
-
-bool QDirect3DPaintEnginePrivate::testCaps()
-{
- D3DCAPS9 caps;
- if (FAILED(m_d3d_object->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps)))
- return false;
-
- if ((caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
- && (caps.DevCaps & D3DDEVCAPS_PUREDEVICE)
- && (caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST)
- && (caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED))
- return true;
-#if 0
- qDebug() << "Direct3D caps:";
- qDebug() << "D3DPRESENT_INTERVAL_IMMEDIATE:" << ((caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) != 0);
- qDebug() << "D3DDEVCAPS_PUREDEVICE:" << ((caps.DevCaps & D3DDEVCAPS_PUREDEVICE) != 0);
- qDebug() << "D3DPRASTERCAPS_SCISSORTEST:" << ((caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST) != 0);
- qDebug() << "D3DSTENCILCAPS_TWOSIDED:" << ((caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0);
-#endif
- return false;
-}
-
-void QDirect3DPaintEnginePrivate::initDevice()
-{
- m_statemanager->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- m_statemanager->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
- m_statemanager->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
- m_statemanager->SetRenderState(D3DRS_LIGHTING, FALSE);
- m_statemanager->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
- m_statemanager->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
- m_statemanager->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);
-}
-
-void QDirect3DPaintEnginePrivate::updatePen(const QPen &pen)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::updatePen";
-#endif
- m_pen = pen;
- m_has_cosmetic_pen = false;
- m_has_pen = (m_pen.style() != Qt::NoPen);
- if (m_has_pen) {
- m_pen_brush_style = m_pen.brush().style();
-
- if (m_pen_brush_style >= Qt::SolidPattern && m_pen_brush_style <= Qt::DiagCrossPattern) {
- int a, r, g, b;
- m_pen.color().getRgb(&r, &g, &b, &a);
- m_pen_color = D3DCOLOR_ARGB((int)(a * m_opacity),r,g,b);
- } else {
- m_pen_color = m_opacity_color;
- }
-
- m_has_cosmetic_pen = m_pen.isCosmetic();
-
- if (m_pen_brush_style != Qt::NoBrush &&
- m_pen_brush_style != Qt::SolidPattern) {
- bool ok;
- m_inv_pen_matrix = m_pen.brush().transform().inverted(&ok);
- if (!ok)
- qWarning() << "QDirect3DPaintEngine: No inverse matix for pen brush matrix.";
- }
-
- m_pen_width = m_pen.widthF();
- if (m_pen_width == 0.0f)
- m_pen_width = 1.0f;
- }
-}
-
-void QDirect3DPaintEnginePrivate::updateBrush(const QBrush &brush)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::updateBrush";
-#endif
- m_brush = brush;
- m_brush_style = m_brush.style();
- m_has_brush = (m_brush_style != Qt::NoBrush);
- if (m_has_brush) {
- if (m_brush_style >= Qt::SolidPattern && m_brush_style <= Qt::DiagCrossPattern) {
- int a, r, g, b;
- m_brush.color().getRgb(&r, &g, &b, &a);
- m_brush_color = D3DCOLOR_ARGB((int)(a * m_opacity),r,g,b);
- } else {
- m_brush_color = m_opacity_color;
- }
-
- if (m_brush_style != Qt::SolidPattern) {
- bool ok;
- m_inv_brush_matrix = (m_brush.transform() * m_brush_origin).inverted(&ok);
- if (!ok)
- qWarning() << "QDirect3DPaintEngine: No inverse matix for brush matrix.";
-
- // make sure the texture is loaded as a texture
- if (m_brush_style == Qt::TexturePattern)
- verifyTexture(m_brush.texture());
-
-
- }
- }
-}
-
-void QDirect3DPaintEnginePrivate::updateTransform(const QTransform &matrix)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::updateTransform";
-#endif
- m_matrix = matrix;
- m_inv_scale = qMax(1 / qMax( qMax(qAbs(m_matrix.m11()), qAbs(m_matrix.m22())),
- qMax(qAbs(m_matrix.m12()), qAbs(m_matrix.m21())) ), 0.0001);
- m_txop = matrix.type();
-}
-
-int QDirect3DPaintEnginePrivate::flushAntialiased(int offset)
-{
- // fills the mask (returns number of items added to the mask)
- int newoffset = m_draw_helper->drawAntialiasedMask(offset, m_batch.m_item_index);
-
- // set the render target to the current output surface
- if (FAILED(m_d3d_device->SetRenderTarget(0, m_current_surface)))
- qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!";
-
- // draw the bounding boxes (using the mask generated by drawAntialiasedMask)
- for (int i=offset; i<newoffset; ++i) {
- QD3DBatchItem *item = &(m_batch.items[i]);
- int pass = (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) ? PASS_AA_DRAW : PASS_AA_DRAW_DIRECT;
- m_statemanager->beginPass(pass);
- prepareItem(item);
- if (item->m_info & QD3DBatchItem::BI_BRECT)
- m_draw_helper->drawAntialiasedBoundingRect(item);
- cleanupItem(item);
- }
-
- m_statemanager->endPass();
-
- return newoffset;
-}
-
-bool QDirect3DPaintEnginePrivate::prepareBatch(QD3DBatchItem *item, int offset)
-{
- if (item->m_info & QD3DBatchItem::BI_CLIP) {
- setRenderTechnique(RT_Aliased);
- if (item->m_info & QD3DBatchItem::BI_CLEARCLIP) {
- m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
- return true;
- }
-
- m_draw_helper->drawAliasedMask(offset);
- m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
- if (item->m_info & QD3DBatchItem::BI_BRECT) {
- m_statemanager->beginPass(PASS_STENCIL_CLIP);
- m_draw_helper->drawAliasedBoundingRect(item);
- m_statemanager->endPass();
- }
-
- return true;
- }
-
- if (item->m_info & QD3DBatchItem::BI_AA) {
- setRenderTechnique(RT_Antialiased);
- } else {
- setRenderTechnique(RT_Aliased);
- }
-
- return false;
-}
-
-void QDirect3DPaintEnginePrivate::prepareItem(QD3DBatchItem *item) {
- // pixmap
- int brushmode = 0;
- m_statemanager->startStateBlock();
- if ((item->m_info & QD3DBatchItem::BI_PIXMAP) || (item->m_info & QD3DBatchItem::BI_IMAGE)) {
- QRasterPixmapData *data = static_cast<QRasterPixmapData*>(item->m_pixmap.data);
- IDirect3DTexture9 *tex = (item->m_info & QD3DBatchItem::BI_PIXMAP) ?
- data->texture : item->m_texture;
- m_statemanager->setTexture(tex);
- brushmode = 5;
- }
-
- if (item->m_info & QD3DBatchItem::BI_AA) {
- m_statemanager->setMaskChannel(item->m_maskpos.channel);
- m_statemanager->setMaskOffset(item->m_xoffset, item->m_yoffset);
- }
-
- if (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) {
- const QBrush brush = item->m_brush;
- switch (brush.style()) {
- case Qt::TexturePattern: {
- QRasterPixmapData *data = static_cast<QRasterPixmapData*>(brush.texture().data);
- m_statemanager->setTexture(data->texture, QGradient::RepeatSpread);
- brushmode = 1;
- break;
- }
- case Qt::LinearGradientPattern:
- m_statemanager->setTexture(m_gradient_cache->
- getBuffer(brush.gradient()->stops(), item->m_opacity),
- brush.gradient()->spread());
- brushmode = 2;
- break;
- case Qt::ConicalGradientPattern:
- m_statemanager->setTexture(m_gradient_cache->
- getBuffer(brush.gradient()->stops(), item->m_opacity),
- brush.gradient()->spread());
- brushmode = 3;
- break;
- case Qt::RadialGradientPattern:
- m_statemanager->setTexture(m_gradient_cache->
- getBuffer(brush.gradient()->stops(), item->m_opacity),
- brush.gradient()->spread());
- m_statemanager->setFocalDistance(item->m_distance);
- brushmode = 4;
- break;
- default: {
- QRasterPixmapData *data = static_cast<QRasterPixmapData*>(getPattern(brush.style()).data);
- m_statemanager->setTexture(data->texture, QGradient::RepeatSpread);
- brushmode = 5;
- }
- };
- }
-
- if (item->m_info & QD3DBatchItem::BI_TRANSFORM) {
- m_statemanager->setTransformation(&item->m_matrix);
- } else {
- m_statemanager->setTransformation();
- }
-
- m_statemanager->setBrushMode(brushmode);
- setCompositionMode(item->m_cmode);
- m_statemanager->endStateBlock();
-}
-
-
-void QDirect3DPaintEnginePrivate::releaseDC()
-{
- if (m_dc) {
- m_dcsurface->ReleaseDC(m_dc);
- m_dcsurface = 0;
- m_dc = 0;
- }
-}
-
-
-void QDirect3DPaintEnginePrivate::cleanupItem(QD3DBatchItem *item)
-{
- if (item->m_info & QD3DBatchItem::BI_PIXMAP)
- item->m_pixmap = QPixmap();
- item->m_brush = QBrush();
-}
-
-void QDirect3DPaintEnginePrivate::verifyTexture(const QPixmap &pm)
-{
- QRasterPixmapData *pmData = static_cast<QRasterPixmapData*>(pm.data);
- if (!pmData->texture) {
- QImage im = pmData->image;
- // bitmaps are drawn with the current pen color
- if (im.depth() == 1) {
- QVector<QRgb> colors(2);
- colors[0] = 0;
- colors[1] = m_pen.color().rgba();
- im.setColorTable(colors);
- }
- im = im.convertToFormat(QImage::Format_ARGB32);
- if (FAILED(m_d3d_device->CreateTexture(im.width(), im.height(), 1, 0,
- D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pmData->texture, 0)))
- {
- qWarning("QDirect3DPaintEngine: unable to create Direct3D texture from pixmap.");
- return;
- }
- D3DLOCKED_RECT rect;
- if (FAILED(pmData->texture->LockRect(0, &rect, 0, 0))) {
- qDebug() << "QDirect3DPaintEngine: unable to lock texture rect.";
- return;
- }
- DWORD *dst = (DWORD *) rect.pBits;
- DWORD *src = (DWORD *) im.scanLine(0);
-
- Q_ASSERT((rect.Pitch/4) == (im.bytesPerLine()/4));
- memcpy(dst, src, rect.Pitch*im.height());
- pmData->texture->UnlockRect(0);
- }
-}
-
-bool QDirect3DPaintEnginePrivate::isFastRect(const QRectF &rect)
-{
- if (m_matrix.type() < QTransform::TxRotate) {
- QRectF r = m_matrix.mapRect(rect);
- return r.topLeft().toPoint() == r.topLeft()
- && r.bottomRight().toPoint() == r.bottomRight();
- }
-
- return false;
-}
-
-void QDirect3DPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode)
-{
- switch(mode) {
- case QPainter::CompositionMode_SourceOver:
- default:
- m_statemanager->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
- m_statemanager->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
- };
-}
-
-void QDirect3DPaintEnginePrivate::cleanup()
-{
- // clean batch
- for(int i=0; i<QD3D_BATCH_SIZE; ++i) {
- m_batch.items[i].m_brush = QBrush();
- m_batch.items[i].m_pixmap = QPixmap();
- }
-
- m_surface_manager.cleanup();
- m_patterns.clear();
-
- delete m_gradient_cache;
- delete m_draw_helper;
-
- if (m_effect)
- m_effect->Release();
-
- if (m_d3d_object)
- m_d3d_object->Release();
-
- m_effect = 0;
- m_d3d_object = 0;
- m_gradient_cache = 0;
- m_draw_helper = 0;
-}
-
-void QDirect3DPaintEnginePrivate::flushAliased(QD3DBatchItem *item, int offset)
-{
- m_draw_helper->drawAliasedMask(offset);
-
- if (item->m_info & QD3DBatchItem::BI_BRECT) {
- int pass = (item->m_info & QD3DBatchItem::BI_MASK) ? PASS_STENCIL_DRAW_DIRECT : PASS_STENCIL_NOSTENCILCHECK_DIRECT;
- if (item->m_info & (QD3DBatchItem::BI_COMPLEXBRUSH|QD3DBatchItem::BI_IMAGE|QD3DBatchItem::BI_PIXMAP) )
- pass = (item->m_info & QD3DBatchItem::BI_MASK) ? PASS_STENCIL_DRAW : PASS_STENCIL_NOSTENCILCHECK;
- m_statemanager->beginPass(pass);
- prepareItem(item);
- m_draw_helper->drawAliasedBoundingRect(item);
- cleanupItem(item);
- m_statemanager->endPass();
- }
-}
-
-void QDirect3DPaintEnginePrivate::flushText(QD3DBatchItem *item, int)
-{
- prepareItem(item);
- m_statemanager->setTexture(item->m_texture);
- m_statemanager->setBrushMode(1);
-// m_statemanager->SetRenderState(D3DRS_BLENDFACTOR, item->m_brush.color().rgba());
- m_statemanager->beginPass(m_cleartype_text ? PASS_CLEARTYPE_TEXT : PASS_TEXT);
- m_draw_helper->drawTextItem(item);
- m_statemanager->endPass();
- cleanupItem(item);
-}
-
-void QDirect3DPaintEnginePrivate::flushLines(QD3DBatchItem *item, int)
-{
- m_draw_helper->drawAliasedLines(item);
-
- if (item->m_info & QD3DBatchItem::BI_BRECT) {
- int pass = (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) ? PASS_STENCIL_DRAW : PASS_STENCIL_DRAW_DIRECT;
- m_statemanager->beginPass(pass);
- prepareItem(item);
- m_draw_helper->drawAliasedBoundingRect(item);
- cleanupItem(item);
- m_statemanager->endPass();
- }
-}
-
-void QDirect3DPaintEnginePrivate::flushBatch()
-{
-// static int dbgcounter = 0;
-// ++dbgcounter;
-// qDebug() << " -> flush" << dbgcounter;
-
- int offset = 0;
- m_draw_helper->unlockVertexBuffer();
- releaseDC();
-
- // iterate over all items in the batch
- while (offset != m_batch.m_item_index) {
- QD3DBatchItem *item = &(m_batch.items[offset]);
-
- if (prepareBatch(item, offset)) {
- ++offset;
- continue;
- }
-
- if (item->m_info & QD3DBatchItem::BI_FASTLINE) {
- flushLines(item, offset++);
- } else if (item->m_info & QD3DBatchItem::BI_AA) {
- offset = flushAntialiased(offset);
- } else if (item->m_info & QD3DBatchItem::BI_TEXT) {
- flushText(item, offset++);
- } else {
- flushAliased(item, offset++);
- }
- }
-
- // reset batch
- m_batch.m_item_index = 0;
-
- // release doomed textures
- for (int i=0; i<qd3d_release_list.size(); ++i)
- qd3d_release_list.at(i)->Release();
- qd3d_release_list.clear();
-}
-
-QDirect3DPaintEngine::QDirect3DPaintEngine()
- : QPaintEngine(*(new QDirect3DPaintEnginePrivate),
- PaintEngineFeatures(AllFeatures & ~ObjectBoundingModeGradients))
-{ }
-
-QDirect3DPaintEngine::~QDirect3DPaintEngine()
-{
-}
-
-bool QDirect3DPaintEngine::begin(QPaintDevice *device)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::begin";
-#endif
- Q_D(QDirect3DPaintEngine);
- setActive(true);
-
- QSize old_size = d->m_surface_size;
- d->m_surface_size = QRect(0, 0, device->width(), device->height()).size();
-
- d->m_current_state = 0;
- d->m_inv_scale = 1;
- d->m_opacity = 1.0f;
- d->m_opacity_color = D3DCOLOR_ARGB(255,255,255,255);
- d->m_matrix = QTransform();
- d->m_brush_origin = QTransform();
- d->m_txop = QTransform::TxNone;
- d->m_cmode = QPainter::CompositionMode_SourceOver;
-
- Q_ASSERT(device && device->devType() == QInternal::Widget);
- if (d->m_d3d_device == 0) {
- qWarning() << "QDirect3DPaintEngine: No Device!";
- return false;
- }
-
- d->m_cleartype_text = false;
-// QT_WA({
-// UINT result;
-// BOOL ok;
-// ok = SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0);
-// if (ok)
-// d->m_cleartype_text = (result == FE_FONTSMOOTHINGCLEARTYPE);
-// }, {
-// UINT result;
-// BOOL ok;
-// ok = SystemParametersInfoA(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0);
-// if (ok)
-// d->m_cleartype_text = (result == FE_FONTSMOOTHINGCLEARTYPE);
-// });
-
- d->m_surface_manager.setPaintDevice(device);
- int status = d->m_surface_manager.status();
- if (status & QD3DSurfaceManager::NeedsResetting) {
- d->m_effect->OnLostDevice();
- d->m_draw_helper->beforeReset();
- d->m_statemanager->reset();
- d->m_surface_manager.reset();
- d->m_draw_helper->afterReset();
- d->m_effect->OnResetDevice();
- d->initDevice();
- }
-
- LPDIRECT3DSURFACE9 newsurface = d->m_surface_manager.renderTarget();
- if (d->m_current_surface != newsurface) {
- d->m_current_surface = newsurface;
- if (FAILED(d->m_d3d_device->SetRenderTarget(0, newsurface)))
- qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!";
- }
-
- status = d->m_surface_manager.status();
- if (status & QD3DSurfaceManager::MaxSizeChanged) {
- QSize maxsize = d->m_surface_manager.maxSize();
- d->m_draw_helper->setMaskSize(maxsize);
- int masksize[2] = {maxsize.width(), maxsize.height()};
- d->m_effect->SetIntArray("g_mMaskSize", masksize, 2);
- }
-
- if (old_size != d->m_surface_size) {
- D3DXMATRIX projMatrix;
- pD3DXMatrixOrthoOffCenterLH(&projMatrix, 0, d->m_surface_size.width(), d->m_surface_size.height(), 0, 0.0f, 1.0f);
- d->m_statemanager->setProjection(&projMatrix);
- }
-
- if (!d->m_in_scene) {
- if (FAILED(d->m_d3d_device->BeginScene())) {
- qWarning() << "QDirect3DPaintEngine: BeginScene() failed.";
- return false;
- }
- QWidget *widget = static_cast<QWidget *>(device);
- if (widget->autoFillBackground() == true) {
- QColor color = widget->palette().brush(widget->backgroundRole()).color();
- RECT rect = {0, 0, widget->width(), widget->height()};
- d->m_d3d_device->ColorFill(d->m_current_surface, &rect,
- D3DCOLOR_ARGB(color.alpha(), color.red(), color.green(), color.blue()));
- }
- d->m_in_scene = true;
- }
-
- // set system clip
- d->m_clipping_enabled = false;
- d->m_has_complex_clipping = false;
-
- d->m_sysclip_region = systemClip();
- QVector<QRect> rects = d->m_sysclip_region.rects();
- if (rects.count() == 1 && rects.at(0).size() == d->m_surface_size)
- d->m_sysclip_region = QRegion();
-
- d->updateClipRegion(QRegion(), Qt::NoClip);
-
- return true;
-}
-
-void QDirect3DPaintEngine::drawEllipse(const QRectF &rect)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawEllipse (float)";
-#endif
- QPaintEngine::drawEllipse(rect);
-}
-
-void QDirect3DPaintEngine::drawEllipse(const QRect &rect)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawEllipse";
-#endif
- QPaintEngine::drawEllipse(rect);
-}
-
-void QDirect3DPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
- Qt::ImageConversionFlags)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawImage";
-#endif
-
- Q_D(QDirect3DPaintEngine);
- int width = image.width();
- int height = image.height();
-
- // transform rectangle
- QPolygonF txrect(QRectF(sr.left() / width, sr.top() / height,
- sr.width() / width, sr.height() / height));
-
- QD3DBatchItem *item = d->nextBatchItem();
- item->m_info = QD3DBatchItem::BI_IMAGE | QD3DBatchItem::BI_TRANSFORM;
- item->m_texture = qd3d_image_cache()->lookup(d->m_d3d_device, image);
- item->m_matrix = d->m_matrix;
- d->m_draw_helper->queueRect(r.adjusted(-0.5f,-0.5f,-0.5f,-0.5f), item, d->m_opacity_color, txrect);
-}
-
-void QDirect3DPaintEngine::drawLines(const QLineF *lines, int lineCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawLines (float)";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- if (!d->m_has_pen)
- return;
-
- if (d->m_has_fast_pen && (d->m_pen_brush_style == Qt::SolidPattern)) {
- QD3DBatchItem *item = d->nextBatchItem();
- if (d->m_pen.isCosmetic())
- item->m_info |= QD3DBatchItem::BI_COSMETICPEN;
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_matrix = d->m_matrix;
- d->m_draw_helper->queueAliasedLines(lines, lineCount, &item);
- } else {
- QRectF brect;
- QPainterPath path;
-
- // creates a path with the lines
- path.moveTo(lines[0].x1(), lines[0].y1());
- qreal lastx = lines[0].x2();
- qreal lasty = lines[0].y2();
- path.lineTo(lastx, lasty);
-
- for (int i=1; i<lineCount; ++i) {
- qreal x = lines[i].x1();
- qreal y = lines[i].y1();
- if (lastx != x || lasty != y) {
- path.moveTo(x, y);
- }
- path.lineTo(lines[i].x2(), lines[i].y2());
- }
-
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- path = d->m_matrix.map(path);
- }
-
- d->strokePath(path, brect, true);
- }
-}
-
-void QDirect3DPaintEngine::drawLines(const QLine *lines, int lineCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawLines";
-#endif
- QPaintEngine::drawLines(lines, lineCount);
-}
-
-void QDirect3DPaintEngine::drawPath(const QPainterPath &path)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPath";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- if (path.isEmpty())
- return;
-
- QRectF brect;
- QPainterPath tpath;
-
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- tpath = d->m_matrix.map(path);
- } else {
- tpath = path;
- }
-
- if (d->m_has_brush)
- d->fillPath(tpath, brect);
-
- if (d->m_has_pen)
- d->strokePath(tpath, brect);
-}
-
-
-QPointF QDirect3DPaintEnginePrivate::transformPoint(const QPointF &p, qreal *w) const
-{
- (*w) = 1.0f;
- qreal fx = p.x();
- qreal fy = p.y();
- qreal nx = m_matrix.m11()*fx + m_matrix.m21()*fy + m_matrix.m31();
- qreal ny = m_matrix.m12()*fx + m_matrix.m22()*fy + m_matrix.m32();
- if (!m_matrix.isAffine()) {
- *w = m_matrix.m13()*fx + m_matrix.m23()*fy + m_matrix.m33();
- //*w = 1/(*w);
- nx = nx/(*w);
- ny = ny/(*w);
- }
- return QPointF(nx, ny);
-}
-
-void QDirect3DPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPixmap";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- if (d->m_draw_helper->needsFlushing())
- d->flushBatch();
-
- int width = pm.width();
- int height = pm.height();
-
- // transform rectangle
- QPolygonF txrect(QRectF(sr.left() / width, sr.top() / height,
- sr.width() / width, sr.height() / height));
-
- QD3DBatchItem *item = d->nextBatchItem();
- item->m_info = QD3DBatchItem::BI_PIXMAP|QD3DBatchItem::BI_TRANSFORM;
-
- item->m_pixmap = pm;
- d->verifyTexture(item->m_pixmap);
-
- item->m_matrix = d->m_matrix;
- d->m_draw_helper->queueRect(r.adjusted(-0.5f,-0.5f,-0.5f,-0.5f), item, d->m_opacity_color, txrect);
-}
-
-void QDirect3DPaintEngine::drawPoints(const QPointF *points, int pointCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPoints (float)";
-#endif
- QPaintEngine::drawPoints(points, pointCount);
-}
-
-void QDirect3DPaintEngine::drawPoints(const QPoint *points, int pointCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPoints";
-#endif
- QPaintEngine::drawPoints(points, pointCount);
-}
-
-void QDirect3DPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPolygon";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- if (d->m_has_brush && mode != PolylineMode) {
- QPainterPath path;
- path.setFillRule(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
- path.moveTo(points[0]);
- for (int i=1; i<pointCount; ++i)
- path.lineTo(points[i]);
- if (path.isEmpty())
- return;
- d->fillPath(path, QRectF());
- }
-
- if (d->m_has_pen) {
- QPainterPath path(points[0]);
- for (int i = 1; i < pointCount; ++i)
- path.lineTo(points[i]);
- if (mode != PolylineMode)
- path.lineTo(points[0]);
-
- if (path.isEmpty())
- return;
- QRectF brect;
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- path = d->m_matrix.map(path);
- }
-
- d->strokePath(path, brect);
- }
-}
-
-void QDirect3DPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPolygon";
-#endif
- QPaintEngine::drawPolygon(points, pointCount, mode);
-}
-
-void QDirect3DPaintEngine::drawRects(const QRectF *rects, int rectCount)
-{
- Q_D(QDirect3DPaintEngine);
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawRects (float)";
-#endif
- for (int i=0; i<rectCount; ++i) {
- if ((d->m_brush_style == Qt::SolidPattern) &&
- (!(d->m_current_state & QD3DBatchItem::BI_AA) || d->isFastRect(rects[i]))) {
- QD3DBatchItem *item = d->nextBatchItem();
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_info &= ~QD3DBatchItem::BI_AA;
- item->m_matrix = d->m_matrix;
- const QRectF rect = rects[i];
- d->m_draw_helper->queueRect(rect, item, d->m_brush_color);
-
- if (d->m_has_pen) {
- if (d->m_has_fast_pen && (d->m_pen_brush_style == Qt::SolidPattern)) {
- QLineF lines[4];
- qreal x1 = rect.x();
- qreal y1 = rect.y();
- qreal x2 = rect.width() + x1;
- qreal y2 = rect.height() + y1;
- lines[0] = QLineF(x1, y1, x2, y1);
- lines[1] = QLineF(x2, y1, x2, y2);
- lines[2] = QLineF(x2, y2, x1, y2);
- lines[3] = QLineF(x1, y2, x1, y1);
- QD3DBatchItem *item = d->nextBatchItem();
- if (d->m_pen.isCosmetic())
- item->m_info |= QD3DBatchItem::BI_COSMETICPEN;
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_matrix = d->m_matrix;
- d->m_draw_helper->queueAliasedLines(lines, 4, &item);
- } else {
- QPainterPath path;
- QRectF brect;
-
- path.addRect(rects[i]);
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- path = d->m_matrix.map(path);
- }
-
- d->strokePath(path, brect, true);
- }
- }
- } else {
- QPainterPath path;
- QRectF brect;
-
- path.addRect(rects[i]);
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- path = d->m_matrix.map(path);
- }
-
- if (d->m_has_brush)
- d->fillPath(path, brect);
-
- if (d->m_has_pen)
- d->strokePath(path, brect, true);
- }
- }
-}
-
-void QDirect3DPaintEngine::drawRects(const QRect *rects, int rectCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawRects";
-#endif
- QPaintEngine::drawRects(rects, rectCount);
-}
-
-
-void QDirect3DPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
-{
- Q_D(QDirect3DPaintEngine);
-
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawTextItem";
-#endif
-// if (d->m_matrix.isScaling() || (d->m_pen_brush_style >= Qt::LinearGradientPattern
-// && d->m_pen_brush_style <= Qt::ConicalGradientPattern)) {
-// QPaintEngine::drawTextItem(p, textItem);
-// return;
-// }
-
- const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
- QVarLengthArray<QFixedPoint> positions;
- QVarLengthArray<glyph_t> glyphs;
- QTransform matrix;
- matrix.translate(p.x(), p.y());
- ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
-
- qd3d_glyph_cache()->cacheGlyphs(this, ti, glyphs, d->m_cleartype_text);
- QD3DFontTexture *font_tex = qd3d_glyph_cache()->fontTexture(ti.fontEngine);
-
- QD3DBatchItem *item = d->nextBatchItem();
- d->m_draw_helper->lockVertexBuffer();
-
- item->m_info = QD3DBatchItem::BI_TEXT
- | (d->m_current_state & ~QD3DBatchItem::BI_AA) | QD3DBatchItem::BI_TRANSFORM;
- item->m_texture = font_tex->texture;
- item->m_offset = d->m_draw_helper->index();
- item->m_matrix = d->m_matrix;
- item->m_count = 0;
- item->m_brush = d->m_pen.brush();
-
- for (int i=0; i< glyphs.size(); ++i) {
- QD3DGlyphCoord *g = qd3d_glyph_cache()->lookup(ti.fontEngine, glyphs[i]);
-
- // we don't cache glyphs with no width/height
- if (!g)
- continue;
-
- // texture coords
- qreal tex_coords[] = { g->x, g->y, g->x + g->width, g->y + g->height };
- QPointF logical_pos(qRound((positions[i].x - g->x_offset).toReal()) - 0.5f,
- qRound((positions[i].y + g->y_offset).toReal()) - 0.5f);
-
- QRectF glyph_rect(logical_pos, QSizeF(g->log_width, g->log_height));
- d->m_draw_helper->queueTextGlyph(glyph_rect, tex_coords, item, d->m_pen_color);
- }
-}
-
-void QDirect3DPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawTiledPixmap";
-#endif
- QPaintEngine::drawTiledPixmap(rect, pixmap, p);
-}
-
-bool QDirect3DPaintEngine::end()
-{
- Q_D(QDirect3DPaintEngine);
-
- d->flushBatch();
-
- if (d->m_flush_on_end) {
- QPaintDevice *pdev = paintDevice();
- LPDIRECT3DSWAPCHAIN9 swapchain = swapChain(pdev);
-
-
- QWidget *w = 0;
- if (pdev->devType() == QInternal::Widget) {
- w = static_cast<QWidget *>(pdev);
- }
-
- if (w && swapchain) {
- QRect br = w->rect();
- QRect wbr = br;//.translated(-w->pos());
-
- RECT destrect;
- destrect.left = wbr.x();
- destrect.top = wbr.y();
- destrect.right = destrect.left + wbr.width();
- destrect.bottom = destrect.top + wbr.height();
-
- RECT srcrect;
- srcrect.left = br.x();// + w->x();
- srcrect.top = br.y();// + w->y();
- srcrect.right = wbr.width() + srcrect.left;
- srcrect.bottom = wbr.height() + srcrect.top;
- int devwidth = w->width();
- int devheight = w->height();
-
- if (devwidth <= srcrect.right) {
- int diff = srcrect.right - devwidth;
- srcrect.right -= diff;
- destrect.right -= diff;
- if (srcrect.right <= srcrect.left)
- return false;
- }
- if (devheight <= srcrect.bottom) {
- int diff = srcrect.bottom - devheight;
- srcrect.bottom -= diff;
- destrect.bottom -= diff;
- if (srcrect.bottom <= srcrect.top)
- return false;
- }
-
- if (FAILED(swapchain->Present(&srcrect, &destrect, w->winId(), 0, 0)))
- qWarning("QDirect3DPaintEngine: failed to present back buffer.");
- }
- }
-
-
- return true;
-}
-
-void QDirect3DPaintEngine::updateState(const QPaintEngineState &state)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::updateState";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- bool update_fast_pen = false;
- DirtyFlags flags = state.state();
-
- if (flags & DirtyOpacity) {
- d->m_opacity = state.opacity();
- if (d->m_opacity > 1.0f)
- d->m_opacity = 1.0f;
- if (d->m_opacity < 0.f)
- d->m_opacity = 0.f;
- uint c = (d->m_opacity * 255);
- d->m_opacity_color = D3DCOLOR_ARGB(c,c,c,c);
- flags |= (DirtyPen | DirtyBrush);
- }
-
- if (flags & DirtyCompositionMode) {
- d->m_cmode = state.compositionMode();
- }
-
- if (flags & DirtyTransform) {
- d->updateTransform(state.transform());
- update_fast_pen = true;
- }
-
- if (flags & DirtyHints) {
- if (state.renderHints() & QPainter::Antialiasing)
- d->m_current_state |= QD3DBatchItem::BI_AA;
- else
- d->m_current_state &= ~QD3DBatchItem::BI_AA;
- update_fast_pen = true;
- }
-
- if (flags & DirtyFont) {
- d->updateFont(state.font());
- }
-
- if (state.state() & DirtyClipEnabled) {
- if (state.isClipEnabled() && !d->m_clipping_enabled) {
- d->m_clipping_enabled = true;
- if (d->m_has_complex_clipping)
- d->updateClipPath(painter()->clipPath(), Qt::ReplaceClip);
- else
- d->updateClipRegion(painter()->clipRegion(), Qt::ReplaceClip);
- } else if (!state.isClipEnabled() && d->m_clipping_enabled) {
- d->m_clipping_enabled = false;
- if (d->m_has_complex_clipping)
- d->updateClipPath(QPainterPath(), Qt::NoClip);
- else
- d->updateClipRegion(QRegion(), Qt::NoClip);
- }
- }
-
- if (flags & DirtyClipRegion) {
- d->updateClipRegion(state.clipRegion(), state.clipOperation());
- }
-
- if (flags & DirtyClipPath) {
- d->updateClipPath(state.clipPath(), state.clipOperation());
- }
-
- if (flags & DirtyBrushOrigin) {
- d->m_brush_origin = QTransform();
- d->m_brush_origin.translate(-state.brushOrigin().x(),
- -state.brushOrigin().y());
- flags |= DirtyBrush;
- }
-
- if (flags & DirtyPen) {
- d->updatePen(state.pen());
- update_fast_pen = true;
- }
-
- if (flags & DirtyBrush)
- d->updateBrush(state.brush());
-
- if (update_fast_pen && d->m_has_pen) {
- if (d->m_current_state & QD3DBatchItem::BI_AA) {
- d->m_has_fast_pen = false;
- d->m_has_aa_fast_pen = ((d->m_txop <= QTransform::TxTranslate) || d->m_has_cosmetic_pen)
- && (d->m_pen_width <= 1.0f)
- && (d->m_pen.style() == Qt::SolidLine);
- } else {
- d->m_has_aa_fast_pen = false;
- d->m_has_fast_pen = ((d->m_txop <= QTransform::TxTranslate) || d->m_has_cosmetic_pen)
- && (d->m_pen.style() == Qt::SolidLine)
- && (d->m_pen.capStyle() == Qt::SquareCap);
- }
- }
-}
-
-void QDirect3DPaintEngine::cleanup()
-{
- Q_D(QDirect3DPaintEngine);
- d->cleanup();
-}
-
-void QDirect3DPaintEngine::scroll(QPaintDevice *pd, const RECT &srcrect, const RECT &destrect)
-{
- Q_D(QDirect3DPaintEngine);
- LPDIRECT3DSURFACE9 srcsurf = d->m_surface_manager.surface(pd);
- LPDIRECT3DSURFACE9 masksurf = d->m_draw_helper->freeMaskSurface();
- if (FAILED(d->m_d3d_device->StretchRect(srcsurf, &srcrect, masksurf, &srcrect, D3DTEXF_NONE)))
- qWarning("QDirect3DPaintEngine: StretchRect failed.");
- if (FAILED(d->m_d3d_device->StretchRect(masksurf, &srcrect, srcsurf, &destrect, D3DTEXF_NONE)))
- qWarning("QDirect3DPaintEngine: StretchRect failed.");
-}
-
-LPDIRECT3DSWAPCHAIN9 QDirect3DPaintEngine::swapChain(QPaintDevice *pd)
-{
- Q_D(QDirect3DPaintEngine);
-
- if (d->m_in_scene) {
- if (d->m_d3d_device == 0) {
- qWarning("QDirect3DPaintEngine: No device!");
- return false;
- }
-
- d->setRenderTechnique(QDirect3DPaintEnginePrivate::RT_NoTechnique);
- if (FAILED(d->m_d3d_device->EndScene()))
- qWarning("QDirect3DPaintEngine: failed to end scene.");
-
- d->m_in_scene = false;
- }
-
- return d->m_surface_manager.swapChain(pd);
-}
-
-void QDirect3DPaintEngine::releaseSwapChain(QPaintDevice *pd)
-{
- Q_D(QDirect3DPaintEngine);
- d->m_surface_manager.releasePaintDevice(pd);
-}
-
-HDC QDirect3DPaintEngine::getDC() const
-{
- QDirect3DPaintEnginePrivate *d = const_cast<QDirect3DPaintEnginePrivate *>(d_func());
-
- if (!d->m_dc && d->m_current_surface) {
- d->m_dcsurface = d->m_current_surface;
- if (FAILED(d->m_current_surface->GetDC(&d->m_dc)))
- qWarning() << "QDirect3DPaintEngine::getDC() failed!";
- }
-
- return d->m_dc;
-}
-
-void QDirect3DPaintEngine::setFlushOnEnd(bool flushOnEnd)
-{
- Q_D(QDirect3DPaintEngine);
-
- d->m_flush_on_end = flushOnEnd;
-}
-
-bool QDirect3DPaintEngine::hasDirect3DSupport()
-{
- Q_D(QDirect3DPaintEngine);
- return d->m_supports_d3d;
-}
-
-QT_END_NAMESPACE
-
-#include "qpaintengine_d3d.moc"
diff --git a/src/gui/painting/qpaintengine_d3d.fx b/src/gui/painting/qpaintengine_d3d.fx
deleted file mode 100644
index 1148b2a..0000000
--- a/src/gui/painting/qpaintengine_d3d.fx
+++ /dev/null
@@ -1,608 +0,0 @@
-bool g_mCosmeticPen;
-int4 g_mChannel;
-float2 g_mMaskOffset;
-int2 g_mMaskSize;
-float4x4 g_mMaskProjection;
-float4x4 g_mViewProjection;
-float4x4 g_mTransformation;
-texture g_mAAMask;
-texture g_mTexture;
-int g_mBrushMode;
-float g_mFocalDist;
-
-#define M_PI 3.14159265358979323846
-
-sampler PixmapSampler = sampler_state
-{
- texture = <g_mTexture>;
- MIPFILTER = NONE;
- MINFILTER = LINEAR;
- MAGFILTER = LINEAR;
-};
-
-sampler TextSampler = sampler_state
-{
- texture = <g_mTexture>;
- MIPFILTER = NONE;
- MINFILTER = POINT;
- MAGFILTER = POINT;
-};
-
-sampler AAMaskSampler = sampler_state
-{
- texture = <g_mAAMask>;
- AddressU = WRAP;
- AddressV = WRAP;
- AddressW = WRAP;
- MIPFILTER = NONE;
- MINFILTER = POINT;
- MAGFILTER = POINT;
-};
-
-struct VS_FULL
-{
- float4 Position : POSITION;
- float4 Diffuse : COLOR0;
- float4 TexCoords0 : TEXCOORD0;
- float4 TexCoords1 : TEXCOORD1;
-};
-
-VS_FULL TrapezoidVS( float4 Position : POSITION,
- float4 Diffuse : COLOR0,
- float4 TexCoords0 : TEXCOORD0,
- float4 TexCoords1 : TEXCOORD1)
-{
- VS_FULL Output;
-
- float a = (TexCoords1.x * Position.x) + (TexCoords1.z * (1.0 - Position.x) ); // left or right a
- float b = (TexCoords1.y * Position.x) + (TexCoords1.w * (1.0 - Position.x) ); // left or right b
- float d = 1.0 - (Position.x * 2);
-
- Position.x = (a * Position.y + b) + ( sqrt( abs(a * a) ) * d );
- //Position.x += step(abs(a), 0) * d;
- Position.x += (0.5 * d);
-
- Output.Position = mul(Position, g_mMaskProjection);
- Output.Diffuse = Diffuse;
- Output.TexCoords0 = TexCoords0;
- Output.TexCoords1 = TexCoords1;
-
- return Output;
-}
-
-struct PS_OUTPUT
-{
- float4 Color : COLOR0;
-};
-
-PS_OUTPUT TrapezoidPS(VS_FULL In, float2 pixelPos : VPOS)
-{
- PS_OUTPUT Out;
-
- float top = max(pixelPos.y - 0.5, In.TexCoords0.x);
- float bottom = min(pixelPos.y + 0.5, In.TexCoords0.y);
-
- float area = bottom - top;
-
- float left = pixelPos.x - 0.5;
- float right = pixelPos.x + 0.5;
-
- // use line equations to compute intersections of left/right edges with top/bottom of truncated pixel
- // vecX: x = (left, top), y = (left, bottom), z = (right, top), w = (right, bottom)
- float4 vecX = In.TexCoords1.xxzz * float2(top, bottom).xyxy + In.TexCoords1.yyww;
-
- float2 invA = In.TexCoords0.zw;
-
- // transform right line to left to be able to use same calculations for both
- vecX.zw = 2 * pixelPos.x - vecX.zw;
-
- float2 topX = float2(vecX.x, vecX.z);
- float2 bottomX = float2(vecX.y, vecX.w);
-
- // transform lines such that top intersection is to the right of bottom intersection
- float2 topXTemp = max(topX, bottomX);
- float2 bottomXTemp = min(topX, bottomX);
-
- // make sure line slope reflects mirrored lines
- invA = lerp(invA, -invA, step(topX, bottomX));
-
- float2 vecLeftRight = float2(left, right);
-
- // compute the intersections of the lines with the left and right edges of the pixel
- // intersectY: x = (left_line, left), y = (left_line, right), z = (right_line, left), w = (right_line, right)
- float4 intersectY = top + (vecLeftRight.xyxy - topXTemp.xxyy) * invA.xxyy;
-
- float2 temp = lerp(area - 0.5 * (right - bottomXTemp) * (bottom - intersectY.yw), // left < bottom < right < top
- (0.5 * (topXTemp + bottomXTemp) - left) * area, // left < bottom < top < right
- step(topXTemp, right));
-
- float2 excluded = 0.5 * (intersectY.xz - top) * (topXTemp - left); // bottom < left < top < right
-
- excluded = lerp(0.5 * (intersectY.yw + intersectY.xz) - top, // bottom < left < right < top
- excluded, step(topXTemp, right));
-
- excluded = lerp(temp, // left < bottom < right (see calculation of temp)
- excluded, step(bottomXTemp, left));
-
- excluded = lerp(float2(area, area), // right < bottom < top
- excluded, step(bottomXTemp, right));
-
- excluded *= step(left, topXTemp);
-
- float result = (area - excluded.x - excluded.y) * step(top, bottom);
- Out.Color.r = result * g_mChannel[0];
- Out.Color.g = result * g_mChannel[1];
- Out.Color.b = result * g_mChannel[2];
- Out.Color.a = result * g_mChannel[3];
-
- return Out;
-}
-
-VS_FULL ViewProjectionVS( float4 Position : POSITION,
- float4 Diffuse : COLOR0,
- float4 TexCoords0 : TEXCOORD0,
- float4 TexCoords1 : TEXCOORD1)
-{
- VS_FULL Output;
-
- Output.Position = mul(Position, g_mTransformation);
- Output.Position = mul(Output.Position, g_mViewProjection);
- Output.Diffuse = Diffuse;
- Output.TexCoords0 = TexCoords0;
- Output.TexCoords1 = TexCoords1;
-
- return Output;
-}
-
-PS_OUTPUT DirectMaskPS(VS_FULL In, float2 pixelPos : VPOS)
-{
- PS_OUTPUT Out;
- Out.Color = In.Diffuse;
-
- float2 maskcoords = ( (pixelPos + g_mMaskOffset) - 0.5 ) / g_mMaskSize;
- float2 clipcoords = (pixelPos - 0.5) / g_mMaskSize;
-
- float4 c = tex2D(AAMaskSampler, maskcoords.xy) * Out.Color.a;
- Out.Color.a = c.r * g_mChannel[0];
- Out.Color.a += c.g * g_mChannel[1];
- Out.Color.a += c.b * g_mChannel[2];
- Out.Color.a += c.a * g_mChannel[3];
-
- return Out;
-}
-
-PS_OUTPUT MaskPS(VS_FULL In, float2 pixelPos : VPOS)
-{
- PS_OUTPUT Out;
-
- if (g_mBrushMode == 1) {
- float x = In.TexCoords0.x;
- float y = In.TexCoords0.y;
- x = x - int(x);
- y = y - int(y);
- Out.Color = tex2D(PixmapSampler, float2(x, y));
- Out.Color.a = Out.Color.a * In.Diffuse.a;
- } else if (g_mBrushMode == 2) {
- Out.Color = tex1D(PixmapSampler, In.TexCoords0.x);
- } else if (g_mBrushMode == 3) {
- float t = atan2(In.TexCoords0.y, -In.TexCoords0.x) / (2 * M_PI);
- Out.Color = tex1D(PixmapSampler, t + 0.5);
- } else if (g_mBrushMode == 4) {
- float2 tc = float2(In.TexCoords0.x, abs(In.TexCoords0.y));
- float a = (tc.x - g_mFocalDist) / tc.y;
- float b = g_mFocalDist;
-
- float A = 1 + (a * a);
- float B = 2.0 * a * b;
- float C = (b * b) - 1;
-
- float y = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A);
- Out.Color = tex1D(PixmapSampler, (tc.y / y) );
- } else if (g_mBrushMode == 5) {
- Out.Color = tex2D(PixmapSampler, In.TexCoords0.xy);
- Out.Color = Out.Color * In.Diffuse;
- } else {
- Out.Color = In.Diffuse;
- }
-
- float2 maskcoords = ( (pixelPos + g_mMaskOffset) - 0.5 ) / g_mMaskSize;
-
- float4 c = tex2D(AAMaskSampler, maskcoords.xy) * Out.Color.a;
- Out.Color.a = c.r * g_mChannel[0];
- Out.Color.a += c.g * g_mChannel[1];
- Out.Color.a += c.b * g_mChannel[2];
- Out.Color.a += c.a * g_mChannel[3];
-
- return Out;
-}
-
-struct VS_NORMAL
-{
- float4 Position : POSITION;
- float4 Diffuse : COLOR0;
- float4 TexCoords : TEXCOORD0;
-};
-
-VS_NORMAL MaskProjectionVS(VS_NORMAL In)
-{
- VS_NORMAL Output;
-
- Output.Position = mul(In.Position, g_mMaskProjection);
- Output.Diffuse = In.Diffuse;
- Output.TexCoords = In.TexCoords;
-
- return Output;
-}
-
-float4 DirectSimplePS(float4 Color : COLOR0) : COLOR0
-{
- return Color;
-}
-
-float4 SimplePS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0
-{
- if (g_mBrushMode == 1) {
- float opacity = Color.a;
- float x = TexCoords.x;
- float y = TexCoords.y;
- x = x - int(x);
- y = y - int(y);
- Color = tex2D(PixmapSampler, float2(x, y));
- Color.a = Color.a * opacity;
- } else if (g_mBrushMode == 2) {
- Color = tex1D(PixmapSampler, TexCoords.x);
- } else if (g_mBrushMode == 3) {
- float t = atan2(TexCoords.y, -TexCoords.x) / (2 * M_PI);
- Color = tex1D(PixmapSampler, t + 0.5);
- } else if (g_mBrushMode == 4) {
- float2 tc = float2(TexCoords.x, abs(TexCoords.y));
- float a = (tc.x - g_mFocalDist) / tc.y;
- float b = g_mFocalDist;
-
- float A = 1 + (a * a);
- float B = 2.0 * a * b;
- float C = (b * b) - 1;
-
- float y = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A);
- Color = tex1D(PixmapSampler, (tc.y / y) );
- } else if (g_mBrushMode == 5) {
- Color = tex2D(PixmapSampler, TexCoords.xy) * Color;
- }
-
- return Color;
-}
-
-float4 TextPS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0
-{
- Color.a *= tex2D(TextSampler, TexCoords.xy).a;
- return Color;
-}
-
-float4 ClearTypePS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0
-{
-// if (g_mUsePixmap) {
-// float4 MaskColor = tex2D(PixmapSampler, TexCoords.xy);
-// Color = float4(1.0, 0.0, 0.0, 1.0);
-// Color.a = (1 - MaskColor.a) + MaskColor.a * Color.a;
-// Color.r = (1.0 - MaskColor.r) + (MaskColor.r * Color.r);
-// Color.g = (1.0 - MaskColor.g) + (MaskColor.g * Color.g);
-// Color.b = (1.0 - MaskColor.b) + (MaskColor.b * Color.b);
-// Color = MaskColor;
- return tex2D(PixmapSampler, TexCoords.xy);
-}
-
-VS_NORMAL NoTxAliasedVS(VS_NORMAL In)
-{
- VS_NORMAL Output;
-
- Output.Position = mul(In.Position, g_mViewProjection);
- Output.Diffuse = In.Diffuse;
- Output.TexCoords = In.TexCoords;
-
- return Output;
-}
-
-VS_NORMAL AliasedVS(VS_NORMAL In)
-{
- VS_NORMAL Output;
-
- Output.Position = mul(In.Position, g_mTransformation);
- Output.Position = mul(Output.Position, g_mViewProjection);
- Output.Diffuse = In.Diffuse;
- Output.TexCoords = In.TexCoords;
-
- return Output;
-}
-
-VS_NORMAL AliasedLinesVS(VS_NORMAL In)
-{
- VS_NORMAL Output;
-
- float4 start = float4(In.Position.x, In.Position.y, 0.5, In.Position.w);
- float4 end = float4(In.TexCoords.z, In.TexCoords.w, 0.5, In.Position.w);
- if (g_mCosmeticPen) {
- start = mul(start, g_mTransformation);
- end = mul(end, g_mTransformation);
- }
-
- float2 line_vec = end - start;
- float2 vec = normalize(line_vec);
- float2 norm = float2(-vec.y, vec.x);
-
- float pen_width = In.Position.z;
- norm = norm * pen_width * 0.5;
- vec = vec * pen_width * 0.5;
-
- Output.Position.w = In.Position.w;
- Output.Position.x = start.x + (vec.x * In.TexCoords.x);
- Output.Position.x = Output.Position.x + (norm.x * In.TexCoords.y);
- Output.Position.x = Output.Position.x + (line_vec.x * step(0, In.TexCoords.x));
- Output.Position.y = start.y + (vec.y * In.TexCoords.x);
- Output.Position.y = Output.Position.y + (norm.y * In.TexCoords.y);
- Output.Position.y = Output.Position.y + (line_vec.y * step(0, In.TexCoords.x));
- Output.Position.z = 0.5;
-
- if (!g_mCosmeticPen) {
- Output.Position = mul(Output.Position, g_mTransformation);
- }
- Output.Position = mul(Output.Position, g_mViewProjection);
-
- Output.Diffuse = In.Diffuse;
- Output.TexCoords = In.TexCoords;
-
- return Output;
-}
-
-
-technique Antialiased
-{
- pass PASS_AA_CREATEMASK
- {
- StencilEnable = False;
- ZWriteEnable = False;
- ColorWriteEnable = 0x0f;
- ZEnable = False;
-
- SrcBlend = One;
- DestBlend = One;
-
- VertexShader = compile vs_3_0 TrapezoidVS();
- PixelShader = compile ps_3_0 TrapezoidPS();
- }
-
- pass PASS_AA_DRAW
- {
- StencilEnable = False;
- ZFunc = Greater;
- ZWriteEnable = False;
- ZEnable = True;
- ColorWriteEnable = 0x0f;
-
- VertexShader = compile vs_3_0 ViewProjectionVS();
- PixelShader = compile ps_3_0 MaskPS();
- }
-
- pass PASS_AA_DRAW_DIRECT
- {
- StencilEnable = False;
- ZFunc = Greater;
- ZEnable = True;
- ZWriteEnable = False;
- ColorWriteEnable = 0x0f;
-
- VertexShader = compile vs_3_0 ViewProjectionVS();
- PixelShader = compile ps_3_0 DirectMaskPS();
- }
-}
-
-technique Aliased
-{
- pass PASS_STENCIL_ODDEVEN
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilPass = Invert;
- StencilFunc = Always;
- ColorWriteEnable = 0;
-
- ZEnable = False;
- ZWriteEnable = False;
-
- VertexShader = compile vs_1_1 NoTxAliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_STENCIL_WINDING
- {
- TwoSidedStencilMode = True;
- StencilEnable = True;
- StencilRef = 0;
- StencilMask = 0xFFFFFFFF;
-
- CCW_StencilPass = Incr;
- CCW_StencilFunc = Always;
-
- StencilPass = Decr;
- StencilFunc = Always;
-
- ColorWriteEnable = 0;
-
- ZEnable = False;
- ZWriteEnable = False;
-
- VertexShader = compile vs_1_1 NoTxAliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_STENCIL_DRAW
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilFunc = NotEqual;
- StencilMask = 0xFFFFFFFF;
- StencilRef = 0;
- StencilPass = Zero;
- StencilFail = Zero;
- StencilZFail = Zero;
-
- ColorWriteEnable = 0x0f;
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 SimplePS();
- }
-
- pass PASS_STENCIL_DRAW_DIRECT
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilFunc = NotEqual;
- StencilMask = 0xFFFFFFFF;
- StencilRef = 0;
- StencilPass = Zero;
- StencilFail = Zero;
- StencilZFail = Zero;
-
- ColorWriteEnable = 0x0f;
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_STENCIL_CLIP
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilFunc = NotEqual;
- StencilMask = 0xFFFFFFFF;
- StencilRef = 0;
- StencilPass = Zero;
- StencilFail = Zero;
- StencilZFail = Zero;
-
- ColorWriteEnable = 0;
- ZEnable = True;
- ZWriteEnable = True;
- ZFunc = Always;
-
- VertexShader = compile vs_1_1 NoTxAliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_STENCIL_NOSTENCILCHECK
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
- SrcBlend = SrcAlpha;
- DestBlend = InvSrcAlpha;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 SimplePS();
- }
-
- pass PASS_STENCIL_NOSTENCILCHECK_DIRECT
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
- SrcBlend = SrcAlpha;
- DestBlend = InvSrcAlpha;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_TEXT
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
- SrcBlend = SrcAlpha;
- DestBlend = InvSrcAlpha;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 TextPS();
- }
-
- pass PASS_CLEARTYPE_TEXT
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
-// SrcBlend = SrcAlpha;
-// DestBlend = InvSrcAlpha;
-
-// SrcBlend = DestColor;
-// DestBlend = Zero;
- SrcBlend = BlendFactor;
- DestBlend = InvSrcColor;
-
-// SrcBlend = Zero;
-// DestBlend = SrcColor;
-
-// SrcBlend = One;
-// DestBlend = Zero;
-
- VertexShader = compile vs_3_0 AliasedVS();
- PixelShader = compile ps_3_0 ClearTypePS();
- }
-
- pass PASS_ALIASED_LINES
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilPass = Invert;
- StencilFunc = Always;
- ColorWriteEnable = 0;
-
- ZEnable = False;
- ZWriteEnable = False;
-
- VertexShader = compile vs_1_1 AliasedLinesVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_ALIASED_LINES_DIRECT
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
- SrcBlend = SrcAlpha;
- DestBlend = InvSrcAlpha;
-
- VertexShader = compile vs_1_1 AliasedLinesVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-}
-
diff --git a/src/gui/painting/qpaintengine_d3d.qrc b/src/gui/painting/qpaintengine_d3d.qrc
deleted file mode 100644
index c106f2b..0000000
--- a/src/gui/painting/qpaintengine_d3d.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
- <file>qpaintengine_d3d.fx</file>
-</qresource>
-</RCC>
diff --git a/src/gui/painting/qpaintengine_d3d_p.h b/src/gui/painting/qpaintengine_d3d_p.h
deleted file mode 100644
index e366a41..0000000
--- a/src/gui/painting/qpaintengine_d3d_p.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPAINTENGINE_D3D_P_H
-#define QPAINTENGINE_D3D_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "QtGui/qpaintengine.h"
-#include <d3d9.h>
-
-QT_BEGIN_NAMESPACE
-
-class QDirect3DPaintEnginePrivate;
-class QDirect3DPaintEngine : public QPaintEngine
-{
- Q_DECLARE_PRIVATE(QDirect3DPaintEngine)
-public:
- QDirect3DPaintEngine();
- ~QDirect3DPaintEngine();
- bool begin(QPaintDevice *device);
-
- void drawEllipse(const QRectF &rect);
- void drawEllipse(const QRect &rect);
-
- void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr,
- Qt::ImageConversionFlags flags = Qt::AutoColor);
-
- void drawLines(const QLineF *lines, int lineCount);
- void drawLines(const QLine *lines, int lineCount);
-
- void drawPath(const QPainterPath &path);
-
- void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
-
- void drawPoints(const QPointF *points, int pointCount);
- void drawPoints(const QPoint *points, int pointCount);
-
- void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
- void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
-
- void drawRects(const QRectF *rects, int rectCount);
- void drawRects(const QRect * rects, int rectCount);
-
- void drawTextItem(const QPointF &p, const QTextItem &textItem);
-
- void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr);
-
- bool end();
-
- Type type() const { return Direct3D; }
- void updateState(const QPaintEngineState &state);
-
- void cleanup();
-
- HDC getDC() const;
- void setFlushOnEnd(bool flushOnEnd);
- bool hasDirect3DSupport();
-
-public:
- void scroll(QPaintDevice *pd, const RECT &srcrect, const RECT &destrect);
- LPDIRECT3DSWAPCHAIN9 swapChain(QPaintDevice *pd);
- void releaseSwapChain(QPaintDevice *pd);
-
-private:
- Q_DISABLE_COPY(QDirect3DPaintEngine)
- friend class QPixmap;
- friend class QD3DGlyphCache;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp
index 40ab95e..934b385 100644
--- a/src/gui/painting/qpaintengine_mac.cpp
+++ b/src/gui/painting/qpaintengine_mac.cpp
@@ -102,14 +102,9 @@ QMacCGContext::QMacCGContext(QPainter *p)
extern CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice);
CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pe->paintDevice());
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
uint flags = kCGImageAlphaPremultipliedFirst;
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
- if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- flags |= kCGBitmapByteOrder32Host;
-#endif
-#else
- CGImageAlphaInfo flags = kCGImageAlphaPremultipliedFirst;
+ flags |= kCGBitmapByteOrder32Host;
#endif
const QImage *image = (const QImage *) pe->paintDevice();
@@ -131,8 +126,8 @@ QMacCGContext::QMacCGContext(QPainter *p)
QPainterState *state = static_cast<QPainterState *>(pe->state);
Q_ASSERT(state);
- if (!state->redirection_offset.isNull())
- CGContextTranslateCTM(context, -state->redirection_offset.x(), -state->redirection_offset.y());
+ if (!state->redirectionMatrix.isIdentity())
+ CGContextTranslateCTM(context, state->redirectionMatrix.dx(), state->redirectionMatrix.dy());
}
}
CGContextRetain(context);
@@ -528,23 +523,12 @@ static void qt_mac_dispose_pattern(void *info)
inline static QPaintEngine::PaintEngineFeatures qt_mac_cg_features()
{
- QPaintEngine::PaintEngineFeatures ret(QPaintEngine::AllFeatures
- & ~QPaintEngine::PaintOutsidePaintEvent
- & ~QPaintEngine::PerspectiveTransform
- & ~QPaintEngine::ConicalGradientFill
- & ~QPaintEngine::LinearGradientFill
- & ~QPaintEngine::RadialGradientFill
- & ~QPaintEngine::BrushStroke);
-
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- ;
- } else
-#endif
- {
- ret &= ~QPaintEngine::BlendModes;
- }
- return ret;
+ return QPaintEngine::PaintEngineFeatures(QPaintEngine::AllFeatures & ~QPaintEngine::PaintOutsidePaintEvent
+ & ~QPaintEngine::PerspectiveTransform
+ & ~QPaintEngine::ConicalGradientFill
+ & ~QPaintEngine::LinearGradientFill
+ & ~QPaintEngine::RadialGradientFill
+ & ~QPaintEngine::BrushStroke);
}
QCoreGraphicsPaintEngine::QCoreGraphicsPaintEngine()
@@ -994,22 +978,8 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co
CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col, d->pdev));
image = qt_mac_create_imagemask(pm, sr);
} else if (differentSize) {
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- QCFType<CGImageRef> img = pm.toMacCGImageRef();
- image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height())));
- } else
-#endif
- {
- const int sx = qRound(sr.x()), sy = qRound(sr.y()), sw = qRound(sr.width()), sh = qRound(sr.height());
- const QMacPixmapData *pmData = static_cast<const QMacPixmapData*>(pm.data);
- quint32 *pantherData = pmData->pixels + sy * (pmData->bytesPerRow / 4) + sx;
- QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(0, pantherData, sw*sh*pmData->bytesPerRow, 0);
- image = CGImageCreate(sw, sh, 8, 32, pmData->bytesPerRow,
- macGenericColorSpace(),
- kCGImageAlphaPremultipliedFirst, provider, 0, 0,
- kCGRenderingIntentDefault);
- }
+ QCFType<CGImageRef> img = pm.toMacCGImageRef();
+ image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height())));
} else {
image = (CGImageRef)pm.macCGHandle();
}
@@ -1031,11 +1001,7 @@ CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imag
else
image = new QImage(img);
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
uint cgflags = kCGImageAlphaNone;
-#else
- CGImageAlphaInfo cgflags = kCGImageAlphaNone;
-#endif
switch (image->format()) {
case QImage::Format_ARGB32_Premultiplied:
cgflags = kCGImageAlphaPremultipliedFirst;
@@ -1048,9 +1014,8 @@ CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imag
default:
break;
}
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) && defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version
- if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- cgflags |= kCGBitmapByteOrder32Host;
+#if defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version
+ cgflags |= kCGBitmapByteOrder32Host;
#endif
QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(image,
static_cast<const QImage *>(image)->bits(),
@@ -1078,27 +1043,9 @@ void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, con
const QImage *image;
QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img, &image);
CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height());
- if (QRectF(0, 0, img.width(), img.height()) != sr) {
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(),
- sr.width(), sr.height()));
- } else
-#endif
- {
- int sx = qRound(sr.x());
- int sy = qRound(sr.y());
- int sw = qRound(sr.width());
- int sh = qRound(sr.height());
- // Make another CGImage based on the part that we need.
- const uchar *pantherData = image->scanLine(sy) + sx * sizeof(uint);
- QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(0, pantherData,
- sw * sh * image->bytesPerLine(), 0);
- cgimage = CGImageCreate(sw, sh, 8, 32, image->bytesPerLine(),
- macGenericColorSpace(),
- CGImageGetAlphaInfo(cgimage), dataProvider, 0, false, kCGRenderingIntentDefault);
- }
- }
+ if (QRectF(0, 0, img.width(), img.height()) != sr)
+ cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(),
+ sr.width(), sr.height()));
qt_mac_drawCGImage(d->hd, &rect, cgimage);
}
@@ -1434,8 +1381,13 @@ QCoreGraphicsPaintEngine::updateRenderHints(QPainter::RenderHints hints)
{
Q_D(QCoreGraphicsPaintEngine);
CGContextSetShouldAntialias(d->hd, hints & QPainter::Antialiasing);
- CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ?
- kCGInterpolationHigh : kCGInterpolationNone);
+ static const CGFloat ScaleFactor = qt_mac_get_scalefactor();
+ if (ScaleFactor > 1.) {
+ CGContextSetInterpolationQuality(d->hd, kCGInterpolationHigh);
+ } else {
+ CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ?
+ kCGInterpolationHigh : kCGInterpolationNone);
+ }
CGContextSetShouldSmoothFonts(d->hd, hints & QPainter::TextAntialiasing);
}
diff --git a/src/gui/painting/qpaintengine_mac_p.h b/src/gui/painting/qpaintengine_mac_p.h
index e1503ce..cffd1a7 100644
--- a/src/gui/painting/qpaintengine_mac_p.h
+++ b/src/gui/painting/qpaintengine_mac_p.h
@@ -58,9 +58,6 @@
#include "private/qpaintengine_p.h"
#include "private/qpolygonclipper_p.h"
#include "QtCore/qhash.h"
-#ifndef QT_MAC_NO_QUICKDRAW
-#include <private/qwidget_p.h>
-#endif
typedef struct CGColorSpace *CGColorSpaceRef;
QT_BEGIN_NAMESPACE
@@ -69,108 +66,6 @@ extern int qt_defaultDpi();
extern int qt_defaultDpiX();
extern int qt_defaultDpiY();
-#ifndef QT_MAC_NO_QUICKDRAW
-class QMacSavedPortInfo
-{
- RgnHandle clip;
- GWorldPtr world;
- GDHandle handle;
- PenState pen; //go pennstate
- RGBColor back, fore;
- bool valid_gworld;
- void init();
-
-public:
- inline QMacSavedPortInfo() { init(); }
- inline QMacSavedPortInfo(QPaintDevice *pd) { init(); setPaintDevice(pd); }
- inline QMacSavedPortInfo(QPaintDevice *pd, const QRect &r)
- { init(); setPaintDevice(pd); setClipRegion(r); }
- inline QMacSavedPortInfo(QPaintDevice *pd, const QRegion &r)
- { init(); setPaintDevice(pd); setClipRegion(r); }
- ~QMacSavedPortInfo();
- static inline bool setClipRegion(const QRect &r);
- static inline bool setClipRegion(const QRegion &r);
- static inline bool setPaintDevice(QPaintDevice *);
-};
-
-inline bool
-QMacSavedPortInfo::setClipRegion(const QRect &rect)
-{
- Rect r;
- SetRect(&r, rect.x(), rect.y(), rect.right()+1, rect.bottom()+1);
- ClipRect(&r);
- return true;
-}
-
-inline bool
-QMacSavedPortInfo::setClipRegion(const QRegion &r)
-{
- if(r.isEmpty())
- return setClipRegion(QRect());
- QMacSmartQuickDrawRegion rgn(r.toQDRgn());
- SetClip(rgn);
- return true;
-}
-
-inline bool
-QMacSavedPortInfo::setPaintDevice(QPaintDevice *pd)
-{
- if(!pd)
- return false;
- bool ret = true;
- extern GrafPtr qt_mac_qd_context(const QPaintDevice *); // qpaintdevice_mac.cpp
- if(pd->devType() == QInternal::Widget)
- SetPortWindowPort(qt_mac_window_for(static_cast<QWidget*>(pd)));
- else if(pd->devType() == QInternal::Pixmap || pd->devType() == QInternal::Printer)
- SetGWorld((GrafPtr)qt_mac_qd_context(pd), 0); //set the gworld
- return ret;
-}
-
-inline void
-QMacSavedPortInfo::init()
-{
- GetBackColor(&back);
- GetForeColor(&fore);
- GetGWorld(&world, &handle);
- valid_gworld = true;
- clip = NewRgn();
- GetClip(clip);
- GetPenState(&pen);
-}
-
-inline QMacSavedPortInfo::~QMacSavedPortInfo()
-{
- bool set_state = false;
- if(valid_gworld) {
- set_state = IsValidPort(world);
- if(set_state)
- SetGWorld(world,handle); //always do this one first
- } else {
- setPaintDevice(qt_mac_safe_pdev);
- }
- if(set_state) {
- SetClip(clip);
- SetPenState(&pen);
- RGBForeColor(&fore);
- RGBBackColor(&back);
- }
- DisposeRgn(clip);
-}
-#else
-class QMacSavedPortInfo
-{
-public:
- inline QMacSavedPortInfo() { }
- inline QMacSavedPortInfo(QPaintDevice *) { }
- inline QMacSavedPortInfo(QPaintDevice *, const QRect &) { }
- inline QMacSavedPortInfo(QPaintDevice *, const QRegion &) { }
- ~QMacSavedPortInfo() { }
- static inline bool setClipRegion(const QRect &) { return false; }
- static inline bool setClipRegion(const QRegion &) { return false; }
- static inline bool setPaintDevice(QPaintDevice *) { return false; }
-};
-#endif
-
class QCoreGraphicsPaintEnginePrivate;
class QCoreGraphicsPaintEngine : public QPaintEngine
{
@@ -233,6 +128,8 @@ protected:
friend class QMacPrintEngine;
friend class QMacPrintEnginePrivate;
friend void qt_mac_display_change_callbk(CGDirectDisplayID, CGDisplayChangeSummaryFlags, void *);
+ friend void qt_color_profile_changed(CFNotificationCenterRef center, void *,
+ CFStringRef , const void *, CFDictionaryRef);
QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr);
private:
diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h
index 74fd313..c18bd6c 100644
--- a/src/gui/painting/qpaintengine_p.h
+++ b/src/gui/painting/qpaintengine_p.h
@@ -72,6 +72,7 @@ public:
QPaintDevice *pdev;
QPaintEngine *q_ptr;
QRegion systemClip;
+ QRect systemRect;
QRegion systemViewport;
QTransform systemTransform;
QWidget *currentClipWidget;
@@ -117,9 +118,6 @@ public:
virtual void systemStateChanged() { }
void drawBoxTextItem(const QPointF &p, const QTextItemInt &ti);
-
-private:
- QRect systemRect;
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 7fce65e..86b2d0f 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -91,6 +91,8 @@
# include <private/qfontengine_qpf_p.h>
# endif
# include <private/qabstractfontengine_p.h>
+#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+# include <private/qfontengine_s60_p.h>
#endif
#if defined(Q_WS_WIN64)
@@ -110,10 +112,6 @@ extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); //
#define qt_swap_int(x, y) { int tmp = (x); (x) = (y); (y) = tmp; }
#define qt_swap_qreal(x, y) { qreal tmp = (x); (x) = (y); (y) = tmp; }
-#ifdef Q_WS_WIN
-static bool qt_enable_16bit_colors = false;
-#endif
-
// #define QT_DEBUG_DRAW
#ifdef QT_DEBUG_DRAW
void dumpClip(int width, int height, QClipData *clip);
@@ -139,7 +137,6 @@ extern bool qt_cleartype_enabled;
* Span functions
*/
static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData);
-static void qt_span_fill_clipRegion(int count, const QSpan *spans, void *userData);
static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData);
static void qt_span_clip(int count, const QSpan *spans, void *userData);
static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result);
@@ -347,31 +344,36 @@ void QRasterPaintEngine::init()
#else
(unsigned char *) malloc(d->rasterPoolSize);
#endif
+ Q_CHECK_PTR(d->rasterPoolBase);
// The antialiasing raster.
- d->grayRaster = new QT_FT_Raster;
- qt_ft_grays_raster.raster_new(0, d->grayRaster);
- qt_ft_grays_raster.raster_reset(*d->grayRaster, d->rasterPoolBase, d->rasterPoolSize);
+ d->grayRaster.reset(new QT_FT_Raster);
+ Q_CHECK_PTR(d->grayRaster.data());
+ if (qt_ft_grays_raster.raster_new(0, d->grayRaster.data()))
+ QT_THROW(std::bad_alloc()); // an error creating the raster is caused by a bad malloc
+
+
+ qt_ft_grays_raster.raster_reset(*d->grayRaster.data(), d->rasterPoolBase, d->rasterPoolSize);
- d->rasterizer = new QRasterizer;
- d->rasterBuffer = new QRasterBuffer();
- d->outlineMapper = new QOutlineMapper;
+ d->rasterizer.reset(new QRasterizer);
+ d->rasterBuffer.reset(new QRasterBuffer());
+ d->outlineMapper.reset(new QOutlineMapper);
d->outlinemapper_xform_dirty = true;
d->basicStroker.setMoveToHook(qt_ft_outline_move_to);
d->basicStroker.setLineToHook(qt_ft_outline_line_to);
d->basicStroker.setCubicToHook(qt_ft_outline_cubic_to);
- d->dashStroker = 0;
- d->baseClip = 0;
+ d->baseClip.reset(new QClipData(d->device->height()));
+ d->baseClip->setClipRect(QRect(0, 0, d->device->width(), d->device->height()));
- d->image_filler.init(d->rasterBuffer, this);
+ d->image_filler.init(d->rasterBuffer.data(), this);
d->image_filler.type = QSpanData::Texture;
- d->image_filler_xform.init(d->rasterBuffer, this);
+ d->image_filler_xform.init(d->rasterBuffer.data(), this);
d->image_filler_xform.type = QSpanData::Texture;
- d->solid_color_filler.init(d->rasterBuffer, this);
+ d->solid_color_filler.init(d->rasterBuffer.data(), this);
d->solid_color_filler.type = QSpanData::Solid;
d->deviceDepth = d->device->depth();
@@ -440,13 +442,7 @@ QRasterPaintEngine::~QRasterPaintEngine()
free(d->rasterPoolBase);
#endif
- qt_ft_grays_raster.raster_done(*d->grayRaster);
- delete d->grayRaster;
-
- delete d->rasterBuffer;
- delete d->outlineMapper;
- delete d->rasterizer;
- delete d->dashStroker;
+ qt_ft_grays_raster.raster_done(*d->grayRaster.data());
}
/*!
@@ -482,13 +478,13 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
d->rasterizer->setClipRect(d->deviceRect);
- s->penData.init(d->rasterBuffer, this);
- s->penData.setup(s->pen.brush(), s->intOpacity);
+ s->penData.init(d->rasterBuffer.data(), this);
+ s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode);
s->stroker = &d->basicStroker;
d->basicStroker.setClipRect(d->deviceRect);
- s->brushData.init(d->rasterBuffer, this);
- s->brushData.setup(s->brush, s->intOpacity);
+ s->brushData.init(d->rasterBuffer.data(), this);
+ s->brushData.setup(s->brush, s->intOpacity, s->composition_mode);
d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver;
@@ -509,16 +505,20 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
if (d->mono_surface)
d->glyphCacheType = QFontEngineGlyphCache::Raster_Mono;
-#ifdef Q_WS_WIN
- else if (qt_cleartype_enabled) {
+#if defined(Q_WS_WIN)
+ else if (qt_cleartype_enabled)
+#elif defined (Q_WS_MAC)
+ else if (true)
+#else
+ else if (false)
+#endif
+ {
QImage::Format format = static_cast<QImage *>(d->device)->format();
if (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)
d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask;
else
d->glyphCacheType = QFontEngineGlyphCache::Raster_A8;
- }
-#endif
- else
+ } else
d->glyphCacheType = QFontEngineGlyphCache::Raster_A8;
setActive(true);
@@ -530,19 +530,14 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
*/
bool QRasterPaintEngine::end()
{
- Q_D(QRasterPaintEngine);
#ifdef QT_DEBUG_DRAW
+ Q_D(QRasterPaintEngine);
qDebug() << "QRasterPaintEngine::end devRect:" << d->deviceRect;
if (d->baseClip) {
dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), d->baseClip);
}
#endif
- if (d->baseClip) {
- delete d->baseClip;
- d->baseClip = 0;
- }
-
return true;
}
@@ -552,8 +547,7 @@ bool QRasterPaintEngine::end()
void QRasterPaintEngine::releaseBuffer()
{
Q_D(QRasterPaintEngine);
- delete d->rasterBuffer;
- d->rasterBuffer = new QRasterBuffer;
+ d->rasterBuffer.reset(new QRasterBuffer);
}
/*!
@@ -618,22 +612,22 @@ void QRasterPaintEngine::updateMatrix(const QTransform &matrix)
d->isPlain45DegreeRotation = false;
if (txop >= QTransform::TxRotate) {
d->isPlain45DegreeRotation =
- (qFuzzyCompare(matrix.m11() + 1, qreal(1))
- && qFuzzyCompare(matrix.m12(), qreal(1))
- && qFuzzyCompare(matrix.m21(), qreal(-1))
- && qFuzzyCompare(matrix.m22() + 1, qreal(1))
+ (qFuzzyIsNull(matrix.m11())
+ && qFuzzyIsNull(matrix.m12() - qreal(1))
+ && qFuzzyIsNull(matrix.m21() + qreal(1))
+ && qFuzzyIsNull(matrix.m22())
)
||
- (qFuzzyCompare(matrix.m11(), qreal(-1))
- && qFuzzyCompare(matrix.m12() + 1, qreal(1))
- && qFuzzyCompare(matrix.m21() + 1, qreal(1))
- && qFuzzyCompare(matrix.m22(), qreal(-1))
+ (qFuzzyIsNull(matrix.m11() + qreal(1))
+ && qFuzzyIsNull(matrix.m12())
+ && qFuzzyIsNull(matrix.m21())
+ && qFuzzyIsNull(matrix.m22() + qreal(1))
)
||
- (qFuzzyCompare(matrix.m11() + 1, qreal(1))
- && qFuzzyCompare(matrix.m12(), qreal(-1))
- && qFuzzyCompare(matrix.m21(), qreal(1))
- && qFuzzyCompare(matrix.m22() + 1, qreal(1))
+ (qFuzzyIsNull(matrix.m11())
+ && qFuzzyIsNull(matrix.m12() + qreal(1))
+ && qFuzzyIsNull(matrix.m21() - qreal(1))
+ && qFuzzyIsNull(matrix.m22())
)
;
}
@@ -769,7 +763,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen)
s->strokeFlags = 0;
s->penData.clip = d->clip();
- s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity);
+ s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s->composition_mode);
if (s->strokeFlags & QRasterPaintEngine::DirtyTransform
|| pen.brush().transform().type() >= QTransform::TxNone) {
@@ -798,7 +792,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen)
s->stroker = &d->basicStroker;
} else if (pen_style != Qt::NoPen) {
if (!d->dashStroker)
- d->dashStroker = new QDashStroker(&d->basicStroker);
+ d->dashStroker.reset(new QDashStroker(&d->basicStroker));
if (pen.isCosmetic()) {
d->dashStroker->setClipRect(d->deviceRect);
} else {
@@ -808,7 +802,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen)
}
d->dashStroker->setDashPattern(pen.dashPattern());
d->dashStroker->setDashOffset(pen.dashOffset());
- s->stroker = d->dashStroker;
+ s->stroker = d->dashStroker.data();
} else {
s->stroker = 0;
}
@@ -869,7 +863,7 @@ void QRasterPaintEngine::updateBrush(const QBrush &brush)
QRasterPaintEngineState *s = state();
// must set clip prior to setup, as setup uses it...
s->brushData.clip = d->clip();
- s->brushData.setup(brush, s->intOpacity);
+ s->brushData.setup(brush, s->intOpacity, s->composition_mode);
if (s->fillFlags & DirtyTransform
|| brush.transform().type() >= QTransform::TxNone)
d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix());
@@ -1024,6 +1018,7 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
{
if (alpha == 0 || !clip.isValid())
return;
+
Q_ASSERT(img.depth() >= 8);
int srcBPL = img.bytesPerLine();
@@ -1092,11 +1087,10 @@ void QRasterPaintEnginePrivate::systemStateChanged()
if (!systemClip.isEmpty()) {
QRegion clippedDeviceRgn = systemClip & clipRect;
deviceRect = clippedDeviceRgn.boundingRect();
- delete baseClip;
- baseClip = new QClipData(device->height());
baseClip->setClipRegion(clippedDeviceRgn);
} else {
deviceRect = clipRect;
+ baseClip->setClipRect(deviceRect);
}
#ifdef QT_DEBUG_DRAW
qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRect << systemClip;
@@ -1171,6 +1165,25 @@ static void checkClipRatios(QRasterPaintEnginePrivate *d)
}
#endif
+static void qrasterpaintengine_state_setNoClip(QRasterPaintEngineState *s)
+{
+ if (s->flags.has_clip_ownership)
+ delete s->clip;
+ s->clip = 0;
+ s->flags.has_clip_ownership = false;
+}
+
+static void qrasterpaintengine_dirty_clip(QRasterPaintEnginePrivate *d, QRasterPaintEngineState *s)
+{
+ s->fillFlags |= QPaintEngine::DirtyClipPath;
+ s->strokeFlags |= QPaintEngine::DirtyClipPath;
+ s->pixmapFlags |= QPaintEngine::DirtyClipPath;
+
+ d->solid_color_filler.clip = d->clip();
+ d->solid_color_filler.adjustSpanMethods();
+}
+
+
/*!
\internal
*/
@@ -1182,12 +1195,12 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
if (path.elements()) {
for (int i=0; i<path.elementCount(); ++i) {
qDebug() << " - " << path.elements()[i]
- << "(" << path.points()[i*2] << ", " << path.points()[i*2+1] << ")";
+ << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')';
}
} else {
for (int i=0; i<path.elementCount(); ++i) {
qDebug() << " ---- "
- << "(" << path.points()[i*2] << ", " << path.points()[i*2+1] << ")";
+ << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')';
}
}
#endif
@@ -1219,13 +1232,10 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
}
if (op == Qt::NoClip) {
- if (s->flags.has_clip_ownership)
- delete s->clip;
- s->clip = 0;
- s->flags.has_clip_ownership = false;
+ qrasterpaintengine_state_setNoClip(s);
} else {
- QClipData *base = d->baseClip;
+ QClipData *base = d->baseClip.data();
// Intersect with current clip when available...
if (op == Qt::IntersectClip && s->clip)
@@ -1264,17 +1274,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
s->clip = newClip;
s->flags.has_clip_ownership = true;
}
-
- s->fillFlags |= DirtyClipPath;
- s->strokeFlags |= DirtyClipPath;
- s->pixmapFlags |= DirtyClipPath;
-
- d->solid_color_filler.clip = d->clip();
- d->solid_color_filler.adjustSpanMethods();
-
-#ifdef QT_CLIPPING_RATIOS
- checkClipRatios(d);
-#endif
+ qrasterpaintengine_dirty_clip(d, s);
}
@@ -1292,10 +1292,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
QRasterPaintEngineState *s = state();
if (op == Qt::NoClip) {
- if (s->flags.has_clip_ownership)
- delete s->clip;
- s->clip = d->baseClip;
- s->flags.has_clip_ownership = false;
+ qrasterpaintengine_state_setNoClip(s);
} else if (op == Qt::UniteClip || s->matrix.type() > QTransform::TxScale) {
QPaintEngineEx::clip(rect, op);
@@ -1341,37 +1338,63 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
return;
}
}
-
- s->brushData.clip = d->clip();
- s->penData.clip = d->clip();
-
- s->fillFlags |= DirtyClipPath;
- s->strokeFlags |= DirtyClipPath;
- s->pixmapFlags |= DirtyClipPath;
-
- d->solid_color_filler.clip = d->clip();
- d->solid_color_filler.adjustSpanMethods();
-
-
-#ifdef QT_CLIPPING_RATIOS
- checkClipRatios(d);
-#endif
+ qrasterpaintengine_dirty_clip(d, s);
}
+
/*!
\internal
*/
void QRasterPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
{
- QPaintEngineEx::clip(region, op);
-}
+#ifdef QT_DEBUG_DRAW
+ qDebug() << "QRasterPaintEngine::clip(): " << region << op;
+#endif
-/*!
- \internal
-*/
-void QRasterPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
-{
- QPaintEngineEx::clip(path, op);
+ Q_D(QRasterPaintEngine);
+
+ if (region.numRects() == 1) {
+ clip(region.boundingRect(), op);
+ return;
+ }
+
+ QRasterPaintEngineState *s = state();
+ const QClipData *clip = d->clip();
+ const QClipData *baseClip = d->baseClip.data();
+
+ if (op == Qt::NoClip) {
+ qrasterpaintengine_state_setNoClip(s);
+ } else if (s->matrix.type() > QTransform::TxScale
+ || op == Qt::UniteClip
+ || (op == Qt::IntersectClip && !clip->hasRectClip && !clip->hasRegionClip)
+ || (op == Qt::ReplaceClip && !baseClip->hasRectClip && !baseClip->hasRegionClip)) {
+ QPaintEngineEx::clip(region, op);
+ } else {
+ const QClipData *curClip;
+ QClipData *newClip;
+
+ if (op == Qt::IntersectClip)
+ curClip = clip;
+ else
+ curClip = baseClip;
+
+ if (s->flags.has_clip_ownership) {
+ newClip = s->clip;
+ Q_ASSERT(newClip);
+ } else {
+ newClip = new QClipData(d->rasterBuffer->height());
+ s->clip = newClip;
+ s->flags.has_clip_ownership = true;
+ }
+
+ QRegion r = s->matrix.map(region);
+ if (curClip->hasRectClip)
+ newClip->setClipRegion(r & curClip->clipRect);
+ else if (curClip->hasRegionClip)
+ newClip->setClipRegion(r & clip->clipRegion);
+
+ qrasterpaintengine_dirty_clip(d, s);
+ }
}
/*!
@@ -1405,7 +1428,7 @@ void QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData)
}
ensureOutlineMapper();
- d->rasterize(d->outlineMapper->convertPath(path), blend, fillData, d->rasterBuffer);
+ d->rasterize(d->outlineMapper->convertPath(path), blend, fillData, d->rasterBuffer.data());
}
static void fillRect_normalized(const QRect &r, QSpanData *data,
@@ -1413,7 +1436,7 @@ static void fillRect_normalized(const QRect &r, QSpanData *data,
{
int x1, x2, y1, y2;
- bool rectClipped = false;
+ bool rectClipped = true;
if (data->clip) {
x1 = qMax(r.x(), data->clip->xmin);
@@ -1643,34 +1666,6 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount)
QPaintEngineEx::drawRects(rects, rectCount);
}
-void QRasterPaintEnginePrivate::strokeProjective(const QPainterPath &path)
-{
- Q_Q(QRasterPaintEngine);
- QRasterPaintEngineState *s = q->state();
-
- const QPen &pen = s->lastPen;
- QPainterPathStroker pathStroker;
- pathStroker.setWidth(pen.width() == 0 ? qreal(1) : pen.width());
- pathStroker.setCapStyle(pen.capStyle());
- pathStroker.setJoinStyle(pen.joinStyle());
- pathStroker.setMiterLimit(pen.miterLimit());
- pathStroker.setDashOffset(pen.dashOffset());
-
- if (qpen_style(pen) == Qt::CustomDashLine)
- pathStroker.setDashPattern(pen.dashPattern());
- else
- pathStroker.setDashPattern(qpen_style(pen));
-
- outlineMapper->setMatrix(QTransform());
- const QPainterPath stroke = pen.isCosmetic()
- ? pathStroker.createStroke(s->matrix.map(path))
- : s->matrix.map(pathStroker.createStroke(path));
-
- rasterize(outlineMapper->convertPath(stroke), s->penData.blend, &s->penData, rasterBuffer);
- outlinemapper_xform_dirty = true;
-}
-
-
/*!
\internal
@@ -1735,6 +1730,8 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
const QLineF *lines = reinterpret_cast<const QLineF *>(path.points());
for (int i = 0; i < lineCount; ++i) {
+ if (path.shape() == QVectorPath::LinesHint)
+ dashOffset = s->lastPen.dashOffset();
if (lines[i].p1() == lines[i].p2()) {
if (s->lastPen.capStyle() != Qt::FlatCap) {
QPointF p = lines[i].p1();
@@ -1762,12 +1759,17 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
static inline QRect toNormalizedFillRect(const QRectF &rect)
{
- const int x1 = qRound(rect.x());
- const int y1 = qRound(rect.y());
- const int x2 = qRound(rect.right());
- const int y2 = qRound(rect.bottom());
+ int x1 = qRound(rect.x() + aliasedCoordinateDelta);
+ int y1 = qRound(rect.y() + aliasedCoordinateDelta);
+ int x2 = qRound(rect.right() + aliasedCoordinateDelta);
+ int y2 = qRound(rect.bottom() + aliasedCoordinateDelta);
- return QRect(x1, y1, x2 - x1, y2 - y1).normalized();
+ if (x2 < x1)
+ qSwap(x1, x2);
+ if (y2 < y1)
+ qSwap(y1, y2);
+
+ return QRect(x1, y1, x2 - x1, y2 - y1);
}
/*!
@@ -1797,9 +1799,8 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
if (path.shape() == QVectorPath::RectangleHint) {
if (!s->flags.antialiased && s->matrix.type() <= QTransform::TxScale) {
const qreal *p = path.points();
- const QPointF offs(aliasedCoordinateDelta, aliasedCoordinateDelta);
- QPointF tl = QPointF(p[0], p[1]) * s->matrix + offs;
- QPointF br = QPointF(p[4], p[5]) * s->matrix + offs;
+ QPointF tl = QPointF(p[0], p[1]) * s->matrix;
+ QPointF br = QPointF(p[4], p[5]) * s->matrix;
fillRect_normalized(toNormalizedFillRect(QRectF(tl, br)), &s->brushData, d);
return;
}
@@ -1839,8 +1840,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
}
// ### Optimize for non transformed ellipses and rectangles...
- QRealRect r = path.controlPointRect();
- QRectF cpRect(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1);
+ QRectF cpRect = path.controlPointRect();
const QRect deviceRect = s->matrix.mapRect(cpRect).toRect();
ProcessSpans blend = d->getBrushFunc(deviceRect, &s->brushData);
@@ -1858,7 +1858,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
// }
ensureOutlineMapper();
- d->rasterize(d->outlineMapper->convertPath(path), blend, &s->brushData, d->rasterBuffer);
+ d->rasterize(d->outlineMapper->convertPath(path), blend, &s->brushData, d->rasterBuffer.data());
}
void QRasterPaintEngine::fillRect(const QRectF &r, QSpanData *data)
@@ -1928,73 +1928,15 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color)
QRasterPaintEngineState *s = state();
d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity));
+ if ((d->solid_color_filler.solid.color & 0xff000000) == 0
+ && s->composition_mode == QPainter::CompositionMode_SourceOver) {
+ return;
+ }
d->solid_color_filler.clip = d->clip();
d->solid_color_filler.adjustSpanMethods();
-
fillRect(r, &d->solid_color_filler);
}
-/*!
- \reimp
-*/
-void QRasterPaintEngine::drawPath(const QPainterPath &path)
-{
-#ifdef QT_DEBUG_DRAW
- QRectF bounds = path.boundingRect();
- qDebug(" - QRasterPaintEngine::drawPath(), [%.2f, %.2f, %.2f, %.2f]",
- bounds.x(), bounds.y(), bounds.width(), bounds.height());
-#endif
-
- if (path.isEmpty())
- return;
-
- // Filling..,
- Q_D(QRasterPaintEngine);
- QRasterPaintEngineState *s = state();
-
- ensureBrush();
- if (s->brushData.blend) {
- ensureOutlineMapper();
- fillPath(path, &s->brushData);
- }
-
- // Stroking...
- ensurePen();
- if (!s->penData.blend)
- return;
- {
- if (s->matrix.type() >= QTransform::TxProject) {
- d->strokeProjective(path);
- } else {
- Q_ASSERT(s->stroker);
- d->outlineMapper->beginOutline(Qt::WindingFill);
- qreal txscale = 1;
- if (s->pen.isCosmetic() || (qt_scaleForTransform(s->matrix, &txscale) && txscale != 1)) {
- const qreal strokeWidth = d->basicStroker.strokeWidth();
- const QRectF clipRect = d->dashStroker ? d->dashStroker->clipRect() : QRectF();
- if (d->dashStroker)
- d->dashStroker->setClipRect(d->deviceRect);
- d->basicStroker.setStrokeWidth(strokeWidth * txscale);
- d->outlineMapper->setMatrix(QTransform());
- s->stroker->strokePath(path, d->outlineMapper, s->matrix);
- d->outlinemapper_xform_dirty = true;
- d->basicStroker.setStrokeWidth(strokeWidth);
- if (d->dashStroker)
- d->dashStroker->setClipRect(clipRect);
- } else {
- ensureOutlineMapper();
- s->stroker->strokePath(path, d->outlineMapper, QTransform());
- }
- d->outlineMapper->endOutline();
-
- ProcessSpans blend = d->getPenFunc(d->outlineMapper->controlPointRect,
- &s->penData);
- d->rasterize(d->outlineMapper->outline(), blend, &s->penData, d->rasterBuffer);
- }
- }
-
-}
-
static inline bool isAbove(const QPointF *a, const QPointF *b)
{
return a->y() < b->y();
@@ -2083,7 +2025,7 @@ void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, Poly
// scanconvert.
ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect,
&s->brushData);
- d->rasterize(outline, brushBlend, &s->brushData, d->rasterBuffer);
+ d->rasterize(outline, brushBlend, &s->brushData, d->rasterBuffer.data());
}
/*!
@@ -2179,7 +2121,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
// scanconvert.
ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect,
&s->brushData);
- d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer);
+ d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data());
d->outlineMapper->setCoordinateRounding(false);
}
}
@@ -2426,7 +2368,7 @@ void QRasterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pixmap)
#endif
if (pixmap.data->classId() == QPixmapData::RasterClass) {
- const QImage &image = ((QRasterPixmapData *) pixmap.data)->image;
+ const QImage &image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image;
if (image.depth() == 1) {
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
@@ -2464,7 +2406,7 @@ void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, cons
#endif
if (pixmap.data->classId() == QPixmapData::RasterClass) {
- const QImage &image = ((QRasterPixmapData *) pixmap.data)->image;
+ const QImage &image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image;
if (image.depth() == 1) {
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
@@ -2550,10 +2492,7 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img)
const QClipData *clip = d->clip();
QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy());
- // ### TODO: remove this eventually...
- static bool NO_BLEND_FUNC = !qgetenv("QT_NO_BLEND_FUNCTIONS").isNull();
-
- if (s->flags.fast_images && !NO_BLEND_FUNC) {
+ if (s->flags.fast_images) {
SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()];
if (func) {
if (!clip) {
@@ -2566,6 +2505,8 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img)
}
}
+
+
d->image_filler.clip = clip;
d->image_filler.initTexture(&img, s->intOpacity, QTextureData::Plain, img.rect());
if (!d->image_filler.blend)
@@ -2594,11 +2535,51 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
qDebug() << " - QRasterPaintEngine::drawImage(), r=" << r << " sr=" << sr << " image=" << img.size() << "depth=" << img.depth();
#endif
+ if (r.isEmpty())
+ return;
+
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
const bool aa = s->flags.antialiased || s->flags.bilinear;
- if (!aa && sr.size() == QSize(1, 1)) {
- fillRect(r, QColor::fromRgba(img.pixel(sr.x(), sr.y())));
+ int sr_l = qFloor(sr.left());
+ int sr_r = qCeil(sr.right()) - 1;
+ int sr_t = qFloor(sr.top());
+ int sr_b = qCeil(sr.bottom()) - 1;
+
+ if (!aa && sr_l == sr_r && sr_t == sr_b) {
+ // as fillRect will apply the aliased coordinate delta we need to
+ // subtract it here as we don't use it for image drawing
+ QTransform old = s->matrix;
+ s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta);
+
+ // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied.
+ QRgb color = img.pixel(sr_l, sr_t);
+ switch (img.format()) {
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ // Combine premultiplied color with the opacity set on the painter.
+ d->solid_color_filler.solid.color =
+ ((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff)
+ | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00);
+ break;
+ default:
+ d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color, s->intOpacity));
+ break;
+ }
+
+ if ((d->solid_color_filler.solid.color & 0xff000000) == 0
+ && s->composition_mode == QPainter::CompositionMode_SourceOver) {
+ return;
+ }
+
+ d->solid_color_filler.clip = d->clip();
+ d->solid_color_filler.adjustSpanMethods();
+ fillRect(r, &d->solid_color_filler);
+
+ s->matrix = old;
return;
}
@@ -2609,14 +2590,24 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) {
if (s->flags.fast_images) {
- SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()];
- if (func && (!clip || clip->hasRectClip)) {
- func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(),
- img.bits(), img.bytesPerLine(),
- qt_mapRect_non_normalizing(r, s->matrix), sr,
- !clip ? d->deviceRect : clip->clipRect,
- s->intOpacity);
- return;
+ if (s->matrix.type() > QTransform::TxScale) {
+ SrcOverTransformFunc func = qTransformFunctions[d->rasterBuffer->format][img.format()];
+ if (func && (!clip || clip->hasRectClip)) {
+ func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), img.bits(),
+ img.bytesPerLine(), r, sr, !clip ? d->deviceRect : clip->clipRect,
+ s->matrix, s->intOpacity);
+ return;
+ }
+ } else {
+ SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()];
+ if (func && (!clip || clip->hasRectClip)) {
+ func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(),
+ img.bits(), img.bytesPerLine(),
+ qt_mapRect_non_normalizing(r, s->matrix), sr,
+ !clip ? d->deviceRect : clip->clipRect,
+ s->intOpacity);
+ return;
+ }
}
}
@@ -2725,7 +2716,7 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap,
QImage image;
if (pixmap.data->classId() == QPixmapData::RasterClass) {
- image = ((QRasterPixmapData *) pixmap.data)->image;
+ image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image;
} else {
image = pixmap.toImage();
}
@@ -2799,7 +2790,7 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
if (!s->penData.blend)
return;
- QRasterBuffer *rb = d->rasterBuffer;
+ QRasterBuffer *rb = d->rasterBuffer.data();
const QRect rect(rx, ry, w, h);
const QClipData *clip = d->clip();
@@ -3092,7 +3083,7 @@ bool QRasterPaintEnginePrivate::isUnclipped_normalized(const QRect &r) const
if (cl->clipRect == deviceRect)
return true;
- if (cl->hasRegionClip) {
+ if (cl->hasRectClip) {
// inline contains() for performance (we know the rects are normalized)
const QRect &r1 = cl->clipRect;
return (r.left() >= r1.left() && r.right() <= r1.right()
@@ -3206,7 +3197,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
ensurePen();
ensureState();
-#if defined (Q_WS_WIN) || defined(Q_WS_MAC)
+#if defined (Q_WS_WIN) || defined(Q_WS_MAC) || (defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE))
bool drawCached = true;
@@ -3221,7 +3212,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
// ### cases we should delegate painting to the font engine
// ### directly...
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
QFontEngine::Type fontEngineType = ti.fontEngine->type();
// qDebug() << "type" << fontEngineType << s->matrix.type();
if ((fontEngineType == QFontEngine::Win && !((QFontEngineWin *) ti.fontEngine)->ttf && s->matrix.type() > QTransform::TxTranslate)
@@ -3239,7 +3230,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
return;
}
-#else // Q_WS_WIN || Q_WS_MAC
+#else // Q_WS_WIN || Q_WS_MAC || Q_OS_SYMBIAN && QT_NO_FREETYPE
QFontEngine *fontEngine = ti.fontEngine;
@@ -3259,7 +3250,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
}
#endif // Q_WS_QWS
-#if (defined(Q_WS_X11) || defined(Q_WS_QWS)) && !defined(QT_NO_FREETYPE)
+#if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2)
if (fontEngine->type() == QFontEngine::QPF2) {
@@ -3331,6 +3322,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
break;
default:
Q_ASSERT(false);
+ depth = 0;
};
for(int i = 0; i < glyphs.size(); i++) {
@@ -3358,6 +3350,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
break;
default:
Q_ASSERT(false);
+ pitch = 0;
};
alphaPenBlt(glyph->data, pitch, depth,
@@ -3501,8 +3494,8 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount)
int m22 = int(s->matrix.m22());
int dx = qFloor(s->matrix.dx() + aliasedCoordinateDelta);
int dy = qFloor(s->matrix.dy() + aliasedCoordinateDelta);
- int dashOffset = int(s->lastPen.dashOffset());
for (int i=0; i<lineCount; ++i) {
+ int dashOffset = int(s->lastPen.dashOffset());
if (s->flags.int_xform) {
const QLine &l = lines[i];
int x1 = l.x1() * m11 + dx;
@@ -3601,8 +3594,8 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount)
? LineDrawNormal
: LineDrawIncludeLastPixel;
- int dashOffset = int(s->lastPen.dashOffset());
for (int i=0; i<lineCount; ++i) {
+ int dashOffset = int(s->lastPen.dashOffset());
QLineF line = (lines[i] * s->matrix).translated(aliasedCoordinateDelta, aliasedCoordinateDelta);
const QRectF brect(QPointF(line.x1(), line.y1()),
QPointF(line.x2(), line.y2()));
@@ -3922,7 +3915,7 @@ static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *r
// find required length
int max = qMax(c1_spans[c1_count - 1].x + c1_spans[c1_count - 1].len,
- c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len);
+ c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len);
buffer.resize(max);
memset(buffer.data(), 0, buffer.size() * sizeof(short));
@@ -4059,7 +4052,7 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
rasterParams.flags |= (QT_FT_RASTER_FLAG_AA | QT_FT_RASTER_FLAG_DIRECT);
rasterParams.gray_spans = callback;
- error = qt_ft_grays_raster.raster_render(*grayRaster, &rasterParams);
+ error = qt_ft_grays_raster.raster_render(*grayRaster.data(), &rasterParams);
// Out of memory, reallocate some more and try again...
if (error == -6) { // -6 is Result_err_OutOfMemory
@@ -4084,10 +4077,11 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
#else
(unsigned char *) malloc(rasterPoolSize);
#endif
+ Q_CHECK_PTR(rasterPoolBase); // note: we just freed the old rasterPoolBase. I hope it's not fatal.
- qt_ft_grays_raster.raster_done(*grayRaster);
- qt_ft_grays_raster.raster_new(0, grayRaster);
- qt_ft_grays_raster.raster_reset(*grayRaster, rasterPoolBase, rasterPoolSize);
+ qt_ft_grays_raster.raster_done(*grayRaster.data());
+ qt_ft_grays_raster.raster_new(0, grayRaster.data());
+ qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize);
} else {
done = true;
}
@@ -4101,7 +4095,7 @@ void QRasterPaintEnginePrivate::recalculateFastImages()
s->flags.fast_images = !(s->renderHints & QPainter::SmoothPixmapTransform)
&& rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver
- && s->matrix.type() <= QTransform::TxScale;
+ && s->matrix.type() <= QTransform::TxShear;
}
@@ -4121,6 +4115,8 @@ QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color)
for (int y=0; y<height; ++y) {
uchar *source = sourceImage.scanLine(y);
QRgb *target = reinterpret_cast<QRgb *>(dest.scanLine(y));
+ if (!source || !target)
+ QT_THROW(std::bad_alloc()); // we must have run out of memory
for (int x=0; x < width; ++x)
target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg;
}
@@ -4206,8 +4202,14 @@ int QCustomRasterPaintDevice::bytesPerLine() const
{
return (width() * depth() + 7) / 8;
}
-#endif // Q_WS_QWS
+#elif defined(Q_OS_SYMBIAN)
+
+void QRasterBuffer::prepareBuffer(int /* width */, int /* height */)
+{
+}
+
+#endif // Q_OS_SYMBIAN
/*!
\class QCustomRasterPaintDevice
@@ -4290,7 +4292,7 @@ QClipData::QClipData(int height)
clipSpanHeight = height;
m_clipLines = 0;
- allocated = height;
+ allocated = 0;
m_spans = 0;
xmin = xmax = ymin = ymax = 0;
count = 0;
@@ -4312,94 +4314,112 @@ void QClipData::initialize()
if (m_spans)
return;
- m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
- m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan));
+ if (!m_clipLines)
+ m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
+
+ Q_CHECK_PTR(m_clipLines);
+ QT_TRY {
+ m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan));
+ allocated = clipSpanHeight;
+ Q_CHECK_PTR(m_spans);
+
+ QT_TRY {
+ if (hasRectClip) {
+ int y = 0;
+ while (y < ymin) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
- if (hasRectClip) {
- int y = 0;
- while (y < ymin) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
- }
+ const int len = clipRect.width();
+ count = 0;
+ while (y < ymax) {
+ QSpan *span = m_spans + count;
+ span->x = xmin;
+ span->len = len;
+ span->y = y;
+ span->coverage = 255;
+ ++count;
- const int len = clipRect.width();
- count = 0;
- while (y < ymax) {
- QSpan *span = m_spans + count;
- span->x = xmin;
- span->len = len;
- span->y = y;
- span->coverage = 255;
- ++count;
-
- m_clipLines[y].spans = span;
- m_clipLines[y].count = 1;
- ++y;
- }
+ m_clipLines[y].spans = span;
+ m_clipLines[y].count = 1;
+ ++y;
+ }
- while (y < clipSpanHeight) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
- }
- } else if (hasRegionClip) {
+ while (y < clipSpanHeight) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
+ } else if (hasRegionClip) {
- const QVector<QRect> rects = clipRegion.rects();
- const int numRects = rects.size();
+ const QVector<QRect> rects = clipRegion.rects();
+ const int numRects = rects.size();
- { // resize
- const int maxSpans = (ymax - ymin) * numRects;
- if (maxSpans > allocated) {
- m_spans = (QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan));
- allocated = maxSpans;
- }
- }
+ { // resize
+ const int maxSpans = (ymax - ymin) * numRects;
+ if (maxSpans > allocated) {
+ m_spans = q_check_ptr((QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan)));
+ allocated = maxSpans;
+ }
+ }
- int y = 0;
- int firstInBand = 0;
- while (firstInBand < numRects) {
- const int currMinY = rects.at(firstInBand).y();
- const int currMaxY = currMinY + rects.at(firstInBand).height();
+ int y = 0;
+ int firstInBand = 0;
+ count = 0;
+ while (firstInBand < numRects) {
+ const int currMinY = rects.at(firstInBand).y();
+ const int currMaxY = currMinY + rects.at(firstInBand).height();
+
+ while (y < currMinY) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
- while (y < currMinY) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
- }
+ int lastInBand = firstInBand;
+ while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y)
+ ++lastInBand;
- int lastInBand = firstInBand;
- while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y)
- ++lastInBand;
+ while (y < currMaxY) {
- while (y < currMaxY) {
+ m_clipLines[y].spans = m_spans + count;
+ m_clipLines[y].count = lastInBand - firstInBand + 1;
- m_clipLines[y].spans = m_spans + count;
- m_clipLines[y].count = lastInBand - firstInBand + 1;
+ for (int r = firstInBand; r <= lastInBand; ++r) {
+ const QRect &currRect = rects.at(r);
+ QSpan *span = m_spans + count;
+ span->x = currRect.x();
+ span->len = currRect.width();
+ span->y = y;
+ span->coverage = 255;
+ ++count;
+ }
+ ++y;
+ }
- for (int r = firstInBand; r <= lastInBand; ++r) {
- const QRect &currRect = rects.at(r);
- QSpan *span = m_spans + count;
- span->x = currRect.x();
- span->len = currRect.width();
- span->y = y;
- span->coverage = 255;
- ++count;
+ firstInBand = lastInBand + 1;
}
- ++y;
- }
- firstInBand = lastInBand + 1;
- }
+ Q_ASSERT(count <= allocated);
- Q_ASSERT(count <= allocated);
+ while (y < clipSpanHeight) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
- while (y < clipSpanHeight) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
+ }
+ } QT_CATCH(...) {
+ free(m_spans); // have to free m_spans again or someone might think that we were successfully initialized.
+ m_spans = 0;
+ QT_RETHROW;
}
-
+ } QT_CATCH(...) {
+ free(m_clipLines); // same for clipLines
+ m_clipLines = 0;
+ QT_RETHROW;
}
}
@@ -4418,20 +4438,37 @@ void QClipData::fixup()
ymax = m_spans[count-1].y + 1;
xmin = INT_MAX;
xmax = 0;
+
+ bool isRect = true;
+ int left = m_spans[0].x;
+ int right = m_spans[0].x + m_spans[0].len;
+
for (int i = 0; i < count; ++i) {
-// qDebug() << " " << spans[i].x << spans[i].y << spans[i].len << spans[i].coverage;
if (m_spans[i].y != y) {
+ if (m_spans[i].y != y + 1 && y != -1) {
+ isRect = false;
+ }
y = m_spans[i].y;
m_clipLines[y].spans = m_spans+i;
m_clipLines[y].count = 0;
// qDebug() << " new line: y=" << y;
}
++m_clipLines[y].count;
+ int sl = (int) m_spans[i].x;
+ int sr = sl + m_spans[i].len;
+
xmin = qMin(xmin, (int)m_spans[i].x);
xmax = qMax(xmax, (int)m_spans[i].x + m_spans[i].len);
+
+ if (sl != left || sr != right)
+ isRect = false;
+ }
+// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d %s", xmin, xmax, ymin, ymax, isRect ? "rectangular" : "");
+
+ if (isRect) {
+ hasRectClip = true;
+ clipRect.setRect(xmin, ymin, xmax - xmin, ymax - ymin);
}
- ++xmax;
-// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d", xmin, xmax, ymin, ymax);
}
/*
@@ -4439,11 +4476,12 @@ void QClipData::fixup()
*/
void QClipData::setClipRect(const QRect &rect)
{
- if (rect == clipRect)
+ if (hasRectClip && rect == clipRect)
return;
// qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect;
hasRectClip = true;
+ hasRegionClip = false;
clipRect = rect;
xmin = rect.x();
@@ -4452,7 +4490,7 @@ void QClipData::setClipRect(const QRect &rect)
ymax = qMin(rect.y() + rect.height(), clipSpanHeight);
if (m_spans) {
- delete m_spans;
+ free(m_spans);
m_spans = 0;
}
@@ -4470,6 +4508,7 @@ void QClipData::setClipRegion(const QRegion &region)
}
hasRegionClip = true;
+ hasRectClip = false;
clipRegion = region;
{ // set bounding rect
@@ -4481,7 +4520,7 @@ void QClipData::setClipRegion(const QRegion &region)
}
if (m_spans) {
- delete m_spans;
+ free(m_spans);
m_spans = 0;
}
@@ -4614,104 +4653,6 @@ static int qt_intersect_spans(QT_FT_Span *spans, int numSpans,
return n;
}
-/*
- \internal
- Clip spans to \a{clip}-region.
- Returns number of unclipped spans
-*/
-static int qt_intersect_spans(QT_FT_Span *spans, int numSpans,
- int *currSpan,
- QT_FT_Span *outSpans, int maxOut,
- const QRegion &clip)
-{
- const QVector<QRect> rects = clip.rects();
- const int numRects = rects.size();
-
- int r = 0;
- short miny, minx, maxx, maxy;
- {
- const QRect &rect = rects[0];
- miny = rect.top();
- minx = rect.left();
- maxx = rect.right();
- maxy = rect.bottom();
- }
-
- // TODO: better mapping of currY and startRect
-
- int n = 0;
- int i = *currSpan;
- int currY = spans[i].y;
- while (i < numSpans) {
-
- if (spans[i].y != currY && r != 0) {
- currY = spans[i].y;
- r = 0;
- const QRect &rect = rects[r];
- miny = rect.top();
- minx = rect.left();
- maxx = rect.right();
- maxy = rect.bottom();
- }
-
- if (spans[i].y < miny) {
- ++i;
- continue;
- }
-
- if (spans[i].y > maxy || spans[i].x > maxx) {
- if (++r >= numRects) {
- ++i;
- continue;
- }
-
- const QRect &rect = rects[r];
- miny = rect.top();
- minx = rect.left();
- maxx = rect.right();
- maxy = rect.bottom();
- continue;
- }
-
- if (spans[i].x + spans[i].len <= minx) {
- ++i;
- continue;
- }
-
- outSpans[n].y = spans[i].y;
- outSpans[n].coverage = spans[i].coverage;
-
- if (spans[i].x < minx) {
- const ushort cutaway = minx - spans[i].x;
- outSpans[n].len = qMin(spans[i].len - cutaway, maxx - minx + 1);
- outSpans[n].x = minx;
- if (outSpans[n].len == spans[i].len - cutaway) {
- ++i;
- } else {
- // span wider than current rect
- spans[i].len -= outSpans[n].len + cutaway;
- spans[i].x = maxx + 1;
- }
- } else { // span starts inside current rect
- outSpans[n].x = spans[i].x;
- outSpans[n].len = qMin(spans[i].len,
- ushort(maxx - spans[i].x + 1));
- if (outSpans[n].len == spans[i].len) {
- ++i;
- } else {
- // span wider than current rect
- spans[i].len -= outSpans[n].len;
- spans[i].x = maxx + 1;
- }
- }
-
- if (++n >= maxOut)
- break;
- }
-
- *currSpan = i;
- return n;
-}
static void qt_span_fill_clipRect(int count, const QSpan *spans,
void *userData)
@@ -4729,29 +4670,6 @@ static void qt_span_fill_clipRect(int count, const QSpan *spans,
fillData->unclipped_blend(count, spans, fillData);
}
-static void qt_span_fill_clipRegion(int count, const QSpan *spans,
- void *userData)
-{
- QSpanData *fillData = reinterpret_cast<QSpanData *>(userData);
- Q_ASSERT(fillData->blend && fillData->unclipped_blend);
-
- Q_ASSERT(fillData->clip);
- Q_ASSERT(!fillData->clip->clipRegion.isEmpty());
-
- const int NSPANS = 256;
- QSpan cspans[NSPANS];
- int currentClip = 0;
- while (currentClip < count) {
- const int unclipped = qt_intersect_spans(const_cast<QSpan*>(spans),
- count, &currentClip,
- &cspans[0], NSPANS,
- fillData->clip->clipRegion);
- if (unclipped > 0)
- fillData->unclipped_blend(unclipped, cspans, fillData);
- }
-
-}
-
static void qt_span_clip(int count, const QSpan *spans, void *userData)
{
ClipData *clipData = reinterpret_cast<ClipData *>(userData);
@@ -4776,8 +4694,8 @@ static void qt_span_clip(int count, const QSpan *spans, void *userData)
&newspans, newClip->allocated - newClip->count);
newClip->count = newspans - newClip->m_spans;
if (spans < end) {
+ newClip->m_spans = q_check_ptr((QSpan *)realloc(newClip->m_spans, newClip->allocated*2*sizeof(QSpan)));
newClip->allocated *= 2;
- newClip->m_spans = (QSpan *)realloc(newClip->m_spans, newClip->allocated*sizeof(QSpan));
}
}
}
@@ -5024,7 +4942,7 @@ void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe)
extern QImage qt_imageForBrush(int brushStyle, bool invert);
-void QSpanData::setup(const QBrush &brush, int alpha)
+void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode)
{
Qt::BrushStyle brushStyle = qbrush_style(brush);
switch (brushStyle) {
@@ -5032,6 +4950,10 @@ void QSpanData::setup(const QBrush &brush, int alpha)
type = Solid;
QColor c = qbrush_color(brush);
solid.color = PREMUL(ARGB_COMBINE_ALPHA(c.rgba(), alpha));
+ if ((solid.color & 0xff000000) == 0
+ && compositionMode == QPainter::CompositionMode_SourceOver) {
+ type = None;
+ }
break;
}
@@ -5172,8 +5094,6 @@ void QSpanData::adjustSpanMethods()
blend = unclipped_blend;
} else if (clip->hasRectClip) {
blend = clip->clipRect.isEmpty() ? 0 : qt_span_fill_clipRect;
- } else if (clip->hasRegionClip) {
- blend = clip->clipRegion.isEmpty() ? 0 : qt_span_fill_clipRegion;
} else {
blend = qt_span_fill_clipped;
}
@@ -5330,6 +5250,13 @@ static void drawLine_midpoint_i(int x1, int y1, int x2, int y2, ProcessSpans spa
dy = -dy;
}
+ int x_lower_limit = - 128;
+ if (x1 < x_lower_limit) {
+ int cy = dy * (x_lower_limit - x1) / dx + y1;
+ drawLine_midpoint_i(x_lower_limit, cy, x2, y2, span_func, data, style, devRect);
+ return;
+ }
+
if (style == LineDrawNormal)
--x2;
@@ -5467,6 +5394,13 @@ static void drawLine_midpoint_i(int x1, int y1, int x2, int y2, ProcessSpans spa
dx = -dx;
}
+ int y_lower_limit = - 128;
+ if (y1 < y_lower_limit) {
+ int cx = dx * (y_lower_limit - y1) / dy + x1;
+ drawLine_midpoint_i(cx, y_lower_limit, x2, y2, span_func, data, style, devRect);
+ return;
+ }
+
if (style == LineDrawNormal)
--y2;
@@ -6154,7 +6088,7 @@ void dumpClip(int width, int height, QClipData *clip)
int y1 = 0;
for (int i = 0; i < clip->count; ++i) {
- QSpan *span = clip->spans + i;
+ QSpan *span = clip->spans() + i;
for (int j = 0; j < span->len; ++j)
clipImg.setPixel(span->x + j, span->y, 0xffffff00);
x0 = qMin(x0, int(span->x));
@@ -6172,7 +6106,7 @@ void dumpClip(int width, int height, QClipData *clip)
Q_ASSERT(x1 >= 0);
fprintf(stderr,"clip %d: %d %d - %d %d\n", counter, x0, y0, x1, y1);
- clipImg.save(QString(QLatin1String("clip-%0.png")).arg(counter++));
+ clipImg.save(QString::fromLatin1("clip-%0.png").arg(counter++));
}
#endif
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index b662e6b..c31a087 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -62,6 +62,7 @@
#include "private/qstroker_p.h"
#include "private/qpainter_p.h"
#include "private/qtextureglyphcache_p.h"
+#include "private/qoutlinemapper_p.h"
#include <stdlib.h>
@@ -165,7 +166,6 @@ public:
void updateMatrix(const QTransform &matrix);
- void drawPath(const QPainterPath &path);
void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
void fillPath(const QPainterPath &path, QSpanData *fillData);
@@ -202,7 +202,6 @@ public:
void clip(const QVectorPath &path, Qt::ClipOperation op);
void clip(const QRect &rect, Qt::ClipOperation op);
void clip(const QRegion &region, Qt::ClipOperation op);
- void clip(const QPainterPath &path, Qt::ClipOperation op);
enum ClipType {
RectClip,
@@ -328,14 +327,13 @@ public:
inline const QClipData *clip() const;
- void strokeProjective(const QPainterPath &path);
void initializeRasterizer(QSpanData *data);
void recalculateFastImages();
QPaintDevice *device;
- QOutlineMapper *outlineMapper;
- QRasterBuffer *rasterBuffer;
+ QScopedPointer<QOutlineMapper> outlineMapper;
+ QScopedPointer<QRasterBuffer> rasterBuffer;
#if defined (Q_WS_WIN)
HDC hdc;
@@ -346,9 +344,9 @@ public:
QRect deviceRect;
QStroker basicStroker;
- QDashStroker *dashStroker;
+ QScopedPointer<QDashStroker> dashStroker;
- QT_FT_Raster *grayRaster;
+ QScopedPointer<QT_FT_Raster> grayRaster;
unsigned long rasterPoolSize;
unsigned char *rasterPoolBase;
@@ -360,7 +358,7 @@ public:
QFontEngineGlyphCache::Type glyphCacheType;
- QClipData *baseClip;
+ QScopedPointer<QClipData> baseClip;
int deviceDepth;
@@ -371,11 +369,11 @@ public:
uint isPlain45DegreeRotation : 1;
#endif
- QRasterizer *rasterizer;
+ QScopedPointer<QRasterizer> rasterizer;
};
-class QClipData {
+class Q_GUI_EXPORT QClipData {
public:
QClipData(int height);
~QClipData();
@@ -482,7 +480,7 @@ private:
/*******************************************************************************
* QRasterBuffer
*/
-class QRasterBuffer
+class Q_GUI_EXPORT QRasterBuffer
{
public:
QRasterBuffer() : m_width(0), m_height(0), m_buffer(0) { init(); }
@@ -542,7 +540,7 @@ inline const QClipData *QRasterPaintEnginePrivate::clip() const {
Q_Q(const QRasterPaintEngine);
if (q->state() && q->state()->clip && q->state()->clip->enabled)
return q->state()->clip;
- return baseClip;
+ return baseClip.data();
}
diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp
index edf29c5..d906b69 100644
--- a/src/gui/painting/qpaintengine_x11.cpp
+++ b/src/gui/painting/qpaintengine_x11.cpp
@@ -271,7 +271,7 @@ void QXRenderTessellator::addTrap(const Trapezoid &trap)
{
if (size == allocated) {
allocated = qMax(2*allocated, 64);
- traps = (XTrapezoid *)realloc(traps, allocated * sizeof(XTrapezoid));
+ traps = q_check_ptr((XTrapezoid *)realloc(traps, allocated * sizeof(XTrapezoid)));
}
traps[size].top = Q27Dot5ToXFixed(trap.top);
traps[size].bottom = Q27Dot5ToXFixed(trap.bottom);
@@ -482,7 +482,7 @@ bool QX11PaintEngine::begin(QPaintDevice *pdev)
d->picture = (::Picture)w->x11PictureHandle();
} else if (pdev->devType() == QInternal::Pixmap) {
const QPixmap *pm = static_cast<const QPixmap *>(pdev);
- QX11PixmapData *data = static_cast<QX11PixmapData*>(pm->data);
+ QX11PixmapData *data = static_cast<QX11PixmapData*>(pm->data.data());
if (X11->use_xrender && data->depth() != 32 && data->x11_mask)
data->convertToARGB32();
d->picture = (::Picture)static_cast<const QPixmap *>(pdev)->x11PictureHandle();
@@ -1365,7 +1365,7 @@ void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
XRenderPictureAttributes attrs;
attrs.repeat = true;
XRenderChangePicture(d->dpy, d->brush_pm.x11PictureHandle(), CPRepeat, &attrs);
- QX11PixmapData *data = static_cast<QX11PixmapData*>(d->brush_pm.data);
+ QX11PixmapData *data = static_cast<QX11PixmapData*>(d->brush_pm.data.data());
if (data->mask_picture)
XRenderChangePicture(d->dpy, data->mask_picture, CPRepeat, &attrs);
}
@@ -1402,13 +1402,13 @@ void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
mask |= GCTile;
#ifndef QT_NO_XRENDER
if (d->pdev_depth == 32 && d->brush_pm.depth() != 32) {
- QX11PixmapData *brushData = static_cast<QX11PixmapData*>(d->brush_pm.data);
+ QX11PixmapData *brushData = static_cast<QX11PixmapData*>(d->brush_pm.data.data());
brushData->convertToARGB32();
}
#endif
vals.tile = (d->brush_pm.depth() == d->pdev_depth
? d->brush_pm.handle()
- : static_cast<QX11PixmapData*>(d->brush_pm.data)->x11ConvertToDefaultDepth());
+ : static_cast<QX11PixmapData*>(d->brush_pm.data.data())->x11ConvertToDefaultDepth());
s = FillTiled;
#if !defined(QT_NO_XRENDER)
d->current_brush = d->cbrush.texture().x11PictureHandle();
@@ -1915,7 +1915,7 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
QPixmap::x11SetDefaultScreen(pixmap.x11Info().screen());
#ifndef QT_NO_XRENDER
- ::Picture src_pict = static_cast<QX11PixmapData*>(pixmap.data)->picture;
+ ::Picture src_pict = static_cast<QX11PixmapData*>(pixmap.data.data())->picture;
if (src_pict && d->picture) {
const int pDepth = pixmap.depth();
if (pDepth == 1 && (d->has_alpha_pen)) {
@@ -1934,7 +1934,7 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
bool mono_dst = d->pdev_depth == 1;
bool restore_clip = false;
- if (static_cast<QX11PixmapData*>(pixmap.data)->x11_mask) { // pixmap has a mask
+ if (static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask) { // pixmap has a mask
QBitmap comb(sw, sh);
GC cgc = XCreateGC(d->dpy, comb.handle(), 0, 0);
XSetForeground(d->dpy, cgc, 0);
@@ -1951,7 +1951,7 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
XSetFillStyle(d->dpy, cgc, FillOpaqueStippled);
XSetTSOrigin(d->dpy, cgc, -sx, -sy);
XSetStipple(d->dpy, cgc,
- static_cast<QX11PixmapData*>(pixmap.data)->x11_mask);
+ static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask);
XFillRectangle(d->dpy, comb.handle(), cgc, 0, 0, sw, sh);
XFreeGC(d->dpy, cgc);
@@ -1994,8 +1994,8 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect
if (d->pdev->devType() == QInternal::Pixmap) {
const QPixmap *px = static_cast<const QPixmap*>(d->pdev);
- Pixmap src_mask = static_cast<QX11PixmapData*>(pixmap.data)->x11_mask;
- Pixmap dst_mask = static_cast<QX11PixmapData*>(px->data)->x11_mask;
+ Pixmap src_mask = static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask;
+ Pixmap dst_mask = static_cast<QX11PixmapData*>(px->data.data())->x11_mask;
if (dst_mask) {
GC cgc = XCreateGC(d->dpy, dst_mask, 0, 0);
if (src_mask) { // copy src mask into dst mask
@@ -2214,7 +2214,7 @@ void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, co
#endif
} else
#endif // !QT_NO_XRENDER
- if (pixmap.depth() > 1 && !static_cast<QX11PixmapData*>(pixmap.data)->x11_mask) {
+ if (pixmap.depth() > 1 && !static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask) {
XSetTile(d->dpy, d->gc, pixmap.handle());
XSetFillStyle(d->dpy, d->gc, FillTiled);
XSetTSOrigin(d->dpy, d->gc, x-sx, y-sy);
@@ -2459,15 +2459,23 @@ void QX11PaintEngine::drawFreetype(const QPointF &p, const QTextItemInt &ti)
XRectangle rects[rectcount];
int num_rects = 0;
+ QPoint delta(qRound(d->matrix.dx()), qRound(d->matrix.dy()));
+ QRect clip(d->polygonClipper.boundingRect());
for (int i=0; i < path.elementCount(); i+=5) {
int x = qRound(path.elementAt(i).x);
int y = qRound(path.elementAt(i).y);
int w = qRound(path.elementAt(i+1).x) - x;
int h = qRound(path.elementAt(i+2).y) - y;
- rects[num_rects].x = x + qRound(d->matrix.dx());
- rects[num_rects].y = y + qRound(d->matrix.dy());
- rects[num_rects].width = w;
- rects[num_rects].height = h;
+
+ QRect rect = QRect(x + delta.x(), y + delta.y(), w, h);
+ rect = rect.intersected(clip);
+ if (rect.isEmpty())
+ continue;
+
+ rects[num_rects].x = short(rect.x());
+ rects[num_rects].y = short(rect.y());
+ rects[num_rects].width = ushort(rect.width());
+ rects[num_rects].height = ushort(rect.height());
++num_rects;
if (num_rects == rectcount) {
XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects);
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 3c82414..c2703bc 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -42,6 +42,7 @@
#include "qpaintengineex_p.h"
#include "qpainter_p.h"
#include "qstroker_p.h"
+#include "qbezier_p.h"
#include <private/qpainterpath_p.h>
#include <qvarlengtharray.h>
@@ -56,15 +57,15 @@ QT_BEGIN_NAMESPACE
*
*/
-const QRealRect &QVectorPath::controlPointRect() const
+QRectF QVectorPath::controlPointRect() const
{
if (m_hints & ControlPointRect)
- return m_cp_rect;
+ return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
if (m_count == 0) {
m_cp_rect.x1 = m_cp_rect.x2 = m_cp_rect.y1 = m_cp_rect.y2 = 0;
m_hints |= ControlPointRect;
- return m_cp_rect;
+ return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
}
Q_ASSERT(m_points && m_count > 0);
@@ -88,7 +89,41 @@ const QRealRect &QVectorPath::controlPointRect() const
}
m_hints |= ControlPointRect;
- return m_cp_rect;
+ return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
+}
+
+QPainterPath QVectorPath::convertToPainterPath() const
+{
+ QPainterPath path;
+
+ if (m_count == 0)
+ return path;
+
+ const QPointF *points = (const QPointF *) m_points;
+
+ if (m_elements) {
+ for (int i=0; i<m_count; ++i) {
+ switch (m_elements[i]) {
+ case QPainterPath::MoveToElement:
+ path.moveTo(points[i]);
+ break;
+ case QPainterPath::LineToElement:
+ path.lineTo(points[i]);
+ break;
+ case QPainterPath::CurveToElement:
+ path.cubicTo(points[i], points[i+1], points[i+2]);
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ path.moveTo(points[0]);
+ for (int i=1; i<m_count; ++i)
+ path.lineTo(points[i]);
+ }
+
+ return path;
}
const QVectorPath &qtVectorPathForPath(const QPainterPath &path)
@@ -100,12 +135,10 @@ const QVectorPath &qtVectorPathForPath(const QPainterPath &path)
#ifndef QT_NO_DEBUG_STREAM
QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path)
{
- QRealRect vectorPathBounds = path.controlPointRect();
- QRectF rf(vectorPathBounds.x1, vectorPathBounds.y1,
- vectorPathBounds.x2 - vectorPathBounds.x1, vectorPathBounds.y2 - vectorPathBounds.y1);
+ QRectF rf = path.controlPointRect();
s << "QVectorPath(size:" << path.elementCount()
<< " hints:" << hex << path.hints()
- << rf << ")";
+ << rf << ')';
return s;
}
#endif
@@ -138,6 +171,69 @@ QPaintEngineExPrivate::~QPaintEngineExPrivate()
}
+void QPaintEngineExPrivate::replayClipOperations()
+{
+ Q_Q(QPaintEngineEx);
+
+ QPainter *p = q->painter();
+ if (!p || !p->d_ptr)
+ return;
+
+ QList<QPainterClipInfo> clipInfo = p->d_ptr->state->clipInfo;
+
+ QTransform transform = q->state()->matrix;
+
+ for (int i = 0; i < clipInfo.size(); ++i) {
+ const QPainterClipInfo &info = clipInfo.at(i);
+
+ if (info.matrix != q->state()->matrix) {
+ q->state()->matrix = info.matrix;
+ q->transformChanged();
+ }
+
+ switch (info.clipType) {
+ case QPainterClipInfo::RegionClip:
+ q->clip(info.region, info.operation);
+ break;
+ case QPainterClipInfo::PathClip:
+ q->clip(info.path, info.operation);
+ break;
+ case QPainterClipInfo::RectClip:
+ q->clip(info.rect, info.operation);
+ break;
+ case QPainterClipInfo::RectFClip: {
+ qreal right = info.rectf.x() + info.rectf.width();
+ qreal bottom = info.rectf.y() + info.rectf.height();
+ qreal pts[] = { info.rectf.x(), info.rectf.y(),
+ right, info.rectf.y(),
+ right, bottom,
+ info.rectf.x(), bottom };
+ QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
+ q->clip(vp, info.operation);
+ break;
+ }
+ }
+ }
+
+ if (transform != q->state()->matrix) {
+ q->state()->matrix = transform;
+ q->transformChanged();
+ }
+}
+
+
+bool QPaintEngineExPrivate::hasClipOperations() const
+{
+ Q_Q(const QPaintEngineEx);
+
+ QPainter *p = q->painter();
+ if (!p || !p->d_ptr)
+ return false;
+
+ QList<QPainterClipInfo> clipInfo = p->d_ptr->state->clipInfo;
+
+ return !clipInfo.isEmpty();
+}
/*******************************************************************************
*
@@ -244,13 +340,18 @@ static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, q
((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement);
}
+QPaintEngineEx::QPaintEngineEx()
+ : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures)
+{
+ extended = true;
+}
+
QPaintEngineEx::QPaintEngineEx(QPaintEngineExPrivate &data)
: QPaintEngine(data, AllFeatures)
{
extended = true;
}
-
QPainterState *QPaintEngineEx::createState(QPainterState *orig) const
{
if (!orig)
@@ -318,7 +419,6 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
const qreal *lastPoint = points + (pointCount<<1);
- d->activeStroker->begin(d->strokeHandler);
d->strokeHandler->types.reset();
d->strokeHandler->pts.reset();
@@ -327,13 +427,13 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin)
flags |= QVectorPath::CurvedShapeHint;
- // ### Perspective Xforms are currently not supported...
qreal txscale = 1;
if (!(pen.isCosmetic() || (qt_scaleForTransform(state()->matrix, &txscale) && txscale != 1))) {
// We include cosmetic pens in this case to avoid having to
// change the current transform. Normal transformed,
// non-cosmetic pens will be transformed as part of fill
// later, so they are also covered here..
+ d->activeStroker->begin(d->strokeHandler);
if (types) {
while (points < lastPoint) {
switch (*types) {
@@ -382,69 +482,75 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
QVectorPath strokePath(d->strokeHandler->pts.data(),
d->strokeHandler->types.size(),
d->strokeHandler->types.data(),
- QVectorPath::WindingFill);
+ flags);
fill(strokePath, pen.brush());
} else {
const qreal strokeWidth = d->stroker.strokeWidth();
d->stroker.setStrokeWidth(strokeWidth * txscale);
// For cosmetic pens we need a bit of trickery... We to process xform the input points
- if (types) {
- while (points < lastPoint) {
- switch (*types) {
- case QPainterPath::MoveToElement: {
- QPointF pt = (*(QPointF *) points) * state()->matrix;
- d->activeStroker->moveTo(pt.x(), pt.y());
- points += 2;
- ++types;
- break;
+ if (state()->matrix.type() >= QTransform::TxProject) {
+ QPainterPath painterPath = state()->matrix.map(path.convertToPainterPath());
+ d->activeStroker->strokePath(painterPath, d->strokeHandler, QTransform());
+ } else {
+ d->activeStroker->begin(d->strokeHandler);
+ if (types) {
+ while (points < lastPoint) {
+ switch (*types) {
+ case QPainterPath::MoveToElement: {
+ QPointF pt = (*(QPointF *) points) * state()->matrix;
+ d->activeStroker->moveTo(pt.x(), pt.y());
+ points += 2;
+ ++types;
+ break;
+ }
+ case QPainterPath::LineToElement: {
+ QPointF pt = (*(QPointF *) points) * state()->matrix;
+ d->activeStroker->lineTo(pt.x(), pt.y());
+ points += 2;
+ ++types;
+ break;
+ }
+ case QPainterPath::CurveToElement: {
+ QPointF c1 = ((QPointF *) points)[0] * state()->matrix;
+ QPointF c2 = ((QPointF *) points)[1] * state()->matrix;
+ QPointF e = ((QPointF *) points)[2] * state()->matrix;
+ d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
+ points += 6;
+ types += 3;
+ flags |= QVectorPath::CurvedShapeHint;
+ break;
+ }
+ default:
+ break;
+ }
}
- case QPainterPath::LineToElement: {
- QPointF pt = (*(QPointF *) points) * state()->matrix;
+ if (path.hasImplicitClose()) {
+ QPointF pt = * ((QPointF *) path.points()) * state()->matrix;
d->activeStroker->lineTo(pt.x(), pt.y());
- points += 2;
- ++types;
- break;
- }
- case QPainterPath::CurveToElement: {
- QPointF c1 = ((QPointF *) points)[0] * state()->matrix;
- QPointF c2 = ((QPointF *) points)[1] * state()->matrix;
- QPointF e = ((QPointF *) points)[2] * state()->matrix;
- d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
- points += 6;
- types += 3;
- flags |= QVectorPath::CurvedShapeHint;
- break;
}
- default:
- break;
- }
- }
- if (path.hasImplicitClose()) {
- QPointF pt = * ((QPointF *) path.points()) * state()->matrix;
- d->activeStroker->lineTo(pt.x(), pt.y());
- }
- } else {
- QPointF p = ((QPointF *)points)[0] * state()->matrix;
- d->activeStroker->moveTo(p.x(), p.y());
- points += 2;
- ++types;
- while (points < lastPoint) {
+ } else {
QPointF p = ((QPointF *)points)[0] * state()->matrix;
- d->activeStroker->lineTo(p.x(), p.y());
+ d->activeStroker->moveTo(p.x(), p.y());
points += 2;
++types;
+ while (points < lastPoint) {
+ QPointF p = ((QPointF *)points)[0] * state()->matrix;
+ d->activeStroker->lineTo(p.x(), p.y());
+ points += 2;
+ ++types;
+ }
+ if (path.hasImplicitClose())
+ d->activeStroker->lineTo(p.x(), p.y());
}
- if (path.hasImplicitClose())
- d->activeStroker->lineTo(p.x(), p.y());
+ d->activeStroker->end();
}
- d->activeStroker->end();
d->stroker.setStrokeWidth(strokeWidth);
QVectorPath strokePath(d->strokeHandler->pts.data(),
d->strokeHandler->types.size(),
d->strokeHandler->types.data(),
- QVectorPath::WindingFill);
+ flags);
QTransform xform = state()->matrix;
state()->matrix = QTransform();
@@ -483,6 +589,9 @@ void QPaintEngineEx::clip(const QRect &r, Qt::ClipOperation op)
void QPaintEngineEx::clip(const QRegion &region, Qt::ClipOperation op)
{
+ if (region.numRects() == 1)
+ clip(region.boundingRect(), op);
+
QVector<QRect> rects = region.rects();
if (rects.size() <= 32) {
qreal pts[2*32*4];
@@ -777,8 +886,7 @@ void QPaintEngineEx::drawImage(const QPointF &pos, const QImage &image)
void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
{
QBrush brush(state()->pen.color(), pixmap);
- QTransform xform;
- xform.translate(-s.x(), -s.y());
+ QTransform xform = QTransform::fromTranslate(r.x() - s.x(), r.y() - s.y());
brush.setTransform(xform);
qreal pts[] = { r.x(), r.y(),
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index eeb7647..a252b5e 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -55,10 +55,10 @@
#include <QtGui/qpaintengine.h>
-#include "qpaintengine_p.h"
-#include "qstroker_p.h"
-#include "qpainter_p.h"
-#include "qvectorpath_p.h"
+#include <private/qpaintengine_p.h>
+#include <private/qstroker_p.h>
+#include <private/qpainter_p.h>
+#include <private/qvectorpath_p.h>
QT_BEGIN_HEADER
@@ -139,29 +139,13 @@ public:
QDebug Q_GUI_EXPORT &operator<<(QDebug &, const QVectorPath &path);
#endif
-class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate
-{
-public:
- QPaintEngineExPrivate();
- ~QPaintEngineExPrivate();
-
- QStroker stroker;
- QDashStroker dasher;
- StrokeHandler *strokeHandler;
- QStrokerOps *activeStroker;
- QPen strokerPen;
-
- QRect exDeviceRect;
-};
-
class QPixmapFilter;
class Q_GUI_EXPORT QPaintEngineEx : public QPaintEngine
{
Q_DECLARE_PRIVATE(QPaintEngineEx)
public:
- inline QPaintEngineEx()
- : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures) { extended = true; }
+ QPaintEngineEx();
virtual QPainterState *createState(QPainterState *orig) const;
@@ -218,12 +202,35 @@ public:
inline QPainterState *state() { return static_cast<QPainterState *>(QPaintEngine::state); }
inline const QPainterState *state() const { return static_cast<const QPainterState *>(QPaintEngine::state); }
+ virtual void sync() {}
+
+ virtual void beginNativePainting() {}
+ virtual void endNativePainting() {}
+
virtual QPixmapFilter *createPixmapFilter(int /*type*/) const { return 0; }
protected:
QPaintEngineEx(QPaintEngineExPrivate &data);
};
+class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate
+{
+ Q_DECLARE_PUBLIC(QPaintEngineEx)
+public:
+ QPaintEngineExPrivate();
+ ~QPaintEngineExPrivate();
+
+ void replayClipOperations();
+ bool hasClipOperations() const;
+
+ QStroker stroker;
+ QDashStroker dasher;
+ StrokeHandler *strokeHandler;
+ QStrokerOps *activeStroker;
+ QPen strokerPen;
+
+ QRect exDeviceRect;
+};
inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) {
switch (mode) {
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 4255635..d82e7ee 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -75,9 +75,6 @@ QT_BEGIN_NAMESPACE
#define QGradient_StretchToDevice 0x10000000
#define QPaintEngine_OpaqueBackground 0x40000000
-// use the same rounding as in qrasterizer.cpp (6 bit fixed point)
-static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
-
// #define QT_DEBUG_DRAW
#ifdef QT_DEBUG_DRAW
bool qt_show_painter_debug_output = true;
@@ -184,7 +181,7 @@ void QPainterPrivate::checkEmulation()
extended = emulationEngine;
extended->setState(state);
}
- } else if (emulationEngine && emulationEngine != extended) {
+ } else if (emulationEngine == extended) {
extended = emulationEngine->real_engine;
}
}
@@ -259,14 +256,16 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
// in 99% of all cases). E.g: A renders B which renders C which renders D.
sp->d_ptr->d_ptrs_size = 4;
sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
+ Q_CHECK_PTR(sp->d_ptr->d_ptrs);
} else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
// However, to support corner cases we grow the array dynamically if needed.
sp->d_ptr->d_ptrs_size <<= 1;
const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
- sp->d_ptr->d_ptrs = (QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize);
+ sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
}
- sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr;
- q->d_ptr = sp->d_ptr;
+ sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
+ q->d_ptr.take();
+ q->d_ptr.reset(sp->d_ptr.data());
Q_ASSERT(q->d_ptr->state);
@@ -281,10 +280,14 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
// Update matrix.
- if (q->d_ptr->state->WxF)
- q->d_ptr->state->worldMatrix.translate(-offset.x(), -offset.y());
- else
- q->d_ptr->state->redirection_offset = offset;
+ if (q->d_ptr->state->WxF) {
+ q->d_ptr->state->redirectionMatrix *= q->d_ptr->state->worldMatrix;
+ q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
+ q->d_ptr->state->worldMatrix = QTransform();
+ q->d_ptr->state->WxF = false;
+ } else {
+ q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
+ }
q->d_ptr->updateMatrix();
QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
@@ -315,7 +318,8 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q)
d_ptrs[refcount - 1] = 0;
q->restore();
- q->d_ptr = original;
+ q->d_ptr.take();
+ q->d_ptr.reset(original);
if (emulationEngine) {
extended = emulationEngine->real_engine;
@@ -410,7 +414,7 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio
bool old_txinv = txinv;
QTransform old_invMatrix = invMatrix;
txinv = true;
- invMatrix = QTransform().translate(-state->redirection_offset.x(), -state->redirection_offset.y());
+ invMatrix = QTransform();
QPainterPath clipPath = q->clipPath();
QRectF r = clipPath.boundingRect().intersected(absPathRect);
absPathRect = r.toAlignedRect();
@@ -634,20 +638,7 @@ void QPainterPrivate::updateMatrix()
state->matrix *= viewTransform();
txinv = false; // no inverted matrix
- if (!state->redirection_offset.isNull()) {
- // We want to translate in dev space so we do the adding of the redirection
- // offset manually.
- if (state->matrix.isAffine()) {
- state->matrix = QTransform(state->matrix.m11(), state->matrix.m12(),
- state->matrix.m21(), state->matrix.m22(),
- state->matrix.dx()-state->redirection_offset.x(),
- state->matrix.dy()-state->redirection_offset.y());
- } else {
- QTransform temp;
- temp.translate(-state->redirection_offset.x(), -state->redirection_offset.y());
- state->matrix *= temp;
- }
- }
+ state->matrix *= state->redirectionMatrix;
if (extended)
extended->transformChanged();
else
@@ -662,18 +653,7 @@ void QPainterPrivate::updateInvMatrix()
{
Q_ASSERT(txinv == false);
txinv = true; // creating inverted matrix
- QTransform m;
-
- if (state->VxF)
- m = viewTransform();
-
- if (state->WxF) {
- if (state->VxF)
- m = state->worldMatrix * m;
- else
- m = state->worldMatrix;
- }
- invMatrix = m.inverted(); // invert matrix
+ invMatrix = state->matrix.inverted();
}
void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
@@ -944,8 +924,8 @@ void QPainterPrivate::updateState(QPainterState *newState)
\brief The QPainter class performs low-level painting on widgets and
other paint devices.
- \ingroup multimedia
- \mainclass
+ \ingroup painting
+
\reentrant
QPainter provides highly optimized functions to do most of the
@@ -1025,7 +1005,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
\o brushOrigin() defines the origin of the tiled brushes, normally
the origin of widget's background.
- \o viewport(), window(), worldMatrix() make up the painter's coordinate
+ \o viewport(), window(), worldTransform() make up the painter's coordinate
transformation system. For more information, see the \l
{Coordinate Transformations} section and the \l {The Coordinate
System} documentation.
@@ -1036,7 +1016,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
\o layoutDirection() defines the layout direction used by the
painter when drawing text.
- \o matrixEnabled() tells whether world transformation is enabled.
+ \o worldMatrixEnabled() tells whether world transformation is enabled.
\o viewTransformEnabled() tells whether view transformation is
enabled.
@@ -1232,15 +1212,15 @@ void QPainterPrivate::updateState(QPainterState *newState)
\endtable
All the tranformation operations operate on the transformation
- worldMatrix(). A matrix transforms a point in the plane to another
+ worldTransform(). A matrix transforms a point in the plane to another
point. For more information about the transformation matrix, see
- the \l {The Coordinate System} and QMatrix documentation.
+ the \l {The Coordinate System} and QTransform documentation.
- The setWorldMatrix() function can replace or add to the currently
- set worldMatrix(). The resetMatrix() function resets any
+ The setWorldTransform() function can replace or add to the currently
+ set worldTransform(). The resetTransform() function resets any
transformations that were made using translate(), scale(),
- shear(), rotate(), setWorldMatrix(), setViewport() and setWindow()
- functions. The deviceMatrix() returns the matrix that transforms
+ shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
+ functions. The deviceTransform() returns the matrix that transforms
from logical coordinates to device coordinates of the platform
dependent paint device. The latter function is only needed when
using platform painting commands on the platform dependent handle,
@@ -1249,11 +1229,11 @@ void QPainterPrivate::updateState(QPainterState *newState)
When drawing with QPainter, we specify points using logical
coordinates which then are converted into the physical coordinates
of the paint device. The mapping of the logical coordinates to the
- physical coordinates are handled by QPainter's combinedMatrix(), a
- combination of viewport() and window() and worldMatrix(). The
+ physical coordinates are handled by QPainter's combinedTransform(), a
+ combination of viewport() and window() and worldTransform(). The
viewport() represents the physical coordinates specifying an
arbitrary rectangle, the window() describes the same rectangle in
- logical coordinates, and the worldMatrix() is identical with the
+ logical coordinates, and the worldTransform() is identical with the
transformation matrix.
See also \l {The Coordinate System} documentation.
@@ -1374,8 +1354,8 @@ void QPainterPrivate::updateState(QPainterState *newState)
*/
QPainter::QPainter()
+ : d_ptr(new QPainterPrivate(this))
{
- d_ptr = new QPainterPrivate(this);
}
/*!
@@ -1407,7 +1387,7 @@ QPainter::QPainter(QPaintDevice *pd)
{
Q_ASSERT(pd != 0);
if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
- d_ptr = new QPainterPrivate(this);
+ d_ptr.reset(new QPainterPrivate(this));
begin(pd);
}
Q_ASSERT(d_ptr);
@@ -1419,11 +1399,14 @@ QPainter::QPainter(QPaintDevice *pd)
QPainter::~QPainter()
{
d_ptr->inDestructor = true;
- if (isActive())
- end();
- else if (d_ptr->refcount > 1)
- d_ptr->detachPainterPrivate(this);
-
+ QT_TRY {
+ if (isActive())
+ end();
+ else if (d_ptr->refcount > 1)
+ d_ptr->detachPainterPrivate(this);
+ } QT_CATCH(...) {
+ // don't throw anything in the destructor.
+ }
if (d_ptr) {
// Make sure we haven't messed things up.
Q_ASSERT(d_ptr->inDestructor);
@@ -1431,7 +1414,6 @@ QPainter::~QPainter()
Q_ASSERT(d_ptr->refcount == 1);
if (d_ptr->d_ptrs)
free(d_ptr->d_ptrs);
- delete d_ptr;
}
}
@@ -1572,10 +1554,8 @@ void QPainter::restore()
// replay the list of clip states,
for (int i=0; i<d->state->clipInfo.size(); ++i) {
const QPainterClipInfo &info = d->state->clipInfo.at(i);
- tmp->matrix.setMatrix(info.matrix.m11(), info.matrix.m12(), info.matrix.m13(),
- info.matrix.m21(), info.matrix.m22(), info.matrix.m23(),
- info.matrix.dx() - d->state->redirection_offset.x(),
- info.matrix.dy() - d->state->redirection_offset.y(), info.matrix.m33());
+ tmp->matrix = info.matrix;
+ tmp->matrix *= d->state->redirectionMatrix;
tmp->clipOperation = info.operation;
if (info.clipType == QPainterClipInfo::RectClip) {
tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
@@ -1689,12 +1669,12 @@ bool QPainter::begin(QPaintDevice *pd)
d->state->painter = this;
d->states.push_back(d->state);
- d->state->redirection_offset = redirectionOffset;
+ d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
d->state->brushOrigin = QPointF();
if (!d->engine) {
qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
- return true;
+ return false;
}
// Slip a painter state into the engine before we do any other operations
@@ -1723,7 +1703,8 @@ bool QPainter::begin(QPaintDevice *pd)
// Adjust offset for alien widgets painting outside the paint event.
if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
&& widget->testAttribute(Qt::WA_WState_Created)) {
- d->state->redirection_offset -= widget->mapTo(widget->nativeParentWidget(), QPoint());
+ const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
+ d->state->redirectionMatrix.translate(offset.x(), offset.y());
}
break;
}
@@ -1805,11 +1786,12 @@ bool QPainter::begin(QPaintDevice *pd)
d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
}
- d->state->redirection_offset += d->engine->coordinateOffset();
+ const QPoint coordinateOffset = d->engine->coordinateOffset();
+ d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
Q_ASSERT(d->engine->isActive());
- if (!d->state->redirection_offset.isNull())
+ if (!d->state->redirectionMatrix.isIdentity())
d->updateMatrix();
Q_ASSERT(d->engine->isActive());
@@ -1907,6 +1889,45 @@ QPaintEngine *QPainter::paintEngine() const
return d->engine;
}
+/*!
+ Flushes the painting pipeline and prepares for the user issuing
+ native painting commands. Must be followed by a call to
+ endNativePainting().
+
+ \sa endNativePainting()
+*/
+void QPainter::beginNativePainting()
+{
+ Q_D(QPainter);
+ if (!d->engine) {
+ qWarning("QPainter::beginNativePainting: Painter not active");
+ return;
+ }
+
+ if (d->extended)
+ d->extended->beginNativePainting();
+}
+
+/*!
+ Restores the painter after manually issuing native painting commands.
+ Lets the painter restore any native state that it relies on before
+ calling any other painter commands.
+
+ \sa beginNativePainting()
+*/
+void QPainter::endNativePainting()
+{
+ Q_D(const QPainter);
+ if (!d->engine) {
+ qWarning("QPainter::beginNativePainting: Painter not active");
+ return;
+ }
+
+ if (d->extended)
+ d->extended->endNativePainting();
+ else
+ d->engine->syncState();
+}
/*!
Returns the font metrics for the painter if the painter is
@@ -2581,7 +2602,9 @@ void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
d->state->clipEnabled = true;
d->extended->clip(vp, op);
- d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform());
+ if (op == Qt::ReplaceClip || op == Qt::NoClip)
+ d->state->clipInfo.clear();
+ d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
d->state->clipOperation = op;
return;
}
@@ -2627,7 +2650,9 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
if (d->extended) {
d->state->clipEnabled = true;
d->extended->clip(rect, op);
- d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform());
+ if (op == Qt::ReplaceClip || op == Qt::NoClip)
+ d->state->clipInfo.clear();
+ d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
d->state->clipOperation = op;
return;
}
@@ -2636,7 +2661,7 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
d->state->clipOperation = op;
if (op == Qt::NoClip || op == Qt::ReplaceClip)
d->state->clipInfo.clear();
- d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
d->state->clipEnabled = true;
d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
d->updateState(d->state);
@@ -2680,7 +2705,9 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
if (d->extended) {
d->state->clipEnabled = true;
d->extended->clip(r, op);
- d->state->clipInfo << QPainterClipInfo(r, op, combinedTransform());
+ if (op == Qt::NoClip || op == Qt::ReplaceClip)
+ d->state->clipInfo.clear();
+ d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
d->state->clipOperation = op;
return;
}
@@ -2689,7 +2716,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
d->state->clipOperation = op;
if (op == Qt::NoClip || op == Qt::ReplaceClip)
d->state->clipInfo.clear();
- d->state->clipInfo << QPainterClipInfo(r, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
d->state->clipEnabled = true;
d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
d->updateState(d->state);
@@ -2697,6 +2724,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
/*!
\since 4.2
+ \obsolete
Sets the transformation matrix to \a matrix and enables transformations.
@@ -2735,7 +2763,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
and window-viewport conversion, see \l {The Coordinate System}
documentation.
- \sa worldMatrixEnabled(), QMatrix
+ \sa setWorldTransform(), QTransform
*/
void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
@@ -2745,6 +2773,7 @@ void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
/*!
\since 4.2
+ \obsolete
Returns the world transformation matrix.
@@ -2794,6 +2823,7 @@ const QMatrix &QPainter::matrix() const
/*!
\since 4.2
+ \obsolete
Returns the transformation matrix combining the current
window/viewport and world transformation.
@@ -2801,7 +2831,7 @@ const QMatrix &QPainter::matrix() const
It is advisable to use combinedTransform() instead of this
function to preserve the properties of perspective transformations.
- \sa setWorldMatrix(), setWindow(), setViewport()
+ \sa setWorldTransform(), setWindow(), setViewport()
*/
QMatrix QPainter::combinedMatrix() const
{
@@ -2810,6 +2840,8 @@ QMatrix QPainter::combinedMatrix() const
/*!
+ \obsolete
+
Returns the matrix that transforms from logical coordinates to
device coordinates of the platform dependent paint device.
@@ -2837,6 +2869,8 @@ const QMatrix &QPainter::deviceMatrix() const
}
/*!
+ \obsolete
+
Resets any transformations that were made using translate(), scale(),
shear(), rotate(), setWorldMatrix(), setViewport() and
setWindow().
@@ -2861,7 +2895,7 @@ void QPainter::resetMatrix()
transformations if \a enable is false. The world transformation
matrix is not changed.
- \sa worldMatrixEnabled(), worldMatrix(), {QPainter#Coordinate
+ \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
Transformations}{Coordinate Transformations}
*/
@@ -2890,7 +2924,7 @@ void QPainter::setWorldMatrixEnabled(bool enable)
Returns true if world transformation is enabled; otherwise returns
false.
- \sa setWorldMatrixEnabled(), worldMatrix(), {The Coordinate System}
+ \sa setWorldMatrixEnabled(), worldTransform(), {The Coordinate System}
*/
bool QPainter::worldMatrixEnabled() const
@@ -2932,7 +2966,7 @@ bool QPainter::matrixEnabled() const
/*!
Scales the coordinate system by (\a{sx}, \a{sy}).
- \sa setWorldMatrix() {QPainter#Coordinate Transformations}{Coordinate
+ \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
Transformations}
*/
@@ -2956,7 +2990,7 @@ void QPainter::scale(qreal sx, qreal sy)
/*!
Shears the coordinate system by (\a{sh}, \a{sv}).
- \sa setWorldMatrix(), {QPainter#Coordinate Transformations}{Coordinate
+ \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
Transformations}
*/
@@ -2982,7 +3016,7 @@ void QPainter::shear(qreal sh, qreal sv)
Rotates the coordinate system the given \a angle clockwise.
- \sa setWorldMatrix(), {QPainter#Coordinate Transformations}{Coordinate
+ \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
Transformations}
*/
@@ -3007,7 +3041,7 @@ void QPainter::rotate(qreal a)
Translates the coordinate system by the given \a offset; i.e. the
given \a offset is added to points.
- \sa setWorldMatrix(), {QPainter#Coordinate Transformations}{Coordinate
+ \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
Transformations}
*/
void QPainter::translate(const QPointF &offset)
@@ -3077,7 +3111,9 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
if (d->extended) {
d->state->clipEnabled = true;
d->extended->clip(path, op);
- d->state->clipInfo << QPainterClipInfo(path, op, combinedTransform());
+ if (op == Qt::NoClip || op == Qt::ReplaceClip)
+ d->state->clipInfo.clear();
+ d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
d->state->clipOperation = op;
return;
}
@@ -3086,7 +3122,7 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
d->state->clipOperation = op;
if (op == Qt::NoClip || op == Qt::ReplaceClip)
d->state->clipInfo.clear();
- d->state->clipInfo << QPainterClipInfo(path, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
d->state->clipEnabled = true;
d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
d->updateState(d->state);
@@ -5699,7 +5735,6 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
engine.justify(line);
}
QFixed x = QFixed::fromReal(p.x());
- QFixed ox = x;
for (int i = 0; i < nItems; ++i) {
int item = visualOrder[i];
@@ -6083,22 +6118,22 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
const QTransform &m = d->state->matrix;
if (d->state->matrix.type() < QTransform::TxShear) {
bool isPlain90DegreeRotation =
- (qFuzzyCompare(m.m11() + 1, qreal(1))
- && qFuzzyCompare(m.m12(), qreal(1))
- && qFuzzyCompare(m.m21(), qreal(-1))
- && qFuzzyCompare(m.m22() + 1, qreal(1))
+ (qFuzzyIsNull(m.m11())
+ && qFuzzyIsNull(m.m12() - qreal(1))
+ && qFuzzyIsNull(m.m21() + qreal(1))
+ && qFuzzyIsNull(m.m22())
)
||
- (qFuzzyCompare(m.m11(), qreal(-1))
- && qFuzzyCompare(m.m12() + 1, qreal(1))
- && qFuzzyCompare(m.m21() + 1, qreal(1))
- && qFuzzyCompare(m.m22(), qreal(-1))
+ (qFuzzyIsNull(m.m11() + qreal(1))
+ && qFuzzyIsNull(m.m12())
+ && qFuzzyIsNull(m.m21())
+ && qFuzzyIsNull(m.m22() + qreal(1))
)
||
- (qFuzzyCompare(m.m11() + 1, qreal(1))
- && qFuzzyCompare(m.m12(), qreal(-1))
- && qFuzzyCompare(m.m21(), qreal(1))
- && qFuzzyCompare(m.m22() + 1, qreal(1))
+ (qFuzzyIsNull(m.m11())
+ && qFuzzyIsNull(m.m12() + qreal(1))
+ && qFuzzyIsNull(m.m21() - qreal(1))
+ && qFuzzyIsNull(m.m22())
)
;
aa = !isPlain90DegreeRotation;
@@ -6789,7 +6824,7 @@ QPainter::RenderHints QPainter::renderHints() const
Returns true if view transformation is enabled; otherwise returns
false.
- \sa setViewTransformEnabled(), worldMatrix()
+ \sa setViewTransformEnabled(), worldTransform()
*/
bool QPainter::viewTransformEnabled() const
@@ -6945,7 +6980,7 @@ QRect QPainter::viewport() const
/*! \fn void QPainter::resetXForm()
\compat
- Use resetMatrix() instead.
+ Use resetTransform() instead.
*/
/*! \fn void QPainter::setViewXForm(bool enabled)
@@ -6991,14 +7026,16 @@ void QPainter::setViewTransformEnabled(bool enable)
#ifdef QT3_SUPPORT
/*!
- Use the worldMatrix() combined with QMatrix::dx() instead.
+ \obsolete
+
+ Use the worldTransform() combined with QTransform::dx() instead.
\oldcode
QPainter painter(this);
qreal x = painter.translationX();
\newcode
QPainter painter(this);
- qreal x = painter.worldMatrix().dx();
+ qreal x = painter.worldTransform().dx();
\endcode
*/
qreal QPainter::translationX() const
@@ -7012,14 +7049,16 @@ qreal QPainter::translationX() const
}
/*!
- Use the worldMatrix() combined with QMatrix::dy() instead.
+ \obsolete
+
+ Use the worldTransform() combined with QTransform::dy() instead.
\oldcode
QPainter painter(this);
qreal y = painter.translationY();
\newcode
QPainter painter(this);
- qreal y = painter.worldMatrix().dy();
+ qreal y = painter.worldTransform().dy();
\endcode
*/
qreal QPainter::translationY() const
@@ -7117,7 +7156,7 @@ QPolygon QPainter::xForm(const QPolygon &a) const
QPolygon transformed = painter.xForm(polygon, index, count)
\newcode
QPainter painter(this);
- QPolygon transformed = polygon.mid(index, count) * painter.combinedMatrix();
+ QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform();
\endcode
*/
@@ -7132,15 +7171,16 @@ QPolygon QPainter::xForm(const QPolygon &av, int index, int npoints) const
/*!
\fn QPoint QPainter::xFormDev(const QPoint &point) const
\overload
+ \obsolete
- Use combinedTransform() combined with QMatrix::inverted() instead.
+ Use combinedTransform() combined with QTransform::inverted() instead.
\oldcode
QPainter painter(this);
QPoint transformed = painter.xFormDev(point);
\newcode
QPainter painter(this);
- QPoint transformed = point * painter.combinedMatrix().inverted();
+ QPoint transformed = point * painter.combinedTransform().inverted();
\endcode
*/
@@ -7159,15 +7199,17 @@ QPoint QPainter::xFormDev(const QPoint &p) const
/*!
\fn QRect QPainter::xFormDev(const QRect &rectangle) const
\overload
+ \obsolete
- Use mapRect() combined with QMatrix::inverted() instead.
+ Use combinedTransform() combined with QTransform::inverted() instead.
\oldcode
QPainter painter(this);
QRect transformed = painter.xFormDev(rectangle);
\newcode
QPainter painter(this);
- QRect transformed = painter.combinedMatrix().inverted(rectangle);
+ QRegion region = QRegion(rectangle) * painter.combinedTransform().inverted();
+ QRect transformed = region.boundingRect();
\endcode
*/
@@ -7187,16 +7229,16 @@ QRect QPainter::xFormDev(const QRect &r) const
\overload
\fn QPoint QPainter::xFormDev(const QPolygon &polygon) const
- \overload
+ \obsolete
- Use combinedMatrix() combined with QMatrix::inverted() instead.
+ Use combinedTransform() combined with QTransform::inverted() instead.
\oldcode
QPainter painter(this);
QPolygon transformed = painter.xFormDev(rectangle);
\newcode
QPainter painter(this);
- QPolygon transformed = polygon * painter.combinedMatrix().inverted();
+ QPolygon transformed = polygon * painter.combinedTransform().inverted();
\endcode
*/
@@ -7215,15 +7257,16 @@ QPolygon QPainter::xFormDev(const QPolygon &a) const
/*!
\fn QPolygon QPainter::xFormDev(const QPolygon &polygon, int index, int count) const
\overload
+ \obsolete
- Use combinedMatrix() combined with QPolygon::mid() and QMatrix::inverted() instead.
+ Use combinedTransform() combined with QPolygon::mid() and QTransform::inverted() instead.
\oldcode
QPainter painter(this);
QPolygon transformed = painter.xFormDev(polygon, index, count);
\newcode
QPainter painter(this);
- QPolygon transformed = polygon.mid(index, count) * painter.combinedMatrix().inverted();
+ QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform().inverted();
\endcode
*/
@@ -7418,8 +7461,21 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
void qt_painter_removePaintDevice(QPaintDevice *dev)
{
- QMutexLocker locker(globalRedirectionsMutex());
- if(QPaintDeviceRedirectionList *redirections = globalRedirections()) {
+ QMutex *mutex = 0;
+ QT_TRY {
+ mutex = globalRedirectionsMutex();
+ } QT_CATCH(...) {
+ // ignore the missing mutex, since we could be called from
+ // a destructor, and destructors shall not throw
+ }
+ QMutexLocker locker(mutex);
+ QPaintDeviceRedirectionList *redirections = 0;
+ QT_TRY {
+ redirections = globalRedirections();
+ } QT_CATCH(...) {
+ // do nothing - code below is safe with redirections being 0.
+ }
+ if (redirections) {
for (int i = 0; i < redirections->size(); ) {
if(redirections->at(i) == dev || redirections->at(i).replacement == dev)
redirections->removeAt(i);
@@ -7486,67 +7542,63 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
if (!painter)
tf |= Qt::TextDontPrint;
- int maxUnderlines = 0;
+ uint maxUnderlines = 0;
int numUnderlines = 0;
- int underlinePositionStack[32];
- int *underlinePositions = underlinePositionStack;
+ QVarLengthArray<int, 32> underlinePositions(1);
QFontMetricsF fm(fnt);
-
QString text = str;
+ int offset = 0;
+start_lengthVariant:
+ bool hasMoreLengthVariants = false;
// compatible behaviour to the old implementation. Replace
// tabs by spaces
- QChar *chr = text.data();
- const QChar *end = chr + str.length();
bool has_tab = false;
- while (chr != end) {
- if (*chr == QLatin1Char('\r') || (singleline && *chr == QLatin1Char('\n'))) {
- *chr = QLatin1Char(' ');
- } else if (*chr == QLatin1Char('\n')) {
- *chr = QChar::LineSeparator;
- } else if (*chr == QLatin1Char('&')) {
+ int old_offset = offset;
+ for (; offset < text.length(); offset++) {
+ QChar chr = text.at(offset);
+ if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
+ text[offset] = QLatin1Char(' ');
+ } else if (chr == QLatin1Char('\n')) {
+ chr = QChar::LineSeparator;
+ } else if (chr == QLatin1Char('&')) {
++maxUnderlines;
- } else if (*chr == QLatin1Char('\t')) {
- has_tab = true;
- }
- ++chr;
- }
- if (has_tab) {
- if (!expandtabs) {
- chr = text.data();
- while (chr != end) {
- if (*chr == QLatin1Char('\t'))
- *chr = QLatin1Char(' ');
- ++chr;
+ } else if (chr == QLatin1Char('\t')) {
+ if (!expandtabs) {
+ text[offset] = QLatin1Char(' ');
+ } else if (!tabarraylen && !tabstops) {
+ tabstops = qRound(fm.width(QLatin1Char('x'))*8);
}
- } else if (!tabarraylen && !tabstops) {
- tabstops = qRound(fm.width(QLatin1Char('x'))*8);
+ has_tab = true;
+ } else if (chr == QChar(ushort(0x9c))) {
+ // string with multiple length variants
+ hasMoreLengthVariants = true;
+ break;
}
}
- if (hidemnmemonic || showmnemonic) {
- if (maxUnderlines > 32)
- underlinePositions = new int[maxUnderlines];
- QChar *cout = text.data();
+ int length = offset - old_offset;
+ if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
+ underlinePositions.resize(maxUnderlines + 1);
+
+ QChar *cout = text.data() + old_offset;
QChar *cin = cout;
- int l = str.length();
+ int l = length;
while (l) {
if (*cin == QLatin1Char('&')) {
++cin;
+ --length;
--l;
if (!l)
break;
if (*cin != QLatin1Char('&') && !hidemnmemonic)
- underlinePositions[numUnderlines++] = cout - text.unicode();
+ underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
}
*cout = *cin;
++cout;
++cin;
--l;
}
- int newlen = cout - text.unicode();
- if (newlen != text.length())
- text.resize(newlen);
}
// no need to do extra work for underlines if we don't paint
@@ -7557,13 +7609,12 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
qreal height = 0;
qreal width = 0;
- QStackTextEngine engine(text, fnt);
+ QString finalText = text.mid(old_offset, length);
+ QStackTextEngine engine(finalText, fnt);
if (option) {
engine.option = *option;
}
-
-
engine.option.setTextDirection(layout_direction);
if (tf & Qt::AlignJustify)
engine.option.setAlignment(Qt::AlignJustify);
@@ -7577,9 +7628,9 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
engine.forceJustification = true;
QTextLayout textLayout(&engine);
textLayout.setCacheEnabled(true);
- textLayout.engine()->underlinePositions = underlinePositions;
+ textLayout.engine()->underlinePositions = underlinePositions.data();
- if (text.isEmpty()) {
+ if (finalText.isEmpty()) {
height = fm.height();
width = 0;
tf |= Qt::TextDontPrint;
@@ -7644,6 +7695,11 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
}
}
QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
+
+ if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
+ offset++;
+ goto start_lengthVariant;
+ }
if (brect)
*brect = bounds;
@@ -7670,9 +7726,6 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
painter->restore();
}
}
-
- if (underlinePositions != underlinePositionStack)
- delete [] underlinePositions;
}
/*!
@@ -7705,7 +7758,7 @@ QPainterState::QPainterState(const QPainterState *s)
clipRegion(s->clipRegion), clipPath(s->clipPath),
clipOperation(s->clipOperation),
renderHints(s->renderHints), clipInfo(s->clipInfo),
- worldMatrix(s->worldMatrix), matrix(s->matrix), redirection_offset(s->redirection_offset),
+ worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
@@ -8127,7 +8180,7 @@ void bitBlt(QPaintDevice *dst, int dx, int dy,
\row \o QPaintEngine::DirtyClipRegion \o clipRegion()
\row \o QPaintEngine::DirtyCompositionMode \o compositionMode()
\row \o QPaintEngine::DirtyFont \o font()
- \row \o QPaintEngine::DirtyTransform \o matrix()
+ \row \o QPaintEngine::DirtyTransform \o transform()
\row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled()
\row \o QPaintEngine::DirtyPen \o pen()
\row \o QPaintEngine::DirtyHints \o renderHints()
@@ -8246,10 +8299,14 @@ QFont QPaintEngineState::font() const
/*!
\since 4.2
+ \obsolete
Returns the matrix in the current paint engine
state.
+ \note It is advisable to use transform() instead of this function to
+ preserve the properties of perspective transformations.
+
This variable should only be used when the state() returns a
combination which includes the QPaintEngine::DirtyTransform flag.
@@ -8430,11 +8487,7 @@ qreal QPaintEngineState::opacity() const
If \a combine is true, the specified \a transform is combined with
the current matrix; otherwise it replaces the current matrix.
- This function has been added for compatibility with setMatrix(),
- but as with setMatrix() the preferred method of setting a
- transformation on the painter is through setWorldTransform().
-
- \sa transform()
+ \sa transform() setWorldTransform()
*/
void QPainter::setTransform(const QTransform &transform, bool combine )
@@ -8444,6 +8497,8 @@ void QPainter::setTransform(const QTransform &transform, bool combine )
/*!
Returns the world transformation matrix.
+
+ \sa worldTransform()
*/
const QTransform & QPainter::transform() const
@@ -8554,7 +8609,7 @@ const QTransform & QPainter::worldTransform() const
Returns the transformation matrix combining the current
window/viewport and world transformation.
- \sa setWorldMatrix(), setWindow(), setViewport()
+ \sa setWorldTransform(), setWindow(), setViewport()
*/
QTransform QPainter::combinedTransform() const
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 1ce7f24..0dd7b7b 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -45,6 +45,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qrect.h>
#include <QtCore/qpoint.h>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qimage.h>
#include <QtGui/qtextoption.h>
@@ -78,6 +79,8 @@ class QTextItem;
class QMatrix;
class QTransform;
+class QPainterPrivateDeleter;
+
class Q_GUI_EXPORT QPainter
{
Q_DECLARE_PRIVATE(QPainter)
@@ -420,6 +423,9 @@ public:
static QPaintDevice *redirected(const QPaintDevice *device, QPoint *offset = 0);
static void restoreRedirected(const QPaintDevice *device);
+ void beginNativePainting();
+ void endNativePainting();
+
#ifdef QT3_SUPPORT
inline QT3_SUPPORT void setBackgroundColor(const QColor &color) { setBackground(color); }
@@ -497,7 +503,7 @@ private:
Q_DISABLE_COPY(QPainter)
friend class Q3Painter;
- QPainterPrivate *d_ptr;
+ QScopedPointer<QPainterPrivate> d_ptr;
friend class QFontEngine;
friend class QFontEngineBox;
@@ -507,6 +513,7 @@ private:
friend class QFontEngineXLFD;
friend class QWSManager;
friend class QPaintEngine;
+ friend class QPaintEngineExPrivate;
friend class QOpenGLPaintEngine;
friend class QX11PaintEngine;
friend class QX11PaintEnginePrivate;
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index d3dd1b4..8843737 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -63,7 +63,7 @@
#include "QtGui/qpaintengine.h"
#include <QtCore/qhash.h>
-#include "qpen_p.h"
+#include <private/qpen_p.h>
QT_BEGIN_NAMESPACE
@@ -92,8 +92,8 @@ inline Qt::PenJoinStyle qpen_joinStyle(const QPen &p) { return data_ptr(p)->join
// QBrush inline functions...
inline QBrush::DataPtr &data_ptr(const QBrush &p) { return const_cast<QBrush &>(p).data_ptr(); }
inline bool qbrush_fast_equals(const QBrush &a, const QBrush &b) { return data_ptr(a) == data_ptr(b); }
-inline Qt::BrushStyle qbrush_style(const QBrush &b) { return data_ptr(b)->style; };
-inline const QColor &qbrush_color(const QBrush &b) { return data_ptr(b)->color; };
+inline Qt::BrushStyle qbrush_style(const QBrush &b) { return data_ptr(b)->style; }
+inline const QColor &qbrush_color(const QBrush &b) { return data_ptr(b)->color; }
inline bool qbrush_has_transform(const QBrush &b) { return data_ptr(b)->transform.type() > QTransform::TxNone; }
class QPainterClipInfo
@@ -158,7 +158,7 @@ public:
QList<QPainterClipInfo> clipInfo; // ### Make me smaller and faster to copy around...
QTransform worldMatrix; // World transformation matrix, not window and viewport
QTransform matrix; // Complete transformation matrix,
- QPoint redirection_offset;
+ QTransform redirectionMatrix;
int wx, wy, ww, wh; // window rectangle
int vx, vy, vw, vh; // viewport rectangle
qreal opacity;
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index ff133b6..8d3cfab 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -73,6 +73,17 @@
QT_BEGIN_NAMESPACE
+struct QPainterPathPrivateDeleter
+{
+ static inline void cleanup(QPainterPathPrivate *d)
+ {
+ // note - we must up-cast to QPainterPathData since QPainterPathPrivate
+ // has a non-virtual destructor!
+ if (d && !d->ref.deref())
+ delete static_cast<QPainterPathData *>(d);
+ }
+};
+
// This value is used to determine the length of control point vectors
// when approximating arc segments as curves. The factor is multiplied
// with the radius of the circle.
@@ -153,7 +164,7 @@ static void qt_debug_path(const QPainterPath &path)
/*!
\class QPainterPath
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
\brief The QPainterPath class provides a container for painting operations,
@@ -506,10 +517,10 @@ QPainterPath::QPainterPath()
\sa operator=()
*/
QPainterPath::QPainterPath(const QPainterPath &other)
- : d_ptr(other.d_ptr)
+ : d_ptr(other.d_ptr.data())
{
- if (d_func())
- d_func()->ref.ref();
+ if (d_ptr)
+ d_ptr->ref.ref();
}
/*!
@@ -530,9 +541,7 @@ QPainterPath::QPainterPath(const QPointF &startPoint)
void QPainterPath::detach_helper()
{
QPainterPathPrivate *data = new QPainterPathData(*d_func());
- if (d_ptr && !d_ptr->ref.deref())
- delete d_ptr;
- d_ptr = data;
+ d_ptr.reset(data);
}
/*!
@@ -544,9 +553,7 @@ void QPainterPath::ensureData_helper()
data->elements.reserve(16);
QPainterPath::Element e = { 0, 0, QPainterPath::MoveToElement };
data->elements << e;
- if (d_ptr && !d_ptr->ref.deref())
- delete d_ptr;
- d_ptr = data;
+ d_ptr.reset(data);
Q_ASSERT(d_ptr != 0);
}
@@ -563,9 +570,7 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other)
QPainterPathPrivate *data = other.d_func();
if (data)
data->ref.ref();
- if (d_ptr && !d_ptr->ref.deref())
- delete d_ptr;
- d_ptr = data;
+ d_ptr.reset(data);
}
return *this;
}
@@ -575,8 +580,6 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other)
*/
QPainterPath::~QPainterPath()
{
- if (d_func() && !d_func()->ref.deref())
- delete d_func();
}
/*!
@@ -1299,10 +1302,10 @@ static QRectF qt_painterpath_bezier_extrema(const QBezier &b)
qreal bx = QT_BEZIER_B(b, x);
qreal cx = QT_BEZIER_C(b, x);
// specialcase quadratic curves to avoid div by zero
- if (qFuzzyCompare(ax + 1, 1)) {
+ if (qFuzzyIsNull(ax)) {
// linear curves are covered by initialization.
- if (!qFuzzyCompare(bx + 1, 1)) {
+ if (!qFuzzyIsNull(bx)) {
qreal t = -cx / bx;
QT_BEZIER_CHECK_T(b, t);
}
@@ -1329,10 +1332,10 @@ static QRectF qt_painterpath_bezier_extrema(const QBezier &b)
qreal cy = QT_BEZIER_C(b, y);
// specialcase quadratic curves to avoid div by zero
- if (qFuzzyCompare(ay + 1, 1)) {
+ if (qFuzzyIsNull(ay)) {
// linear curves are covered by initialization.
- if (!qFuzzyCompare(by + 1, 1)) {
+ if (!qFuzzyIsNull(by)) {
qreal t = -cy / by;
QT_BEZIER_CHECK_T(b, t);
}
@@ -1517,12 +1520,6 @@ QList<QPolygonF> QPainterPath::toSubpathPolygons(const QMatrix &matrix) const
return toSubpathPolygons(QTransform(matrix));
}
-static inline bool rect_intersects(const QRectF &r1, const QRectF &r2)
-{
- return qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right())
- && qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom());
-}
-
/*!
Converts the path into a list of polygons using the
QTransform \a matrix, and returns the list.
@@ -1575,7 +1572,7 @@ QList<QPolygonF> QPainterPath::toFillPolygons(const QTransform &matrix) const
continue;
QRectF cbounds = bounds.at(j);
for (int i=0; i<count; ++i) {
- if (rect_intersects(cbounds, bounds.at(i))) {
+ if (cbounds.intersects(bounds.at(i))) {
isects[j] << i;
}
}
@@ -2000,7 +1997,63 @@ bool QPainterPath::intersects(const QRectF &rect) const
return false;
}
+/*!
+ Translates all elements in the path by (\a{dx}, \a{dy}).
+
+ \since 4.6
+ \sa translated()
+*/
+void QPainterPath::translate(qreal dx, qreal dy)
+{
+ if (!d_ptr || (dx == 0 && dy == 0))
+ return;
+
+ int elementsLeft = d_ptr->elements.size();
+ if (elementsLeft <= 0)
+ return;
+
+ detach();
+ QPainterPath::Element *element = d_func()->elements.data();
+ Q_ASSERT(element);
+ while (elementsLeft--) {
+ element->x += dx;
+ element->y += dy;
+ ++element;
+ }
+}
+
+/*!
+ \fn void QPainterPath::translate(const QPointF &offset)
+ \overload
+ \since 4.6
+
+ Translates all elements in the path by the given \a offset.
+
+ \sa translated()
+*/
+
+/*!
+ Returns a copy of the path that is translated by (\a{dx}, \a{dy}).
+
+ \since 4.6
+ \sa translate()
+*/
+QPainterPath QPainterPath::translated(qreal dx, qreal dy) const
+{
+ QPainterPath copy(*this);
+ copy.translate(dx, dy);
+ return copy;
+}
+
+/*!
+ \fn QPainterPath QPainterPath::translated(const QPointF &offset) const;
+ \overload
+ \since 4.6
+
+ Returns a copy of the path that is translated by the given \a offset.
+ \sa translate()
+*/
/*!
\fn bool QPainterPath::contains(const QRectF &rectangle) const
@@ -2310,7 +2363,7 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
p.d_func()->dirtyControlBounds = true;
return s;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*******************************************************************************
@@ -2340,7 +2393,7 @@ void qt_path_stroke_cubic_to(qfixed c1x, qfixed c1y,
/*!
\since 4.1
\class QPainterPathStroker
- \ingroup multimedia
+ \ingroup painting
\brief The QPainterPathStroker class is used to generate fillable
outlines for a given painter path.
@@ -2408,7 +2461,6 @@ QPainterPathStroker::QPainterPathStroker()
*/
QPainterPathStroker::~QPainterPathStroker()
{
- delete d_ptr;
}
@@ -2867,7 +2919,7 @@ qreal QPainterPath::angleAtPercent(qreal t) const
return QLineF(0, 0, m1, m2).angle();
}
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#pragma warning( disable : 4056 4756 )
#endif
@@ -3100,7 +3152,7 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd)
Set operations on paths will treat the paths as areas. Non-closed
paths will be treated as implicitly closed.
- \sa intersected(), subtracted(), subtractedInverted()
+ \sa intersected(), subtracted()
*/
QPainterPath QPainterPath::united(const QPainterPath &p) const
{
@@ -3215,6 +3267,8 @@ void QPainterPath::setDirty(bool dirty)
{
d_func()->dirtyBounds = dirty;
d_func()->dirtyControlBounds = dirty;
+ delete d_func()->pathConverter;
+ d_func()->pathConverter = 0;
}
void QPainterPath::computeBoundingRect() const
@@ -3292,7 +3346,7 @@ QDebug operator<<(QDebug s, const QPainterPath &p)
s.nospace() << "QPainterPath: Element count=" << p.elementCount() << endl;
const char *types[] = {"MoveTo", "LineTo", "CurveTo", "CurveToData"};
for (int i=0; i<p.elementCount(); ++i) {
- s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ")" << endl;
+ s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << endl;
}
return s;
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index 03e01eb..9d472e8 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -47,6 +47,7 @@
#include <QtCore/qrect.h>
#include <QtCore/qline.h>
#include <QtCore/qvector.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -56,6 +57,7 @@ QT_MODULE(Gui)
class QFont;
class QPainterPathPrivate;
+struct QPainterPathPrivateDeleter;
class QPainterPathData;
class QPainterPathStrokerPrivate;
class QPolygonF;
@@ -147,6 +149,12 @@ public:
bool contains(const QRectF &rect) const;
bool intersects(const QRectF &rect) const;
+ void translate(qreal dx, qreal dy);
+ inline void translate(const QPointF &offset);
+
+ QPainterPath translated(qreal dx, qreal dy) const;
+ inline QPainterPath translated(const QPointF &offset) const;
+
QRectF boundingRect() const;
QRectF controlPointRect() const;
@@ -195,7 +203,7 @@ public:
QPainterPath &operator-=(const QPainterPath &other);
private:
- QPainterPathPrivate *d_ptr;
+ QScopedPointer<QPainterPathPrivate, QPainterPathPrivateDeleter> d_ptr;
inline void ensureData() { if (!d_ptr) ensureData_helper(); }
void ensureData_helper();
@@ -205,7 +213,7 @@ private:
void computeBoundingRect() const;
void computeControlPointRect() const;
- QPainterPathData *d_func() const { return reinterpret_cast<QPainterPathData *>(d_ptr); }
+ QPainterPathData *d_func() const { return reinterpret_cast<QPainterPathData *>(d_ptr.data()); }
friend class QPainterPathData;
friend class QPainterPathStroker;
@@ -229,6 +237,7 @@ public:
friend class QPainterPathStrokerPrivate;
friend class QMatrix;
friend class QTransform;
+ friend struct QPainterPathPrivateDeleter;
#ifndef QT_NO_DATASTREAM
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPainterPath &);
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPainterPath &);
@@ -279,7 +288,7 @@ public:
private:
friend class QX11PaintEngine;
- QPainterPathStrokerPrivate *d_ptr;
+ QScopedPointer<QPainterPathStrokerPrivate> d_ptr;
};
inline void QPainterPath::moveTo(qreal x, qreal y)
@@ -292,9 +301,9 @@ inline void QPainterPath::lineTo(qreal x, qreal y)
lineTo(QPointF(x, y));
}
-inline void QPainterPath::arcTo(qreal x, qreal y, qreal w, qreal h, qreal startAngle, qreal arcLenght)
+inline void QPainterPath::arcTo(qreal x, qreal y, qreal w, qreal h, qreal startAngle, qreal arcLength)
{
- arcTo(QRectF(x, y, w, h), startAngle, arcLenght);
+ arcTo(QRectF(x, y, w, h), startAngle, arcLength);
}
inline void QPainterPath::arcMoveTo(qreal x, qreal y, qreal w, qreal h, qreal angle)
@@ -365,6 +374,12 @@ inline void QPainterPath::addText(qreal x, qreal y, const QFont &f, const QStrin
addText(QPointF(x, y), f, text);
}
+inline void QPainterPath::translate(const QPointF &offset)
+{ translate(offset.x(), offset.y()); }
+
+inline QPainterPath QPainterPath::translated(const QPointF &offset) const
+{ return translated(offset.x(), offset.y()); }
+
inline bool QPainterPath::isEmpty() const
{
return !d_ptr || (d_ptr->elements.size() == 1 && d_ptr->elements.first().type == MoveToElement);
diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h
index ac42904..bb455cf 100644
--- a/src/gui/painting/qpainterpath_p.h
+++ b/src/gui/painting/qpainterpath_p.h
@@ -124,7 +124,7 @@ private:
Q_DISABLE_COPY(QVectorPathConverter)
};
-class Q_GUI_EXPORT QPainterPathData : public QPainterPathPrivate
+class QPainterPathData : public QPainterPathPrivate
{
public:
QPainterPathData() :
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index 3e5a8f1..2befd86 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -151,11 +151,11 @@ bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const
const qreal par = pDelta.x() * qDelta.y() - pDelta.y() * qDelta.x();
- if (qFuzzyCompare(par + 1, 1)) {
+ if (qFuzzyIsNull(par)) {
const QPointF normal(-pDelta.y(), pDelta.x());
// coinciding?
- if (qFuzzyCompare(dot(normal, q1 - p1) + 1, 1)) {
+ if (qFuzzyIsNull(dot(normal, q1 - p1))) {
const qreal dp = dot(pDelta, pDelta);
const qreal tq1 = dot(pDelta, q1 - p1);
@@ -217,13 +217,13 @@ void QIntersectionFinder::intersectBeziers(const QBezier &one, const QBezier &tw
qreal alpha_q = t.at(i).second;
QPointF pt;
- if (qFuzzyCompare(alpha_p + 1, 1)) {
+ if (qFuzzyIsNull(alpha_p)) {
pt = one.pt1();
- } else if (qFuzzyCompare(alpha_p, 1)) {
+ } else if (qFuzzyIsNull(alpha_p - 1)) {
pt = one.pt4();
- } else if (qFuzzyCompare(alpha_q + 1, 1)) {
+ } else if (qFuzzyIsNull(alpha_q)) {
pt = two.pt1();
- } else if (qFuzzyCompare(alpha_q, 1)) {
+ } else if (qFuzzyIsNull(alpha_q - 1)) {
pt = two.pt4();
} else {
pt = one.pointAt(alpha_p);
@@ -265,11 +265,11 @@ void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QData
const qreal par = pDelta.x() * qDelta.y() - pDelta.y() * qDelta.x();
- if (qFuzzyCompare(par + 1, 1)) {
+ if (qFuzzyIsNull(par)) {
const QPointF normal(-pDelta.y(), pDelta.x());
// coinciding?
- if (qFuzzyCompare(dot(normal, q1 - p1) + 1, 1)) {
+ if (qFuzzyIsNull(dot(normal, q1 - p1))) {
const qreal invDp = 1 / dot(pDelta, pDelta);
const qreal tq1 = dot(pDelta, q1 - p1) * invDp;
@@ -330,11 +330,11 @@ void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QData
if (tp<0 || tp>1 || tq<0 || tq>1)
return;
- const bool p_zero = qFuzzyCompare(tp + 1, 1);
- const bool p_one = qFuzzyCompare(tp, 1);
+ const bool p_zero = qFuzzyIsNull(tp);
+ const bool p_one = qFuzzyIsNull(tp - 1);
- const bool q_zero = qFuzzyCompare(tq + 1, 1);
- const bool q_one = qFuzzyCompare(tq, 1);
+ const bool q_zero = qFuzzyIsNull(tq);
+ const bool q_one = qFuzzyIsNull(tq - 1);
if ((q_zero || q_one) && (p_zero || p_one))
return;
@@ -937,7 +937,7 @@ qreal QWingedEdge::delta(int vertex, int a, int b) const
qreal result = b_angle - a_angle;
- if (qFuzzyCompare(result + 1, 1) || qFuzzyCompare(result, 128))
+ if (qFuzzyIsNull(result) || qFuzzyCompare(result, 128))
return 0;
if (result < 0)
@@ -966,7 +966,7 @@ static inline QPointF tangentAt(const QWingedEdge &list, int vi, int ei)
if (ep->bezier) {
normal = ep->bezier->derivedAt(t);
- if (qFuzzyCompare(normal.x() + 1, 1) && qFuzzyCompare(normal.y() + 1, 1))
+ if (qFuzzyIsNull(normal.x()) && qFuzzyIsNull(normal.y()))
normal = ep->bezier->secondDerivedAt(t);
} else {
const QPointF a = *list.vertex(ep->first);
@@ -1095,7 +1095,7 @@ QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus(int vi, int ei) const
qDebug() << "Delta to edge" << status.edge << d2 << ", angles: " << op->angle << op->invAngle;
#endif
- if (!(qFuzzyCompare(d2 + 1, 1) && isLeftOf(*this, vi, status.edge, ei))
+ if (!(qFuzzyIsNull(d2) && isLeftOf(*this, vi, status.edge, ei))
&& (d2 < d || (qFuzzyCompare(d2, d) && isLeftOf(*this, vi, status.edge, position)))) {
position = status.edge;
d = d2;
@@ -1247,10 +1247,10 @@ int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal
QPointF aTangent = bezier->derivedAt(t0);
QPointF bTangent = -bezier->derivedAt(t1);
- if (qFuzzyCompare(aTangent.x() + 1, 1) && qFuzzyCompare(aTangent.y() + 1, 1))
+ if (qFuzzyIsNull(aTangent.x()) && qFuzzyIsNull(aTangent.y()))
aTangent = bezier->secondDerivedAt(t0);
- if (qFuzzyCompare(bTangent.x() + 1, 1) && qFuzzyCompare(bTangent.y() + 1, 1))
+ if (qFuzzyIsNull(bTangent.x()) && qFuzzyIsNull(bTangent.y()))
bTangent = bezier->secondDerivedAt(t1);
ep->angle = computeAngle(aTangent);
@@ -1415,7 +1415,7 @@ static void addLineTo(QPainterPath &path, const QPointF &point)
const QPointF p(-d1.y(), d1.x());
- if (qFuzzyCompare(dot(p, d2) + 1, 1)) {
+ if (qFuzzyIsNull(dot(p, d2))) {
path.setElementPositionAt(elementCount - 1, point.x(), point.y());
return;
}
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index 641ecdd..e9569bb 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -160,8 +160,6 @@ public:
Direction directionTo(int vertex) const;
int vertex(Direction direction) const;
- bool isBezier() const;
-
private:
int m_next[2][2];
};
@@ -347,11 +345,6 @@ inline int QPathEdge::vertex(Direction direction) const
return direction == Backward ? first : second;
}
-inline bool QPathEdge::isBezier() const
-{
- return bezier >= 0;
-}
-
inline QPathVertex::QPathVertex(const QPointF &p, int e)
: edge(e)
, x(p.x())
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 21d44ef..e60f50f 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -48,6 +48,10 @@
#include "qprinterinfo.h"
#include <qnumeric.h>
+#ifdef Q_OS_UNIX
+#include "private/qcore_unix_p.h" // overrides QT_OPEN
+#endif
+
QT_BEGIN_NAMESPACE
extern int qt_defaultDpi();
@@ -309,7 +313,7 @@ QByteArray QPdf::generatePath(const QPainterPath &path, const QTransform &matrix
Qt::FillRule fillRule = path.fillRule();
- const char *op = 0;
+ const char *op = "";
switch (flags) {
case ClipPath:
op = (fillRule == Qt::WindingFill) ? "W n\n" : "W* n\n";
@@ -346,7 +350,7 @@ QByteArray QPdf::generateDashes(const QPen &pen)
{
QByteArray result;
ByteStream s(&result);
- s << "[";
+ s << '[';
QVector<qreal> dasharray = pen.dashPattern();
qreal w = pen.widthF();
@@ -357,7 +361,7 @@ QByteArray QPdf::generateDashes(const QPen &pen)
if (dw < 0.0001) dw = 0.0001;
s << dw;
}
- s << "]";
+ s << ']';
//qDebug() << "dasharray: pen has" << dasharray;
//qDebug() << " => " << result;
return result;
@@ -915,17 +919,17 @@ const char *QPdf::paperSizeToString(QPrinter::PaperSize paperSize)
QByteArray QPdf::stripSpecialCharacters(const QByteArray &string)
{
QByteArray s = string;
- s.replace(" ", "");
- s.replace("(", "");
- s.replace(")", "");
- s.replace("<", "");
- s.replace(">", "");
- s.replace("[", "");
- s.replace("]", "");
- s.replace("{", "");
- s.replace("}", "");
- s.replace("/", "");
- s.replace("%", "");
+ s.replace(' ', "");
+ s.replace('(', "");
+ s.replace(')', "");
+ s.replace('<', "");
+ s.replace('>', "");
+ s.replace('[', "");
+ s.replace(']', "");
+ s.replace('{', "");
+ s.replace('}', "");
+ s.replace('/', "");
+ s.replace('%', "");
return s;
}
@@ -1467,10 +1471,10 @@ void QPdfBaseEngine::setProperty(PrintEnginePropertyKey key, const QVariant &val
{
QList<QVariant> margins(value.toList());
Q_ASSERT(margins.size() == 4);
- d->leftMargin = margins.at(0).toDouble();
- d->topMargin = margins.at(1).toDouble();
- d->rightMargin = margins.at(2).toDouble();
- d->bottomMargin = margins.at(3).toDouble();
+ d->leftMargin = margins.at(0).toReal();
+ d->topMargin = margins.at(1).toReal();
+ d->rightMargin = margins.at(2).toReal();
+ d->bottomMargin = margins.at(3).toReal();
d->hasCustomPageMargins = true;
break;
}
@@ -1572,7 +1576,7 @@ QVariant QPdfBaseEngine::property(PrintEnginePropertyKey key) const
margins << d->leftMargin << d->topMargin
<< d->rightMargin << d->bottomMargin;
} else {
- const int defaultMargin = 10; // ~3.5 mm
+ const qreal defaultMargin = 10; // ~3.5 mm
margins << defaultMargin << defaultMargin
<< defaultMargin << defaultMargin;
}
@@ -1652,7 +1656,7 @@ static void closeAllOpenFds()
#endif
// leave stdin/out/err untouched
while(--i > 2)
- ::close(i);
+ QT_CLOSE(i);
}
#endif
@@ -1686,7 +1690,7 @@ bool QPdfBaseEnginePrivate::openPrintDevice()
if (!printerName.isEmpty())
pr = printerName;
int fds[2];
- if (pipe(fds) != 0) {
+ if (qt_safe_pipe(fds) != 0) {
qWarning("QPdfPrinter: Could not open pipe to print");
return false;
}
@@ -1705,9 +1709,9 @@ bool QPdfBaseEnginePrivate::openPrintDevice()
(void)execlp("true", "true", (char *)0);
(void)execl("/bin/true", "true", (char *)0);
(void)execl("/usr/bin/true", "true", (char *)0);
- ::exit(0);
+ ::_exit(0);
}
- dup2(fds[0], 0);
+ qt_safe_dup2(fds[0], 0, 0);
closeAllOpenFds();
@@ -1769,19 +1773,22 @@ bool QPdfBaseEnginePrivate::openPrintDevice()
(void)execv("/bin/lpr", lprargs);
(void)execv("/usr/bin/lp", lpargs);
(void)execv("/usr/bin/lpr", lprargs);
+
+ delete []lpargs;
+ delete []lprargs;
}
// if we couldn't exec anything, close the fd,
// wait for a second so the parent process (the
// child of the GUI process) has exited. then
// exit.
- ::close(0);
+ QT_CLOSE(0);
(void)::sleep(1);
- ::exit(0);
+ ::_exit(0);
}
// parent process
- ::close(fds[0]);
+ QT_CLOSE(fds[0]);
fd = fds[1];
- (void)::waitpid(pid, 0, 0);
+ (void)qt_safe_waitpid(pid, 0, 0);
if (fd < 0)
return false;
@@ -1928,14 +1935,13 @@ void QPdfBaseEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &t
#ifdef Q_WS_WIN
if (ti.fontEngine->type() == QFontEngine::Win) {
QFontEngineWin *fe = static_cast<QFontEngineWin *>(ti.fontEngine);
- size = fe->tm.w.tmHeight;
+ size = fe->tm.tmHeight;
}
#endif
QVarLengthArray<glyph_t> glyphs;
QVarLengthArray<QFixedPoint> positions;
- QTransform m;
- m.translate(p.x(), p.y());
+ QTransform m = QTransform::fromTranslate(p.x(), p.y());
ti.fontEngine->getGlyphPositions(ti.glyphs, m, ti.flags,
glyphs, positions);
if (glyphs.size() == 0)
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index 1f0ef14..2da8d8a 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -158,7 +158,7 @@ namespace QPdf {
QByteArray stripSpecialCharacters(const QByteArray &string);
-};
+}
class QPdfPage : public QPdf::ByteStream
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index d7b2341..24606a9 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -52,9 +52,9 @@ typedef QPenPrivate QPenData;
/*!
\class QPen
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
- \mainclass
+
\brief The QPen class defines how a QPainter should draw lines and outlines
of shapes.
@@ -978,7 +978,7 @@ QDebug operator<<(QDebug dbg, const QPen &p)
dbg.nospace() << "QPen(" << p.width() << ',' << p.brush()
<< ',' << int(p.style()) << ',' << int(p.capStyle())
<< ',' << int(p.joinStyle()) << ',' << p.dashPattern()
- << "," << p.dashOffset()
+ << ',' << p.dashOffset()
<< ',' << p.miterLimit() << ')';
return dbg.space();
#else
diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp
index 663dd09..d23af90 100644
--- a/src/gui/painting/qpolygon.cpp
+++ b/src/gui/painting/qpolygon.cpp
@@ -91,7 +91,7 @@ static void qt_polygon_isect_line(const QPointF &p1, const QPointF &p2, const QP
\reentrant
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
A QPolygon object is a QVector<QPoint>. The easiest way to add
@@ -208,10 +208,15 @@ QPolygon::QPolygon(int nPoints, const int *points)
/*!
Translates all points in the polygon by (\a{dx}, \a{dy}).
+
+ \sa translated()
*/
void QPolygon::translate(int dx, int dy)
{
+ if (dx == 0 && dy == 0)
+ return;
+
register QPoint *p = data();
register int i = size();
QPoint pt(dx, dy);
@@ -226,8 +231,32 @@ void QPolygon::translate(int dx, int dy)
\overload
Translates all points in the polygon by the given \a offset.
+
+ \sa translated()
+*/
+
+/*!
+ Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}).
+
+ \since 4.6
+ \sa translate()
*/
+QPolygon QPolygon::translated(int dx, int dy) const
+{
+ QPolygon copy(*this);
+ copy.translate(dx, dy);
+ return copy;
+}
+
+/*!
+ \fn void QPolygon::translated(const QPoint &offset) const
+ \overload
+ \since 4.6
+
+ Returns a copy of the polygon that is translated by the given \a offset.
+ \sa translate()
+*/
/*!
Extracts the coordinates of the point at the given \a index to
@@ -460,7 +489,7 @@ QDebug operator<<(QDebug dbg, const QPolygon &a)
floating point precision.
\reentrant
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
A QPolygonF is a QVector<QPointF>. The easiest way to add points
@@ -565,10 +594,15 @@ QPolygonF::QPolygonF(const QPolygon &a)
/*!
Translate all points in the polygon by the given \a offset.
+
+ \sa translated()
*/
void QPolygonF::translate(const QPointF &offset)
{
+ if (offset.isNull())
+ return;
+
register QPointF *p = data();
register int i = size();
while (i--) {
@@ -582,6 +616,31 @@ void QPolygonF::translate(const QPointF &offset)
\overload
Translates all points in the polygon by (\a{dx}, \a{dy}).
+
+ \sa translated()
+*/
+
+/*!
+ Returns a copy of the polygon that is translated by the given \a offset.
+
+ \since 4.6
+ \sa translate()
+*/
+QPolygonF QPolygonF::translated(const QPointF &offset) const
+{
+ QPolygonF copy(*this);
+ copy.translate(offset);
+ return copy;
+}
+
+/*!
+ \fn void QPolygonF::translated(qreal dx, qreal dy) const
+ \overload
+ \since 4.6
+
+ Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}).
+
+ \sa translate()
*/
/*!
@@ -683,7 +742,7 @@ QDataStream &operator>>(QDataStream &s, QPolygon &a)
QVector<QPoint> &v = a;
return s >> v;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*****************************************************************************
QPolygonF stream functions
diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h
index 3803432..22d063c 100644
--- a/src/gui/painting/qpolygon.h
+++ b/src/gui/painting/qpolygon.h
@@ -71,6 +71,10 @@ public:
void translate(int dx, int dy);
void translate(const QPoint &offset);
+
+ QPolygon translated(int dx, int dy) const;
+ inline QPolygon translated(const QPoint &offset) const;
+
QRect boundingRect() const;
void point(int i, int *x, int *y) const;
@@ -120,6 +124,9 @@ inline QPoint QPolygon::point(int index) const
inline void QPolygon::translate(const QPoint &offset)
{ translate(offset.x(), offset.y()); }
+inline QPolygon QPolygon::translated(const QPoint &offset) const
+{ return translated(offset.x(), offset.y()); }
+
class QRectF;
class Q_GUI_EXPORT QPolygonF : public QVector<QPointF>
@@ -136,6 +143,9 @@ public:
inline void translate(qreal dx, qreal dy);
void translate(const QPointF &offset);
+ inline QPolygonF translated(qreal dx, qreal dy) const;
+ QPolygonF translated(const QPointF &offset) const;
+
QPolygon toPolygon() const;
bool isClosed() const { return !isEmpty() && first() == last(); }
@@ -166,6 +176,9 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QPolygonF &array);
inline void QPolygonF::translate(qreal dx, qreal dy)
{ translate(QPointF(dx, dy)); }
+inline QPolygonF QPolygonF::translated(qreal dx, qreal dy) const
+{ return translated(QPointF(dx, dy)); }
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/painting/qprintengine_mac.mm b/src/gui/painting/qprintengine_mac.mm
index 456ed1e..5a15dc2 100644
--- a/src/gui/painting/qprintengine_mac.mm
+++ b/src/gui/painting/qprintengine_mac.mm
@@ -92,16 +92,8 @@ bool QMacPrintEngine::begin(QPaintDevice *dev)
}
OSStatus status = noErr;
#ifndef QT_MAC_USE_COCOA
-# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- status = d->shouldSuppressStatus() ? PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format)
- : PMSessionBeginCGDocument(d->session, d->settings, d->format);
- } else
-# endif
- {
- status = d->shouldSuppressStatus() ? PMSessionBeginDocumentNoDialog(d->session, d->settings, d->format)
- : PMSessionBeginDocument(d->session, d->settings, d->format);
- }
+ status = d->shouldSuppressStatus() ? PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format)
+ : PMSessionBeginCGDocument(d->session, d->settings, d->format);
#else
status = PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format);
#endif
@@ -468,23 +460,6 @@ void QMacPrintEnginePrivate::initialize()
#endif
#ifndef QT_MAC_USE_COCOA
-# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_4)
-# endif
- {
- if(paintEngine->type() == QPaintEngine::CoreGraphics) {
- CFStringRef strings[1] = { kPMGraphicsContextCoreGraphics };
- QCFType<CFArrayRef> contextArray = CFArrayCreate(kCFAllocatorDefault,
- reinterpret_cast<const void **>(strings),
- 1, &kCFTypeArrayCallBacks);
- OSStatus err = PMSessionSetDocumentFormatGeneration(session, kPMDocumentFormatPDF,
- contextArray, 0);
- if(err != noErr) {
- qWarning("QMacPrintEngine::initialize: Cannot set format generation to PDF: %ld", err);
- state = QPrinter::Error;
- }
- }
- }
if (!settingsOK || !formatOK) {
qWarning("QMacPrintEngine::initialize: Unable to initialize QPainter");
state = QPrinter::Error;
@@ -551,19 +526,7 @@ bool QMacPrintEnginePrivate::newPage_helper()
CGContextRef cgContext;
OSStatus err = noErr;
-#ifndef QT_MAC_USE_COCOA
-# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- err = PMSessionGetCGGraphicsContext(session, &cgContext);
- } else
-# endif
- {
- err = PMSessionGetGraphicsContext(session, kPMGraphicsContextCoreGraphics,
- reinterpret_cast<void **>(&cgContext));
- }
-#else
err = PMSessionGetCGGraphicsContext(session, &cgContext);
-#endif
if(err != noErr) {
qWarning("QMacPrintEngine::newPage: Cannot retrieve CoreGraphics context: %ld", long(err));
state = QPrinter::Error;
diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp
index af39f7e..17a8ae6 100644
--- a/src/gui/painting/qprintengine_pdf.cpp
+++ b/src/gui/painting/qprintengine_pdf.cpp
@@ -423,7 +423,7 @@ int QPdfEnginePrivate::addConstantAlphaObject(int brushAlpha, int penAlpha)
object = addXrefEntry(-1);
QByteArray alphaDef;
QPdf::ByteStream s(&alphaDef);
- s << "<<\n/ca " << (brushAlpha/qreal(255.)) << "\n";
+ s << "<<\n/ca " << (brushAlpha/qreal(255.)) << '\n';
s << "/CA " << (penAlpha/qreal(255.)) << "\n>>";
xprintf("%s\nendobj\n", alphaDef.constData());
alphaCache.insert(QPair<uint, uint>(brushAlpha, penAlpha), object);
@@ -655,7 +655,7 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti)
#ifdef Q_WS_WIN
if (ti.fontEngine->type() == QFontEngine::Win) {
QFontEngineWin *fe = static_cast<QFontEngineWin *>(ti.fontEngine);
- size = fe->tm.w.tmHeight;
+ size = fe->tm.tmHeight;
}
#endif
int synthesized = ti.fontEngine->synthesized();
@@ -1010,7 +1010,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
s << (char)('A' + (tag % 26));
tag /= 26;
}
- s << "+" << properties.postscriptName << "\n"
+ s << '+' << properties.postscriptName << "\n"
"/Flags " << 4 << "\n"
"/FontBBox ["
<< properties.boundingBox.x()*scale
diff --git a/src/gui/painting/qprintengine_ps.cpp b/src/gui/painting/qprintengine_ps.cpp
index a22427e..189988b 100644
--- a/src/gui/painting/qprintengine_ps.cpp
+++ b/src/gui/painting/qprintengine_ps.cpp
@@ -167,7 +167,7 @@ static QByteArray wrapDSC(const QByteArray &str)
}
wrapped += "\n%%+" + tmp;
}
- return wrapped + "\n";
+ return wrapped + '\n';
}
// ----------------------------- Internal class declarations -----------------------------
@@ -422,7 +422,7 @@ void QPSPrintEnginePrivate::drawImageHelper(qreal x, qreal y, qreal w, qreal h,
<< size << " string readstring\n";
ps_r7(*currentPage, out, out.size());
*currentPage << " pop def\n";
- *currentPage << width << ' ' << height << "[" << scaleX << " 0 0 " << scaleY << " 0 0]sl "
+ *currentPage << width << ' ' << height << '[' << scaleX << " 0 0 " << scaleY << " 0 0]sl "
<< bits << (!mask.isNull() ? "mask " : "false ")
<< x << ' ' << y << " di\n";
}
@@ -529,7 +529,7 @@ void QPSPrintEnginePrivate::emitHeader(bool finished)
else
s << "\n%%BoundingBox: 0 0 " << w << h;
}
- s << "\n" << wrapDSC("%%Creator: " + creator.toUtf8());
+ s << '\n' << wrapDSC("%%Creator: " + creator.toUtf8());
if (!title.isEmpty())
s << wrapDSC("%%Title: " + title.toUtf8());
#ifndef QT_NO_DATESTRING
@@ -549,7 +549,7 @@ void QPSPrintEnginePrivate::emitHeader(bool finished)
"% Prolog copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).\n"
"% You may copy this prolog in any way that is directly related to this document.\n"
"% For other use of this prolog, see your licensing agreement for Qt.\n"
- << ps_header << "\n";
+ << ps_header << '\n';
s << "/pageinit {\n";
@@ -560,12 +560,12 @@ void QPSPrintEnginePrivate::emitHeader(bool finished)
s << mtop*scale << mleft*scale << "translate\n";
}
if (orientation == QPrinter::Portrait) {
- s << "% " << printer->widthMM() << "*" << printer->heightMM()
+ s << "% " << printer->widthMM() << '*' << printer->heightMM()
<< "mm (portrait)\n0 " << height*scale
- << "translate " << scale << "-" << scale << "scale } def\n";
+ << "translate " << scale << '-' << scale << "scale } def\n";
} else {
- s << "% " << printer->heightMM() << "*" << printer->widthMM()
- << " mm (landscape)\n 90 rotate " << scale << "-" << scale << "scale } def\n";
+ s << "% " << printer->heightMM() << '*' << printer->widthMM()
+ << " mm (landscape)\n 90 rotate " << scale << '-' << scale << "scale } def\n";
}
s << "%%EndProlog\n";
@@ -619,8 +619,8 @@ void QPSPrintEnginePrivate::flushPage(bool last)
QPdf::ByteStream e(&trailer);
buffer << "%%Page: "
<< pageCount << pageCount << "\n"
- << "%%BeginPageSetup\n"
- << "QI\n";
+ "%%BeginPageSetup\n"
+ "QI\n";
if (hugeDocument) {
for (QHash<QFontEngine::FaceId, QFontSubset *>::const_iterator it = fonts.constBegin();
it != fonts.constEnd(); ++it) {
@@ -776,8 +776,8 @@ bool QPSPrintEngine::end()
d->flushPage(true);
QByteArray trailer;
QPdf::ByteStream s(&trailer);
- s << "%%Trailer\n";
- s << "%%Pages: " << d->pageCount - 1 << "\n" <<
+ s << "%%Trailer\n"
+ "%%Pages: " << d->pageCount - 1 << '\n' <<
wrapDSC("%%DocumentFonts: " + d->fontsUsed);
s << "%%EOF\n";
d->outDevice->write(trailer);
diff --git a/src/gui/painting/qprintengine_win.cpp b/src/gui/painting/qprintengine_win.cpp
index 38c14eb..05bddaa 100644
--- a/src/gui/painting/qprintengine_win.cpp
+++ b/src/gui/painting/qprintengine_win.cpp
@@ -199,33 +199,18 @@ bool QWin32PrintEngine::begin(QPaintDevice *pdev)
if (d->printToFile && d->fileName.isEmpty())
d->fileName = d->port;
- QT_WA({
- d->devModeW()->dmCopies = d->num_copies;
- DOCINFO di;
- memset(&di, 0, sizeof(DOCINFO));
- di.cbSize = sizeof(DOCINFO);
- di.lpszDocName = reinterpret_cast<const wchar_t *>(d->docName.utf16());
- if (d->printToFile && !d->fileName.isEmpty())
- di.lpszOutput = reinterpret_cast<const wchar_t *>(d->fileName.utf16());
- if (ok && StartDoc(d->hdc, &di) == SP_ERROR) {
- qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed");
- ok = false;
- }
- } , {
- d->devModeA()->dmCopies = d->num_copies;
- DOCINFOA di;
- memset(&di, 0, sizeof(DOCINFOA));
- di.cbSize = sizeof(DOCINFOA);
- QByteArray docNameA = d->docName.toLocal8Bit();
- di.lpszDocName = docNameA.data();
- QByteArray outfileA = d->fileName.toLocal8Bit();
- if (d->printToFile && !d->fileName.isEmpty())
- di.lpszOutput = outfileA;
- if (ok && StartDocA(d->hdc, &di) == SP_ERROR) {
- qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed");
- ok = false;
- }
- });
+ d->devMode->dmCopies = d->num_copies;
+
+ DOCINFO di;
+ memset(&di, 0, sizeof(DOCINFO));
+ di.cbSize = sizeof(DOCINFO);
+ di.lpszDocName = reinterpret_cast<const wchar_t *>(d->docName.utf16());
+ if (d->printToFile && !d->fileName.isEmpty())
+ di.lpszOutput = reinterpret_cast<const wchar_t *>(d->fileName.utf16());
+ if (ok && StartDoc(d->hdc, &di) == SP_ERROR) {
+ qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed");
+ ok = false;
+ }
if (StartPage(d->hdc) <= 0) {
qErrnoWarning("QWin32PrintEngine::begin: StartPage failed");
@@ -317,11 +302,6 @@ bool QWin32PrintEngine::newPage()
bool success = false;
if (d->hdc && d->state == QPrinter::Active) {
-// bool restorePainter = false;
-// if ((qWinVersion()& Qt::WV_DOS_based) && painter && painter->isActive()) {
-// painter->save(); // EndPage/StartPage ruins the DC
-// restorePainter = true;
-// }
if (EndPage(d->hdc) != SP_ERROR) {
// reinitialize the DC before StartPage if needed,
// because resetdc is disabled between calls to the StartPage and EndPage functions
@@ -337,16 +317,10 @@ bool QWin32PrintEngine::newPage()
}
success = (StartPage(d->hdc) != SP_ERROR);
}
- if (!success)
+ if (!success) {
d->state = QPrinter::Aborted;
-
-// if (qWinVersion() & Qt::WV_DOS_based)
-// if (restorePainter) {
-// painter->restore();
-// }
-
- if (!success)
return false;
+ }
}
return true;
}
@@ -369,7 +343,7 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
QRgb brushColor = state->pen().brush().color().rgb();
bool fallBack = state->pen().brush().style() != Qt::SolidPattern
|| qAlpha(brushColor) != 0xff
- || QT_WA_INLINE(d->txop >= QTransform::TxProject, d->txop >= QTransform::TxScale)
+ || d->txop >= QTransform::TxProject
|| ti.fontEngine->type() != QFontEngine::Win;
@@ -380,17 +354,10 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
SelectObject(d->hdc, fe->hfont);
if (GetDeviceCaps(d->hdc, TECHNOLOGY) != DT_CHARSTREAM) {
- QT_WA({
- TCHAR n[64];
- GetTextFaceW(d->hdc, 64, n);
- fallBack = QString::fromUtf16((ushort *)n)
- != QString::fromUtf16((ushort *)fe->logfont.lfFaceName);
- } , {
- char an[64];
- GetTextFaceA(d->hdc, 64, an);
- fallBack = QString::fromLocal8Bit(an)
- != QString::fromLocal8Bit(((LOGFONTA*)(&fe->logfont))->lfFaceName);
- });
+ wchar_t n[64];
+ GetTextFace(d->hdc, 64, n);
+ fallBack = QString::fromWCharArray(n)
+ != QString::fromWCharArray(fe->logfont.lfFaceName);
}
}
@@ -663,8 +630,7 @@ void QWin32PrintEngine::drawPixmap(const QRectF &targetRect,
qreal scaleX = 1.0f;
qreal scaleY = 1.0f;
- QTransform scaleMatrix;
- scaleMatrix.scale(r.width() / pixmap.width(), r.height() / pixmap.height());
+ QTransform scaleMatrix = QTransform::fromScale(r.width() / pixmap.width(), r.height() / pixmap.height());
QTransform adapted = QPixmap::trueMatrix(d->painterMatrix * scaleMatrix,
pixmap.width(), pixmap.height());
@@ -984,22 +950,14 @@ void QWin32PrintEnginePrivate::queryDefault()
* Strings "windows" and "device" are specified in the MSDN under EnumPrinters()
*/
QString noPrinters(QLatin1String("qt_no_printers"));
- QString output;
- QT_WA({
- ushort buffer[256];
- GetProfileStringW(L"windows", L"device",
- reinterpret_cast<const wchar_t *>(noPrinters.utf16()),
- reinterpret_cast<wchar_t *>(buffer), 256);
- output = QString::fromUtf16(buffer);
- if (output.isEmpty() || output == noPrinters) // no printers
- return;
- }, {
- char buffer[256];
- GetProfileStringA("windows", "device", noPrinters.toLatin1(), buffer, 256);
- output = QString::fromLocal8Bit(buffer);
- if (output.isEmpty() || output == noPrinters) // no printers
- return;
- });
+ wchar_t buffer[256];
+ GetProfileString(L"windows", L"device",
+ reinterpret_cast<const wchar_t *>(noPrinters.utf16()),
+ buffer, 256);
+ QString output = QString::fromWCharArray(buffer);
+ if (output.isEmpty() || output == noPrinters) // no printers
+ return;
+
QStringList info = output.split(QLatin1Char(','));
if (info.size() > 0) {
if (name.isEmpty())
@@ -1031,13 +989,7 @@ void QWin32PrintEnginePrivate::initialize()
txop = QTransform::TxNone;
- bool ok;
- QT_WA( {
- ok = OpenPrinterW((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0);
- }, {
- ok = OpenPrinterA((LPSTR)name.toLatin1().data(), (LPHANDLE)&hPrinter, 0);
- } );
-
+ bool ok = OpenPrinter((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0);
if (!ok) {
qErrnoWarning("QWin32PrintEngine::initialize: OpenPrinter failed");
return;
@@ -1046,22 +998,10 @@ void QWin32PrintEnginePrivate::initialize()
// Fetch the PRINTER_INFO_2 with DEVMODE data containing the
// printer settings.
DWORD infoSize, numBytes;
- ok = true;
- QT_WA( {
- GetPrinterW(hPrinter, 2, NULL, 0, &infoSize);
- hMem = GlobalAlloc(GHND, infoSize);
- pInfo = GlobalLock(hMem);
- if (!GetPrinterW(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes)) {
- ok = false;
- }
- }, {
- GetPrinterA(hPrinter, 2, NULL, 0, &infoSize);
- hMem = GlobalAlloc(GHND, infoSize);
- pInfo = GlobalLock(hMem);
- if (!GetPrinterA(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes)) {
- ok = false;
- }
- });
+ GetPrinter(hPrinter, 2, NULL, 0, &infoSize);
+ hMem = GlobalAlloc(GHND, infoSize);
+ pInfo = (PRINTER_INFO_2*) GlobalLock(hMem);
+ ok = GetPrinter(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes);
if (!ok) {
qErrnoWarning("QWin32PrintEngine::initialize: GetPrinter failed");
@@ -1074,28 +1014,15 @@ void QWin32PrintEnginePrivate::initialize()
return;
}
- QT_WA( {
- devMode = pInfoW()->pDevMode;
- }, {
- devMode = pInfoA()->pDevMode;
- } );
-
- QT_WA( {
- hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()),
- reinterpret_cast<const wchar_t *>(name.utf16()), 0, devModeW());
- }, {
- hdc = CreateDCA(program.toLatin1(), name.toLatin1(), 0, devModeA());
- } );
+ devMode = pInfo->pDevMode;
+ hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()),
+ reinterpret_cast<const wchar_t *>(name.utf16()), 0, devMode);
Q_ASSERT(hPrinter);
Q_ASSERT(pInfo);
if (devMode) {
- QT_WA( {
- num_copies = devModeW()->dmCopies;
- }, {
- num_copies = devModeA()->dmCopies;
- } );
+ num_copies = devMode->dmCopies;
}
initHDC();
@@ -1213,28 +1140,18 @@ void QWin32PrintEnginePrivate::release()
QList<QVariant> QWin32PrintEnginePrivate::queryResolutions() const
{
// Read the supported resolutions of the printer.
- DWORD numRes;
- LONG *enumRes;
- DWORD errRes;
QList<QVariant> list;
- QT_WA({
- numRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()),
- reinterpret_cast<const wchar_t *>(port.utf16()),
- DC_ENUMRESOLUTIONS, 0, 0);
- if (numRes == (DWORD)-1)
- return list;
- enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG));
- errRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()),
- reinterpret_cast<const wchar_t *>(port.utf16()),
- DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0);
- }, {
- numRes = DeviceCapabilitiesA(name.toLocal8Bit(), port.toLocal8Bit(), DC_ENUMRESOLUTIONS, 0, 0);
- if (numRes == (DWORD)-1)
- return list;
- enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG));
- errRes = DeviceCapabilitiesA(name.toLocal8Bit(), port.toLocal8Bit(), DC_ENUMRESOLUTIONS, (LPSTR)enumRes, 0);
- });
+ DWORD numRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()),
+ reinterpret_cast<const wchar_t *>(port.utf16()),
+ DC_ENUMRESOLUTIONS, 0, 0);
+ if (numRes == (DWORD)-1)
+ return list;
+
+ LONG *enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG));
+ DWORD errRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()),
+ reinterpret_cast<const wchar_t *>(port.utf16()),
+ DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0);
if (errRes == (DWORD)-1) {
qErrnoWarning("QWin32PrintEngine::queryResolutions: DeviceCapabilities failed");
@@ -1242,7 +1159,8 @@ QList<QVariant> QWin32PrintEnginePrivate::queryResolutions() const
}
for (uint i=0; i<numRes; ++i)
- list.append(int(enumRes[i*2]));
+ list.append(int(enumRes[i * 2]));
+
return list;
}
@@ -1286,9 +1204,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
{
if (!d->devMode)
break;
- short collate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE;
- QT_WA( { d->devModeW()->dmCollate = collate; },
- { d->devModeA()->dmCollate = collate; } );
+ d->devMode->dmCollate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE;
d->doReinit();
}
break;
@@ -1297,8 +1213,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
{
if (!d->devMode)
break;
- int cm = value.toInt() == QPrinter::Color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME;
- QT_WA( { d->devModeW()->dmColor = cm; }, { d->devModeA()->dmColor = cm; } );
+ d->devMode->dmColor = (value.toInt() == QPrinter::Color) ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME;
d->doReinit();
}
break;
@@ -1324,8 +1239,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
if (!d->devMode)
break;
d->num_copies = value.toInt();
- QT_WA( { d->devModeW()->dmCopies = d->num_copies; },
- { d->devModeA()->dmCopies = d->num_copies; });
+ d->devMode->dmCopies = d->num_copies;
d->doReinit();
break;
@@ -1334,14 +1248,8 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
if (!d->devMode)
break;
int orientation = value.toInt() == QPrinter::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
- int old_orientation;
- QT_WA( {
- old_orientation = d->devModeW()->dmOrientation;
- d->devModeW()->dmOrientation = orientation;
- }, {
- old_orientation = d->devModeA()->dmOrientation;
- d->devModeA()->dmOrientation = orientation;
- } );
+ int old_orientation = d->devMode->dmOrientation;
+ d->devMode->dmOrientation = orientation;
if (d->has_custom_paper_size && old_orientation != orientation)
d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width());
d->doReinit();
@@ -1360,11 +1268,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
case PPK_PaperSize:
if (!d->devMode)
break;
- QT_WA( {
- d->devModeW()->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt()));
- }, {
- d->devModeA()->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt()));
- } );
+ d->devMode->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt()));
d->has_custom_paper_size = (QPrinter::PaperSize(value.toInt()) == QPrinter::Custom);
d->doReinit();
break;
@@ -1379,11 +1283,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
if (v.contains(value))
dmMapped = mapPaperSourceDevmode(QPrinter::PaperSource(value.toInt()));
- QT_WA( {
- d->devModeW()->dmDefaultSource = dmMapped;
- }, {
- d->devModeA()->dmDefaultSource = dmMapped;
- } );
+ d->devMode->dmDefaultSource = dmMapped;
d->doReinit();
}
break;
@@ -1417,11 +1317,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
if (!d->devMode)
break;
d->has_custom_paper_size = false;
- QT_WA( {
- d->devModeW()->dmPaperSize = value.toInt();
- }, {
- d->devModeA()->dmPaperSize = value.toInt();
- } );
+ d->devMode->dmPaperSize = value.toInt();
d->doReinit();
break;
@@ -1431,33 +1327,28 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
d->paper_size = value.toSizeF();
if (!d->devMode)
break;
- int orientation;
- QT_WA( {
- orientation = d->devModeW()->dmOrientation;
- DWORD needed = 0;
- DWORD returned = 0;
- if (!EnumForms(d->hPrinter, 1, 0, 0, &needed, &returned)) {
- BYTE *forms = (BYTE *) malloc(needed);
- if (EnumForms(d->hPrinter, 1, forms, needed, &needed, &returned)) {
- for (DWORD i=0; i< returned; ++i) {
- FORM_INFO_1 *formArray = reinterpret_cast<FORM_INFO_1 *>(forms);
- // the form sizes are specified in 1000th of a mm,
- // convert the size to Points
- QSizeF size((formArray[i].Size.cx * 72/25.4)/1000.0,
- (formArray[i].Size.cy * 72/25.4)/1000.0);
- if (qAbs(d->paper_size.width() - size.width()) <= 2
- && qAbs(d->paper_size.height() - size.height()) <= 2)
- {
- d->devModeW()->dmPaperSize = i+1;
- break;
- }
+ int orientation = d->devMode->dmOrientation;
+ DWORD needed = 0;
+ DWORD returned = 0;
+ if (!EnumForms(d->hPrinter, 1, 0, 0, &needed, &returned)) {
+ BYTE *forms = (BYTE *) malloc(needed);
+ if (EnumForms(d->hPrinter, 1, forms, needed, &needed, &returned)) {
+ for (DWORD i=0; i< returned; ++i) {
+ FORM_INFO_1 *formArray = reinterpret_cast<FORM_INFO_1 *>(forms);
+ // the form sizes are specified in 1000th of a mm,
+ // convert the size to Points
+ QSizeF size((formArray[i].Size.cx * 72/25.4)/1000.0,
+ (formArray[i].Size.cy * 72/25.4)/1000.0);
+ if (qAbs(d->paper_size.width() - size.width()) <= 2
+ && qAbs(d->paper_size.height() - size.height()) <= 2)
+ {
+ d->devMode->dmPaperSize = i + 1;
+ break;
}
}
- free(forms);
}
- }, {
- orientation = d->devModeA()->dmOrientation;
- } );
+ free(forms);
+ }
if (orientation != DMORIENT_PORTRAIT)
d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width());
break;
@@ -1469,10 +1360,10 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
Q_ASSERT(margins.size() == 4);
int left, top, right, bottom;
// specified in 1/100 mm
- left = (margins.at(0).toDouble()*25.4/72.0) * 100;
- top = (margins.at(1).toDouble()*25.4/72.0) * 100;
- right = (margins.at(2).toDouble()*25.4/72.0) * 100;
- bottom = (margins.at(3).toDouble()*25.4/72.0) * 100;
+ left = (margins.at(0).toReal()*25.4/72.0) * 100;
+ top = (margins.at(1).toReal()*25.4/72.0) * 100;
+ right = (margins.at(2).toReal()*25.4/72.0) * 100;
+ bottom = (margins.at(3).toReal()*25.4/72.0) * 100;
d->setPageMargins(left, top, right, bottom);
break;
}
@@ -1497,13 +1388,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
if (!d->devMode) {
value = QPrinter::Color;
} else {
- int mode;
- QT_WA( {
- mode = d->devModeW()->dmColor;
- }, {
- mode = d->devModeA()->dmColor;
- } );
- value = mode == DMCOLOR_COLOR ? QPrinter::Color : QPrinter::GrayScale;
+ value = (d->devMode->dmColor == DMCOLOR_COLOR) ? QPrinter::Color : QPrinter::GrayScale;
}
}
break;
@@ -1525,9 +1410,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
if (!d->devMode) {
value = QPrinter::Portrait;
} else {
- int o;
- QT_WA( { o = d->devModeW()->dmOrientation; }, { o = d->devModeA()->dmOrientation; } );
- value = o == DMORIENT_LANDSCAPE ? QPrinter::Landscape : QPrinter::Portrait;
+ value = (d->devMode->dmOrientation == DMORIENT_LANDSCAPE) ? QPrinter::Landscape : QPrinter::Portrait;
}
}
break;
@@ -1561,11 +1444,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
if (!d->devMode) {
value = QPrinter::A4;
} else {
- QT_WA( {
- value = mapDevmodePaperSize(d->devModeW()->dmPaperSize);
- }, {
- value = mapDevmodePaperSize(d->devModeA()->dmPaperSize);
- } );
+ value = mapDevmodePaperSize(d->devMode->dmPaperSize);
}
}
break;
@@ -1584,11 +1463,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
if (!d->devMode) {
value = QPrinter::Auto;
} else {
- QT_WA( {
- value = mapDevmodePaperSource(d->devModeW()->dmDefaultSource);
- }, {
- value = mapDevmodePaperSource(d->devModeA()->dmDefaultSource);
- } );
+ value = mapDevmodePaperSource(d->devMode->dmDefaultSource);
}
break;
@@ -1609,38 +1484,21 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
if (!d->devMode) {
value = -1;
} else {
- QT_WA( {
- value = d->devModeW()->dmPaperSize;
- }, {
- value = d->devModeA()->dmPaperSize;
- } );
+ value = d->devMode->dmPaperSize;
}
break;
case PPK_PaperSources:
{
- int available, count;
- WORD *data;
-
- QT_WA({
- available = DeviceCapabilitiesW((const WCHAR *)d->name.utf16(), (const WCHAR *)d->port.utf16(), DC_BINS, 0,
- d->devModeW());
- }, {
- available = DeviceCapabilitiesA(d->name.toLatin1(), d->port.toLatin1(), DC_BINS, 0,
- d->devModeA());
- });
+ int available = DeviceCapabilities((const wchar_t *)d->name.utf16(),
+ (const wchar_t *)d->port.utf16(), DC_BINS, 0, d->devMode);
if (available <= 0)
break;
- data = (WORD *) malloc(available * sizeof(WORD));
- QT_WA({
- count = DeviceCapabilitiesW((const WCHAR *)d->name.utf16(), (const WCHAR *)d->port.utf16(), DC_BINS, (WCHAR *)data,
- d->devModeW());
- }, {
- count = DeviceCapabilitiesA(d->name.toLatin1(), d->port.toLatin1(), DC_BINS,
- (char *) data, d->devModeA());
- });
+ wchar_t *data = new wchar_t[available];
+ int count = DeviceCapabilities((const wchar_t *)d->name.utf16(),
+ (const wchar_t *)d->port.utf16(), DC_BINS, data, d->devMode);
QList<QVariant> out;
for (int i=0; i<count; ++i) {
@@ -1649,7 +1507,8 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
out << (int) src;
}
value = out;
- free(data);
+
+ delete [] data;
}
break;
@@ -1694,24 +1553,23 @@ void QWin32PrintEngine::releaseDC(HDC) const
HGLOBAL *QWin32PrintEnginePrivate::createDevNames()
{
- QT_WA( {
- int size = sizeof(DEVNAMES)
- + program.length() * 2 + 2
- + name.length() * 2 + 2
- + port.length() * 2 + 2;
- HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size);
- DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal);
+ int size = sizeof(DEVNAMES)
+ + program.length() * 2 + 2
+ + name.length() * 2 + 2
+ + port.length() * 2 + 2;
+ HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size);
+ DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal);
- dn->wDriverOffset = sizeof(DEVNAMES) / sizeof(TCHAR);
- dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1;
- dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1;
+ dn->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
+ dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1;
+ dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1;
- memcpy((ushort*)dn + dn->wDriverOffset, program.utf16(), program.length() * 2 + 2);
- memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2);
- memcpy((ushort*)dn + dn->wOutputOffset, port.utf16(), port.length() * 2 + 2);
- dn->wDefault = 0;
+ memcpy((ushort*)dn + dn->wDriverOffset, program.utf16(), program.length() * 2 + 2);
+ memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2);
+ memcpy((ushort*)dn + dn->wOutputOffset, port.utf16(), port.length() * 2 + 2);
+ dn->wDefault = 0;
- GlobalUnlock(hGlobal);
+ GlobalUnlock(hGlobal);
// printf("QPrintDialogWinPrivate::createDevNames()\n"
// " -> wDriverOffset: %d\n"
@@ -1722,89 +1580,46 @@ HGLOBAL *QWin32PrintEnginePrivate::createDevNames()
// dn->wOutputOffset);
// printf("QPrintDialogWinPrivate::createDevNames(): %s, %s, %s\n",
-// QString::fromUtf16((ushort*)(dn) + dn->wDriverOffset).latin1(),
-// QString::fromUtf16((ushort*)(dn) + dn->wDeviceOffset).latin1(),
-// QString::fromUtf16((ushort*)(dn) + dn->wOutputOffset).latin1());
-
- return hGlobal;
- }, {
- int size = sizeof(DEVNAMES)
- + program.length() + 2
- + name.length() + 2
- + port.length() + 2;
- HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size);
- DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal);
-
- dn->wDriverOffset = sizeof(DEVNAMES);
- dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1;
- dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1;
-
- memcpy((char*)dn + dn->wDriverOffset, program.toLatin1(), program.length() + 2);
- memcpy((char*)dn + dn->wDeviceOffset, name.toLatin1(), name.length() + 2);
- memcpy((char*)dn + dn->wOutputOffset, port.toLatin1(), port.length() + 2);
- dn->wDefault = 0;
-
- GlobalUnlock(hGlobal);
- return hGlobal;
- } );
+// QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset).latin1(),
+// QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset).latin1(),
+// QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset).latin1());
+
+ return hGlobal;
}
void QWin32PrintEnginePrivate::readDevnames(HGLOBAL globalDevnames)
{
if (globalDevnames) {
- QT_WA( {
- DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames);
- name = QString::fromUtf16((ushort*)(dn) + dn->wDeviceOffset);
- port = QString::fromUtf16((ushort*)(dn) + dn->wOutputOffset);
- program = QString::fromUtf16((ushort*)(dn) + dn->wDriverOffset);
- GlobalUnlock(globalDevnames);
- }, {
- DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames);
- name = QString::fromLatin1((char*)(dn) + dn->wDeviceOffset);
- port = QString::fromLatin1((char*)(dn) + dn->wOutputOffset);
- program = QString::fromLatin1((char*)(dn) + dn->wDriverOffset);
- GlobalUnlock(globalDevnames);
- } );
+ DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames);
+ name = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset);
+ port = QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset);
+ program = QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset);
+ GlobalUnlock(globalDevnames);
}
}
void QWin32PrintEnginePrivate::readDevmode(HGLOBAL globalDevmode)
{
if (globalDevmode) {
- QT_WA( {
- DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevmode);
- release();
- globalDevMode = globalDevmode;
- devMode = dm;
- hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()),
- reinterpret_cast<const wchar_t *>(name.utf16()), 0, dm);
-
- num_copies = devModeW()->dmCopies;
- if (!OpenPrinterW((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0))
- qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE.");
- }, {
- DEVMODEA *dm = (DEVMODEA*) GlobalLock(globalDevmode);
- release();
- globalDevMode = globalDevmode;
- devMode = dm;
- hdc = CreateDCA(program.toLatin1(), name.toLatin1(), 0, dm);
-
- num_copies = devModeA()->dmCopies;
- if (!OpenPrinterA((LPSTR)name.toLatin1().data(), (LPHANDLE)&hPrinter, 0))
- qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE.");
- } );
+ DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevmode);
+ release();
+ globalDevMode = globalDevmode;
+ devMode = dm;
+ hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()),
+ reinterpret_cast<const wchar_t *>(name.utf16()), 0, dm);
+
+ num_copies = devMode->dmCopies;
+ if (!OpenPrinter((wchar_t*)name.utf16(), &hPrinter, 0))
+ qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE.");
}
if (hdc)
initHDC();
}
-static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc,
+static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc,
bool convertToText, const QTransform &xform, const QPointF &topLeft)
{
-
- // Make sure we translate for systems that can't handle world transforms
- QPointF pos(QT_WA_INLINE(_pos, _pos + QPointF(xform.dx(), xform.dy())));
QFontEngine *fe = ti.fontEngine;
QPointF baseline_pos = xform.inverted().map(xform.map(pos) - topLeft);
@@ -1816,12 +1631,10 @@ static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC
HFONT hfont;
bool ttf = false;
- bool useTextOutA = false;
if (winfe) {
hfont = winfe->hfont;
ttf = winfe->ttf;
- useTextOutA = winfe->useTextOutA;
} else {
hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
}
@@ -1831,154 +1644,115 @@ static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC
wchar_t *convertedGlyphs = (wchar_t *)ti.chars;
QGlyphLayout glyphs = ti.glyphs;
- if (!(ti.flags & QTextItem::RightToLeft) && useTextOutA) {
- qreal x = pos.x();
- qreal y = pos.y();
-
- // hack to get symbol fonts working on Win95. See also QFontEngine constructor
- // can only happen if !ttf
- for(int i = 0; i < glyphs.numGlyphs; i++) {
- QString str(QChar(glyphs.glyphs[i]));
- QT_WA({
- TextOutW(hdc, qRound(x + glyphs.offsets[i].x.toReal()),
- qRound(y + glyphs.offsets[i].y.toReal()),
- (LPWSTR)str.utf16(), str.length());
- } , {
- QByteArray cstr = str.toLocal8Bit();
- TextOutA(hdc, qRound(x + glyphs.offsets[i].x.toReal()),
- qRound(y + glyphs.offsets[i].y.toReal()),
- cstr.data(), cstr.length());
- });
- x += glyphs.effectiveAdvance(i).toReal();
- }
- } else {
- bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft);
- for(int i = 0; fast && i < glyphs.numGlyphs; i++) {
- if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0
- || glyphs.attributes[i].dontPrint) {
- fast = false;
- break;
- }
+ bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft);
+ for (int i = 0; fast && i < glyphs.numGlyphs; i++) {
+ if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0
+ || glyphs.attributes[i].dontPrint) {
+ fast = false;
+ break;
}
+ }
#if !defined(Q_OS_WINCE)
- // Scale, rotate and translate here. This is only valid for systems > Windows Me.
- // We should never get here on Windows Me or lower if the transformation specifies
- // scaling or rotation.
- QT_WA({
- XFORM win_xform;
- win_xform.eM11 = xform.m11();
- win_xform.eM12 = xform.m12();
- win_xform.eM21 = xform.m21();
- win_xform.eM22 = xform.m22();
- win_xform.eDx = xform.dx();
- win_xform.eDy = xform.dy();
- SetGraphicsMode(hdc, GM_ADVANCED);
- SetWorldTransform(hdc, &win_xform);
- }, {
- // nothing
- });
+ // Scale, rotate and translate here.
+ XFORM win_xform;
+ win_xform.eM11 = xform.m11();
+ win_xform.eM12 = xform.m12();
+ win_xform.eM21 = xform.m21();
+ win_xform.eM22 = xform.m22();
+ win_xform.eDx = xform.dx();
+ win_xform.eDy = xform.dy();
+
+ SetGraphicsMode(hdc, GM_ADVANCED);
+ SetWorldTransform(hdc, &win_xform);
#endif
- if (fast) {
- // fast path
- QVarLengthArray<wchar_t> g(glyphs.numGlyphs);
- for (int i = 0; i < glyphs.numGlyphs; ++i)
- g[i] = glyphs.glyphs[i];
- ExtTextOutW(hdc,
- qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()),
- qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()),
- options, 0, convertToText ? convertedGlyphs : g.data(), glyphs.numGlyphs, 0);
- } else {
- QVarLengthArray<QFixedPoint> positions;
- QVarLengthArray<glyph_t> _glyphs;
-
- QTransform matrix;
- matrix.translate(baseline_pos.x(), baseline_pos.y());
- ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags,
- _glyphs, positions);
- if (_glyphs.size() == 0) {
- SelectObject(hdc, old_font);
- return;
- }
-
- convertToText = convertToText && glyphs.numGlyphs == _glyphs.size();
-
- bool outputEntireItem = (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)
- && QSysInfo::WindowsVersion != QSysInfo::WV_NT
- && _glyphs.size() > 0;
+ if (fast) {
+ // fast path
+ QVarLengthArray<wchar_t> g(glyphs.numGlyphs);
+ for (int i = 0; i < glyphs.numGlyphs; ++i)
+ g[i] = glyphs.glyphs[i];
+ ExtTextOut(hdc,
+ qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()),
+ qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()),
+ options, 0, convertToText ? convertedGlyphs : g.data(), glyphs.numGlyphs, 0);
+ } else {
+ QVarLengthArray<QFixedPoint> positions;
+ QVarLengthArray<glyph_t> _glyphs;
+
+ QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y());
+ ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags,
+ _glyphs, positions);
+ if (_glyphs.size() == 0) {
+ SelectObject(hdc, old_font);
+ return;
+ }
- if (outputEntireItem) {
- options |= ETO_PDY;
- QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
- QVarLengthArray<wchar_t> g(_glyphs.size());
- for (int i=0; i<_glyphs.size() - 1; ++i) {
- glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
- glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
- g[i] = _glyphs[i];
- }
- glyphDistances[(_glyphs.size() - 1) * 2] = 0;
- glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0;
- g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1];
- ExtTextOutW(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0,
- convertToText ? convertedGlyphs : g.data(), _glyphs.size(),
- glyphDistances.data());
- } else {
- int i = 0;
- while(i < _glyphs.size()) {
- wchar_t g = _glyphs[i];
-
- ExtTextOutW(hdc, qRound(positions[i].x),
- qRound(positions[i].y), options, 0,
- convertToText ? convertedGlyphs + i : &g, 1, 0);
- ++i;
- }
+ convertToText = convertToText && glyphs.numGlyphs == _glyphs.size();
+ bool outputEntireItem = _glyphs.size() > 0;
+
+ if (outputEntireItem) {
+ options |= ETO_PDY;
+ QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
+ QVarLengthArray<wchar_t> g(_glyphs.size());
+ for (int i=0; i<_glyphs.size() - 1; ++i) {
+ glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
+ glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
+ g[i] = _glyphs[i];
+ }
+ glyphDistances[(_glyphs.size() - 1) * 2] = 0;
+ glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0;
+ g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1];
+ ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0,
+ convertToText ? convertedGlyphs : g.data(), _glyphs.size(),
+ glyphDistances.data());
+ } else {
+ int i = 0;
+ while(i < _glyphs.size()) {
+ wchar_t g = _glyphs[i];
+
+ ExtTextOut(hdc, qRound(positions[i].x),
+ qRound(positions[i].y), options, 0,
+ convertToText ? convertedGlyphs + i : &g, 1, 0);
+ ++i;
}
}
+ }
#if !defined(Q_OS_WINCE)
- QT_WA({
- XFORM win_xform;
- win_xform.eM11 = win_xform.eM22 = 1.0;
- win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0;
- SetWorldTransform(hdc, &win_xform);
- }, {
- // nothing
- });
+ win_xform.eM11 = win_xform.eM22 = 1.0;
+ win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0;
+ SetWorldTransform(hdc, &win_xform);
#endif
- }
+
SelectObject(hdc, old_font);
}
void QWin32PrintEnginePrivate::updateCustomPaperSize()
{
- QT_WA( {
- uint paperSize = devModeW()->dmPaperSize;
- if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) {
- has_custom_paper_size = true;
- DWORD needed = 0;
- DWORD returned = 0;
- if (!EnumForms(hPrinter, 1, 0, 0, &needed, &returned)) {
- BYTE *forms = (BYTE *) malloc(needed);
- if (EnumForms(hPrinter, 1, forms, needed, &needed, &returned)) {
- if (paperSize <= returned) {
- FORM_INFO_1 *formArray = (FORM_INFO_1 *) forms;
- int width = formArray[paperSize-1].Size.cx; // 1/1000 of a mm
- int height = formArray[paperSize-1].Size.cy; // 1/1000 of a mm
- paper_size = QSizeF((width*72/25.4)/1000.0, (height*72/25.4)/1000.0);
- } else {
- has_custom_paper_size = false;
- }
+ uint paperSize = devMode->dmPaperSize;
+ if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) {
+ has_custom_paper_size = true;
+ DWORD needed = 0;
+ DWORD returned = 0;
+ if (!EnumForms(hPrinter, 1, 0, 0, &needed, &returned)) {
+ BYTE *forms = (BYTE *) malloc(needed);
+ if (EnumForms(hPrinter, 1, forms, needed, &needed, &returned)) {
+ if (paperSize <= returned) {
+ FORM_INFO_1 *formArray = (FORM_INFO_1 *) forms;
+ int width = formArray[paperSize - 1].Size.cx; // 1/1000 of a mm
+ int height = formArray[paperSize - 1].Size.cy; // 1/1000 of a mm
+ paper_size = QSizeF((width * 72 /25.4) / 1000.0, (height * 72 / 25.4) / 1000.0);
+ } else {
+ has_custom_paper_size = false;
}
- free(forms);
}
- } else {
- has_custom_paper_size = false;
+ free(forms);
}
- }, {
- // Not supported under Win98
- } );
+ } else {
+ has_custom_paper_size = false;
+ }
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qprintengine_win_p.h b/src/gui/painting/qprintengine_win_p.h
index 92ddac2..472a55b 100644
--- a/src/gui/painting/qprintengine_win_p.h
+++ b/src/gui/painting/qprintengine_win_p.h
@@ -169,18 +169,8 @@ public:
void readDevmode(HGLOBAL globalDevmode);
void readDevnames(HGLOBAL globalDevnames);
- inline DEVMODEW *devModeW() const { return (DEVMODEW*) devMode; }
- inline DEVMODEA *devModeA() const { return (DEVMODEA*) devMode; }
-
- inline PRINTER_INFO_2W *pInfoW() { return (PRINTER_INFO_2W*) pInfo; };
- inline PRINTER_INFO_2A *pInfoA() { return (PRINTER_INFO_2A*) pInfo; };
-
inline bool resetDC() {
- QT_WA( {
- hdc = ResetDCW(hdc, devModeW());
- }, {
- hdc = ResetDCA(hdc, devModeA());
- } );
+ hdc = ResetDC(hdc, devMode);
return hdc != 0;
}
@@ -202,8 +192,8 @@ public:
HANDLE hPrinter;
HGLOBAL globalDevMode;
- void *devMode;
- void *pInfo;
+ DEVMODE *devMode;
+ PRINTER_INFO_2 *pInfo;
HGLOBAL hMem;
HDC hdc;
diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp
index bbd41db..882e6bc 100644
--- a/src/gui/painting/qprinter.cpp
+++ b/src/gui/painting/qprinter.cpp
@@ -268,8 +268,8 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
\brief The QPrinter class is a paint device that paints on a printer.
- \ingroup multimedia
- \mainclass
+ \ingroup printing
+
This device represents a series of pages of printed output, and is
used in almost exactly the same way as other paint devices such as
@@ -712,7 +712,6 @@ QPrinter::~QPrinter()
#ifndef QT_NO_PRINTPREVIEWWIDGET
delete d->previewEngine;
#endif
- delete d;
}
/*!
@@ -793,7 +792,8 @@ QPrinter::OutputFormat QPrinter::outputFormat() const
-/*! \reimp */
+/*! \internal
+*/
int QPrinter::devType() const
{
return QInternal::Printer;
@@ -834,11 +834,15 @@ void QPrinter::setPrinterName(const QString &name)
#endif
QList<QPrinterInfo> prnList = QPrinterInfo::availablePrinters();
- d->validPrinter = false;
- for (int i = 0; i < prnList.size(); ++i) {
- if (prnList[i].printerName() == name) {
- d->validPrinter = true;
- break;
+ if (name.isEmpty()) {
+ d->validPrinter = d->outputFormat == QPrinter::PdfFormat || d->outputFormat == QPrinter::PostScriptFormat;
+ } else {
+ d->validPrinter = false;
+ for (int i = 0; i < prnList.size(); ++i) {
+ if (prnList[i].printerName() == name) {
+ d->validPrinter = true;
+ break;
+ }
}
}
@@ -1304,6 +1308,9 @@ void QPrinter::setNumCopies(int numCopies)
Returns true if collation is turned on when multiple copies is selected.
Returns false if it is turned off when multiple copies is selected.
+ When collating is turned off the printing of each individual page will be repeated
+ the numCopies() amount before the next page is started. With collating turned on
+ all pages are printed before the next copy of those pages is started.
\sa setCollateCopies()
*/
@@ -1657,10 +1664,10 @@ void QPrinter::getPageMargins(qreal *left, qreal *top, qreal *right, qreal *bott
Q_ASSERT(left && top && right && bottom);
const qreal multiplier = qt_multiplierForUnit(unit, resolution());
QList<QVariant> margins(d->printEngine->property(QPrintEngine::PPK_PageMargins).toList());
- *left = margins.at(0).toDouble() / multiplier;
- *top = margins.at(1).toDouble() / multiplier;
- *right = margins.at(2).toDouble() / multiplier;
- *bottom = margins.at(3).toDouble() / multiplier;
+ *left = margins.at(0).toReal() / multiplier;
+ *top = margins.at(1).toReal() / multiplier;
+ *right = margins.at(2).toReal() / multiplier;
+ *bottom = margins.at(3).toReal() / multiplier;
}
/*!
@@ -2154,8 +2161,8 @@ bool QPrinter::collateCopiesEnabled() const
}
/*!
- Use QPrintDialog::addEnabledOption(QPrintDialog::PrintCollateCopies)
- or QPrintDialog::setEnabledOptions(QPrintDialog::enabledOptions()
+ Use QPrintDialog::setOption(QPrintDialog::PrintCollateCopies)
+ or QPrintDialog::setOptions(QPrintDialog::options()
& ~QPrintDialog::PrintCollateCopies) instead, depending on \a
enable.
*/
@@ -2196,7 +2203,7 @@ bool QPrinter::isOptionEnabled( PrinterOption option ) const
\class QPrintEngine
\reentrant
- \ingroup multimedia
+ \ingroup printing
\brief The QPrintEngine class defines an interface for how QPrinter
interacts with a given printing subsystem.
diff --git a/src/gui/painting/qprinter.h b/src/gui/painting/qprinter.h
index 14799e3..46419f4 100644
--- a/src/gui/painting/qprinter.h
+++ b/src/gui/painting/qprinter.h
@@ -42,8 +42,9 @@
#ifndef QPRINTER_H
#define QPRINTER_H
-#include <QtGui/qpaintdevice.h>
#include <QtCore/qstring.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtGui/qpaintdevice.h>
QT_BEGIN_HEADER
@@ -288,7 +289,7 @@ private:
Q_DISABLE_COPY(QPrinter)
- QPrinterPrivate *d_ptr;
+ QScopedPointer<QPrinterPrivate> d_ptr;
friend class QPrintDialogPrivate;
friend class QAbstractPrintDialog;
diff --git a/src/gui/painting/qprinterinfo.h b/src/gui/painting/qprinterinfo.h
index 162c729..2467fc6 100644
--- a/src/gui/painting/qprinterinfo.h
+++ b/src/gui/painting/qprinterinfo.h
@@ -53,6 +53,7 @@ QT_MODULE(Gui)
#ifndef QT_NO_PRINTER
class QPrinterInfoPrivate;
+class QPrinterInfoPrivateDeleter;
class Q_GUI_EXPORT QPrinterInfo
{
Q_DECLARE_PRIVATE(QPrinterInfo)
@@ -76,7 +77,7 @@ public:
private:
QPrinterInfo(const QString& name);
- QPrinterInfoPrivate* d_ptr;
+ QScopedPointer<QPrinterInfoPrivate, QPrinterInfoPrivateDeleter> d_ptr;
};
#endif // QT_NO_PRINTER
diff --git a/src/gui/painting/qprinterinfo.qdoc b/src/gui/painting/qprinterinfo.qdoc
new file mode 100644
index 0000000..13d76f6
--- /dev/null
+++ b/src/gui/painting/qprinterinfo.qdoc
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPrinterInfo
+
+ \brief The QPrinterInfo class gives access to information about
+ existing printers.
+
+ \ingroup printing
+
+ Use the static functions to generate a list of QPrinterInfo
+ objects. Each QPrinterInfo object in the list represents a single
+ printer and can be queried for name, supported paper sizes, and
+ whether or not it is the default printer.
+
+ \since 4.4
+*/
+
+/*!
+ \fn QList<QPrinterInfo> QPrinterInfo::availablePrinters()
+
+ Returns a list of available printers on the system.
+*/
+
+/*!
+ \fn QPrinterInfo QPrinterInfo::defaultPrinter()
+
+ Returns the default printer on the system.
+
+ The return value should be checked using isNull() before being
+ used, in case there is no default printer.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QPrinterInfo::QPrinterInfo()
+
+ Constructs an empty QPrinterInfo object.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
+
+ Constructs a copy of \a src.
+*/
+
+/*!
+ \fn QPrinterInfo::QPrinterInfo(const QPrinter& printer)
+
+ Constructs a QPrinterInfo object from \a printer.
+*/
+
+/*!
+ \fn QPrinterInfo::~QPrinterInfo()
+
+ Destroys the QPrinterInfo object. References to the values in the
+ object become invalid.
+*/
+
+/*!
+ \fn QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
+
+ Sets the QPrinterInfo object to be equal to \a src.
+*/
+
+/*!
+ \fn QString QPrinterInfo::printerName() const
+
+ Returns the name of the printer.
+
+ \sa QPrinter::setPrinterName()
+*/
+
+/*!
+ \fn bool QPrinterInfo::isNull() const
+
+ Returns whether this QPrinterInfo object holds a printer definition.
+
+ An empty QPrinterInfo object could result for example from calling
+ defaultPrinter() when there are no printers on the system.
+*/
+
+/*!
+ \fn bool QPrinterInfo::isDefault() const
+
+ Returns whether this printer is the default printer.
+*/
+
+/*!
+ \fn QList< QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
+ \since 4.4
+
+ Returns a list of supported paper sizes by the printer.
+
+ Not all printer drivers support this query, so the list may be empty.
+ On Mac OS X 10.3, this function always returns an empty list.
+*/
diff --git a/src/gui/painting/qprinterinfo_mac.cpp b/src/gui/painting/qprinterinfo_mac.cpp
index 014a234..ee0042e 100644
--- a/src/gui/painting/qprinterinfo_mac.cpp
+++ b/src/gui/painting/qprinterinfo_mac.cpp
@@ -65,6 +65,16 @@ private:
static QPrinterInfoPrivate nullQPrinterInfoPrivate;
+class QPrinterInfoPrivateDeleter
+{
+public:
+ static inline void cleanup(QPrinterInfoPrivate *d)
+ {
+ if (d != &nullQPrinterInfoPrivate)
+ delete d;
+ }
+};
+
extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF& size);
/////////////////////////////////////////////////////////////////////////////
@@ -106,8 +116,8 @@ QPrinterInfo QPrinterInfo::defaultPrinter(){
/////////////////////////////////////////////////////////////////////////////
QPrinterInfo::QPrinterInfo(const QPrinter& prn)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
QList<QPrinterInfo> list = availablePrinters();
for (int c = 0; c < list.size(); ++c) {
if (prn.printerName() == list[c].printerName()) {
@@ -115,39 +125,33 @@ QPrinterInfo::QPrinterInfo(const QPrinter& prn)
return;
}
}
-
- *this = QPrinterInfo();
}
QPrinterInfo::~QPrinterInfo()
{
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
}
QPrinterInfo::QPrinterInfo()
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
}
QPrinterInfo::QPrinterInfo(const QString& name)
+ : d_ptr(new QPrinterInfoPrivate(name))
{
- d_ptr = new QPrinterInfoPrivate(name);
d_ptr->q_ptr = this;
}
QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
*this = src;
}
QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
{
Q_ASSERT(d_ptr);
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
- d_ptr = new QPrinterInfoPrivate(*src.d_ptr);
+ d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
d_ptr->q_ptr = this;
return *this;
}
@@ -172,16 +176,9 @@ bool QPrinterInfo::isDefault() const
QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
{
-#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4)
- return QList<QPrinter::PaperSize>();
-#else
- if (QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4)
- return QList<QPrinter::PaperSize>();
-
const Q_D(QPrinterInfo);
- PMPrinter cfPrn = PMPrinterCreateFromPrinterID(
- QCFString::toCFStringRef(d->m_name));
+ PMPrinter cfPrn = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(d->m_name));
if (!cfPrn) return QList<QPrinter::PaperSize>();
@@ -211,7 +208,6 @@ QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
PMRelease(cfPrn);
return paperList;
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED
}
/////////////////////////////////////////////////////////////////////////////
diff --git a/src/gui/painting/qprinterinfo_unix.cpp b/src/gui/painting/qprinterinfo_unix.cpp
index c35d2c8..78919d2 100644
--- a/src/gui/painting/qprinterinfo_unix.cpp
+++ b/src/gui/painting/qprinterinfo_unix.cpp
@@ -82,6 +82,16 @@ private:
static QPrinterInfoPrivate nullQPrinterInfoPrivate;
+class QPrinterInfoPrivateDeleter
+{
+public:
+ static inline void cleanup(QPrinterInfoPrivate *d)
+ {
+ if (d != &nullQPrinterInfoPrivate)
+ delete d;
+ }
+};
+
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
@@ -822,7 +832,7 @@ QList<QPrinterInfo> QPrinterInfo::availablePrinters()
for (int i = 0; i < cupsPrinterCount; ++i) {
QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
if (cupsPrinters[i].instance)
- printerName += QLatin1String("/") + QString::fromLocal8Bit(cupsPrinters[i].instance);
+ printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
list.append(QPrinterInfo(printerName));
if (cupsPrinters[i].is_default)
list[i].d_ptr->m_default = true;
@@ -867,19 +877,19 @@ QPrinterInfo QPrinterInfo::defaultPrinter()
}
QPrinterInfo::QPrinterInfo()
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
}
QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
*this = src;
}
QPrinterInfo::QPrinterInfo(const QPrinter& printer)
+ : d_ptr(new QPrinterInfoPrivate(printer.printerName()))
{
- d_ptr = new QPrinterInfoPrivate(printer.printerName());
Q_D(QPrinterInfo);
d->q_ptr = this;
@@ -893,7 +903,7 @@ QPrinterInfo::QPrinterInfo(const QPrinter& printer)
for (int i = 0; i < cupsPrinterCount; ++i) {
QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
if (cupsPrinters[i].instance)
- printerName += QLatin1String("/") + QString::fromLocal8Bit(cupsPrinters[i].instance);
+ printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
if (printerName == printer.printerName()) {
if (cupsPrinters[i].is_default)
d->m_default = true;
@@ -929,28 +939,23 @@ QPrinterInfo::QPrinterInfo(const QPrinter& printer)
#endif
// Printer not found.
- delete d;
- d_ptr = &nullQPrinterInfoPrivate;
+ d_ptr.reset(&nullQPrinterInfoPrivate);
}
QPrinterInfo::QPrinterInfo(const QString& name)
+ : d_ptr(new QPrinterInfoPrivate(name))
{
- d_ptr = new QPrinterInfoPrivate(name);
d_ptr->q_ptr = this;
}
QPrinterInfo::~QPrinterInfo()
{
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
}
QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
{
Q_ASSERT(d_ptr);
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
- d_ptr = new QPrinterInfoPrivate(*src.d_ptr);
+ d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
d_ptr->q_ptr = this;
return *this;
}
diff --git a/src/gui/painting/qprinterinfo_win.cpp b/src/gui/painting/qprinterinfo_win.cpp
index 2b6fa42..f834d5c 100644
--- a/src/gui/painting/qprinterinfo_win.cpp
+++ b/src/gui/painting/qprinterinfo_win.cpp
@@ -43,7 +43,7 @@
#include <qstringlist.h>
-#include <windows.h>
+#include <qt_windows.h>
QT_BEGIN_NAMESPACE
@@ -69,6 +69,16 @@ private:
static QPrinterInfoPrivate nullQPrinterInfoPrivate;
+class QPrinterInfoPrivateDeleter
+{
+public:
+ static inline void cleanup(QPrinterInfoPrivate *d)
+ {
+ if (d != &nullQPrinterInfoPrivate)
+ delete d;
+ }
+};
+
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
@@ -79,45 +89,24 @@ QList<QPrinterInfo> QPrinterInfo::availablePrinters()
DWORD needed = 0;
DWORD returned = 0;
- QT_WA({
- if (!EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL,
- 4, 0, 0, &needed, &returned))
- {
- buffer = new BYTE[needed];
- if (!EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS , NULL,
- 4, buffer, needed, &needed, &returned))
- {
- delete [] buffer;
- return printers;
- }
- PPRINTER_INFO_4 infoList = reinterpret_cast<PPRINTER_INFO_4>(buffer);
- QPrinterInfo defPrn = defaultPrinter();
- for (uint i = 0; i < returned; ++i) {
- printers.append(QPrinterInfo(QString::fromUtf16(reinterpret_cast<const ushort*>(infoList[i].pPrinterName))));
- if (printers.at(i).printerName() == defPrn.printerName())
- printers[i].d_ptr->m_default = true;
- }
- delete [] buffer;
- }
- }, {
- // In Windows 98 networked printers are served through the local connection
- if (!EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, 0, 0, &needed, &returned)) {
- buffer = new BYTE[needed];
- if (!EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, buffer, needed, &needed, &returned)) {
- delete [] buffer;
- return printers;
- }
-
- PPRINTER_INFO_5 infoList = reinterpret_cast<PPRINTER_INFO_5>(buffer);
- QPrinterInfo defPrn = defaultPrinter();
- for (uint i = 0; i < returned; ++i) {
- printers.append(QPrinterInfo(QString::fromLocal8Bit(reinterpret_cast<const char*>(infoList[i].pPrinterName))));
- if (printers.at(i).printerName() == defPrn.printerName())
- printers[i].d_ptr->m_default = true;
- }
- delete [] buffer;
- }
- });
+ if ( !EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, 0, 0, &needed, &returned))
+ {
+ buffer = new BYTE[needed];
+ if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS , NULL,
+ 4, buffer, needed, &needed, &returned))
+ {
+ delete [] buffer;
+ return printers;
+ }
+ PPRINTER_INFO_4 infoList = reinterpret_cast<PPRINTER_INFO_4>(buffer);
+ QPrinterInfo defPrn = defaultPrinter();
+ for (uint i = 0; i < returned; ++i) {
+ printers.append(QPrinterInfo(QString::fromWCharArray(infoList[i].pPrinterName)));
+ if (printers.at(i).printerName() == defPrn.printerName())
+ printers[i].d_ptr->m_default = true;
+ }
+ delete [] buffer;
+ }
return printers;
}
@@ -125,18 +114,9 @@ QList<QPrinterInfo> QPrinterInfo::availablePrinters()
QPrinterInfo QPrinterInfo::defaultPrinter()
{
QString noPrinters(QLatin1String("qt_no_printers"));
- QString output;
- QT_WA({
- ushort buffer[256];
- GetProfileStringW(L"windows", L"device",
- reinterpret_cast<const wchar_t *>(noPrinters.utf16()),
- reinterpret_cast<wchar_t *>(buffer), 256);
- output = QString::fromUtf16(buffer);
- }, {
- char buffer[256];
- GetProfileStringA("windows", "device", noPrinters.toLatin1(), buffer, 256);
- output = QString::fromLocal8Bit(buffer);
- });
+ wchar_t buffer[256];
+ GetProfileString(L"windows", L"device", (wchar_t*)noPrinters.utf16(), buffer, 256);
+ QString output = QString::fromWCharArray(buffer);
// Filter out the name of the printer, which should be everything
// before a comma.
@@ -155,25 +135,25 @@ QPrinterInfo QPrinterInfo::defaultPrinter()
/////////////////////////////////////////////////////////////////////////////
QPrinterInfo::QPrinterInfo()
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
}
QPrinterInfo::QPrinterInfo(const QString& name)
+ : d_ptr(new QPrinterInfoPrivate(name))
{
- d_ptr = new QPrinterInfoPrivate(name);
d_ptr->q_ptr = this;
}
QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
*this = src;
}
QPrinterInfo::QPrinterInfo(const QPrinter& prn)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
QList<QPrinterInfo> list = availablePrinters();
for (int c = 0; c < list.size(); ++c) {
if (prn.printerName() == list[c].printerName()) {
@@ -187,16 +167,12 @@ QPrinterInfo::QPrinterInfo(const QPrinter& prn)
QPrinterInfo::~QPrinterInfo()
{
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
}
QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
{
Q_ASSERT(d_ptr);
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
- d_ptr = new QPrinterInfoPrivate(*src.d_ptr);
+ d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
d_ptr->q_ptr = this;
return *this;
}
@@ -222,26 +198,16 @@ bool QPrinterInfo::isDefault() const
QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
{
const Q_D(QPrinterInfo);
- DWORD size;
- WORD* papers;
QList<QPrinter::PaperSize> paperList;
- QT_WA({
- size = DeviceCapabilitiesW(reinterpret_cast<const WCHAR*>(d->m_name.utf16()),
- NULL, DC_PAPERS, NULL, NULL);
- if ((int)size == -1)
- return paperList;
- papers = new WORD[size];
- size = DeviceCapabilitiesW(reinterpret_cast<const WCHAR*>(d->m_name.utf16()),
- NULL, DC_PAPERS, reinterpret_cast<WCHAR*>(papers), NULL);
- }, {
- size = DeviceCapabilitiesA(d->m_name.toLatin1().data(), NULL, DC_PAPERS, NULL, NULL);
- if ((int)size == -1)
- return paperList;
- papers = new WORD[size];
- size = DeviceCapabilitiesA(d->m_name.toLatin1().data(), NULL, DC_PAPERS,
- reinterpret_cast<char*>(papers), NULL);
- });
+ DWORD size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->m_name.utf16()),
+ NULL, DC_PAPERS, NULL, NULL);
+ if ((int)size == -1)
+ return paperList;
+
+ wchar_t *papers = new wchar_t[size];
+ size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->m_name.utf16()),
+ NULL, DC_PAPERS, papers, NULL);
for (int c = 0; c < (int)size; ++c) {
paperList.append(mapDevmodePaperSize(papers[c]));
diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp
index fe90221..2b73f9b 100644
--- a/src/gui/painting/qrasterizer.cpp
+++ b/src/gui/painting/qrasterizer.cpp
@@ -436,8 +436,9 @@ void QScanConverter::end()
inline void QScanConverter::allocate(int size)
{
if (m_alloc < size) {
- m_alloc = qMax(size, 2 * m_alloc);
- m_intersections = (Intersection *)realloc(m_intersections, m_alloc * sizeof(Intersection));
+ int newAlloc = qMax(size, 2 * m_alloc);
+ m_intersections = q_check_ptr((Intersection *)realloc(m_intersections, newAlloc * sizeof(Intersection)));
+ m_alloc = newAlloc;
}
}
diff --git a/src/gui/painting/qrasterizer_p.h b/src/gui/painting/qrasterizer_p.h
index e6a354d..4cfdbbf 100644
--- a/src/gui/painting/qrasterizer_p.h
+++ b/src/gui/painting/qrasterizer_p.h
@@ -65,7 +65,7 @@ struct QSpanData;
class QRasterBuffer;
class QRasterizerPrivate;
-class QRasterizer
+class Q_GUI_EXPORT QRasterizer
{
public:
QRasterizer();
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index badc14a..d138663 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -49,7 +49,7 @@
#include <qdebug.h>
-#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE)
+#if defined(Q_OS_UNIX) || defined(Q_WS_WIN)
#include "qimage.h"
#include "qbitmap.h"
#include <stdlib.h>
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
\class QRegion
\brief The QRegion class specifies a clip region for a painter.
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
QRegion is used with QPainter::setClipRegion() to limit the paint
@@ -92,10 +92,6 @@ QT_BEGIN_NAMESPACE
Example of using complex regions:
\snippet doc/src/snippets/code/src_gui_painting_qregion.cpp 0
- \warning Due to window system limitations, the whole coordinate space for a
- region is limited to the points between -32767 and 32767 on Windows
- 95/98/ME. You can circumvent this limitation by using a QPainterPath.
-
\section1 Additional License Information
On Embedded Linux, Windows CE and X11 platforms, parts of this class rely on
@@ -450,9 +446,9 @@ QDebug operator<<(QDebug s, const QRegion &r)
{
QVector<QRect> rects = r.rects();
s.nospace() << "QRegion(size=" << rects.size() << "), "
- << "bounds = " << r.boundingRect() << "\n";
+ << "bounds = " << r.boundingRect() << '\n';
for (int i=0; i<rects.size(); ++i)
- s << "- " << i << rects.at(i) << "\n";
+ s << "- " << i << rects.at(i) << '\n';
return s;
}
#endif
@@ -549,7 +545,7 @@ QRegion& QRegion::operator|=(const QRegion &r)
\sa intersected()
*/
-#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE)
+#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN)
QRegion& QRegion::operator+=(const QRect &r)
{
return operator+=(QRegion(r));
@@ -565,16 +561,14 @@ QRegion& QRegion::operator+=(const QRect &r)
\sa intersected()
*/
-#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE)
QRegion& QRegion::operator&=(const QRegion &r)
{ return *this = *this & r; }
-#endif
/*!
\overload
\since 4.4
*/
-#if defined (Q_OS_UNIX) || defined (Q_OS_WINCE)
+#if defined (Q_OS_UNIX) || defined (Q_WS_WIN)
QRegion& QRegion::operator&=(const QRect &r)
{
return *this = *this & r;
@@ -595,10 +589,8 @@ QRegion& QRegion::operator&=(const QRect &r)
\sa subtracted()
*/
-#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE)
QRegion& QRegion::operator-=(const QRegion &r)
{ return *this = *this - r; }
-#endif
/*!
Applies the xored() function to this region and \a r and
@@ -698,6 +690,8 @@ bool QRegion::intersects(const QRegion &region) const
if (!rect_intersects(boundingRect(), region.boundingRect()))
return false;
+ if (numRects() == 1 && region.numRects() == 1)
+ return true;
const QVector<QRect> myRects = rects();
const QVector<QRect> otherRects = region.rects();
@@ -723,6 +717,8 @@ bool QRegion::intersects(const QRect &rect) const
const QRect r = rect.normalized();
if (!rect_intersects(boundingRect(), r))
return false;
+ if (numRects() == 1)
+ return true;
const QVector<QRect> myRects = rects();
for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it)
@@ -731,7 +727,7 @@ bool QRegion::intersects(const QRect &rect) const
return false;
}
-#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE)
+#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN)
/*!
\overload
\since 4.4
@@ -1086,7 +1082,7 @@ Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion &region)
return result;
}
-#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE)
+#if defined(Q_OS_UNIX) || defined(Q_WS_WIN)
//#define QT_REGION_DEBUG
/*
@@ -1601,7 +1597,7 @@ void QRegionPrivate::selfTest() const
for (int i = 0; i < numRects; ++i) {
const QRect r = rects.at(i);
if ((r.width() * r.height()) > innerArea)
- qDebug() << "selfTest(): innerRect" << innerRect << "<" << r;
+ qDebug() << "selfTest(): innerRect" << innerRect << '<' << r;
}
QRect r = rects.first();
@@ -1627,9 +1623,9 @@ QT_END_INCLUDE_NAMESPACE
QT_BEGIN_INCLUDE_NAMESPACE
# include "qregion_mac.cpp"
QT_END_INCLUDE_NAMESPACE
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
QT_BEGIN_INCLUDE_NAMESPACE
-# include "qregion_wince.cpp"
+# include "qregion_win.cpp"
QT_END_INCLUDE_NAMESPACE
#elif defined(Q_WS_QWS)
static QRegionPrivate qrp;
@@ -3167,6 +3163,7 @@ static void InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE, int scanline,
{
tmpSLLBlock =
(ScanLineListBlock *)malloc(sizeof(ScanLineListBlock));
+ Q_CHECK_PTR(tmpSLLBlock);
(*SLLBlock)->next = tmpSLLBlock;
tmpSLLBlock->next = (ScanLineListBlock *)NULL;
*SLLBlock = tmpSLLBlock;
@@ -3553,6 +3550,8 @@ static void PtsToRegion(register int numFullPtBlocks, register int iCurPtBlock,
* Scan converts a polygon by returning a run-length
* encoding of the resultant bitmap -- the run-length
* encoding is in the form of an array of rectangles.
+ *
+ * Can return 0 in case of errors.
*/
static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
//Point *Pts; /* the pts */
@@ -3624,75 +3623,28 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
}
- if (rule == EvenOddRule) {
- /*
- * for each scanline
- */
- for (y = ET.ymin; y < ET.ymax; ++y) {
-
- /*
- * Add a new edge to the active edge table when we
- * get to the next edge.
- */
- if (pSLL && y == pSLL->scanline) {
- loadAET(&AET, pSLL->edgelist);
- pSLL = pSLL->next;
- }
- pPrevAET = &AET;
- pAET = AET.next;
-
+ QT_TRY {
+ if (rule == EvenOddRule) {
/*
- * for each active edge
+ * for each scanline
*/
- while (pAET) {
- pts->setX(pAET->bres.minor_axis);
- pts->setY(y);
- ++pts;
- ++iPts;
+ for (y = ET.ymin; y < ET.ymax; ++y) {
/*
- * send out the buffer
+ * Add a new edge to the active edge table when we
+ * get to the next edge.
*/
- if (iPts == NUMPTSTOBUFFER) {
- tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK));
- tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data);
- curPtBlock->next = tmpPtBlock;
- curPtBlock = tmpPtBlock;
- pts = curPtBlock->pts;
- ++numFullPtBlocks;
- iPts = 0;
+ if (pSLL && y == pSLL->scanline) {
+ loadAET(&AET, pSLL->edgelist);
+ pSLL = pSLL->next;
}
- EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
- }
- InsertionSort(&AET);
- }
- } else {
- /*
- * for each scanline
- */
- for (y = ET.ymin; y < ET.ymax; ++y) {
- /*
- * Add a new edge to the active edge table when we
- * get to the next edge.
- */
- if (pSLL && y == pSLL->scanline) {
- loadAET(&AET, pSLL->edgelist);
- computeWAET(&AET);
- pSLL = pSLL->next;
- }
- pPrevAET = &AET;
- pAET = AET.next;
- pWETE = pAET;
+ pPrevAET = &AET;
+ pAET = AET.next;
- /*
- * for each active edge
- */
- while (pAET) {
/*
- * add to the buffer only those edges that
- * are in the Winding active edge table.
+ * for each active edge
*/
- if (pWETE == pAET) {
+ while (pAET) {
pts->setX(pAET->bres.minor_axis);
pts->setY(y);
++pts;
@@ -3702,7 +3654,8 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
* send out the buffer
*/
if (iPts == NUMPTSTOBUFFER) {
- tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK)));
+ tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK));
+ Q_CHECK_PTR(tmpPtBlock);
tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data);
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
@@ -3710,21 +3663,81 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
++numFullPtBlocks;
iPts = 0;
}
- pWETE = pWETE->nextWETE;
+ EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
}
- EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
+ InsertionSort(&AET);
}
-
+ } else {
/*
- * recompute the winding active edge table if
- * we just resorted or have exited an edge.
+ * for each scanline
*/
- if (InsertionSort(&AET) || fixWAET) {
- computeWAET(&AET);
- fixWAET = false;
+ for (y = ET.ymin; y < ET.ymax; ++y) {
+ /*
+ * Add a new edge to the active edge table when we
+ * get to the next edge.
+ */
+ if (pSLL && y == pSLL->scanline) {
+ loadAET(&AET, pSLL->edgelist);
+ computeWAET(&AET);
+ pSLL = pSLL->next;
+ }
+ pPrevAET = &AET;
+ pAET = AET.next;
+ pWETE = pAET;
+
+ /*
+ * for each active edge
+ */
+ while (pAET) {
+ /*
+ * add to the buffer only those edges that
+ * are in the Winding active edge table.
+ */
+ if (pWETE == pAET) {
+ pts->setX(pAET->bres.minor_axis);
+ pts->setY(y);
+ ++pts;
+ ++iPts;
+
+ /*
+ * send out the buffer
+ */
+ if (iPts == NUMPTSTOBUFFER) {
+ tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK)));
+ tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data);
+ curPtBlock->next = tmpPtBlock;
+ curPtBlock = tmpPtBlock;
+ pts = curPtBlock->pts;
+ ++numFullPtBlocks;
+ iPts = 0;
+ }
+ pWETE = pWETE->nextWETE;
+ }
+ EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
+ }
+
+ /*
+ * recompute the winding active edge table if
+ * we just resorted or have exited an edge.
+ */
+ if (InsertionSort(&AET) || fixWAET) {
+ computeWAET(&AET);
+ fixWAET = false;
+ }
}
}
+ } QT_CATCH(...) {
+ FreeStorage(SLLBlock.next);
+ PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
+ for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
+ tmpPtBlock = curPtBlock->next;
+ free(curPtBlock);
+ curPtBlock = tmpPtBlock;
+ }
+ free(pETEs);
+ return 0; // this function returns 0 in case of an error
}
+
FreeStorage(SLLBlock.next);
PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
@@ -3829,7 +3842,7 @@ QRegion::QRegion(const QRect &r, RegionType t)
#if defined(Q_WS_X11)
d->rgn = 0;
d->xrectangles = 0;
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
d->rgn = 0;
#endif
if (t == Rectangle) {
@@ -3851,7 +3864,7 @@ QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
#if defined(Q_WS_X11)
d->rgn = 0;
d->xrectangles = 0;
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
d->rgn = 0;
#endif
d->qt_rgn = PolygonRegion(a.constData(), a.size(),
@@ -3881,7 +3894,7 @@ QRegion::QRegion(const QBitmap &bm)
#if defined(Q_WS_X11)
d->rgn = 0;
d->xrectangles = 0;
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
d->rgn = 0;
#endif
d->qt_rgn = qt_bitmapToRegion(bm);
@@ -3896,7 +3909,7 @@ void QRegion::cleanUp(QRegion::QRegionData *x)
XDestroyRegion(x->rgn);
if (x->xrectangles)
free(x->xrectangles);
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
if (x->rgn)
qt_win_dispose_rgn(x->rgn);
#endif
@@ -3923,16 +3936,15 @@ QRegion &QRegion::operator=(const QRegion &r)
/*!
\internal
*/
-
QRegion QRegion::copy() const
{
QRegion r;
- QRegionData *x = new QRegionData;
+ QScopedPointer<QRegionData> x(new QRegionData);
x->ref = 1;
#if defined(Q_WS_X11)
x->rgn = 0;
x->xrectangles = 0;
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
x->rgn = 0;
#endif
if (d->qt_rgn)
@@ -3941,7 +3953,7 @@ QRegion QRegion::copy() const
x->qt_rgn = new QRegionPrivate;
if (!r.d->ref.deref())
cleanUp(r.d);
- r.d = x;
+ r.d = x.take();
return r;
}
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index 67f1355..226e3fa 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -59,7 +59,7 @@ QT_MODULE(Gui)
template <class T> class QVector;
class QVariant;
-#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
struct QRegionPrivate;
#endif
@@ -148,6 +148,7 @@ public:
#elif defined(Q_WS_MAC)
#if defined Q_WS_MAC32
RgnHandle toQDRgn() const;
+ RgnHandle toQDRgnForUpdate_sys() const;
static QRegion fromQDRgn(RgnHandle shape);
#endif
#ifdef QT_MAC_USE_COCOA
@@ -199,7 +200,7 @@ private:
#elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
mutable RgnHandle unused; // Here for binary compatability reasons. ### Qt 5 remove.
#endif
-#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
QRegionPrivate *qt_rgn;
#endif
};
diff --git a/src/gui/painting/qregion_mac.cpp b/src/gui/painting/qregion_mac.cpp
index 160622b..c887171 100644
--- a/src/gui/painting/qregion_mac.cpp
+++ b/src/gui/painting/qregion_mac.cpp
@@ -155,6 +155,43 @@ RgnHandle QRegion::toQDRgn() const
}
return rgnHandle;
}
+
+/*!
+ \internal
+ Create's a RegionHandle, it's the caller's responsibility to release.
+ Returns 0 if the QRegion overflows.
+*/
+RgnHandle QRegion::toQDRgnForUpdate_sys() const
+{
+ RgnHandle rgnHandle = qt_mac_get_rgn();
+ if(d->qt_rgn && d->qt_rgn->numRects) {
+ RgnHandle tmp_rgn = qt_mac_get_rgn();
+ int n = d->qt_rgn->numRects;
+ const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData();
+ while (n--) {
+
+ // detect overflow. Tested for use with HIViewSetNeedsDisplayInRegion
+ // in QWidgetPrivate::update_sys().
+ enum { HIViewSetNeedsDisplayInRegionOverflow = 10000 }; // empirically determined conservative value
+ if (qt_r->right() > HIViewSetNeedsDisplayInRegionOverflow || qt_r->bottom() > HIViewSetNeedsDisplayInRegionOverflow) {
+ qt_mac_dispose_rgn(tmp_rgn);
+ qt_mac_dispose_rgn(rgnHandle);
+ return 0;
+ }
+
+ SetRectRgn(tmp_rgn,
+ qMax(SHRT_MIN, qt_r->x()),
+ qMax(SHRT_MIN, qt_r->y()),
+ qMin(SHRT_MAX, qt_r->right() + 1),
+ qMin(SHRT_MAX, qt_r->bottom() + 1));
+ UnionRgn(rgnHandle, tmp_rgn, rgnHandle);
+ ++qt_r;
+ }
+ qt_mac_dispose_rgn(tmp_rgn);
+ }
+ return rgnHandle;
+}
+
#endif
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
diff --git a/src/gui/embedded/qkbdyopy_qws.h b/src/gui/painting/qregion_s60.cpp
index cb49632..5600ece 100644
--- a/src/gui/embedded/qkbdyopy_qws.h
+++ b/src/gui/painting/qregion_s60.cpp
@@ -3,14 +3,14 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtGui module of the Qt Toolkit.
+** This file is part of the QtGui of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -21,53 +21,32 @@
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QKBDYOPY_QWS_H
-#define QKBDYOPY_QWS_H
-
-#include <QtGui/qkbd_qws.h>
-
-QT_BEGIN_HEADER
+#include "qbitmap.h"
+#include "qbuffer.h"
+#include "qimage.h"
+#include "qpolygon.h"
+#include "qregion.h"
QT_BEGIN_NAMESPACE
-QT_MODULE(Gui)
-
-#ifndef QT_NO_QWS_KBD_YOPY
-
-class QWSYopyKbPrivate;
-
-class QWSYopyKeyboardHandler : public QWSKeyboardHandler
-{
-public:
- explicit QWSYopyKeyboardHandler(const QString&);
- virtual ~QWSYopyKeyboardHandler();
-
-private:
- QWSYopyKbPrivate *d;
-};
-
-#endif // QT_NO_QWS_KBD_YOPY
+QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 };
QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QKBDYOPY_QWS_H
diff --git a/src/gui/painting/qregion_win.cpp b/src/gui/painting/qregion_win.cpp
index 9b31e7b..d262198 100644
--- a/src/gui/painting/qregion_win.cpp
+++ b/src/gui/painting/qregion_win.cpp
@@ -39,27 +39,24 @@
**
****************************************************************************/
+#include "qatomic.h"
#include "qbitmap.h"
#include "qbuffer.h"
#include "qimage.h"
#include "qpolygon.h"
#include "qregion.h"
#include "qt_windows.h"
+#include "qpainterpath.h"
QT_BEGIN_NAMESPACE
+QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 };
-/*
- In Windows versions before Windows Vista CreateRectRgn - when called in a multi-threaded
- environment - might return an invalid handle. This function works around this limitation
- by verifying the handle with a quick GetRegionData() call and re-creates the region
- if necessary.
-*/
HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom)
{
const int tries = 10;
for (int i = 0; i < tries; ++i) {
- HRGN region;
+ HRGN region = 0;
switch (type) {
case QRegion::Rectangle:
region = CreateRectRgn(left, top, right, bottom);
@@ -80,497 +77,73 @@ HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right,
return 0;
}
-#ifndef Q_OS_WINCE
-HRGN qt_tryCreatePolygonRegion(const QPolygon &a, Qt::FillRule fillRule)
-{
- const int tries = 10;
- for (int i = 0; i < tries; ++i) {
- HRGN region = CreatePolygonRgn(reinterpret_cast<const POINT*>(a.data()), a.size(),
- fillRule == Qt::OddEvenFill ? ALTERNATE : WINDING);
- if (region) {
- if (GetRegionData(region, 0, 0))
- return region;
- else
- DeleteObject(region);
- }
- }
- return 0;
-}
-#endif
-
-QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 };
-
-QRegion::QRegion()
- : d(&shared_empty)
-{
- d->ref.ref();
-}
-
-#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp
-QRegion::QRegion(const QRect &r, RegionType t)
-{
- if (r.isEmpty()) {
- d = &shared_empty;
- d->ref.ref();
- } else {
- d = new QRegionData;
- d->ref = 1;
- if (t == Rectangle)
- d->rgn = qt_tryCreateRegion(t, r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
- else if (t == Ellipse) {
- // need to add 1 to width/height for the ellipse to have correct boundingrect.
- d->rgn = qt_tryCreateRegion(t, r.x(), r.y(), r.x() + r.width() + 1, r.y() + r.height() + 1);
- }
- }
-}
-#endif
-
-#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp
-QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
-{
- if (a.size() < 3) {
- d = &shared_empty;
- d->ref.ref();
- } else {
- d = new QRegionData;
- d->ref = 1;
- d->rgn = qt_tryCreatePolygonRegion(a, fillRule);
- }
-}
-#endif
-
-QRegion::QRegion(const QRegion &r)
-{
- d = r.d;
- d->ref.ref();
-}
-
-HRGN qt_win_bitmapToRegion(const QBitmap& bitmap)
-{
- HRGN region=0;
- QImage image = bitmap.toImage();
- const int MAXRECT = 256;
- struct RData {
- RGNDATAHEADER header;
- RECT rect[MAXRECT];
- };
- RData data;
-
-#define FlushSpans \
- { \
- data.header.dwSize = sizeof(RGNDATAHEADER); \
- data.header.iType = RDH_RECTANGLES; \
- data.header.nCount = n; \
- data.header.nRgnSize = 0; \
- data.header.rcBound.bottom = y; \
- HRGN r = ExtCreateRegion(0, \
- sizeof(RGNDATAHEADER)+n*sizeof(RECT),(RGNDATA*)&data); \
- if (region) { \
- CombineRgn(region, region, r, RGN_OR); \
- DeleteObject(r); \
- } else { \
- region = r; \
- } \
- data.header.rcBound.top = y; \
- }
-
-#define AddSpan \
- { \
- data.rect[n].left=prev1; \
- data.rect[n].top=y; \
- data.rect[n].right=x-1+1; \
- data.rect[n].bottom=y+1; \
- n++; \
- if (n == MAXRECT) { \
- FlushSpans \
- n=0; \
- } \
- }
-
- data.header.rcBound.top = 0;
- data.header.rcBound.left = 0;
- data.header.rcBound.right = image.width()-1;
- int n = 0;
-
- int zero = 0x00;
-
- int x, y;
- for (y = 0; y < image.height(); ++y) {
- uchar *line = image.scanLine(y);
- int w = image.width();
- uchar all=zero;
- int prev1 = -1;
- for (x = 0; x < w;) {
- uchar byte = line[x/8];
- if (x > w - 8 || byte != all) {
- for (int b = 8; b > 0 && x < w; --b) {
- if (!(byte & 0x01) == !all) {
- // More of the same
- } else {
- // A change.
- if (all != zero) {
- AddSpan;
- all = zero;
- } else {
- prev1 = x;
- all = ~zero;
- }
- }
- byte >>= 1;
- ++x;
- }
- } else {
- x += 8;
- }
- }
- if (all != zero) {
- AddSpan;
- }
- }
- if (n) {
- FlushSpans;
- }
-
- if (!region) {
- // Surely there is some better way.
- region = qt_tryCreateRegion(QRegion::Rectangle, 0,0,1,1);
- CombineRgn(region, region, region, RGN_XOR);
- }
- return region;
-}
-
-#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp
-QRegion::QRegion(const QBitmap &bm)
-{
- if (bm.isNull()) {
- d = &shared_empty;
- d->ref.ref();
- } else {
- d = new QRegionData;
- d->ref = 1;
- d->rgn = qt_win_bitmapToRegion(bm);
- }
-}
-#endif
-
-void QRegion::cleanUp(QRegion::QRegionData *x)
-{
- if (x->rgn)
- DeleteObject(x->rgn);
- delete x;
-}
-
-QRegion::~QRegion()
-{
- if (!d->ref.deref())
- cleanUp(d);
-}
-
-QRegion &QRegion::operator=(const QRegion &r)
-{
- r.d->ref.ref();
- if (!d->ref.deref())
- cleanUp(d);
- d = r.d;
- return *this;
-}
-
-
-QRegion QRegion::copy() const
-{
- QRegion r;
- QRegionData *x = new QRegionData;
- x->ref = 1;
- if (d->rgn) {
- x->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 2, 2);
- CombineRgn(x->rgn, d->rgn, 0, RGN_COPY);
- } else {
- x->rgn = 0;
- }
- if (!r.d->ref.deref())
- cleanUp(r.d);
- r.d = x;
- return r;
-}
-
-bool QRegion::isEmpty() const
-{
- return (d == &shared_empty || boundingRect().isEmpty());
-}
-
-
-bool QRegion::contains(const QPoint &p) const
-{
- return d->rgn ? PtInRegion(d->rgn, p.x(), p.y()) : false;
-}
-
-bool QRegion::contains(const QRect &r) const
-{
- if (!d->rgn)
- return false;
- RECT rect;
- SetRect(&rect, r.left(), r.top(), r.right(), r.bottom());
- return RectInRegion(d->rgn, &rect);
-}
-
-
-void QRegion::translate(int dx, int dy)
-{
- if (!d->rgn || (dx == 0 && dy == 0))
- return;
- detach();
- OffsetRgn(d->rgn, dx, dy);
-}
-
-
-#define RGN_NOP -1
-
-// Duplicates of those in qregion.cpp
-#define QRGN_OR 6
-#define QRGN_AND 7
-#define QRGN_SUB 8
-#define QRGN_XOR 9
-
-/*
- Performs the actual OR, AND, SUB and XOR operation between regions.
- Sets the resulting region handle to 0 to indicate an empty region.
-*/
-
-QRegion QRegion::winCombine(const QRegion &r, int op) const
+QRegion qt_region_from_HRGN(HRGN rgn)
{
- int both=RGN_NOP,
- left=RGN_NOP,
- right=RGN_NOP;
- switch (op) {
- case QRGN_OR:
- both = RGN_OR;
- left = right = RGN_COPY;
- break;
- case QRGN_AND:
- both = RGN_AND;
- break;
- case QRGN_SUB:
- both = RGN_DIFF;
- left = RGN_COPY;
- break;
- case QRGN_XOR:
- both = RGN_XOR;
- left = right = RGN_COPY;
- break;
- default:
- qWarning("QRegion: Internal error in winCombine");
- }
-
- int allCombineRgnResults = NULLREGION;
- QRegion result;
- result.detach();
- result.d->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 0, 0);
- if (d->rgn && r.d->rgn)
- allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, r.d->rgn, both);
- else if (d->rgn && left != RGN_NOP)
- allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, d->rgn, left);
- else if (r.d->rgn && right != RGN_NOP)
- allCombineRgnResults = CombineRgn(result.d->rgn, r.d->rgn, r.d->rgn, right);
-
- if (allCombineRgnResults == NULLREGION || allCombineRgnResults == ERROR)
- result = QRegion();
-
- //##### do not delete this. A null pointer is different from an empty region in SelectClipRgn in qpainter_win! (M)
-// if (allCombineRgnResults == NULLREGION) {
-// if (result.data->rgn)
-// DeleteObject(result.data->rgn);
-// result.data->rgn = 0; // empty region
-// }
- return result;
-}
-
-QRegion QRegion::unite(const QRegion &r) const
-{
- if (!d->rgn)
- return r;
- if (!r.d->rgn)
- return *this;
- return winCombine(r, QRGN_OR);
-}
-
-QRegion QRegion::unite(const QRect &r) const
-{
- return unite(QRegion(r));
-}
-
-QRegion QRegion::intersect(const QRegion &r) const
-{
- if (!r.d->rgn || !d->rgn)
- return QRegion();
- return winCombine(r, QRGN_AND);
-}
-
-QRegion QRegion::subtract(const QRegion &r) const
-{
- if (!r.d->rgn || !d->rgn)
- return *this;
- return winCombine(r, QRGN_SUB);
-}
-
-QRegion QRegion::eor(const QRegion &r) const
-{
- if (!d->rgn)
- return r;
- if (!r.d->rgn)
- return *this;
- return winCombine(r, QRGN_XOR);
-}
-
-
-QRect QRegion::boundingRect() const
-{
- if (!d->rgn)
- return QRect();
- RECT r;
- if (GetRgnBox(d->rgn, &r) == NULLREGION)
- return QRect();
- else
- return QRect(r.left, r.top, r.right - r.left, r.bottom - r.top);
-}
-
-QVector<QRect> QRegion::rects() const
-{
- if (d->rgn == 0)
- return QVector<QRect>();
-
- int numBytes = GetRegionData(d->rgn, 0, 0);
+ int numBytes = GetRegionData(rgn, 0, 0);
if (numBytes == 0)
- return QVector<QRect>();
+ return QRegion();
char *buf = new char[numBytes];
if (buf == 0)
- return QVector<QRect>();
+ return QRegion();
RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf);
- if (GetRegionData(d->rgn, numBytes, rd) == 0) {
+ if (GetRegionData(rgn, numBytes, rd) == 0) {
delete [] buf;
- return QVector<QRect>();
+ return QRegion();
}
- QVector<QRect> a(rd->rdh.nCount);
+ QRegion region;
RECT *r = reinterpret_cast<RECT*>(rd->Buffer);
- for (int i = 0; i < a.size(); ++i) {
- a[i].setCoords(r->left, r->top, r->right - 1, r->bottom - 1);
+ for (uint i = 0; i < rd->rdh.nCount; ++i) {
+ QRect rect;
+ rect.setCoords(r->left, r->top, r->right - 1, r->bottom - 1);
++r;
+ region |= rect;
}
delete [] buf;
- return a;
-}
-
-void QRegion::setRects(const QRect *rects, int num)
-{
- *this = QRegion();
- if (!rects || num == 0 || (num == 1 && rects->isEmpty()))
- return;
- for (int i = 0; i < num; ++i)
- *this |= rects[i];
-}
-
-int QRegion::numRects() const
-{
- if (d->rgn == 0)
- return 0;
-
- const int numBytes = GetRegionData(d->rgn, 0, 0);
- if (numBytes == 0)
- return 0;
-
- char *buf = new char[numBytes];
- if (buf == 0)
- return 0;
-
- RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf);
- if (GetRegionData(d->rgn, numBytes, rd) == 0) {
- delete[] buf;
- return 0;
- }
-
- const int n = rd->rdh.nCount;
- delete[] buf;
- return n;
+ return region;
}
-bool QRegion::operator==(const QRegion &r) const
+void qt_win_dispose_rgn(HRGN r)
{
- if (d == r.d)
- return true;
- if ((d->rgn == 0) ^ (r.d->rgn == 0)) // one is empty, not both
- return false;
- return d->rgn == 0 ? true // both empty
- : EqualRgn(d->rgn, r.d->rgn); // both non-empty
+ if (r)
+ DeleteObject(r);
}
-QRegion& QRegion::operator+=(const QRegion &r)
+static void qt_add_rect(HRGN &winRegion, QRect r)
{
- if (!r.d->rgn)
- return *this;
-
- if (!d->rgn) {
- *this = r;
- return *this;
+ HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
+ if (rgn) {
+ HRGN dest = CreateRectRgn(0,0,0,0);
+ int result = CombineRgn(dest, winRegion, rgn, RGN_OR);
+ if (result) {
+ DeleteObject(winRegion);
+ winRegion = dest;
+ }
+ DeleteObject(rgn);
}
-
- detach();
-
- int result;
- result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_OR);
- if (result == NULLREGION || result == ERROR)
- *this = QRegion();
-
- return *this;
-}
-
-QRegion& QRegion::operator-=(const QRegion &r)
-{
- if (!r.d->rgn || !d->rgn)
- return *this;
-
- detach();
-
- int result;
- result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_DIFF);
- if (result == NULLREGION || result == ERROR)
- *this = QRegion();
-
- return *this;
}
-QRegion& QRegion::operator&=(const QRegion &r)
+void QRegion::ensureHandle() const
{
- if (!d->rgn)
- return *this;
-
- if (!r.d->rgn) {
- *this = QRegion();
- return *this;
+ if (d->rgn)
+ DeleteObject(d->rgn);
+ d->rgn = CreateRectRgn(0,0,0,0);
+ if (d->qt_rgn) {
+ if (d->qt_rgn->numRects == 1) {
+ QRect r = d->qt_rgn->extents;
+ qt_add_rect(d->rgn, r);
+ return;
+ }
+ for (int i = 0;i < d->qt_rgn->numRects;i++) {
+ QRect r = d->qt_rgn->rects.at(i);
+ qt_add_rect(d->rgn, r);
+ }
}
-
- detach();
-
- int result;
- result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_AND);
- if (result == NULLREGION || result == ERROR)
- *this = QRegion();
-
- return *this;
-}
-
-bool qt_region_strictContains(const QRegion &region, const QRect &rect)
-{
- Q_UNUSED(region);
- Q_UNUSED(rect);
- return false;
}
-void QRegion::ensureHandle() const
-{
-}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qregion_wince.cpp b/src/gui/painting/qregion_wince.cpp
deleted file mode 100644
index 39d19b0..0000000
--- a/src/gui/painting/qregion_wince.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qatomic.h"
-#include "qbitmap.h"
-#include "qbuffer.h"
-#include "qimage.h"
-#include "qpolygon.h"
-#include "qregion.h"
-#include "qt_windows.h"
-#include "qpainterpath.h"
-#include "qguifunctions_wince.h"
-
-QT_BEGIN_NAMESPACE
-
-QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 };
-
-HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom)
-{
- const int tries = 10;
- for (int i = 0; i < tries; ++i) {
- HRGN region;
- switch (type) {
- case QRegion::Rectangle:
- region = CreateRectRgn(left, top, right, bottom);
- break;
- case QRegion::Ellipse:
-#ifndef Q_OS_WINCE
- region = CreateEllipticRgn(left, top, right, bottom);
-#endif
- break;
- }
- if (region) {
- if (GetRegionData(region, 0, 0))
- return region;
- else
- DeleteObject(region);
- }
- }
- return 0;
-}
-
-void qt_win_dispose_rgn(HRGN r)
-{
- if (r)
- DeleteObject(r);
-}
-
-static void qt_add_rect(HRGN &winRegion, QRect r)
-{
- HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
- if (rgn) {
- HRGN dest = CreateRectRgn(0,0,0,0);
- int result = CombineRgn(dest, winRegion, rgn, RGN_OR);
- if (result) {
- DeleteObject(winRegion);
- winRegion = dest;
- }
- }
-}
-
-void QRegion::ensureHandle() const
-{
- if (d->rgn)
- DeleteObject(d->rgn);
- d->rgn = CreateRectRgn(0,0,0,0);
- if (d->qt_rgn) {
- if (d->qt_rgn->numRects == 1) {
- QRect r = d->qt_rgn->extents;
- qt_add_rect(d->rgn, r);
- return;
- }
- for (int i = 0;i < d->qt_rgn->numRects;i++) {
- QRect r = d->qt_rgn->rects.at(i);
- qt_add_rect(d->rgn, r);
- }
- }
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index 94f5e2e..196a365 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -763,7 +763,7 @@ template <class Iterator> bool qt_stroke_side(Iterator *it,
qreal qt_t_for_arc_angle(qreal angle)
{
- if (qFuzzyCompare(angle + 1, qreal(1)))
+ if (qFuzzyIsNull(angle))
return 0;
if (qFuzzyCompare(angle, qreal(90)))
@@ -904,13 +904,13 @@ QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLengt
}
// avoid empty start segment
- if (qFuzzyCompare(startT, qreal(1))) {
+ if (qFuzzyIsNull(startT - qreal(1))) {
startT = 0;
startSegment += delta;
}
// avoid empty end segment
- if (qFuzzyCompare(endT + 1, qreal(1))) {
+ if (qFuzzyIsNull(endT)) {
endT = 1;
endSegment -= delta;
}
@@ -918,8 +918,8 @@ QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLengt
startT = qt_t_for_arc_angle(startT * 90);
endT = qt_t_for_arc_angle(endT * 90);
- const bool splitAtStart = !qFuzzyCompare(startT + 1, qreal(1));
- const bool splitAtEnd = !qFuzzyCompare(endT, qreal(1));
+ const bool splitAtStart = !qFuzzyIsNull(startT);
+ const bool splitAtEnd = !qFuzzyIsNull(endT - qreal(1));
const int end = endSegment + delta;
@@ -1021,7 +1021,7 @@ void QDashStroker::processCurrentSubpath()
longestLength = dashes[i];
}
- if (qFuzzyCompare(sumLength + 1, qreal(1)))
+ if (qFuzzyIsNull(sumLength))
return;
Q_ASSERT(dashCount > 0);
diff --git a/src/gui/painting/qstylepainter.cpp b/src/gui/painting/qstylepainter.cpp
index ce78200..7b83527 100644
--- a/src/gui/painting/qstylepainter.cpp
+++ b/src/gui/painting/qstylepainter.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
elements inside a widget.
\ingroup appearance
- \ingroup multimedia
+ \ingroup painting
QStylePainter extends QPainter with a set of high-level \c
draw...() functions implemented on top of QStyle's API. The
diff --git a/src/gui/painting/qtessellator.cpp b/src/gui/painting/qtessellator.cpp
index 10c7b32..0fa1d51 100644
--- a/src/gui/painting/qtessellator.cpp
+++ b/src/gui/painting/qtessellator.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
#ifdef DEBUG
#define QDEBUG qDebug
#else
-#define QDEBUG if (1); else qDebug
+#define QDEBUG if (1){} else qDebug
#endif
static const bool emit_clever = true;
@@ -406,9 +406,9 @@ void QTessellatorPrivate::Scanline::init(int maxActiveEdges)
if (!edges || maxActiveEdges > default_alloc) {
max_edges = maxActiveEdges;
int s = qMax(maxActiveEdges + 1, default_alloc + 1);
- edges = (Edge **)realloc(edges, s*sizeof(Edge *));
- edge_table = (Edge *)realloc(edge_table, s*sizeof(Edge));
- old = (Edge **)realloc(old, s*sizeof(Edge *));
+ edges = q_check_ptr((Edge **)realloc(edges, s*sizeof(Edge *)));
+ edge_table = q_check_ptr((Edge *)realloc(edge_table, s*sizeof(Edge)));
+ old = q_check_ptr((Edge **)realloc(old, s*sizeof(Edge *)));
}
size = 0;
old_size = 0;
@@ -566,8 +566,8 @@ void QTessellatorPrivate::Vertices::init(int maxVertices)
{
if (!storage || maxVertices > allocated) {
int size = qMax((int)default_alloc, maxVertices);
- storage = (Vertex *)realloc(storage, size*sizeof(Vertex));
- sorted = (Vertex **)realloc(sorted, size*sizeof(Vertex *));
+ storage = q_check_ptr((Vertex *)realloc(storage, size*sizeof(Vertex)));
+ sorted = q_check_ptr((Vertex **)realloc(sorted, size*sizeof(Vertex *)));
allocated = maxVertices;
}
}
@@ -703,7 +703,6 @@ struct QCoincidingEdge {
}
};
-
static void cancelEdges(QCoincidingEdge &e1, QCoincidingEdge &e2)
{
if (e1.before) {
@@ -740,7 +739,7 @@ void QTessellatorPrivate::cancelCoincidingEdges()
if (testListSize > tlSize - 2) {
tlSize = qMax(tlSize*2, 16);
- tl = (QCoincidingEdge *)realloc(tl, tlSize*sizeof(QCoincidingEdge));
+ tl = q_check_ptr((QCoincidingEdge *)realloc(tl, tlSize*sizeof(QCoincidingEdge)));
}
if (n->flags & (LineBeforeStarts|LineBeforeHorizontal)) {
tl[testListSize].start = n;
@@ -1081,7 +1080,7 @@ void QTessellatorPrivate::addIntersection(const Edge *e1, const Edge *e2)
yi = y;
}
QDEBUG() << " between edges " << e1->edge << "and" << e2->edge << "at point ("
- << Q27Dot5ToDouble(yi) << ")";
+ << Q27Dot5ToDouble(yi) << ')';
Intersection i1;
i1.y = yi;
@@ -1174,7 +1173,7 @@ void QTessellatorPrivate::addIntersections()
for (int i = 0; i < scanline.size; ++i) {
Edge *e = scanline.edges[i];
QDEBUG() << " " << i << e->edge << "isect=(" << e->intersect_left << e->intersect_right
- << ")";
+ << ')';
}
#endif
@@ -1240,8 +1239,8 @@ QRectF QTessellator::tessellate(const QPointF *points, int nPoints)
QDEBUG() << " " << i << ": "
<< "point=" << d->vertices.position(d->vertices.sorted[i])
<< "flags=" << d->vertices.sorted[i]->flags
- << "pos=(" << Q27Dot5ToDouble(d->vertices.sorted[i]->x) << "/"
- << Q27Dot5ToDouble(d->vertices.sorted[i]->y) << ")";
+ << "pos=(" << Q27Dot5ToDouble(d->vertices.sorted[i]->x) << '/'
+ << Q27Dot5ToDouble(d->vertices.sorted[i]->y) << ')';
}
#endif
@@ -1271,9 +1270,9 @@ QRectF QTessellator::tessellate(const QPointF *points, int nPoints)
for (int i = 0; i < d->scanline.size; ++i) {
QDEBUG() << " " << d->scanline.edges[i]->edge
<< "p0= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v0->x)
- << "/" << Q27Dot5ToDouble(d->scanline.edges[i]->v0->y)
+ << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v0->y)
<< ") p1= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v1->x)
- << "/" << Q27Dot5ToDouble(d->scanline.edges[i]->v1->y) << ")"
+ << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v1->y) << ')'
<< "x=" << Q27Dot5ToDouble(d->scanline.edges[i]->positionAt(d->y))
<< "isLeftOfNext="
<< ((i < d->scanline.size - 1)
@@ -1436,7 +1435,7 @@ void QTessellator::tessellateRect(const QPointF &a_, const QPointF &b_, qreal wi
QPointF perp(pb.y() - pa.y(), pa.x() - pb.x());
qreal length = qSqrt(perp.x() * perp.x() + perp.y() * perp.y());
- if (qFuzzyCompare(length + 1, static_cast<qreal>(1)))
+ if (qFuzzyIsNull(length))
return;
// need the half of the width
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 444231d..ee523b8 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -157,6 +157,46 @@ void QTextureGlyphCache::populate(const QTextItemInt &ti,
}
+QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const
+{
+#if defined(Q_WS_X11)
+ if (m_transform.type() > QTransform::TxTranslate) {
+ QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_None;
+ QImage::Format imageFormat = QImage::Format_Invalid;
+ switch (m_type) {
+ case Raster_RGBMask:
+ format = QFontEngineFT::Format_A32;
+ imageFormat = QImage::Format_RGB32;
+ break;
+ case Raster_A8:
+ format = QFontEngineFT::Format_A8;
+ imageFormat = QImage::Format_Indexed8;
+ break;
+ case Raster_Mono:
+ format = QFontEngineFT::Format_Mono;
+ imageFormat = QImage::Format_Mono;
+ break;
+ };
+
+ QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_textitem->fontEngine);
+ QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
+
+ if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
+ QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g);
+ const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3
+ : (glyph->width + 3) & ~3);
+ return QImage(glyph->data, glyph->width, glyph->height, bytesPerLine, imageFormat);
+ }
+ } else
+#endif
+ if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
+ return m_current_textitem->fontEngine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
+ else
+ return m_current_textitem->fontEngine->alphaMapForGlyph(g, m_transform);
+
+ return QImage();
+}
+
/************************************************************************
* QImageTextureGlyphCache
*/
@@ -198,34 +238,7 @@ int QImageTextureGlyphCache::glyphMargin() const
void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g)
{
- QImage mask;
-#if defined(Q_WS_X11)
- if (m_transform.type() > QTransform::TxTranslate) {
- QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_None;
- switch (m_type) {
- case Raster_RGBMask:
- format = QFontEngineFT::Format_A32; break;
- case Raster_A8:
- format = QFontEngineFT::Format_A8; break;
- case Raster_Mono:
- format = QFontEngineFT::Format_Mono; break;
- };
-
- QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_textitem->fontEngine);
- QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
-
- if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
- QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g);
- const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3
- : (glyph->width + 3) & ~3);
- mask = QImage(glyph->data, glyph->width, glyph->height, bytesPerLine, m_image.format());
- }
- } else
-#endif
- if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
- mask = m_current_textitem->fontEngine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
- else
- mask = m_current_textitem->fontEngine->alphaMapForGlyph(g, m_transform);
+ QImage mask = textureMapForGlyph(g);
#ifdef CACHE_DEBUG
printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height());
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index 1035ed1..f14c790 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -60,6 +60,10 @@
#include <private/qfontengineglyphcache_p.h>
+#if defined(Q_OS_VXWORKS) && defined(m_type)
+# undef m_type
+#endif
+
struct glyph_metrics_t;
typedef unsigned int glyph_t;
@@ -108,6 +112,8 @@ public:
QHash<glyph_t, Coord> coords;
+ QImage textureMapForGlyph(glyph_t g) const;
+
protected:
const QTextItemInt *m_current_textitem;
@@ -116,11 +122,10 @@ protected:
int m_cx; // current x
int m_cy; // current y
QFontEngineGlyphCache::Type m_type;
-
};
-class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache
+class QImageTextureGlyphCache : public QTextureGlyphCache
{
public:
QImageTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix)
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 0da0a15..4f27596 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -48,11 +48,15 @@
#include "qvariant.h"
#include <qmath.h>
+#include <private/qbezier_p.h>
+
QT_BEGIN_NAMESPACE
#define Q_NEAR_CLIP 0.000001
-
+#ifdef MAP
+# undef MAP
+#endif
#define MAP(x, y, nx, ny) \
do { \
qreal FX_ = x; \
@@ -76,7 +80,9 @@ QT_BEGIN_NAMESPACE
nx = affine._m11 * FX_ + affine._m21 * FY_ + affine._dx; \
ny = affine._m12 * FX_ + affine._m22 * FY_ + affine._dy; \
if (t == TxProject) { \
- qreal w = 1./(m_13 * FX_ + m_23 * FY_ + m_33); \
+ qreal w = (m_13 * FX_ + m_23 * FY_ + m_33); \
+ if (w < qreal(Q_NEAR_CLIP)) w = qreal(Q_NEAR_CLIP); \
+ w = 1./w; \
nx *= w; \
ny *= w; \
} \
@@ -87,7 +93,7 @@ QT_BEGIN_NAMESPACE
\class QTransform
\brief The QTransform class specifies 2D transformations of a coordinate system.
\since 4.3
- \ingroup multimedia
+ \ingroup painting
A transformation specifies how to translate, scale, shear, rotate
or project the coordinate system, and is typically used when
@@ -97,7 +103,7 @@ QT_BEGIN_NAMESPACE
allowing perspective transformations. QTransform's toAffine()
method allows casting QTransform to QMatrix. If a perspective
transformation has been specified on the matrix, then the
- conversion to an affine QMatrix will cause loss of data.
+ conversion will cause loss of data.
QTransform is the recommended transformation class in Qt.
@@ -121,11 +127,13 @@ QT_BEGIN_NAMESPACE
which returns true if the matrix is non-singular (i.e. AB = BA =
I). The inverted() function returns an inverted copy of \e this
matrix if it is invertible (otherwise it returns the identity
- matrix). In addition, QTransform provides the det() function
- returning the matrix's determinant.
+ matrix), and adjoint() returns the matrix's classical adjoint.
+ In addition, QTransform provides the determinant() function which
+ returns the matrix's determinant.
- Finally, the QTransform class supports matrix multiplication, and
- objects of the class can be streamed as well as compared.
+ Finally, the QTransform class supports matrix multiplication, addition
+ and subtraction, and objects of the class can be streamed as well
+ as compared.
\tableofcontents
@@ -187,7 +195,7 @@ QT_BEGIN_NAMESPACE
The various matrix elements can be set when constructing the
matrix, or by using the setMatrix() function later on. They can also
be manipulated using the translate(), rotate(), scale() and
- shear() convenience functions, The currently set values can be
+ shear() convenience functions. The currently set values can be
retrieved using the m11(), m12(), m13(), m21(), m22(), m23(),
m31(), m32(), m33(), dx() and dy() functions.
@@ -200,9 +208,9 @@ QT_BEGIN_NAMESPACE
to 0) mapping a point to itself. Shearing is controlled by \c m12
and \c m21. Setting these elements to values different from zero
will twist the coordinate system. Rotation is achieved by
- carefully setting both the shearing factors and the scaling
- factors. Perspective transformation is achieved by carefully setting
- both the projection factors and the scaling factors.
+ setting both the shearing factors and the scaling factors. Perspective
+ transformation is achieved by setting both the projection factors and
+ the scaling factors.
Here's the combined transformations example using basic matrix
operations:
@@ -230,6 +238,11 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QTransform::QTransform(Qt::Initialization)
+ \internal
+*/
+
+/*!
Constructs an identity matrix.
All elements are set to zero except \c m11 and \c m22 (specifying
@@ -238,11 +251,11 @@ QT_BEGIN_NAMESPACE
\sa reset()
*/
QTransform::QTransform()
- : m_13(0), m_23(0), m_33(1)
+ : affine(true)
+ , m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxNone)
{
-
}
/*!
@@ -256,12 +269,11 @@ QTransform::QTransform()
QTransform::QTransform(qreal h11, qreal h12, qreal h13,
qreal h21, qreal h22, qreal h23,
qreal h31, qreal h32, qreal h33)
- : affine(h11, h12, h21, h22, h31, h32),
- m_13(h13), m_23(h23), m_33(h33)
+ : affine(h11, h12, h21, h22, h31, h32, true)
+ , m_13(h13), m_23(h23), m_33(h33)
, m_type(TxNone)
, m_dirty(TxProject)
{
-
}
/*!
@@ -273,12 +285,11 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h13,
*/
QTransform::QTransform(qreal h11, qreal h12, qreal h21,
qreal h22, qreal dx, qreal dy)
- : affine(h11, h12, h21, h22, dx, dy),
- m_13(0), m_23(0), m_33(1)
+ : affine(h11, h12, h21, h22, dx, dy, true)
+ , m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxShear)
{
-
}
/*!
@@ -289,12 +300,11 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h21,
and 1 respectively.
*/
QTransform::QTransform(const QMatrix &mtx)
- : affine(mtx),
+ : affine(mtx._m11, mtx._m12, mtx._m21, mtx._m22, mtx._dx, mtx._dy, true),
m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxShear)
{
-
}
/*!
@@ -317,7 +327,7 @@ QTransform QTransform::adjoint() const
return QTransform(h11, h12, h13,
h21, h22, h23,
- h31, h32, h33);
+ h31, h32, h33, true);
}
/*!
@@ -327,7 +337,7 @@ QTransform QTransform::transposed() const
{
QTransform t(affine._m11, affine._m21, affine._dx,
affine._m12, affine._m22, affine._dy,
- m_13, m_23, m_33);
+ m_13, m_23, m_33, true);
t.m_type = m_type;
t.m_dirty = m_dirty;
return t;
@@ -345,11 +355,10 @@ QTransform QTransform::transposed() const
*/
QTransform QTransform::inverted(bool *invertible) const
{
- QTransform invert;
+ QTransform invert(true);
bool inv = true;
- qreal det;
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
break;
case TxTranslate:
@@ -357,11 +366,11 @@ QTransform QTransform::inverted(bool *invertible) const
invert.affine._dy = -affine._dy;
break;
case TxScale:
- inv = !qFuzzyCompare(affine._m11 + 1, 1);
- inv &= !qFuzzyCompare(affine._m22 + 1, 1);
+ inv = !qFuzzyIsNull(affine._m11);
+ inv &= !qFuzzyIsNull(affine._m22);
if (inv) {
- invert.affine._m11 = 1 / affine._m11;
- invert.affine._m22 = 1 / affine._m22;
+ invert.affine._m11 = 1. / affine._m11;
+ invert.affine._m22 = 1. / affine._m22;
invert.affine._dx = -affine._dx * invert.affine._m11;
invert.affine._dy = -affine._dy * invert.affine._m22;
}
@@ -372,8 +381,8 @@ QTransform QTransform::inverted(bool *invertible) const
break;
default:
// general case
- det = determinant();
- inv = !qFuzzyCompare(det + 1, 1);
+ qreal det = determinant();
+ inv = !qFuzzyIsNull(det);
if (inv)
invert = adjoint() / det;
break;
@@ -397,12 +406,12 @@ QTransform QTransform::inverted(bool *invertible) const
\sa setMatrix()
*/
-QTransform & QTransform::translate(qreal dx, qreal dy)
+QTransform &QTransform::translate(qreal dx, qreal dy)
{
if (dx == 0 && dy == 0)
return *this;
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
affine._dx = dx;
affine._dy = dy;
@@ -424,7 +433,8 @@ QTransform & QTransform::translate(qreal dx, qreal dy)
affine._dy += dy*affine._m22 + dx*affine._m12;
break;
}
- m_dirty |= TxTranslate;
+ if (m_dirty < TxTranslate)
+ m_dirty = TxTranslate;
return *this;
}
@@ -437,11 +447,12 @@ QTransform & QTransform::translate(qreal dx, qreal dy)
*/
QTransform QTransform::fromTranslate(qreal dx, qreal dy)
{
- QTransform transform(1, 0, 0, 1, dx, dy);
+ QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true);
if (dx == 0 && dy == 0)
- transform.m_dirty = TxNone;
+ transform.m_type = TxNone;
else
- transform.m_dirty = TxTranslate;
+ transform.m_type = TxTranslate;
+ transform.m_dirty = TxNone;
return transform;
}
@@ -456,7 +467,7 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
if (sx == 1 && sy == 1)
return *this;
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
case TxTranslate:
affine._m11 = sx;
@@ -476,7 +487,8 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
affine._m22 *= sy;
break;
}
- m_dirty |= TxScale;
+ if (m_dirty < TxScale)
+ m_dirty = TxScale;
return *this;
}
@@ -489,11 +501,12 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
*/
QTransform QTransform::fromScale(qreal sx, qreal sy)
{
- QTransform transform(sx, 0, 0, sy, 0, 0);
- if (sx == 1 && sy == 1)
- transform.m_dirty = TxNone;
+ QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true);
+ if (sx == 1. && sy == 1.)
+ transform.m_type = TxNone;
else
- transform.m_dirty = TxScale;
+ transform.m_type = TxScale;
+ transform.m_dirty = TxNone;
return transform;
}
@@ -505,7 +518,10 @@ QTransform QTransform::fromScale(qreal sx, qreal sy)
*/
QTransform & QTransform::shear(qreal sh, qreal sv)
{
- switch(type()) {
+ if (sh == 0 && sv == 0)
+ return *this;
+
+ switch(inline_type()) {
case TxNone:
case TxTranslate:
affine._m12 = sv;
@@ -533,7 +549,8 @@ QTransform & QTransform::shear(qreal sh, qreal sv)
break;
}
}
- m_dirty |= TxShear;
+ if (m_dirty < TxShear)
+ m_dirty = TxShear;
return *this;
}
@@ -574,7 +591,7 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
}
if (axis == Qt::ZAxis) {
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
case TxTranslate:
affine._m11 = cosa;
@@ -609,7 +626,8 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
break;
}
}
- m_dirty |= TxRotate;
+ if (m_dirty < TxRotate)
+ m_dirty = TxRotate;
} else {
QTransform result;
if (axis == Qt::YAxis) {
@@ -646,7 +664,7 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
qreal cosa = qCos(a);
if (axis == Qt::ZAxis) {
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
case TxTranslate:
affine._m11 = cosa;
@@ -681,7 +699,8 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
break;
}
}
- m_dirty |= TxRotate;
+ if (m_dirty < TxRotate)
+ m_dirty = TxRotate;
} else {
QTransform result;
if (axis == Qt::YAxis) {
@@ -704,11 +723,15 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
*/
bool QTransform::operator==(const QTransform &o) const
{
-#define qFZ qFuzzyCompare
- return qFZ(affine._m11, o.affine._m11) && qFZ(affine._m12, o.affine._m12) && qFZ(m_13, o.m_13)
- && qFZ(affine._m21, o.affine._m21) && qFZ(affine._m22, o.affine._m22) && qFZ(m_23, o.m_23)
- && qFZ(affine._dx, o.affine._dx) && qFZ(affine._dy, o.affine._dy) && qFZ(m_33, o.m_33);
-#undef qFZ
+ return affine._m11 == o.affine._m11 &&
+ affine._m12 == o.affine._m12 &&
+ affine._m21 == o.affine._m21 &&
+ affine._m22 == o.affine._m22 &&
+ affine._dx == o.affine._dx &&
+ affine._dy == o.affine._dy &&
+ m_13 == o.m_13 &&
+ m_23 == o.m_23 &&
+ m_33 == o.m_33;
}
/*!
@@ -730,11 +753,11 @@ bool QTransform::operator!=(const QTransform &o) const
*/
QTransform & QTransform::operator*=(const QTransform &o)
{
- const TransformationType otherType = o.type();
+ const TransformationType otherType = o.inline_type();
if (otherType == TxNone)
return *this;
- const TransformationType thisType = type();
+ const TransformationType thisType = inline_type();
if (thisType == TxNone)
return operator=(o);
@@ -812,9 +835,77 @@ QTransform & QTransform::operator*=(const QTransform &o)
*/
QTransform QTransform::operator*(const QTransform &m) const
{
- QTransform result = *this;
- result *= m;
- return result;
+ const TransformationType otherType = m.inline_type();
+ if (otherType == TxNone)
+ return *this;
+
+ const TransformationType thisType = inline_type();
+ if (thisType == TxNone)
+ return m;
+
+ QTransform t(true);
+ TransformationType type = qMax(thisType, otherType);
+ switch(type) {
+ case TxNone:
+ break;
+ case TxTranslate:
+ t.affine._dx = affine._dx + m.affine._dx;
+ t.affine._dy += affine._dy + m.affine._dy;
+ break;
+ case TxScale:
+ {
+ qreal m11 = affine._m11*m.affine._m11;
+ qreal m22 = affine._m22*m.affine._m22;
+
+ qreal m31 = affine._dx*m.affine._m11 + m.affine._dx;
+ qreal m32 = affine._dy*m.affine._m22 + m.affine._dy;
+
+ t.affine._m11 = m11;
+ t.affine._m22 = m22;
+ t.affine._dx = m31; t.affine._dy = m32;
+ break;
+ }
+ case TxRotate:
+ case TxShear:
+ {
+ qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21;
+ qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22;
+
+ qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21;
+ qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22;
+
+ qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m.affine._dx;
+ qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m.affine._dy;
+
+ t.affine._m11 = m11; t.affine._m12 = m12;
+ t.affine._m21 = m21; t.affine._m22 = m22;
+ t.affine._dx = m31; t.affine._dy = m32;
+ break;
+ }
+ case TxProject:
+ {
+ qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21 + m_13*m.affine._dx;
+ qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22 + m_13*m.affine._dy;
+ qreal m13 = affine._m11*m.m_13 + affine._m12*m.m_23 + m_13*m.m_33;
+
+ qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21 + m_23*m.affine._dx;
+ qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22 + m_23*m.affine._dy;
+ qreal m23 = affine._m21*m.m_13 + affine._m22*m.m_23 + m_23*m.m_33;
+
+ qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m_33*m.affine._dx;
+ qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m_33*m.affine._dy;
+ qreal m33 = affine._dx*m.m_13 + affine._dy*m.m_23 + m_33*m.m_33;
+
+ t.affine._m11 = m11; t.affine._m12 = m12; t.m_13 = m13;
+ t.affine._m21 = m21; t.affine._m22 = m22; t.m_23 = m23;
+ t.affine._dx = m31; t.affine._dy = m32; t.m_33 = m33;
+ }
+ }
+
+ t.m_dirty = type;
+ t.m_type = type;
+
+ return t;
}
/*!
@@ -871,8 +962,8 @@ QTransform & QTransform::operator=(const QTransform &matrix)
/*!
Resets the matrix to an identity matrix, i.e. all elements are set
- to zero, except \c m11 and \c m22 (specifying the scale) which are
- set to 1.
+ to zero, except \c m11 and \c m22 (specifying the scale) and \c m33
+ which are set to 1.
\sa QTransform(), isIdentity(), {QTransform#Basic Matrix
Operations}{Basic Matrix Operations}
@@ -956,7 +1047,7 @@ QDebug operator<<(QDebug dbg, const QTransform &m)
<< " 31=" << m.m31()
<< " 32=" << m.m32()
<< " 33=" << m.m33()
- << ")";
+ << ')';
return dbg.space();
}
#endif
@@ -976,7 +1067,7 @@ QPoint QTransform::map(const QPoint &p) const
qreal x = 0, y = 0;
- TransformationType t = type();
+ TransformationType t = inline_type();
switch(t) {
case TxNone:
x = fx;
@@ -1027,7 +1118,7 @@ QPointF QTransform::map(const QPointF &p) const
qreal x = 0, y = 0;
- TransformationType t = type();
+ TransformationType t = inline_type();
switch(t) {
case TxNone:
x = fx;
@@ -1098,7 +1189,7 @@ QLine QTransform::map(const QLine &l) const
qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
- TransformationType t = type();
+ TransformationType t = inline_type();
switch(t) {
case TxNone:
x1 = fx1;
@@ -1157,7 +1248,7 @@ QLineF QTransform::map(const QLineF &l) const
qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
- TransformationType t = type();
+ TransformationType t = inline_type();
switch(t) {
case TxNone:
x1 = fx1;
@@ -1245,7 +1336,10 @@ static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &pol
*/
QPolygonF QTransform::map(const QPolygonF &a) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
+ if (t <= TxTranslate)
+ return a.translated(affine._dx, affine._dy);
+
if (t >= QTransform::TxProject)
return mapProjective(*this, a);
@@ -1272,7 +1366,10 @@ QPolygonF QTransform::map(const QPolygonF &a) const
*/
QPolygon QTransform::map(const QPolygon &a) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
+ if (t <= TxTranslate)
+ return a.translated(qRound(affine._dx), qRound(affine._dy));
+
if (t >= QTransform::TxProject)
return mapProjective(*this, QPolygonF(a)).toPolygon();
@@ -1314,7 +1411,7 @@ extern QPainterPath qt_regionToPath(const QRegion &region);
*/
QRegion QTransform::map(const QRegion &r) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
if (t == TxNone)
return r;
@@ -1341,7 +1438,7 @@ struct QHomogeneousCoordinate
QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_) : x(x_), y(y_), w(w_) {}
const QPointF toPoint() const {
- qreal iw = 1 / w;
+ qreal iw = 1. / w;
return QPointF(x * iw, y * iw);
}
};
@@ -1397,27 +1494,12 @@ static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transfor
static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo)
{
- const QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
- const QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
- const QHomogeneousCoordinate hc = mapHomogeneous(transform, c);
- const QHomogeneousCoordinate hd = mapHomogeneous(transform, d);
-
- if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP && hc.w < Q_NEAR_CLIP && hd.w < Q_NEAR_CLIP)
- return false;
-
- if (ha.w >= Q_NEAR_CLIP && hb.w >= Q_NEAR_CLIP && hc.w >= Q_NEAR_CLIP && hd.w >= Q_NEAR_CLIP) {
- if (needsMoveTo)
- path.moveTo(ha.toPoint());
+ // Convert projective xformed curves to line
+ // segments so they can be transformed more accurately
+ QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon();
- path.cubicTo(hb.toPoint(), hc.toPoint(), hd.toPoint());
- return true;
- }
-
- if (lineTo_clipped(path, transform, a, b, needsMoveTo))
- needsMoveTo = false;
- if (lineTo_clipped(path, transform, b, c, needsMoveTo))
- needsMoveTo = false;
- if (lineTo_clipped(path, transform, c, d, needsMoveTo))
+ for (int i = 0; i < segment.size() - 1; ++i)
+ if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
needsMoveTo = false;
return !needsMoveTo;
@@ -1482,7 +1564,7 @@ static QPainterPath mapProjective(const QTransform &transform, const QPainterPat
*/
QPainterPath QTransform::map(const QPainterPath &path) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
if (t == TxNone || path.isEmpty())
return path;
@@ -1490,15 +1572,11 @@ QPainterPath QTransform::map(const QPainterPath &path) const
return mapProjective(*this, path);
QPainterPath copy = path;
- copy.detach();
if (t == TxTranslate) {
- for (int i=0; i<path.elementCount(); ++i) {
- QPainterPath::Element &e = copy.d_ptr->elements[i];
- e.x += affine._dx;
- e.y += affine._dy;
- }
+ copy.translate(affine._dx, affine._dy);
} else {
+ copy.detach();
// Full xform
for (int i=0; i<path.elementCount(); ++i) {
QPainterPath::Element &e = copy.d_ptr->elements[i];
@@ -1531,7 +1609,7 @@ QPainterPath QTransform::map(const QPainterPath &path) const
*/
QPolygon QTransform::mapToPolygon(const QRect &rect) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
QPolygon a(4);
qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
@@ -1685,7 +1763,7 @@ bool QTransform::quadToQuad(const QPolygonF &one,
Sets the matrix elements to the specified values, \a m11,
\a m12, \a m13 \a m21, \a m22, \a m23 \a m31, \a m32 and
\a m33. Note that this function replaces the previous values.
- QMatrix provides the translate(), rotate(), scale() and shear()
+ QTransform provides the translate(), rotate(), scale() and shear()
convenience functions to manipulate the various matrix elements
based on the currently defined coordinate system.
@@ -1703,9 +1781,20 @@ void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
m_dirty = TxProject;
}
+static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform)
+{
+ const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right());
+ const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom());
+
+ return wx + wy + transform.m33() < Q_NEAR_CLIP;
+}
+
QRect QTransform::mapRect(const QRect &rect) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
+ if (t <= TxTranslate)
+ return rect.translated(qRound(affine._dx), qRound(affine._dy));
+
if (t <= TxScale) {
int x = qRound(affine._m11*rect.x() + affine._dx);
int y = qRound(affine._m22*rect.y() + affine._dy);
@@ -1720,7 +1809,7 @@ QRect QTransform::mapRect(const QRect &rect) const
y -= h;
}
return QRect(x, y, w, h);
- } else if (t < TxProject) {
+ } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
// see mapToPolygon for explanations of the algorithm.
qreal x = 0, y = 0;
MAP(rect.left(), rect.top(), x, y);
@@ -1772,7 +1861,10 @@ QRect QTransform::mapRect(const QRect &rect) const
*/
QRectF QTransform::mapRect(const QRectF &rect) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
+ if (t <= TxTranslate)
+ return rect.translated(affine._dx, affine._dy);
+
if (t <= TxScale) {
qreal x = affine._m11*rect.x() + affine._dx;
qreal y = affine._m22*rect.y() + affine._dy;
@@ -1787,7 +1879,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const
y -= h;
}
return QRectF(x, y, w, h);
- } else if (t < TxProject) {
+ } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
qreal x = 0, y = 0;
MAP(rect.x(), rect.y(), x, y);
qreal xmin = x;
@@ -1843,7 +1935,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const
*/
void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
MAP(x, y, *tx, *ty);
}
@@ -1857,7 +1949,7 @@ void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const
*/
void QTransform::map(int x, int y, int *tx, int *ty) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
qreal fx = 0, fy = 0;
MAP(x, y, fx, fy);
*tx = qRound(fx);
@@ -1865,8 +1957,11 @@ void QTransform::map(int x, int y, int *tx, int *ty) const
}
/*!
- Returns the QTransform cast to a QMatrix.
- */
+ Returns the QTransform as an affine matrix.
+
+ \warning If a perspective transformation has been specified,
+ then the conversion will cause loss of data.
+*/
const QMatrix &QTransform::toAffine() const
{
return affine;
@@ -1886,25 +1981,41 @@ const QMatrix &QTransform::toAffine() const
*/
QTransform::TransformationType QTransform::type() const
{
- if (m_dirty >= m_type) {
- if (m_dirty > TxShear && (!qFuzzyCompare(m_13 + 1, 1) || !qFuzzyCompare(m_23 + 1, 1) || !qFuzzyCompare(m_33, 1)))
+ if(m_dirty == TxNone || m_dirty < m_type)
+ return static_cast<TransformationType>(m_type);
+
+ switch (static_cast<TransformationType>(m_dirty)) {
+ case TxProject:
+ if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) {
m_type = TxProject;
- else if (m_dirty > TxScale && (!qFuzzyCompare(affine._m12 + 1, 1) || !qFuzzyCompare(affine._m21 + 1, 1))) {
+ break;
+ }
+ case TxShear:
+ case TxRotate:
+ if (!qFuzzyIsNull(affine._m12) || !qFuzzyIsNull(affine._m21)) {
const qreal dot = affine._m11 * affine._m12 + affine._m21 * affine._m22;
- if (qFuzzyCompare(dot + 1, 1))
+ if (qFuzzyIsNull(dot))
m_type = TxRotate;
else
m_type = TxShear;
- } else if (m_dirty > TxTranslate && (!qFuzzyCompare(affine._m11, 1) || !qFuzzyCompare(affine._m22, 1)))
+ break;
+ }
+ case TxScale:
+ if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) {
m_type = TxScale;
- else if (m_dirty > TxNone && (!qFuzzyCompare(affine._dx + 1, 1) || !qFuzzyCompare(affine._dy + 1, 1)))
+ break;
+ }
+ case TxTranslate:
+ if (!qFuzzyIsNull(affine._dx) || !qFuzzyIsNull(affine._dy)) {
m_type = TxTranslate;
- else
- m_type = TxNone;
-
- m_dirty = TxNone;
+ break;
+ }
+ case TxNone:
+ m_type = TxNone;
+ break;
}
+ m_dirty = TxNone;
return static_cast<TransformationType>(m_type);
}
@@ -1928,8 +2039,9 @@ QTransform::operator QVariant() const
/*!
\fn qreal QTransform::det() const
+ \obsolete
- Returns the matrix's determinant.
+ Returns the matrix's determinant. Use determinant() instead.
*/
@@ -2083,6 +2195,17 @@ QTransform::operator QVariant() const
\sa reset()
*/
+/*!
+ \fn bool qFuzzyCompare(const QTransform& t1, const QTransform& t2)
+
+ \relates QTransform
+ \since 4.6
+
+ Returns true if \a t1 and \a t2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+
// returns true if the transform is uniformly scaling
// (same scale in x and y direction)
// scale is set to the max of x and y scaling factors
diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h
index 4201e10..e6c1a4e 100644
--- a/src/gui/painting/qtransform.h
+++ b/src/gui/painting/qtransform.h
@@ -50,6 +50,10 @@
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
+#if defined(Q_OS_VXWORKS) && defined(m_type)
+# undef m_type
+#endif
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -71,6 +75,7 @@ public:
TxProject = 0x10
};
+ inline explicit QTransform(Qt::Initialization) : affine(Qt::Uninitialized) {}
QTransform();
QTransform(qreal h11, qreal h12, qreal h13,
qreal h21, qreal h22, qreal h23,
@@ -159,6 +164,19 @@ public:
static QTransform fromScale(qreal dx, qreal dy);
private:
+ inline QTransform(qreal h11, qreal h12, qreal h13,
+ qreal h21, qreal h22, qreal h23,
+ qreal h31, qreal h32, qreal h33, bool)
+ : affine(h11, h12, h21, h22, h31, h32, true)
+ , m_13(h13), m_23(h23), m_33(h33)
+ , m_type(TxNone)
+ , m_dirty(TxProject) {}
+ inline QTransform(bool)
+ : affine(true)
+ , m_13(0), m_23(0), m_33(1)
+ , m_type(TxNone)
+ , m_dirty(TxNone) {}
+ inline TransformationType inline_type() const;
QMatrix affine;
qreal m_13;
qreal m_23;
@@ -173,18 +191,25 @@ private:
Q_DECLARE_TYPEINFO(QTransform, Q_MOVABLE_TYPE);
/******* inlines *****/
+inline QTransform::TransformationType QTransform::inline_type() const
+{
+ if (m_dirty == TxNone)
+ return static_cast<TransformationType>(m_type);
+ return type();
+}
+
inline bool QTransform::isAffine() const
{
- return type() < TxProject;
+ return inline_type() < TxProject;
}
inline bool QTransform::isIdentity() const
{
- return type() == TxNone;
+ return inline_type() == TxNone;
}
inline bool QTransform::isInvertible() const
{
- return !qFuzzyCompare(determinant() + 1, 1);
+ return !qFuzzyIsNull(determinant());
}
inline bool QTransform::isScaling() const
@@ -193,12 +218,12 @@ inline bool QTransform::isScaling() const
}
inline bool QTransform::isRotating() const
{
- return type() >= TxRotate;
+ return inline_type() >= TxRotate;
}
inline bool QTransform::isTranslating() const
{
- return type() >= TxTranslate;
+ return inline_type() >= TxTranslate;
}
inline qreal QTransform::determinant() const
@@ -311,9 +336,25 @@ inline QTransform &QTransform::operator-=(qreal num)
return *this;
}
+inline bool qFuzzyCompare(const QTransform& t1, const QTransform& t2)
+{
+ return qFuzzyCompare(t1.m11(), t2.m11())
+ && qFuzzyCompare(t1.m12(), t2.m12())
+ && qFuzzyCompare(t1.m13(), t2.m13())
+ && qFuzzyCompare(t1.m21(), t2.m21())
+ && qFuzzyCompare(t1.m22(), t2.m22())
+ && qFuzzyCompare(t1.m23(), t2.m23())
+ && qFuzzyCompare(t1.m31(), t2.m31())
+ && qFuzzyCompare(t1.m32(), t2.m32())
+ && qFuzzyCompare(t1.m33(), t2.m33());
+}
+
+
/****** stream functions *******************/
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTransform &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTransform &);
+#endif
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QTransform &);
diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h
index a03a8e1..1e909d4 100644
--- a/src/gui/painting/qvectorpath_p.h
+++ b/src/gui/painting/qvectorpath_p.h
@@ -55,9 +55,9 @@
#include <QtGui/qpaintengine.h>
-#include "qpaintengine_p.h"
-#include "qstroker_p.h"
-#include "qpainter_p.h"
+#include <private/qpaintengine_p.h>
+#include <private/qstroker_p.h>
+#include <private/qpainter_p.h>
QT_BEGIN_HEADER
@@ -94,7 +94,7 @@ public:
// Shape rendering specifiers...
OddEvenFill = 0x1000,
WindingFill = 0x2000,
- ImplicitClose = 0x4000,
+ ImplicitClose = 0x4000
};
// ### Falcon: introduca a struct XY for points so lars is not so confused...
@@ -112,7 +112,7 @@ public:
{
}
- const QRealRect &controlPointRect() const;
+ QRectF controlPointRect() const;
inline Hint shape() const { return (Hint) (m_hints & ShapeHintMask); }
@@ -130,6 +130,8 @@ public:
static inline uint polygonFlags(QPaintEngine::PolygonDrawMode mode);
+ QPainterPath convertToPainterPath() const;
+
private:
Q_DISABLE_COPY(QVectorPath)
diff --git a/src/gui/painting/qwindowsurface_d3d.cpp b/src/gui/painting/qwindowsurface_d3d.cpp
deleted file mode 100644
index 8f9403f..0000000
--- a/src/gui/painting/qwindowsurface_d3d.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//#define D3D_DEBUG_BACKBUFFER
-
-#include <QtGui/QPaintDevice>
-#include <QtGui/QWidget>
-#include "qdebug.h"
-
-#include "qpaintengine_d3d_p.h"
-#include "qwindowsurface_d3d_p.h"
-#include "private/qwidget_p.h"
-#include "private/qbackingstore_p.h"
-
-#include <d3d9.h>
-
-QT_BEGIN_NAMESPACE
-
-extern QDirect3DPaintEngine *qt_d3dEngine();
-
-struct QD3DWindowSurfacePrivate
-{
- QSize m_lastSize;
- QWidget *m_widget;
-};
-
-QD3DWindowSurface::QD3DWindowSurface(QWidget *window)
- : QWindowSurface(window), d_ptr(new QD3DWindowSurfacePrivate)
-{
- Q_ASSERT(window->isTopLevel());
- d_ptr->m_widget = window;
-}
-
-
-QD3DWindowSurface::~QD3DWindowSurface()
-{
- delete d_ptr;
-}
-
-QPaintDevice *QD3DWindowSurface::paintDevice()
-{
- return d_ptr->m_widget;
-}
-
-
-void QD3DWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset)
-{
- QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft();
-
- QDirect3DPaintEngine *engine = qt_d3dEngine();
- LPDIRECT3DSWAPCHAIN9 swapchain = engine->swapChain(d_ptr->m_widget);
-
- if (swapchain) {
- QRect br = rgn.boundingRect();
- QRect wbr = br.translated(-wOffset);
-
- RECT destrect;
- destrect.left = wbr.x();
- destrect.top = wbr.y();
- destrect.right = destrect.left + wbr.width();
- destrect.bottom = destrect.top + wbr.height();
-
- RECT srcrect;
- srcrect.left = br.x() + offset.x();
- srcrect.top = br.y() + offset.y();
- srcrect.right = wbr.width() + srcrect.left;
- srcrect.bottom = wbr.height() + srcrect.top;
- int devwidth = d_ptr->m_lastSize.width();
- int devheight = d_ptr->m_lastSize.height();
-
- if (devwidth <= srcrect.right) {
- int diff = srcrect.right - devwidth;
- srcrect.right -= diff;
- destrect.right -= diff;
- if (srcrect.right <= srcrect.left)
- return;
- }
- if (devheight <= srcrect.bottom) {
- int diff = srcrect.bottom - devheight;
- srcrect.bottom -= diff;
- destrect.bottom -= diff;
- if (srcrect.bottom <= srcrect.top)
- return;
- }
-
- if (FAILED(swapchain->Present(&srcrect, &destrect, widget->winId(), 0, 0)))
- qWarning("QDirect3DPaintEngine: failed to present back buffer.");
-
-#ifdef D3D_DEBUG_BACKBUFFER
- qDebug() << widget << srcrect.left << srcrect.top << wbr.width() << wbr.height() << "Dest: " << destrect.left << destrect.top;
- IDirect3DSurface9 *surface;
- swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &surface);
- QString filename("C:\\test.bmp");
- D3DXSaveSurfaceToFile(filename.utf16(), D3DXIFF_BMP, surface, 0, 0);
- surface->Release();
-#endif
- }
-}
-
-void QD3DWindowSurface::setGeometry(const QRect &rect)
-{
- if (rect.isEmpty())
- qt_d3dEngine()->releaseSwapChain(d_ptr->m_widget);
-
- d_ptr->m_lastSize = rect.size();
- QWindowSurface::setGeometry(rect);
-}
-
-
-bool QD3DWindowSurface::scroll(const QRegion &area, int dx, int dy)
-{
- QDirect3DPaintEngine *engine = qt_d3dEngine();
- QRect rect = area.boundingRect();
-
- RECT destrect;
- destrect.left = rect.x()+dx;
- destrect.top = rect.y()+dy;
- destrect.right = rect.width() + destrect.left;
- destrect.bottom = rect.height() + destrect.top;
-
- RECT srcrect;
- srcrect.left = rect.x();
- srcrect.top = rect.y();
- srcrect.right = rect.width() + srcrect.left;
- srcrect.bottom = rect.height() + srcrect.top;
-
- engine->scroll(d_ptr->m_widget, srcrect, destrect);
- return true;
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp
index 2348cce..514dc72 100644
--- a/src/gui/painting/qwindowsurface_raster.cpp
+++ b/src/gui/painting/qwindowsurface_raster.cpp
@@ -43,6 +43,7 @@
#include <qglobal.h> // for Q_WS_WIN define (non-PCH)
#ifdef Q_WS_WIN
+#include <qlibrary.h>
#include <qt_windows.h>
#endif
@@ -67,10 +68,6 @@
QT_BEGIN_NAMESPACE
-#ifdef Q_WS_WIN
-PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect;
-#endif
-
class QRasterWindowSurfacePrivate
{
public:
@@ -82,9 +79,6 @@ public:
uint translucentBackground : 1;
#endif
#endif
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
- uint canUseLayeredWindow : 1;
-#endif
uint inSetGeometry : 1;
};
@@ -98,10 +92,6 @@ QRasterWindowSurface::QRasterWindowSurface(QWidget *window)
&& window->x11Info().depth() == 32;
#endif
#endif
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
- d_ptr->canUseLayeredWindow = ptrUpdateLayeredWindowIndirect
- && (qt_widget_private(window)->data.window_flags & Qt::FramelessWindowHint);
-#endif
d_ptr->image = 0;
d_ptr->inSetGeometry = false;
setStaticContentsSupport(true);
@@ -115,8 +105,6 @@ QRasterWindowSurface::~QRasterWindowSurface()
#endif
if (d_ptr->image)
delete d_ptr->image;
-
- delete d_ptr;
}
@@ -127,11 +115,10 @@ QPaintDevice *QRasterWindowSurface::paintDevice()
void QRasterWindowSurface::beginPaint(const QRegion &rgn)
{
-#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE))
+#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE))
if (!qt_widget_private(window())->isOpaque && window()->testAttribute(Qt::WA_TranslucentBackground)) {
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
- if (d_ptr->image->image.format() != QImage::Format_ARGB32_Premultiplied
- && d_ptr->canUseLayeredWindow)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
+ if (d_ptr->image->image.format() != QImage::Format_ARGB32_Premultiplied)
prepareBuffer(QImage::Format_ARGB32_Premultiplied, window());
#endif
QPainter p(&d_ptr->image->image);
@@ -159,8 +146,11 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
#ifdef Q_WS_WIN
QRect br = rgn.boundingRect();
-#ifndef Q_OS_WINCE
- if (!qt_widget_private(window())->isOpaque && d->canUseLayeredWindow && window()->testAttribute(Qt::WA_TranslucentBackground)) {
+#ifndef Q_WS_WINCE
+ if (!qt_widget_private(window())->isOpaque
+ && window()->testAttribute(Qt::WA_TranslucentBackground)
+ && (qt_widget_private(window())->data.window_flags & Qt::FramelessWindowHint))
+ {
QRect r = window()->frameGeometry();
QPoint frameOffset = qt_widget_private(window())->frameStrut().topLeft();
QRect dirtyRect = br.translated(offset + frameOffset);
@@ -168,12 +158,11 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
SIZE size = {r.width(), r.height()};
POINT ptDst = {r.x(), r.y()};
POINT ptSrc = {0, 0};
- Q_BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * window()->windowOpacity()), Q_AC_SRC_ALPHA};
+ BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * window()->windowOpacity()), Q_AC_SRC_ALPHA};
RECT dirty = {dirtyRect.x(), dirtyRect.y(),
dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()};
Q_UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, d->image->hdc, &ptSrc, 0, &blend, Q_ULW_ALPHA, &dirty};
-
- (*ptrUpdateLayeredWindowIndirect)(window()->internalWinId(), &info);
+ ptrUpdateLayeredWindowIndirect(window()->internalWinId(), &info);
} else
#endif
{
@@ -296,6 +285,12 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
CGContextFlush(context);
#endif
#endif
+
+#ifdef Q_OS_SYMBIAN
+ Q_UNUSED(widget);
+ Q_UNUSED(rgn);
+ Q_UNUSED(offset);
+#endif
}
void QRasterWindowSurface::setGeometry(const QRect &rect)
@@ -304,11 +299,11 @@ void QRasterWindowSurface::setGeometry(const QRect &rect)
Q_D(QRasterWindowSurface);
d->inSetGeometry = true;
if (d->image == 0 || d->image->width() < rect.width() || d->image->height() < rect.height()) {
-#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE))
+#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE))
#ifndef Q_WS_WIN
if (d_ptr->translucentBackground)
#else
- if (!qt_widget_private(window())->isOpaque && d->canUseLayeredWindow)
+ if (!qt_widget_private(window())->isOpaque)
#endif
prepareBuffer(QImage::Format_ARGB32_Premultiplied, window());
else
diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h
index b74600a..a53a863 100644
--- a/src/gui/painting/qwindowsurface_raster_p.h
+++ b/src/gui/painting/qwindowsurface_raster_p.h
@@ -64,13 +64,6 @@ QT_BEGIN_NAMESPACE
#define Q_ULW_ALPHA 0x00000002 // copied from ULW_ALPHA in winuser.h
#define Q_AC_SRC_ALPHA 0x00000001 // copied from AC_SRC_ALPHA in winuser.h
-struct Q_BLENDFUNCTION {
- BYTE BlendOp;
- BYTE BlendFlags;
- BYTE SourceConstantAlpha;
- BYTE AlphaFormat;
-};
-
struct Q_UPDATELAYEREDWINDOWINFO {
DWORD cbSize;
HDC hdcDst;
@@ -79,12 +72,16 @@ struct Q_UPDATELAYEREDWINDOWINFO {
HDC hdcSrc;
const POINT *pptSrc;
COLORREF crKey;
- const Q_BLENDFUNCTION *pblend;
+ const BLENDFUNCTION *pblend;
DWORD dwFlags;
const RECT *prcDirty;
};
+typedef BOOL (WINAPI *PtrUpdateLayeredWindow)(HWND hwnd, HDC hdcDst, const POINT *pptDst,
+ const SIZE *psize, HDC hdcSrc, const POINT *pptSrc, COLORREF crKey,
+ const BLENDFUNCTION *pblend, DWORD dwflags);
typedef BOOL (WINAPI *PtrUpdateLayeredWindowIndirect)(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *pULWInfo);
+extern PtrUpdateLayeredWindow ptrUpdateLayeredWindow;
extern PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect;
#endif
@@ -112,7 +109,7 @@ public:
private:
void prepareBuffer(QImage::Format format, QWidget *widget);
Q_DECLARE_PRIVATE(QRasterWindowSurface)
- QRasterWindowSurfacePrivate *d_ptr;
+ QScopedPointer<QRasterWindowSurfacePrivate> d_ptr;
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp
new file mode 100644
index 0000000..622b8de
--- /dev/null
+++ b/src/gui/painting/qwindowsurface_s60.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h> // for Q_WS_WIN define (non-PCH)
+
+#include <QtGui/qpaintdevice.h>
+#include <private/qwidget_p.h>
+#include "qwindowsurface_s60_p.h"
+#include "qt_s60_p.h"
+#include "private/qdrawhelper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QS60WindowSurfacePrivate
+{
+ QImage device;
+ CFbsBitmap *bitmap;
+ uchar* bytes;
+
+ // Since only one CFbsBitmap is allowed to be locked at a time, this is static.
+ static QS60WindowSurface* lockedSurface;
+};
+QS60WindowSurface* QS60WindowSurfacePrivate::lockedSurface = NULL;
+
+QS60WindowSurface::QS60WindowSurface(QWidget* widget)
+ : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate)
+{
+ d_ptr->bytes = 0;
+ d_ptr->bitmap = 0;
+
+ TDisplayMode mode = S60->screenDevice()->DisplayMode();
+ bool isOpaque = qt_widget_private(widget)->isOpaque;
+ if (mode == EColor16MA && isOpaque)
+ mode = EColor16MU; // Faster since 16MU -> 16MA is typically accelerated
+ else if (mode == EColor16MU && !isOpaque)
+ mode = EColor16MA; // Try for transparency anyway
+
+
+ // We create empty CFbsBitmap here -> it will be resized in setGeometry
+ d_ptr->bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new
+ qt_symbian_throwIfError( d_ptr->bitmap->Create(TSize(0, 0), mode ) );
+
+ updatePaintDeviceOnBitmap();
+
+ setStaticContentsSupport(true);
+}
+
+QS60WindowSurface::~QS60WindowSurface()
+{
+ if (QS60WindowSurfacePrivate::lockedSurface == this)
+ unlockBitmapHeap();
+
+ delete d_ptr->bitmap;
+ delete d_ptr;
+}
+
+void QS60WindowSurface::beginPaint(const QRegion &rgn)
+{
+ if(!d_ptr->bitmap)
+ return;
+
+ if (QS60WindowSurfacePrivate::lockedSurface)
+ unlockBitmapHeap();
+
+ QS60WindowSurfacePrivate::lockedSurface = this;
+ lockBitmapHeap();
+
+ if (!qt_widget_private(window())->isOpaque) {
+ QRgb *data = reinterpret_cast<QRgb *>(d_ptr->device.bits());
+ const int row_stride = d_ptr->device.bytesPerLine() / 4;
+
+ const QVector<QRect> rects = rgn.rects();
+ for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
+ const int x_start = it->x();
+ const int width = it->width();
+
+ const int y_start = it->y();
+ const int height = it->height();
+
+ QRgb *row = data + row_stride * y_start;
+ for (int y = 0; y < height; ++y) {
+ qt_memfill(row + x_start, 0U, width);
+ row += row_stride;
+ }
+ }
+ }
+}
+
+void QS60WindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &)
+{
+ const QVector<QRect> subRects = region.rects();
+ for (int i = 0; i < subRects.count(); ++i) {
+ TRect tr = qt_QRect2TRect(subRects[i]);
+ widget->winId()->DrawNow(tr);
+ }
+}
+
+bool QS60WindowSurface::scroll(const QRegion &area, int dx, int dy)
+{
+ QRect rect = area.boundingRect();
+
+ if (dx == 0 && dy == 0)
+ return false;
+
+ if (d_ptr->device.isNull())
+ return false;
+
+ CFbsBitmapDevice *bitmapDevice = 0;
+ QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(d_ptr->bitmap));
+ CBitmapContext *bitmapContext;
+ TInt err = bitmapDevice->CreateBitmapContext(bitmapContext);
+ if (err != KErrNone) {
+ CBase::Delete(bitmapDevice);
+ return false;
+ }
+ bitmapContext->CopyRect(TPoint(dx, dy), qt_QRect2TRect(rect));
+ CBase::Delete(bitmapContext);
+ CBase::Delete(bitmapDevice);
+ return true;
+}
+
+void QS60WindowSurface::endPaint(const QRegion & /* rgn */)
+{
+ if(!d_ptr->bitmap)
+ return;
+
+ Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface);
+ unlockBitmapHeap();
+ QS60WindowSurfacePrivate::lockedSurface = NULL;
+}
+
+QPaintDevice* QS60WindowSurface::paintDevice()
+{
+ return &d_ptr->device;
+}
+
+void QS60WindowSurface::setGeometry(const QRect& rect)
+{
+ if (rect == geometry())
+ return;
+
+ QWindowSurface::setGeometry(rect);
+
+ TRect nativeRect(qt_QRect2TRect(rect));
+ qt_symbian_throwIfError(d_ptr->bitmap->Resize(nativeRect.Size()));
+
+ if (!rect.isNull())
+ updatePaintDeviceOnBitmap();
+}
+
+void QS60WindowSurface::lockBitmapHeap()
+{
+ if (!QS60WindowSurfacePrivate::lockedSurface)
+ return;
+
+ // Get some local variables to make later code lines more clear to read
+ CFbsBitmap*& bitmap = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap;
+ QImage& device = QS60WindowSurfacePrivate::lockedSurface->d_ptr->device;
+ uchar*& bytes = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bytes;
+
+ bitmap->LockHeap();
+ uchar *newBytes = (uchar*)bitmap->DataAddress();
+ if (newBytes != bytes) {
+ bytes = newBytes;
+
+ // Get some values for QImage creation
+ TDisplayMode mode = bitmap->DisplayMode();
+ if (mode == EColor16MA
+ && qt_widget_private(QS60WindowSurfacePrivate::lockedSurface->window())->isOpaque)
+ mode = EColor16MU;
+ QImage::Format format = qt_TDisplayMode2Format( mode );
+ TSize bitmapSize = bitmap->SizeInPixels();
+ int bytesPerLine = CFbsBitmap::ScanLineLength( bitmapSize.iWidth, mode);
+
+ device = QImage( bytes, bitmapSize.iWidth, bitmapSize.iHeight, bytesPerLine, format );
+ }
+}
+
+void QS60WindowSurface::unlockBitmapHeap()
+{
+ if (!QS60WindowSurfacePrivate::lockedSurface)
+ return;
+
+ QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap->UnlockHeap();
+}
+
+void QS60WindowSurface::updatePaintDeviceOnBitmap()
+{
+ // This forces the actual device to be updated based on CFbsBitmap
+ beginPaint(QRegion());
+ endPaint(QRegion());
+}
+
+CFbsBitmap *QS60WindowSurface::symbianBitmap() const
+{
+ return d_ptr->bitmap;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qwindowsurface_s60_p.h b/src/gui/painting/qwindowsurface_s60_p.h
new file mode 100644
index 0000000..87dfd5e
--- /dev/null
+++ b/src/gui/painting/qwindowsurface_s60_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSURFACE_S60_P_H
+#define QWINDOWSURFACE_S60_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qglobal.h>
+#include "private/qwindowsurface_p.h"
+
+class CFbsBitmap;
+
+QT_BEGIN_NAMESPACE
+
+struct QS60WindowSurfacePrivate;
+
+class QS60WindowSurface : public QWindowSurface
+{
+public:
+ QS60WindowSurface(QWidget *widget);
+ ~QS60WindowSurface();
+
+ QPaintDevice *paintDevice();
+ void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
+ bool scroll(const QRegion &area, int dx, int dy);
+
+ void beginPaint(const QRegion &);
+ void endPaint(const QRegion &);
+
+ void setGeometry(const QRect &rect);
+
+ static void lockBitmapHeap();
+ static void unlockBitmapHeap();
+
+ CFbsBitmap *symbianBitmap() const;
+
+private:
+ void updatePaintDeviceOnBitmap();
+
+private:
+ QS60WindowSurfacePrivate* d_ptr;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSURFACE_S60_P_H
diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp
index 2952c9d..c2d4f44 100644
--- a/src/gui/painting/qwindowsurface_x11.cpp
+++ b/src/gui/painting/qwindowsurface_x11.cpp
@@ -96,7 +96,7 @@ void QX11WindowSurface::beginPaint(const QRegion &rgn)
#ifndef QT_NO_XRENDER
if (d_ptr->translucentBackground) {
if (d_ptr->device.depth() != 32)
- static_cast<QX11PixmapData *>(d_ptr->device.data_ptr())->convertToARGB32();
+ static_cast<QX11PixmapData *>(d_ptr->device.data_ptr().data())->convertToARGB32();
::Picture src = X11->getSolidFill(d_ptr->device.x11Info().screen(), Qt::transparent);
::Picture dst = d_ptr->device.x11PictureHandle();
const QVector<QRect> rects = rgn.rects();
@@ -128,7 +128,7 @@ void QX11WindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint
return;
// qDebug() << "XSetClipRectangles";
// for (int i = 0; i < num; ++i)
-// qDebug() << " " << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height;
+// qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height;
XSetClipRectangles(X11->display, gc, 0, 0, rects, num, YXBanded);
XCopyArea(X11->display, d_ptr->device.handle(), widget->handle(), gc,
br.x() + offset.x(), br.y() + offset.y(), br.width(), br.height(), wbr.x(), wbr.y());
@@ -154,7 +154,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect)
QX11PixmapData *oldData = static_cast<QX11PixmapData *>(d_ptr->device.pixmapData());
Q_ASSERT(oldData);
- if (!oldData->uninit && hasStaticContents()) {
+ if (!(oldData->flags & QX11PixmapData::Uninitialized) && hasStaticContents()) {
// Copy the content of the old pixmap into the new one.
QX11PixmapData *newData = new QX11PixmapData(QPixmapData::PixmapType);
newData->resize(size.width(), size.height());
@@ -175,7 +175,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect)
dx, dy, qMin(boundingRect.width(), size.width()),
qMin(boundingRect.height(), size.height()), dx, dy);
XFreeGC(X11->display, tmpGc);
- newData->uninit = false;
+ newData->flags &= ~QX11PixmapData::Uninitialized;
d_ptr->device = QPixmap(newData);
} else {
diff --git a/src/gui/statemachine/qbasickeyeventtransition.cpp b/src/gui/statemachine/qbasickeyeventtransition.cpp
new file mode 100644
index 0000000..9348ba3
--- /dev/null
+++ b/src/gui/statemachine/qbasickeyeventtransition.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbasickeyeventtransition_p.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <QtGui/qevent.h>
+#include <qdebug.h>
+#include <private/qabstracttransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QBasicKeyEventTransition
+ \since 4.6
+ \ingroup statemachine
+
+ \brief The QBasicKeyEventTransition class provides a transition for Qt key events.
+*/
+
+class QBasicKeyEventTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QBasicKeyEventTransition)
+public:
+ QBasicKeyEventTransitionPrivate();
+
+ static QBasicKeyEventTransitionPrivate *get(QBasicKeyEventTransition *q);
+
+ QEvent::Type eventType;
+ int key;
+ Qt::KeyboardModifiers modifiersMask;
+};
+
+QBasicKeyEventTransitionPrivate::QBasicKeyEventTransitionPrivate()
+{
+ eventType = QEvent::None;
+ key = 0;
+ modifiersMask = Qt::NoModifier;
+}
+
+QBasicKeyEventTransitionPrivate *QBasicKeyEventTransitionPrivate::get(QBasicKeyEventTransition *q)
+{
+ return q->d_func();
+}
+
+/*!
+ Constructs a new key event transition with the given \a sourceState.
+*/
+QBasicKeyEventTransition::QBasicKeyEventTransition(QState *sourceState)
+ : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new event transition for events of the given \a type for the
+ given \a key, with the given \a sourceState.
+*/
+QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key,
+ QState *sourceState)
+ : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->eventType = type;
+ d->key = key;
+}
+
+/*!
+ Constructs a new event transition for events of the given \a type for the
+ given \a key, with the given \a modifiersMask and \a sourceState.
+*/
+QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key,
+ Qt::KeyboardModifiers modifiersMask,
+ QState *sourceState)
+ : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->eventType = type;
+ d->key = key;
+ d->modifiersMask = modifiersMask;
+}
+
+/*!
+ Destroys this event transition.
+*/
+QBasicKeyEventTransition::~QBasicKeyEventTransition()
+{
+}
+
+/*!
+ Returns the event type that this key event transition is associated with.
+*/
+QEvent::Type QBasicKeyEventTransition::eventType() const
+{
+ Q_D(const QBasicKeyEventTransition);
+ return d->eventType;
+}
+
+/*!
+ Sets the event \a type that this key event transition is associated with.
+*/
+void QBasicKeyEventTransition::setEventType(QEvent::Type type)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->eventType = type;
+}
+
+/*!
+ Returns the key that this key event transition checks for.
+*/
+int QBasicKeyEventTransition::key() const
+{
+ Q_D(const QBasicKeyEventTransition);
+ return d->key;
+}
+
+/*!
+ Sets the key that this key event transition will check for.
+*/
+void QBasicKeyEventTransition::setKey(int key)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->key = key;
+}
+
+/*!
+ Returns the keyboard modifiers mask that this key event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QBasicKeyEventTransition::modifiersMask() const
+{
+ Q_D(const QBasicKeyEventTransition);
+ return d->modifiersMask;
+}
+
+/*!
+ Sets the keyboard modifiers mask that this key event transition will check
+ for.
+*/
+void QBasicKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->modifiersMask = modifiersMask;
+}
+
+/*!
+ \reimp
+*/
+bool QBasicKeyEventTransition::eventTest(QEvent *event)
+{
+ Q_D(const QBasicKeyEventTransition);
+ if (event->type() == d->eventType) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ return (ke->key() == d->key)
+ && ((ke->modifiers() & d->modifiersMask) == d->modifiersMask);
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QBasicKeyEventTransition::onTransition(QEvent *)
+{
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qbasickeyeventtransition_p.h b/src/gui/statemachine/qbasickeyeventtransition_p.h
new file mode 100644
index 0000000..0dfe392
--- /dev/null
+++ b/src/gui/statemachine/qbasickeyeventtransition_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBASICKEYEVENTTRANSITION_P_H
+#define QBASICKEYEVENTTRANSITION_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/qabstracttransition.h>
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBasicKeyEventTransitionPrivate;
+class Q_AUTOTEST_EXPORT QBasicKeyEventTransition : public QAbstractTransition
+{
+ Q_OBJECT
+public:
+ QBasicKeyEventTransition(QState *sourceState = 0);
+ QBasicKeyEventTransition(QEvent::Type type, int key, QState *sourceState = 0);
+ QBasicKeyEventTransition(QEvent::Type type, int key,
+ Qt::KeyboardModifiers modifiersMask,
+ QState *sourceState = 0);
+ ~QBasicKeyEventTransition();
+
+ QEvent::Type eventType() const;
+ void setEventType(QEvent::Type type);
+
+ int key() const;
+ void setKey(int key);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+protected:
+ bool eventTest(QEvent *event);
+ void onTransition(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QBasicKeyEventTransition)
+ Q_DECLARE_PRIVATE(QBasicKeyEventTransition)
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
+
+#endif
diff --git a/src/gui/statemachine/qbasicmouseeventtransition.cpp b/src/gui/statemachine/qbasicmouseeventtransition.cpp
new file mode 100644
index 0000000..e6eb0b1
--- /dev/null
+++ b/src/gui/statemachine/qbasicmouseeventtransition.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbasicmouseeventtransition_p.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <QtGui/qevent.h>
+#include <QtGui/qpainterpath.h>
+#include <qdebug.h>
+#include <private/qabstracttransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QBasicMouseEventTransition
+ \since 4.6
+ \ingroup statemachine
+
+ \brief The QBasicMouseEventTransition class provides a transition for Qt mouse events.
+*/
+
+class QBasicMouseEventTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QBasicMouseEventTransition)
+public:
+ QBasicMouseEventTransitionPrivate();
+
+ static QBasicMouseEventTransitionPrivate *get(QBasicMouseEventTransition *q);
+
+ QEvent::Type eventType;
+ Qt::MouseButton button;
+ Qt::KeyboardModifiers modifiersMask;
+ QPainterPath path;
+};
+
+QBasicMouseEventTransitionPrivate::QBasicMouseEventTransitionPrivate()
+{
+ eventType = QEvent::None;
+ button = Qt::NoButton;
+}
+
+QBasicMouseEventTransitionPrivate *QBasicMouseEventTransitionPrivate::get(QBasicMouseEventTransition *q)
+{
+ return q->d_func();
+}
+
+/*!
+ Constructs a new mouse event transition with the given \a sourceState.
+*/
+QBasicMouseEventTransition::QBasicMouseEventTransition(QState *sourceState)
+ : QAbstractTransition(*new QBasicMouseEventTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new mouse event transition for events of the given \a type.
+*/
+QBasicMouseEventTransition::QBasicMouseEventTransition(QEvent::Type type,
+ Qt::MouseButton button,
+ QState *sourceState)
+ : QAbstractTransition(*new QBasicMouseEventTransitionPrivate, sourceState)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->eventType = type;
+ d->button = button;
+}
+
+/*!
+ Destroys this mouse event transition.
+*/
+QBasicMouseEventTransition::~QBasicMouseEventTransition()
+{
+}
+
+/*!
+ Returns the event type that this mouse event transition is associated with.
+*/
+QEvent::Type QBasicMouseEventTransition::eventType() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->eventType;
+}
+
+/*!
+ Sets the event \a type that this mouse event transition is associated with.
+*/
+void QBasicMouseEventTransition::setEventType(QEvent::Type type)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->eventType = type;
+}
+
+/*!
+ Returns the button that this mouse event transition checks for.
+*/
+Qt::MouseButton QBasicMouseEventTransition::button() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->button;
+}
+
+/*!
+ Sets the button that this mouse event transition will check for.
+*/
+void QBasicMouseEventTransition::setButton(Qt::MouseButton button)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->button = button;
+}
+
+/*!
+ Returns the keyboard modifiers mask that this mouse event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QBasicMouseEventTransition::modifiersMask() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->modifiersMask;
+}
+
+/*!
+ Sets the keyboard modifiers mask that this mouse event transition will check
+ for.
+*/
+void QBasicMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->modifiersMask = modifiersMask;
+}
+
+/*!
+ Returns the path for this mouse event transition.
+*/
+QPainterPath QBasicMouseEventTransition::path() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->path;
+}
+
+/*!
+ Sets the path for this mouse event transition.
+*/
+void QBasicMouseEventTransition::setPath(const QPainterPath &path)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->path = path;
+}
+
+/*!
+ \reimp
+*/
+bool QBasicMouseEventTransition::eventTest(QEvent *event)
+{
+ Q_D(const QBasicMouseEventTransition);
+ if (event->type() == d->eventType) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ return (me->button() == d->button)
+ && ((me->modifiers() & d->modifiersMask) == d->modifiersMask)
+ && (d->path.isEmpty() || d->path.contains(me->pos()));
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QBasicMouseEventTransition::onTransition(QEvent *)
+{
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qbasicmouseeventtransition_p.h b/src/gui/statemachine/qbasicmouseeventtransition_p.h
new file mode 100644
index 0000000..52ced12
--- /dev/null
+++ b/src/gui/statemachine/qbasicmouseeventtransition_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBASICMOUSEEVENTTRANSITION_P_H
+#define QBASICMOUSEEVENTTRANSITION_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/qabstracttransition.h>
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPainterPath;
+
+class QBasicMouseEventTransitionPrivate;
+class Q_AUTOTEST_EXPORT QBasicMouseEventTransition : public QAbstractTransition
+{
+ Q_OBJECT
+public:
+ QBasicMouseEventTransition(QState *sourceState = 0);
+ QBasicMouseEventTransition(QEvent::Type type, Qt::MouseButton button,
+ QState *sourceState = 0);
+ ~QBasicMouseEventTransition();
+
+ QEvent::Type eventType() const;
+ void setEventType(QEvent::Type type);
+
+ Qt::MouseButton button() const;
+ void setButton(Qt::MouseButton button);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+ QPainterPath path() const;
+ void setPath(const QPainterPath &path);
+
+protected:
+ bool eventTest(QEvent *event);
+ void onTransition(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QBasicMouseEventTransition)
+ Q_DECLARE_PRIVATE(QBasicMouseEventTransition)
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
+
+#endif
diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp
new file mode 100644
index 0000000..c837517
--- /dev/null
+++ b/src/gui/statemachine/qguistatemachine.cpp
@@ -0,0 +1,566 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstatemachine.h>
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <private/qstatemachine_p.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qgraphicssceneevent.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler();
+
+static QEvent *cloneEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ return new QMouseEvent(*static_cast<QMouseEvent*>(e));
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ return new QKeyEvent(*static_cast<QKeyEvent*>(e));
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ return new QFocusEvent(*static_cast<QFocusEvent*>(e));
+ case QEvent::Enter:
+ return new QEvent(*e);
+ case QEvent::Leave:
+ return new QEvent(*e);
+ break;
+ case QEvent::Paint:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Move:
+ return new QMoveEvent(*static_cast<QMoveEvent*>(e));
+ case QEvent::Resize:
+ return new QResizeEvent(*static_cast<QResizeEvent*>(e));
+ case QEvent::Create:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Destroy:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Show:
+ return new QShowEvent(*static_cast<QShowEvent*>(e));
+ case QEvent::Hide:
+ return new QHideEvent(*static_cast<QHideEvent*>(e));
+ case QEvent::Close:
+ return new QCloseEvent(*static_cast<QCloseEvent*>(e));
+ case QEvent::Quit:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ParentChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ParentAboutToChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ThreadChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ return new QEvent(*e);
+
+ case QEvent::ShowToParent:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HideToParent:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Wheel:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowTitleChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowIconChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationWindowIconChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationFontChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationLayoutDirectionChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationPaletteChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::PaletteChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Clipboard:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Speech:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::MetaCall:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::SockAct:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WinEventAct:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::DeferredDelete:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#ifndef QT_NO_DRAGANDDROP
+ case QEvent::DragEnter:
+ return new QDragEnterEvent(*static_cast<QDragEnterEvent*>(e));
+ case QEvent::DragMove:
+ return new QDragMoveEvent(*static_cast<QDragMoveEvent*>(e));
+ case QEvent::DragLeave:
+ return new QDragLeaveEvent(*static_cast<QDragLeaveEvent*>(e));
+ case QEvent::Drop:
+ return new QDropEvent(*static_cast<QDragMoveEvent*>(e));
+ case QEvent::DragResponse:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::ChildAdded:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ChildPolished:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInsertedRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ChildInserted:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LayoutHint:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::ChildRemoved:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ShowWindowRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::PolishRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Polish:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LayoutRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::UpdateRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::UpdateLater:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::EmbeddingControl:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ActivateControl:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::DeactivateControl:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ContextMenu:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::InputMethod:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::AccessibilityPrepare:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LocaleChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LanguageChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LayoutDirectionChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Style:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletPress:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletRelease:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::OkRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HelpRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::IconDrag:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::FontChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::EnabledChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ActivationChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::StyleChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::IconTextChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ModifiedChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::MouseTrackingChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::WindowBlocked:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowUnblocked:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowStateChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ToolTip:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WhatsThis:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::StatusTip:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#ifndef QT_NO_ACTION
+ case QEvent::ActionChanged:
+ case QEvent::ActionAdded:
+ case QEvent::ActionRemoved:
+ return new QActionEvent(*static_cast<QActionEvent*>(e));
+#endif
+ case QEvent::FileOpen:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::Shortcut:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ShortcutOverride:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+#ifdef QT3_SUPPORT
+ case QEvent::Accel:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::AccelAvailable:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+
+ case QEvent::WhatsThisClicked:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ToolBarChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ApplicationActivate:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationDeactivate:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::QueryWhatsThis:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::EnterWhatsThisMode:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LeaveWhatsThisMode:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ZOrderChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::HoverEnter:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HoverLeave:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HoverMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::AccessibilityHelp:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::AccessibilityDescription:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+#ifdef QT_KEYPAD_NAVIGATION
+ case QEvent::EnterEditFocus:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LeaveEditFocus:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::AcceptDropsChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::MenubarUpdated:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ZeroTimerEvent:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMouseDoubleClick: {
+ QGraphicsSceneMouseEvent *me = static_cast<QGraphicsSceneMouseEvent*>(e);
+ QGraphicsSceneMouseEvent *me2 = new QGraphicsSceneMouseEvent(me->type());
+ me2->setWidget(me->widget());
+ me2->setPos(me->pos());
+ me2->setScenePos(me->scenePos());
+ me2->setScreenPos(me->screenPos());
+// ### for all buttons
+ me2->setButtonDownPos(Qt::LeftButton, me->buttonDownPos(Qt::LeftButton));
+ me2->setButtonDownPos(Qt::RightButton, me->buttonDownPos(Qt::RightButton));
+ me2->setButtonDownScreenPos(Qt::LeftButton, me->buttonDownScreenPos(Qt::LeftButton));
+ me2->setButtonDownScreenPos(Qt::RightButton, me->buttonDownScreenPos(Qt::RightButton));
+ me2->setLastPos(me->lastPos());
+ me2->setLastScenePos(me->lastScenePos());
+ me2->setLastScreenPos(me->lastScreenPos());
+ me2->setButtons(me->buttons());
+ me2->setButton(me->button());
+ me2->setModifiers(me->modifiers());
+ return me2;
+ }
+
+ case QEvent::GraphicsSceneContextMenu: {
+ QGraphicsSceneContextMenuEvent *me = static_cast<QGraphicsSceneContextMenuEvent*>(e);
+ QGraphicsSceneContextMenuEvent *me2 = new QGraphicsSceneContextMenuEvent(me->type());
+ me2->setWidget(me->widget());
+ me2->setPos(me->pos());
+ me2->setScenePos(me->scenePos());
+ me2->setScreenPos(me->screenPos());
+ me2->setModifiers(me->modifiers());
+ me2->setReason(me->reason());
+ return me2;
+ }
+
+ case QEvent::GraphicsSceneHoverEnter:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneHoverMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneHoverLeave:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneHelp:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDragEnter:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDragMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDragLeave:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDrop:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneWheel:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::KeyboardLayoutChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::DynamicPropertyChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::TabletEnterProximity:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletLeaveProximity:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::NonClientAreaMouseMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::NonClientAreaMouseButtonPress:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::NonClientAreaMouseButtonRelease:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::NonClientAreaMouseButtonDblClick:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::MacSizeChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ContentsRectChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::MacGLWindowChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::FutureCallOut:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneResize:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneMove: {
+ QGraphicsSceneMoveEvent *me = static_cast<QGraphicsSceneMoveEvent*>(e);
+ QGraphicsSceneMoveEvent *me2 = new QGraphicsSceneMoveEvent();
+ me2->setWidget(me->widget());
+ me2->setNewPos(me->newPos());
+ me2->setOldPos(me->oldPos());
+ return me2;
+ }
+#endif
+ case QEvent::CursorChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ToolTipChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::NetworkReplyUpdated:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::GrabMouse:
+ case QEvent::UngrabMouse:
+ case QEvent::GrabKeyboard:
+ case QEvent::UngrabKeyboard:
+ return new QEvent(*e);
+
+#ifdef QT_MAC_USE_COCOA
+ case QEvent::CocoaRequestModal:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::User:
+ case QEvent::MaxUser:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ default:
+ ;
+ }
+ return qcoreStateMachineHandler()->cloneEvent(e);
+}
+
+const QStateMachinePrivate::Handler qt_gui_statemachine_handler = {
+ cloneEvent
+};
+
+static const QStateMachinePrivate::Handler *qt_guistatemachine_last_handler = 0;
+int qRegisterGuiStateMachine()
+{
+ qt_guistatemachine_last_handler = QStateMachinePrivate::handler;
+ QStateMachinePrivate::handler = &qt_gui_statemachine_handler;
+ return 1;
+}
+Q_CONSTRUCTOR_FUNCTION(qRegisterGuiStateMachine)
+
+int qUnregisterGuiStateMachine()
+{
+ QStateMachinePrivate::handler = qt_guistatemachine_last_handler;
+ return 1;
+}
+Q_DESTRUCTOR_FUNCTION(qUnregisterGuiStateMachine)
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp
new file mode 100644
index 0000000..a1c898a
--- /dev/null
+++ b/src/gui/statemachine/qkeyeventtransition.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkeyeventtransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qbasickeyeventtransition_p.h"
+#include <QtCore/qwrappedevent.h>
+#include <private/qeventtransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QKeyEventTransition
+
+ \brief The QKeyEventTransition class provides a transition for key events.
+
+ \since 4.6
+ \ingroup statemachine
+
+ QKeyEventTransition is part of \l{The State Machine Framework}.
+
+ \sa QState::addTransition()
+*/
+
+/*!
+ \property QKeyEventTransition::key
+
+ \brief the key that this key event transition is associated with
+*/
+
+/*!
+ \property QKeyEventTransition::modifiersMask
+
+ \brief the keyboard modifiers mask that this key event transition checks for
+*/
+
+class QKeyEventTransitionPrivate : public QEventTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QKeyEventTransition)
+public:
+ QKeyEventTransitionPrivate() {}
+
+ QBasicKeyEventTransition *transition;
+};
+
+/*!
+ Constructs a new key event transition with the given \a sourceState.
+*/
+QKeyEventTransition::QKeyEventTransition(QState *sourceState)
+ : QEventTransition(*new QKeyEventTransitionPrivate, sourceState)
+{
+ Q_D(QKeyEventTransition);
+ d->transition = new QBasicKeyEventTransition();
+}
+
+/*!
+ Constructs a new key event transition for events of the given \a type for
+ the given \a object, with the given \a key and \a sourceState.
+*/
+QKeyEventTransition::QKeyEventTransition(QObject *object, QEvent::Type type,
+ int key, QState *sourceState)
+ : QEventTransition(*new QKeyEventTransitionPrivate, object, type, sourceState)
+{
+ Q_D(QKeyEventTransition);
+ d->transition = new QBasicKeyEventTransition(type, key);
+}
+
+/*!
+ Destroys this key event transition.
+*/
+QKeyEventTransition::~QKeyEventTransition()
+{
+ Q_D(QKeyEventTransition);
+ delete d->transition;
+}
+
+/*!
+ Returns the key that this key event transition checks for.
+*/
+int QKeyEventTransition::key() const
+{
+ Q_D(const QKeyEventTransition);
+ return d->transition->key();
+}
+
+/*!
+ Sets the key that this key event transition will check for.
+*/
+void QKeyEventTransition::setKey(int key)
+{
+ Q_D(QKeyEventTransition);
+ d->transition->setKey(key);
+}
+
+/*!
+ Returns the keyboard modifiers mask that this key event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QKeyEventTransition::modifiersMask() const
+{
+ Q_D(const QKeyEventTransition);
+ return d->transition->modifiersMask();
+}
+
+/*!
+ Sets the keyboard \a modifiers mask that this key event transition will
+ check for.
+*/
+void QKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QKeyEventTransition);
+ d->transition->setModifiersMask(modifiersMask);
+}
+
+/*!
+ \reimp
+*/
+bool QKeyEventTransition::eventTest(QEvent *event)
+{
+ Q_D(const QKeyEventTransition);
+ if (!QEventTransition::eventTest(event))
+ return false;
+ QWrappedEvent *we = static_cast<QWrappedEvent*>(event);
+ d->transition->setEventType(we->event()->type());
+ return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event());
+}
+
+/*!
+ \reimp
+*/
+void QKeyEventTransition::onTransition(QEvent *event)
+{
+ QEventTransition::onTransition(event);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h
new file mode 100644
index 0000000..8ac1484
--- /dev/null
+++ b/src/gui/statemachine/qkeyeventtransition.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKEYEVENTTRANSITION_H
+#define QKEYEVENTTRANSITION_H
+
+#include <QtCore/qeventtransition.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QKeyEventTransitionPrivate;
+class Q_GUI_EXPORT QKeyEventTransition : public QEventTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(int key READ key WRITE setKey)
+ Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask)
+public:
+ QKeyEventTransition(QState *sourceState = 0);
+ QKeyEventTransition(QObject *object, QEvent::Type type, int key,
+ QState *sourceState = 0);
+ ~QKeyEventTransition();
+
+ int key() const;
+ void setKey(int key);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+protected:
+ void onTransition(QEvent *event);
+ bool eventTest(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QKeyEventTransition)
+ Q_DECLARE_PRIVATE(QKeyEventTransition)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp
new file mode 100644
index 0000000..268b655
--- /dev/null
+++ b/src/gui/statemachine/qmouseeventtransition.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmouseeventtransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qbasicmouseeventtransition_p.h"
+#include <QtCore/qwrappedevent.h>
+#include <QtGui/qpainterpath.h>
+#include <private/qeventtransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMouseEventTransition
+
+ \brief The QMouseEventTransition class provides a transition for mouse events.
+
+ \since 4.6
+ \ingroup statemachine
+
+ QMouseEventTransition is part of \l{The State Machine Framework}.
+
+ \sa QState::addTransition()
+*/
+
+/*!
+ \property QMouseEventTransition::button
+
+ \brief the button that this mouse event transition is associated with
+*/
+
+/*!
+ \property QMouseEventTransition::modifiersMask
+
+ \brief the keyboard modifiers mask that this mouse event transition checks for
+*/
+
+class QMouseEventTransitionPrivate : public QEventTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QMouseEventTransition)
+public:
+ QMouseEventTransitionPrivate();
+
+ QBasicMouseEventTransition *transition;
+};
+
+QMouseEventTransitionPrivate::QMouseEventTransitionPrivate()
+{
+}
+
+/*!
+ Constructs a new mouse event transition with the given \a sourceState.
+*/
+QMouseEventTransition::QMouseEventTransition(QState *sourceState)
+ : QEventTransition(*new QMouseEventTransitionPrivate, sourceState)
+{
+ Q_D(QMouseEventTransition);
+ d->transition = new QBasicMouseEventTransition();
+}
+
+/*!
+ Constructs a new mouse event transition for events of the given \a type for
+ the given \a object, with the given \a button and \a sourceState.
+*/
+QMouseEventTransition::QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button,
+ QState *sourceState)
+ : QEventTransition(*new QMouseEventTransitionPrivate, object, type, sourceState)
+{
+ Q_D(QMouseEventTransition);
+ d->transition = new QBasicMouseEventTransition(type, button);
+}
+
+/*!
+ Destroys this mouse event transition.
+*/
+QMouseEventTransition::~QMouseEventTransition()
+{
+ Q_D(QMouseEventTransition);
+ delete d->transition;
+}
+
+/*!
+ Returns the button that this mouse event transition checks for.
+*/
+Qt::MouseButton QMouseEventTransition::button() const
+{
+ Q_D(const QMouseEventTransition);
+ return d->transition->button();
+}
+
+/*!
+ Sets the \a button that this mouse event transition will check for.
+*/
+void QMouseEventTransition::setButton(Qt::MouseButton button)
+{
+ Q_D(QMouseEventTransition);
+ d->transition->setButton(button);
+}
+
+/*!
+ Returns the keyboard modifiers mask that this mouse event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QMouseEventTransition::modifiersMask() const
+{
+ Q_D(const QMouseEventTransition);
+ return d->transition->modifiersMask();
+}
+
+/*!
+ Sets the keyboard \a modifiers mask that this mouse event transition will
+ check for.
+*/
+void QMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QMouseEventTransition);
+ d->transition->setModifiersMask(modifiersMask);
+}
+
+/*!
+ Returns the path for this mouse event transition.
+*/
+QPainterPath QMouseEventTransition::path() const
+{
+ Q_D(const QMouseEventTransition);
+ return d->transition->path();
+}
+
+/*!
+ Sets the \a path for this mouse event transition.
+ If a valid path has been set, the transition will only trigger if the mouse
+ event position (QMouseEvent::pos()) is inside the path.
+
+ \sa QPainterPath::contains()
+*/
+void QMouseEventTransition::setPath(const QPainterPath &path)
+{
+ Q_D(QMouseEventTransition);
+ d->transition->setPath(path);
+}
+
+/*!
+ \reimp
+*/
+bool QMouseEventTransition::eventTest(QEvent *event)
+{
+ Q_D(const QMouseEventTransition);
+ if (!QEventTransition::eventTest(event))
+ return false;
+ QWrappedEvent *we = static_cast<QWrappedEvent*>(event);
+ d->transition->setEventType(we->event()->type());
+ return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event());
+}
+
+/*!
+ \reimp
+*/
+void QMouseEventTransition::onTransition(QEvent *event)
+{
+ QEventTransition::onTransition(event);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h
new file mode 100644
index 0000000..1676fe1
--- /dev/null
+++ b/src/gui/statemachine/qmouseeventtransition.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEEVENTTRANSITION_H
+#define QMOUSEEVENTTRANSITION_H
+
+#include <QtCore/qeventtransition.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QMouseEventTransitionPrivate;
+class QPainterPath;
+class Q_GUI_EXPORT QMouseEventTransition : public QEventTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::MouseButton button READ button WRITE setButton)
+ Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask)
+public:
+ QMouseEventTransition(QState *sourceState = 0);
+ QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button, QState *sourceState = 0);
+ ~QMouseEventTransition();
+
+ Qt::MouseButton button() const;
+ void setButton(Qt::MouseButton button);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+ QPainterPath path() const;
+ void setPath(const QPainterPath &path);
+
+protected:
+ void onTransition(QEvent *event);
+ bool eventTest(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QMouseEventTransition)
+ Q_DECLARE_PRIVATE(QMouseEventTransition)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/statemachine/statemachine.pri b/src/gui/statemachine/statemachine.pri
new file mode 100644
index 0000000..2eb1e05
--- /dev/null
+++ b/src/gui/statemachine/statemachine.pri
@@ -0,0 +1,13 @@
+SOURCES += $$PWD/qguistatemachine.cpp
+!contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) {
+ HEADERS += \
+ $$PWD/qkeyeventtransition.h \
+ $$PWD/qmouseeventtransition.h \
+ $$PWD/qbasickeyeventtransition_p.h \
+ $$PWD/qbasicmouseeventtransition_p.h
+ SOURCES += \
+ $$PWD/qkeyeventtransition.cpp \
+ $$PWD/qmouseeventtransition.cpp \
+ $$PWD/qbasickeyeventtransition.cpp \
+ $$PWD/qbasicmouseeventtransition.cpp
+}
diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp
index eddd482..0d34c77 100644
--- a/src/gui/styles/gtksymbols.cpp
+++ b/src/gui/styles/gtksymbols.cpp
@@ -60,6 +60,7 @@
#include <QtCore/QHash>
#include <private/qapplication_p.h>
+#include <private/qiconloader_p.h>
#include <QtGui/QMenu>
#include <QtGui/QStyle>
@@ -68,6 +69,7 @@
#include <QtGui/QStatusBar>
#include <QtGui/QMenuBar>
#include <QtGui/QToolBar>
+#include <QtGui/QToolButton>
#include <QtGui/QX11Info>
#include <X11/Xlib.h>
@@ -166,6 +168,7 @@ Ptr_gtk_file_filter_set_name QGtk::gtk_file_filter_set_name = 0;
Ptr_gtk_file_filter_add_pattern QGtk::gtk_file_filter_add_pattern = 0;
Ptr_gtk_file_chooser_add_filter QGtk::gtk_file_chooser_add_filter = 0;
Ptr_gtk_file_chooser_set_filter QGtk::gtk_file_chooser_set_filter = 0;
+Ptr_gtk_file_chooser_get_filter QGtk::gtk_file_chooser_get_filter = 0;
Ptr_gtk_file_chooser_dialog_new QGtk::gtk_file_chooser_dialog_new = 0;
Ptr_gtk_file_chooser_set_current_folder QGtk::gtk_file_chooser_set_current_folder = 0;
Ptr_gtk_file_chooser_get_filename QGtk::gtk_file_chooser_get_filename = 0;
@@ -207,118 +210,119 @@ static QString classPath(GtkWidget *widget)
static void resolveGtk()
{
- const QString GTK_PATH(QLS("gtk-x11-2.0"));
- QGtk::gtk_init = (Ptr_gtk_init)QLibrary::resolve(GTK_PATH, 0, "gtk_init");
- QGtk::gtk_window_new = (Ptr_gtk_window_new)QLibrary::resolve(GTK_PATH, 0, "gtk_window_new");
- QGtk::gtk_style_attach = (Ptr_gtk_style_attach)QLibrary::resolve(GTK_PATH, 0, "gtk_style_attach");
- QGtk::gtk_widget_destroy = (Ptr_gtk_widget_destroy)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_destroy");
- QGtk::gtk_widget_realize = (Ptr_gtk_widget_realize)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_realize");
-
- QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_current_folder");
- QGtk::gtk_file_filter_new = (Ptr_gtk_file_filter_new)QLibrary::resolve(GTK_PATH, 0, "gtk_file_filter_new");
- QGtk::gtk_file_filter_set_name = (Ptr_gtk_file_filter_set_name)QLibrary::resolve(GTK_PATH, 0, "gtk_file_filter_set_name");
- QGtk::gtk_file_filter_add_pattern = (Ptr_gtk_file_filter_add_pattern)QLibrary::resolve(GTK_PATH, 0, "gtk_file_filter_add_pattern");
- QGtk::gtk_file_chooser_add_filter = (Ptr_gtk_file_chooser_add_filter)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_add_filter");
- QGtk::gtk_file_chooser_set_filter = (Ptr_gtk_file_chooser_set_filter)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_filter");
- QGtk::gtk_file_chooser_dialog_new = (Ptr_gtk_file_chooser_dialog_new)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_dialog_new");
- QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_current_folder");
- QGtk::gtk_file_chooser_get_filename = (Ptr_gtk_file_chooser_get_filename)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_get_filename");
- QGtk::gtk_file_chooser_get_filenames = (Ptr_gtk_file_chooser_get_filenames)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_get_filenames");
- QGtk::gtk_file_chooser_set_current_name = (Ptr_gtk_file_chooser_set_current_name)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_current_name");
- QGtk::gtk_dialog_run = (Ptr_gtk_dialog_run)QLibrary::resolve(GTK_PATH, 0, "gtk_dialog_run");
- QGtk::gtk_file_chooser_set_filename = (Ptr_gtk_file_chooser_set_filename)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_filename");
-
- QGtk::gdk_pixbuf_get_pixels = (Ptr_gdk_pixbuf_get_pixels)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_pixels");
- QGtk::gdk_pixbuf_get_width = (Ptr_gdk_pixbuf_get_width)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_width");
- QGtk::gdk_pixbuf_get_height = (Ptr_gdk_pixbuf_get_height)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_height");
- QGtk::gdk_pixmap_new = (Ptr_gdk_pixmap_new)QLibrary::resolve(GTK_PATH, 0, "gdk_pixmap_new");
- QGtk::gdk_pixbuf_new = (Ptr_gdk_pixbuf_new)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_new");
- QGtk::gdk_pixbuf_get_from_drawable = (Ptr_gdk_pixbuf_get_from_drawable)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_from_drawable");
- QGtk::gdk_draw_rectangle = (Ptr_gdk_draw_rectangle)QLibrary::resolve(GTK_PATH, 0, "gdk_draw_rectangle");
- QGtk::gdk_pixbuf_unref = (Ptr_gdk_pixbuf_unref)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_unref");
- QGtk::gdk_drawable_unref = (Ptr_gdk_drawable_unref)QLibrary::resolve(GTK_PATH, 0, "gdk_drawable_unref");
- QGtk::gdk_drawable_get_depth = (Ptr_gdk_drawable_get_depth)QLibrary::resolve(GTK_PATH, 0, "gdk_drawable_get_depth");
- QGtk::gdk_color_free = (Ptr_gdk_color_free)QLibrary::resolve(GTK_PATH, 0, "gdk_color_free");
- QGtk::gdk_x11_window_set_user_time = (Ptr_gdk_x11_window_set_user_time)QLibrary::resolve(GTK_PATH, 0, "gdk_x11_window_set_user_time");
- QGtk::gdk_x11_drawable_get_xid = (Ptr_gdk_x11_drawable_get_xid)QLibrary::resolve(GTK_PATH, 0, "gdk_x11_drawable_get_xid");
- QGtk::gdk_x11_drawable_get_xdisplay = (Ptr_gdk_x11_drawable_get_xdisplay)QLibrary::resolve(GTK_PATH, 0, "gdk_x11_drawable_get_xdisplay");
-
- QGtk::gtk_widget_set_default_direction = (Ptr_gtk_widget_set_default_direction)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_set_default_direction");
- QGtk::gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_modify_fg");
- QGtk::gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_modify_bg");
- QGtk::gtk_arrow_new = (Ptr_gtk_arrow_new)QLibrary::resolve(GTK_PATH, 0, "gtk_arrow_new");
- QGtk::gtk_menu_item_new = (Ptr_gtk_menu_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_item_new");
- QGtk::gtk_check_menu_item_new = (Ptr_gtk_check_menu_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_check_menu_item_new");
- QGtk::gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_bar_new");
- QGtk::gtk_menu_new = (Ptr_gtk_menu_new)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_new");
- QGtk::gtk_toolbar_new = (Ptr_gtk_toolbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_toolbar_new");
- QGtk::gtk_separator_tool_item_new = (Ptr_gtk_separator_tool_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_separator_tool_item_new");
- QGtk::gtk_toolbar_insert = (Ptr_gtk_toolbar_insert)QLibrary::resolve(GTK_PATH, 0, "gtk_toolbar_insert");
- QGtk::gtk_button_new = (Ptr_gtk_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_button_new");
- QGtk::gtk_hbutton_box_new = (Ptr_gtk_hbutton_box_new)QLibrary::resolve(GTK_PATH, 0, "gtk_hbutton_box_new");
- QGtk::gtk_check_button_new = (Ptr_gtk_check_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_check_button_new");
- QGtk::gtk_radio_button_new = (Ptr_gtk_radio_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_radio_button_new");
- QGtk::gtk_notebook_new = (Ptr_gtk_notebook_new)QLibrary::resolve(GTK_PATH, 0, "gtk_notebook_new");
- QGtk::gtk_progress_bar_new = (Ptr_gtk_progress_bar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_progress_bar_new");
- QGtk::gtk_spin_button_new = (Ptr_gtk_spin_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_spin_button_new");
- QGtk::gtk_hscale_new = (Ptr_gtk_hscale_new)QLibrary::resolve(GTK_PATH, 0, "gtk_hscale_new");
- QGtk::gtk_vscale_new = (Ptr_gtk_vscale_new)QLibrary::resolve(GTK_PATH, 0, "gtk_vscale_new");
- QGtk::gtk_hscrollbar_new = (Ptr_gtk_hscrollbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_hscrollbar_new");
- QGtk::gtk_vscrollbar_new = (Ptr_gtk_vscrollbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_vscrollbar_new");
- QGtk::gtk_scrolled_window_new = (Ptr_gtk_scrolled_window_new)QLibrary::resolve(GTK_PATH, 0, "gtk_scrolled_window_new");
- QGtk::gtk_menu_shell_append = (Ptr_gtk_menu_shell_append)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_shell_append");
- QGtk::gtk_entry_new = (Ptr_gtk_entry_new)QLibrary::resolve(GTK_PATH, 0, "gtk_entry_new");
- QGtk::gtk_tree_view_new = (Ptr_gtk_tree_view_new)QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_new");
- QGtk::gtk_combo_box_new = (Ptr_gtk_combo_box_new)QLibrary::resolve(GTK_PATH, 0, "gtk_combo_box_new");
- QGtk::gtk_progress_set_adjustment = (Ptr_gtk_progress_set_adjustment)QLibrary::resolve(GTK_PATH, 0, "gtk_progress_set_adjustment");
- QGtk::gtk_range_set_adjustment = (Ptr_gtk_range_set_adjustment)QLibrary::resolve(GTK_PATH, 0, "gtk_range_set_adjustment");
- QGtk::gtk_range_set_inverted = (Ptr_gtk_range_set_inverted)QLibrary::resolve(GTK_PATH, 0, "gtk_range_set_inverted");
- QGtk::gtk_container_add = (Ptr_gtk_container_add)QLibrary::resolve(GTK_PATH, 0, "gtk_container_add");
- QGtk::gtk_icon_factory_lookup_default = (Ptr_gtk_icon_factory_lookup_default)QLibrary::resolve(GTK_PATH, 0, "gtk_icon_factory_lookup_default");
- QGtk::gtk_widget_style_get = (Ptr_gtk_widget_style_get)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_style_get");
- QGtk::gtk_icon_set_render_icon = (Ptr_gtk_icon_set_render_icon)QLibrary::resolve(GTK_PATH, 0, "gtk_icon_set_render_icon");
- QGtk::gtk_fixed_new = (Ptr_gtk_fixed_new)QLibrary::resolve(GTK_PATH, 0, "gtk_fixed_new");
- QGtk::gtk_tree_view_column_new = (Ptr_gtk_tree_view_column_new)QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_column_new");
- QGtk::gtk_tree_view_append_column= (Ptr_gtk_tree_view_append_column )QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_append_column");
- QGtk::gtk_tree_view_get_column = (Ptr_gtk_tree_view_get_column )QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_get_column");
- QGtk::gtk_paint_check = (Ptr_gtk_paint_check)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_check");
- QGtk::gtk_paint_box = (Ptr_gtk_paint_box)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_box");
- QGtk::gtk_paint_flat_box = (Ptr_gtk_paint_flat_box)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_flat_box");
- QGtk::gtk_paint_check = (Ptr_gtk_paint_check)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_check");
- QGtk::gtk_paint_box = (Ptr_gtk_paint_box)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_box");
- QGtk::gtk_paint_resize_grip = (Ptr_gtk_paint_resize_grip)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_resize_grip");
- QGtk::gtk_paint_focus = (Ptr_gtk_paint_focus)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_focus");
- QGtk::gtk_paint_shadow = (Ptr_gtk_paint_shadow)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_shadow");
- QGtk::gtk_paint_slider = (Ptr_gtk_paint_slider)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_slider");
- QGtk::gtk_paint_expander = (Ptr_gtk_paint_expander)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_expander");
- QGtk::gtk_paint_handle = (Ptr_gtk_paint_handle)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_handle");
- QGtk::gtk_paint_option = (Ptr_gtk_paint_option)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_option");
- QGtk::gtk_paint_arrow = (Ptr_gtk_paint_arrow)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_arrow");
- QGtk::gtk_paint_box_gap = (Ptr_gtk_paint_box_gap)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_box_gap");
- QGtk::gtk_paint_extension = (Ptr_gtk_paint_extension)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_extension");
- QGtk::gtk_paint_hline = (Ptr_gtk_paint_hline)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_hline");
- QGtk::gtk_paint_vline = (Ptr_gtk_paint_vline)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_vline");
- QGtk::gtk_adjustment_new = (Ptr_gtk_adjustment_new)QLibrary::resolve(GTK_PATH, 0, "gtk_adjustment_new");
- QGtk::gtk_menu_item_set_submenu = (Ptr_gtk_menu_item_set_submenu)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_item_set_submenu");
- QGtk::gtk_settings_get_default = (Ptr_gtk_settings_get_default)QLibrary::resolve(GTK_PATH, 0, "gtk_settings_get_default");
- QGtk::gtk_separator_menu_item_new = (Ptr_gtk_separator_menu_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_separator_menu_item_new");
- QGtk::gtk_frame_new = (Ptr_gtk_frame_new)QLibrary::resolve(GTK_PATH, 0, "gtk_frame_new");
- QGtk::gtk_expander_new = (Ptr_gtk_expander_new)QLibrary::resolve(GTK_PATH, 0, "gtk_expander_new");
- QGtk::gtk_statusbar_new = (Ptr_gtk_statusbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_statusbar_new");
- QGtk::gtk_combo_box_entry_new = (Ptr_gtk_combo_box_entry_new)QLibrary::resolve(GTK_PATH, 0, "gtk_combo_box_entry_new");
- QGtk::gtk_container_forall = (Ptr_gtk_container_forall)QLibrary::resolve(GTK_PATH, 0, "gtk_container_forall");
- QGtk::gtk_widget_size_allocate =(Ptr_gtk_widget_size_allocate)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_size_allocate");
- QGtk::gtk_widget_set_direction =(Ptr_gtk_widget_set_direction)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_set_direction");
- QGtk::gtk_widget_path =(Ptr_gtk_widget_path)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_path");
- QGtk::gtk_container_get_type =(Ptr_gtk_container_get_type)QLibrary::resolve(GTK_PATH, 0, "gtk_container_get_type");
- QGtk::gtk_window_get_type =(Ptr_gtk_window_get_type)QLibrary::resolve(GTK_PATH, 0, "gtk_window_get_type");
- QGtk::gtk_widget_get_type =(Ptr_gtk_widget_get_type)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_get_type");
- QGtk::gtk_rc_get_style_by_paths =(Ptr_gtk_rc_get_style_by_paths)QLibrary::resolve(GTK_PATH, 0, "gtk_rc_get_style_by_paths");
- QGtk::gtk_check_version =(Ptr_gtk_check_version)QLibrary::resolve(GTK_PATH, 0, "gtk_check_version");
- QGtk::pango_font_description_get_size = (Ptr_pango_font_description_get_size)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_size");
- QGtk::pango_font_description_get_weight = (Ptr_pango_font_description_get_weight)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_weight");
- QGtk::pango_font_description_get_family = (Ptr_pango_font_description_get_family)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_family");
- QGtk::pango_font_description_get_style = (Ptr_pango_font_description_get_style)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_style");
+ QLibrary libgtk(QLS("gtk-x11-2.0"));
+ QGtk::gtk_init = (Ptr_gtk_init)libgtk.resolve("gtk_init");
+ QGtk::gtk_window_new = (Ptr_gtk_window_new)libgtk.resolve("gtk_window_new");
+ QGtk::gtk_style_attach = (Ptr_gtk_style_attach)libgtk.resolve("gtk_style_attach");
+ QGtk::gtk_widget_destroy = (Ptr_gtk_widget_destroy)libgtk.resolve("gtk_widget_destroy");
+ QGtk::gtk_widget_realize = (Ptr_gtk_widget_realize)libgtk.resolve("gtk_widget_realize");
+
+ QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder");
+ QGtk::gtk_file_filter_new = (Ptr_gtk_file_filter_new)libgtk.resolve("gtk_file_filter_new");
+ QGtk::gtk_file_filter_set_name = (Ptr_gtk_file_filter_set_name)libgtk.resolve("gtk_file_filter_set_name");
+ QGtk::gtk_file_filter_add_pattern = (Ptr_gtk_file_filter_add_pattern)libgtk.resolve("gtk_file_filter_add_pattern");
+ QGtk::gtk_file_chooser_add_filter = (Ptr_gtk_file_chooser_add_filter)libgtk.resolve("gtk_file_chooser_add_filter");
+ QGtk::gtk_file_chooser_set_filter = (Ptr_gtk_file_chooser_set_filter)libgtk.resolve("gtk_file_chooser_set_filter");
+ QGtk::gtk_file_chooser_get_filter = (Ptr_gtk_file_chooser_get_filter)libgtk.resolve("gtk_file_chooser_get_filter");
+ QGtk::gtk_file_chooser_dialog_new = (Ptr_gtk_file_chooser_dialog_new)libgtk.resolve("gtk_file_chooser_dialog_new");
+ QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder");
+ QGtk::gtk_file_chooser_get_filename = (Ptr_gtk_file_chooser_get_filename)libgtk.resolve("gtk_file_chooser_get_filename");
+ QGtk::gtk_file_chooser_get_filenames = (Ptr_gtk_file_chooser_get_filenames)libgtk.resolve("gtk_file_chooser_get_filenames");
+ QGtk::gtk_file_chooser_set_current_name = (Ptr_gtk_file_chooser_set_current_name)libgtk.resolve("gtk_file_chooser_set_current_name");
+ QGtk::gtk_dialog_run = (Ptr_gtk_dialog_run)libgtk.resolve("gtk_dialog_run");
+ QGtk::gtk_file_chooser_set_filename = (Ptr_gtk_file_chooser_set_filename)libgtk.resolve("gtk_file_chooser_set_filename");
+
+ QGtk::gdk_pixbuf_get_pixels = (Ptr_gdk_pixbuf_get_pixels)libgtk.resolve("gdk_pixbuf_get_pixels");
+ QGtk::gdk_pixbuf_get_width = (Ptr_gdk_pixbuf_get_width)libgtk.resolve("gdk_pixbuf_get_width");
+ QGtk::gdk_pixbuf_get_height = (Ptr_gdk_pixbuf_get_height)libgtk.resolve("gdk_pixbuf_get_height");
+ QGtk::gdk_pixmap_new = (Ptr_gdk_pixmap_new)libgtk.resolve("gdk_pixmap_new");
+ QGtk::gdk_pixbuf_new = (Ptr_gdk_pixbuf_new)libgtk.resolve("gdk_pixbuf_new");
+ QGtk::gdk_pixbuf_get_from_drawable = (Ptr_gdk_pixbuf_get_from_drawable)libgtk.resolve("gdk_pixbuf_get_from_drawable");
+ QGtk::gdk_draw_rectangle = (Ptr_gdk_draw_rectangle)libgtk.resolve("gdk_draw_rectangle");
+ QGtk::gdk_pixbuf_unref = (Ptr_gdk_pixbuf_unref)libgtk.resolve("gdk_pixbuf_unref");
+ QGtk::gdk_drawable_unref = (Ptr_gdk_drawable_unref)libgtk.resolve("gdk_drawable_unref");
+ QGtk::gdk_drawable_get_depth = (Ptr_gdk_drawable_get_depth)libgtk.resolve("gdk_drawable_get_depth");
+ QGtk::gdk_color_free = (Ptr_gdk_color_free)libgtk.resolve("gdk_color_free");
+ QGtk::gdk_x11_window_set_user_time = (Ptr_gdk_x11_window_set_user_time)libgtk.resolve("gdk_x11_window_set_user_time");
+ QGtk::gdk_x11_drawable_get_xid = (Ptr_gdk_x11_drawable_get_xid)libgtk.resolve("gdk_x11_drawable_get_xid");
+ QGtk::gdk_x11_drawable_get_xdisplay = (Ptr_gdk_x11_drawable_get_xdisplay)libgtk.resolve("gdk_x11_drawable_get_xdisplay");
+
+ QGtk::gtk_widget_set_default_direction = (Ptr_gtk_widget_set_default_direction)libgtk.resolve("gtk_widget_set_default_direction");
+ QGtk::gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_fg");
+ QGtk::gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_bg");
+ QGtk::gtk_arrow_new = (Ptr_gtk_arrow_new)libgtk.resolve("gtk_arrow_new");
+ QGtk::gtk_menu_item_new = (Ptr_gtk_menu_item_new)libgtk.resolve("gtk_menu_item_new");
+ QGtk::gtk_check_menu_item_new = (Ptr_gtk_check_menu_item_new)libgtk.resolve("gtk_check_menu_item_new");
+ QGtk::gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)libgtk.resolve("gtk_menu_bar_new");
+ QGtk::gtk_menu_new = (Ptr_gtk_menu_new)libgtk.resolve("gtk_menu_new");
+ QGtk::gtk_toolbar_new = (Ptr_gtk_toolbar_new)libgtk.resolve("gtk_toolbar_new");
+ QGtk::gtk_separator_tool_item_new = (Ptr_gtk_separator_tool_item_new)libgtk.resolve("gtk_separator_tool_item_new");
+ QGtk::gtk_toolbar_insert = (Ptr_gtk_toolbar_insert)libgtk.resolve("gtk_toolbar_insert");
+ QGtk::gtk_button_new = (Ptr_gtk_button_new)libgtk.resolve("gtk_button_new");
+ QGtk::gtk_hbutton_box_new = (Ptr_gtk_hbutton_box_new)libgtk.resolve("gtk_hbutton_box_new");
+ QGtk::gtk_check_button_new = (Ptr_gtk_check_button_new)libgtk.resolve("gtk_check_button_new");
+ QGtk::gtk_radio_button_new = (Ptr_gtk_radio_button_new)libgtk.resolve("gtk_radio_button_new");
+ QGtk::gtk_notebook_new = (Ptr_gtk_notebook_new)libgtk.resolve("gtk_notebook_new");
+ QGtk::gtk_progress_bar_new = (Ptr_gtk_progress_bar_new)libgtk.resolve("gtk_progress_bar_new");
+ QGtk::gtk_spin_button_new = (Ptr_gtk_spin_button_new)libgtk.resolve("gtk_spin_button_new");
+ QGtk::gtk_hscale_new = (Ptr_gtk_hscale_new)libgtk.resolve("gtk_hscale_new");
+ QGtk::gtk_vscale_new = (Ptr_gtk_vscale_new)libgtk.resolve("gtk_vscale_new");
+ QGtk::gtk_hscrollbar_new = (Ptr_gtk_hscrollbar_new)libgtk.resolve("gtk_hscrollbar_new");
+ QGtk::gtk_vscrollbar_new = (Ptr_gtk_vscrollbar_new)libgtk.resolve("gtk_vscrollbar_new");
+ QGtk::gtk_scrolled_window_new = (Ptr_gtk_scrolled_window_new)libgtk.resolve("gtk_scrolled_window_new");
+ QGtk::gtk_menu_shell_append = (Ptr_gtk_menu_shell_append)libgtk.resolve("gtk_menu_shell_append");
+ QGtk::gtk_entry_new = (Ptr_gtk_entry_new)libgtk.resolve("gtk_entry_new");
+ QGtk::gtk_tree_view_new = (Ptr_gtk_tree_view_new)libgtk.resolve("gtk_tree_view_new");
+ QGtk::gtk_combo_box_new = (Ptr_gtk_combo_box_new)libgtk.resolve("gtk_combo_box_new");
+ QGtk::gtk_progress_set_adjustment = (Ptr_gtk_progress_set_adjustment)libgtk.resolve("gtk_progress_set_adjustment");
+ QGtk::gtk_range_set_adjustment = (Ptr_gtk_range_set_adjustment)libgtk.resolve("gtk_range_set_adjustment");
+ QGtk::gtk_range_set_inverted = (Ptr_gtk_range_set_inverted)libgtk.resolve("gtk_range_set_inverted");
+ QGtk::gtk_container_add = (Ptr_gtk_container_add)libgtk.resolve("gtk_container_add");
+ QGtk::gtk_icon_factory_lookup_default = (Ptr_gtk_icon_factory_lookup_default)libgtk.resolve("gtk_icon_factory_lookup_default");
+ QGtk::gtk_widget_style_get = (Ptr_gtk_widget_style_get)libgtk.resolve("gtk_widget_style_get");
+ QGtk::gtk_icon_set_render_icon = (Ptr_gtk_icon_set_render_icon)libgtk.resolve("gtk_icon_set_render_icon");
+ QGtk::gtk_fixed_new = (Ptr_gtk_fixed_new)libgtk.resolve("gtk_fixed_new");
+ QGtk::gtk_tree_view_column_new = (Ptr_gtk_tree_view_column_new)libgtk.resolve("gtk_tree_view_column_new");
+ QGtk::gtk_tree_view_append_column= (Ptr_gtk_tree_view_append_column )libgtk.resolve("gtk_tree_view_append_column");
+ QGtk::gtk_tree_view_get_column = (Ptr_gtk_tree_view_get_column )libgtk.resolve("gtk_tree_view_get_column");
+ QGtk::gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check");
+ QGtk::gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box");
+ QGtk::gtk_paint_flat_box = (Ptr_gtk_paint_flat_box)libgtk.resolve("gtk_paint_flat_box");
+ QGtk::gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check");
+ QGtk::gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box");
+ QGtk::gtk_paint_resize_grip = (Ptr_gtk_paint_resize_grip)libgtk.resolve("gtk_paint_resize_grip");
+ QGtk::gtk_paint_focus = (Ptr_gtk_paint_focus)libgtk.resolve("gtk_paint_focus");
+ QGtk::gtk_paint_shadow = (Ptr_gtk_paint_shadow)libgtk.resolve("gtk_paint_shadow");
+ QGtk::gtk_paint_slider = (Ptr_gtk_paint_slider)libgtk.resolve("gtk_paint_slider");
+ QGtk::gtk_paint_expander = (Ptr_gtk_paint_expander)libgtk.resolve("gtk_paint_expander");
+ QGtk::gtk_paint_handle = (Ptr_gtk_paint_handle)libgtk.resolve("gtk_paint_handle");
+ QGtk::gtk_paint_option = (Ptr_gtk_paint_option)libgtk.resolve("gtk_paint_option");
+ QGtk::gtk_paint_arrow = (Ptr_gtk_paint_arrow)libgtk.resolve("gtk_paint_arrow");
+ QGtk::gtk_paint_box_gap = (Ptr_gtk_paint_box_gap)libgtk.resolve("gtk_paint_box_gap");
+ QGtk::gtk_paint_extension = (Ptr_gtk_paint_extension)libgtk.resolve("gtk_paint_extension");
+ QGtk::gtk_paint_hline = (Ptr_gtk_paint_hline)libgtk.resolve("gtk_paint_hline");
+ QGtk::gtk_paint_vline = (Ptr_gtk_paint_vline)libgtk.resolve("gtk_paint_vline");
+ QGtk::gtk_adjustment_new = (Ptr_gtk_adjustment_new)libgtk.resolve("gtk_adjustment_new");
+ QGtk::gtk_menu_item_set_submenu = (Ptr_gtk_menu_item_set_submenu)libgtk.resolve("gtk_menu_item_set_submenu");
+ QGtk::gtk_settings_get_default = (Ptr_gtk_settings_get_default)libgtk.resolve("gtk_settings_get_default");
+ QGtk::gtk_separator_menu_item_new = (Ptr_gtk_separator_menu_item_new)libgtk.resolve("gtk_separator_menu_item_new");
+ QGtk::gtk_frame_new = (Ptr_gtk_frame_new)libgtk.resolve("gtk_frame_new");
+ QGtk::gtk_expander_new = (Ptr_gtk_expander_new)libgtk.resolve("gtk_expander_new");
+ QGtk::gtk_statusbar_new = (Ptr_gtk_statusbar_new)libgtk.resolve("gtk_statusbar_new");
+ QGtk::gtk_combo_box_entry_new = (Ptr_gtk_combo_box_entry_new)libgtk.resolve("gtk_combo_box_entry_new");
+ QGtk::gtk_container_forall = (Ptr_gtk_container_forall)libgtk.resolve("gtk_container_forall");
+ QGtk::gtk_widget_size_allocate =(Ptr_gtk_widget_size_allocate)libgtk.resolve("gtk_widget_size_allocate");
+ QGtk::gtk_widget_set_direction =(Ptr_gtk_widget_set_direction)libgtk.resolve("gtk_widget_set_direction");
+ QGtk::gtk_widget_path =(Ptr_gtk_widget_path)libgtk.resolve("gtk_widget_path");
+ QGtk::gtk_container_get_type =(Ptr_gtk_container_get_type)libgtk.resolve("gtk_container_get_type");
+ QGtk::gtk_window_get_type =(Ptr_gtk_window_get_type)libgtk.resolve("gtk_window_get_type");
+ QGtk::gtk_widget_get_type =(Ptr_gtk_widget_get_type)libgtk.resolve("gtk_widget_get_type");
+ QGtk::gtk_rc_get_style_by_paths =(Ptr_gtk_rc_get_style_by_paths)libgtk.resolve("gtk_rc_get_style_by_paths");
+ QGtk::gtk_check_version =(Ptr_gtk_check_version)libgtk.resolve("gtk_check_version");
+ QGtk::pango_font_description_get_size = (Ptr_pango_font_description_get_size)libgtk.resolve("pango_font_description_get_size");
+ QGtk::pango_font_description_get_weight = (Ptr_pango_font_description_get_weight)libgtk.resolve("pango_font_description_get_weight");
+ QGtk::pango_font_description_get_family = (Ptr_pango_font_description_get_family)libgtk.resolve("pango_font_description_get_family");
+ QGtk::pango_font_description_get_style = (Ptr_pango_font_description_get_style)libgtk.resolve("pango_font_description_get_style");
}
void QGtk::cleanup_gtk_widgets()
@@ -338,9 +342,9 @@ static bool resolveGConf()
typedef int (*x11ErrorHandler)(Display*, XErrorEvent*);
-static QString getGConfString(const QString &value)
+QString QGtk::getGConfString(const QString &value, const QString &fallback)
{
- QString retVal;
+ QString retVal = fallback;
if (resolveGConf()) {
g_type_init();
GConfClient* client = QGtk::gconf_client_get_default();
@@ -374,8 +378,8 @@ static QString getThemeName()
while(!in.atEnd()) {
QString line = in.readLine();
if (line.contains(QLS("gtk-theme-name"))) {
- line = line.right(line.length() - line.indexOf(QLS("=")) - 1);
- line.remove(QLS("\""));
+ line = line.right(line.length() - line.indexOf(QLatin1Char('=')) - 1);
+ line.remove(QLatin1Char('\"'));
line = line.trimmed();
themeName = line;
break;
@@ -390,7 +394,7 @@ static QString getThemeName()
// Fall back to gconf
if (themeName.isEmpty() && resolveGConf())
- themeName = getGConfString(QLS("/desktop/gnome/interface/gtk_theme"));
+ themeName = QGtk::getGConfString(QLS("/desktop/gnome/interface/gtk_theme"));
return themeName;
}
@@ -543,9 +547,13 @@ void QGtkStyleUpdateScheduler::updateTheme()
{
static QString oldTheme(QLS("qt_not_set"));
QPixmapCache::clear();
+
+ QFont font = QGtk::getThemeFont();
+ if (QApplication::font() != font)
+ qApp->setFont(font);
+
if (oldTheme != getThemeName()) {
oldTheme = getThemeName();
- qApp->setFont(QGtk::getThemeFont());
QPalette newPalette = qApp->style()->standardPalette();
QApplicationPrivate::setSystemPalette(newPalette);
QApplication::setPalette(newPalette);
@@ -558,6 +566,7 @@ void QGtkStyleUpdateScheduler::updateTheme()
QApplication::sendEvent(widget, &e);
}
}
+ QIconLoader::instance()->updateSystemTheme();
}
static void add_widget(GtkWidget *widget)
@@ -633,6 +642,20 @@ GtkStyle* QGtk::gtkStyle(const QString &path)
return 0;
}
+static void update_toolbar_style(GtkWidget *gtkToolBar, GParamSpec *, gpointer)
+{
+ GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS;
+ g_object_get(gtkToolBar, "toolbar-style", &toolbar_style, NULL);
+ QWidgetList widgets = QApplication::allWidgets();
+ for (int i = 0; i < widgets.size(); ++i) {
+ QWidget *widget = widgets.at(i);
+ if (qobject_cast<QToolButton*>(widget)) {
+ QEvent event(QEvent::StyleChange);
+ QApplication::sendEvent(widget, &event);
+ }
+ }
+}
+
void QGtk::initGtkWidgets()
{
// From gtkmain.c
@@ -679,6 +702,7 @@ void QGtk::initGtkWidgets()
add_widget(QGtk::gtk_spin_button_new((GtkAdjustment*)
(QGtk::gtk_adjustment_new(1, 0, 1, 0, 0, 0)), 0.1, 3));
GtkWidget *toolbar = QGtk::gtk_toolbar_new();
+ g_signal_connect (toolbar, "notify::toolbar-style", G_CALLBACK (update_toolbar_style), toolbar);
QGtk::gtk_toolbar_insert((GtkToolbar*)toolbar, QGtk::gtk_separator_tool_item_new(), -1);
add_widget(toolbar);
init_gtk_treeview();
@@ -695,7 +719,7 @@ void QGtk::initGtkWidgets()
QHashIterator<QString, GtkWidget*> it(oldMap);
while (it.hasNext()) {
it.next();
- if (!it.key().contains(QLS("."))) {
+ if (!it.key().contains(QLatin1Char('.'))) {
add_all_sub_widgets(it.value());
}
}
@@ -720,7 +744,8 @@ extern QStringList qt_make_filter_list(const QString &filter);
static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent,
const QString &dir, const QString &filter, QString *selectedFilter,
- QFileDialog::Options options, bool isSaveDialog = false)
+ QFileDialog::Options options, bool isSaveDialog = false,
+ QMap<GtkFileFilter *, QString> *filterMap = 0)
{
g_object_set(gtkFileChooser, "do-overwrite-confirmation", gboolean(!(options & QFileDialog::DontConfirmOverwrite)), NULL);
g_object_set(gtkFileChooser, "local_only", gboolean(true), NULL);
@@ -752,6 +777,8 @@ static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent,
QGtk::gtk_file_filter_add_pattern (gtkFilter, qPrintable(caseInsensitive));
}
+ if (filterMap)
+ filterMap->insert(gtkFilter, rawfilter);
QGtk::gtk_file_chooser_add_filter((GtkFileChooser*)gtkFileChooser, gtkFilter);
if (selectedFilter && (rawfilter == *selectedFilter))
QGtk::gtk_file_chooser_set_filter((GtkFileChooser*)gtkFileChooser, gtkFilter);
@@ -788,7 +815,7 @@ static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent,
QString QGtk::openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter,
QString *selectedFilter, QFileDialog::Options options)
{
-
+ QMap<GtkFileFilter *, QString> filterMap;
GtkWidget *gtkFileChooser = QGtk::gtk_file_chooser_dialog_new (qPrintable(caption),
NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
@@ -796,7 +823,7 @@ QString QGtk::openFilename(QWidget *parent, const QString &caption, const QStrin
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
- setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options);
+ setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap);
QWidget modal_widget;
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
@@ -808,6 +835,10 @@ QString QGtk::openFilename(QWidget *parent, const QString &caption, const QStrin
char *gtk_filename = QGtk::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser);
filename = QString::fromUtf8(gtk_filename);
g_free (gtk_filename);
+ if (selectedFilter) {
+ GtkFileFilter *gtkFilter = QGtk::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser);
+ *selectedFilter = filterMap.value(gtkFilter);
+ }
}
QApplicationPrivate::leaveModal(&modal_widget);
@@ -818,6 +849,7 @@ QString QGtk::openFilename(QWidget *parent, const QString &caption, const QStrin
QString QGtk::openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options)
{
+ QMap<GtkFileFilter *, QString> filterMap;
GtkWidget *gtkFileChooser = QGtk::gtk_file_chooser_dialog_new (qPrintable(caption),
NULL,
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
@@ -847,6 +879,7 @@ QStringList QGtk::openFilenames(QWidget *parent, const QString &caption, const Q
QString *selectedFilter, QFileDialog::Options options)
{
QStringList filenames;
+ QMap<GtkFileFilter *, QString> filterMap;
GtkWidget *gtkFileChooser = QGtk::gtk_file_chooser_dialog_new (qPrintable(caption),
NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
@@ -854,7 +887,7 @@ QStringList QGtk::openFilenames(QWidget *parent, const QString &caption, const Q
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
- setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options);
+ setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap);
g_object_set(gtkFileChooser, "select-multiple", gboolean(true), NULL);
QWidget modal_widget;
@@ -867,6 +900,10 @@ QStringList QGtk::openFilenames(QWidget *parent, const QString &caption, const Q
for (GSList *iterator = gtk_file_names ; iterator; iterator = iterator->next)
filenames << QString::fromUtf8((const char*)iterator->data);
g_slist_free(gtk_file_names);
+ if (selectedFilter) {
+ GtkFileFilter *gtkFilter = QGtk::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser);
+ *selectedFilter = filterMap.value(gtkFilter);
+ }
}
QApplicationPrivate::leaveModal(&modal_widget);
@@ -877,13 +914,14 @@ QStringList QGtk::openFilenames(QWidget *parent, const QString &caption, const Q
QString QGtk::saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter,
QString *selectedFilter, QFileDialog::Options options)
{
+ QMap<GtkFileFilter *, QString> filterMap;
GtkWidget *gtkFileChooser = QGtk::gtk_file_chooser_dialog_new (qPrintable(caption),
NULL,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
NULL);
- setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, true);
+ setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, true, &filterMap);
QWidget modal_widget;
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
@@ -895,6 +933,10 @@ QString QGtk::saveFilename(QWidget *parent, const QString &caption, const QStrin
char *gtk_filename = QGtk::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser);
filename = QString::fromUtf8(gtk_filename);
g_free (gtk_filename);
+ if (selectedFilter) {
+ GtkFileFilter *gtkFilter = QGtk::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser);
+ *selectedFilter = filterMap.value(gtkFilter);
+ }
}
QApplicationPrivate::leaveModal(&modal_widget);
diff --git a/src/gui/styles/gtksymbols_p.h b/src/gui/styles/gtksymbols_p.h
index c2c8e36..596a312 100644
--- a/src/gui/styles/gtksymbols_p.h
+++ b/src/gui/styles/gtksymbols_p.h
@@ -162,6 +162,7 @@ typedef void (*Ptr_gtk_file_filter_set_name)(GtkFileFilter *, const gchar *);
typedef void (*Ptr_gtk_file_filter_add_pattern)(GtkFileFilter *filter, const gchar *pattern);
typedef void (*Ptr_gtk_file_chooser_add_filter)(GtkFileChooser *chooser, GtkFileFilter *filter);
typedef void (*Ptr_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter);
+typedef GtkFileFilter* (*Ptr_gtk_file_chooser_get_filter)(GtkFileChooser *chooser);
typedef gchar* (*Ptr_gtk_file_chooser_get_filename)(GtkFileChooser *chooser);
typedef GSList* (*Ptr_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
typedef GtkWidget* (*Ptr_gtk_file_chooser_dialog_new)(const gchar *title,
@@ -215,6 +216,7 @@ public:
static QString openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);
static QStringList openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter,
QString *selectedFilter, QFileDialog::Options options);
+ static QString getGConfString(const QString &key, const QString &fallback = QString());
static Ptr_gtk_container_forall gtk_container_forall;
static Ptr_gtk_init gtk_init;
@@ -302,6 +304,7 @@ public:
static Ptr_gtk_file_filter_add_pattern gtk_file_filter_add_pattern;
static Ptr_gtk_file_chooser_add_filter gtk_file_chooser_add_filter;
static Ptr_gtk_file_chooser_set_filter gtk_file_chooser_set_filter;
+ static Ptr_gtk_file_chooser_get_filter gtk_file_chooser_get_filter;
static Ptr_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new;
static Ptr_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder;
static Ptr_gtk_file_chooser_get_filename gtk_file_chooser_get_filename;
diff --git a/src/gui/styles/images/defaults60theme.blob b/src/gui/styles/images/defaults60theme.blob
new file mode 100644
index 0000000..f3a5952
--- /dev/null
+++ b/src/gui/styles/images/defaults60theme.blob
Binary files differ
diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp
index 3f813f9..6d957ca 100644
--- a/src/gui/styles/qcleanlooksstyle.cpp
+++ b/src/gui/styles/qcleanlooksstyle.cpp
@@ -44,6 +44,7 @@
#if !defined(QT_NO_STYLE_CLEANLOOKS) || defined(QT_PLUGIN)
+#include <private/qstylehelper_p.h>
#include "qwindowsstyle_p.h"
#include <qcombobox.h>
#include <qpushbutton.h>
@@ -72,7 +73,7 @@
QT_BEGIN_NAMESPACE
-static const bool UsePixmapCache = true;
+using namespace QStyleHelper;
enum Direction {
TopDown,
@@ -83,14 +84,9 @@ enum Direction {
// from windows style
static const int windowsItemFrame = 2; // menu item frame width
-static const int windowsSepHeight = 6; // separator item height
static const int windowsItemHMargin = 3; // menu item hor text margin
static const int windowsItemVMargin = 8; // menu item ver text margin
-static const int windowsArrowHMargin = 6; // arrow horizontal margin
-static const int windowsTabSpacing = 12; // space between text and tab
-static const int windowsCheckMarkHMargin = 2; // horiz. margins of check mark
static const int windowsRightBorder = 15; // right border on windows
-static const int windowsCheckMarkWidth = 12; // checkmarks width on windows
/* XPM */
static const char * const dock_widget_close_xpm[] = {
@@ -461,26 +457,6 @@ static const char * const qt_cleanlooks_checkbox_checked[] = {
" ",
" "};
-#ifdef Q_WS_X11
-extern "C" {
- struct GConfClient;
- struct GError;
- typedef void (*Ptr_g_type_init)();
- typedef GConfClient* (*Ptr_gconf_client_get_default)();
- typedef char* (*Ptr_gconf_client_get_string)(GConfClient*, const char*, GError **);
- typedef void (*Ptr_g_object_unref)(void *);
- typedef void (*Ptr_g_error_free)(GError *);
- typedef void (*Ptr_g_free)(void*);
-}
-
-static Ptr_g_type_init p_g_type_init = 0;
-static Ptr_gconf_client_get_default p_gconf_client_get_default = 0;
-static Ptr_gconf_client_get_string p_gconf_client_get_string = 0;
-static Ptr_g_object_unref p_g_object_unref = 0;
-static Ptr_g_error_free p_g_error_free = 0;
-static Ptr_g_free p_g_free = 0;
-#endif
-
static void qt_cleanlooks_draw_gradient(QPainter *painter, const QRect &rect, const QColor &gradientStart,
const QColor &gradientStop, Direction direction = TopDown, QBrush bgBrush = QBrush())
{
@@ -553,26 +529,6 @@ static void qt_cleanlooks_draw_buttongradient(QPainter *painter, const QRect &re
delete gradient;
}
-static QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size)
-{
- QString tmp;
- const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option);
- tmp.sprintf("%s-%d-%d-%lld-%dx%d-%d", key.toLatin1().constData(), uint(option->state),
- complexOption ? uint(complexOption->activeSubControls) : uint(0),
- option->palette.cacheKey(), size.width(), size.height(), option->direction);
-#ifndef QT_NO_SPINBOX
- if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- tmp.append(QLatin1Char('-'));
- tmp.append(QString::number(spinBox->buttonSymbols));
- tmp.append(QLatin1Char('-'));
- tmp.append(QString::number(spinBox->stepEnabled));
- tmp.append(QLatin1Char('-'));
- tmp.append(QLatin1Char(spinBox->frame ? '1' : '0'));
- }
-#endif // QT_NO_SPINBOX
- return tmp;
-}
-
static void qt_cleanlooks_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken)
{
QColor dark;
@@ -782,7 +738,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
QStyleOptionButton button;
button.QStyleOption::operator=(*option);
button.state &= ~State_MouseOver;
- drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
}
return;
case PE_IndicatorHeaderArrow:
@@ -802,7 +758,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
}
break;
case PE_IndicatorButtonDropDown:
- drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
break;
case PE_IndicatorToolBarSeparator:
{
@@ -887,9 +843,9 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
if (widget && widget->inherits("QDockWidgetTitleButton")) {
if (option->state & State_MouseOver)
- drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
} else {
- drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
}
}
painter->restore();
@@ -902,7 +858,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
dockWidgetHandle.state &= ~State_Horizontal;
else
dockWidgetHandle.state |= State_Horizontal;
- drawControl(CE_Splitter, &dockWidgetHandle, painter, widget);
+ proxy()->drawControl(CE_Splitter, &dockWidgetHandle, painter, widget);
}
break;
case PE_FrameWindow:
@@ -928,7 +884,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
#endif // QT_NO_LINEEDIT
#ifdef QT3_SUPPORT
if (widget && widget->inherits("Q3ToolBar")) {
- drawPrimitive(PE_Q3Separator, option, painter, widget);
+ proxy()->drawPrimitive(PE_Q3Separator, option, painter, widget);
break;
}
#endif
@@ -1257,7 +1213,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
QColor alphaCornerColor = mergedColors(borderColor, option->palette.background().color());
QColor innerShadow = mergedColors(borderColor, option->palette.base().color());
- int borderThickness = pixelMetric(PM_TabBarBaseOverlap, twf, widget);
+ int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, twf, widget);
bool reverse = (twf->direction == Qt::RightToLeft);
QRect tabBarRect;
@@ -1370,9 +1326,9 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
if (d->tabBarcloseButtonIcon.isNull())
d->tabBarcloseButtonIcon = standardIcon(SP_DialogCloseButton, option, widget);
if ((option->state & State_Enabled) && (option->state & State_MouseOver))
- drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On);
- drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap);
}
break;
@@ -1543,7 +1499,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
default:
break;
}
- if (QApplication::layoutDirection() == Qt::RightToLeft) { //reverse layout changes the order of Beginning/end
+ if (toolbar->direction == Qt::RightToLeft) { //reverse layout changes the order of Beginning/end
bool tmp = paintLeftBorder;
paintRightBorder=paintLeftBorder;
paintLeftBorder=tmp;
@@ -1649,7 +1605,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
QString titleText
= painter->fontMetrics().elidedText(dwOpt->title,
Qt::ElideRight, titleRect.width());
- drawItemText(painter,
+ proxy()->drawItemText(painter,
titleRect,
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, titleText,
@@ -1664,9 +1620,9 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
// Draws the header in tables.
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QPixmap cache;
- QString pixmapName = uniqueName(QLatin1String("headersection"), option, option->rect.size());
- pixmapName += QLatin1String("-") + QString::number(int(header->position));
- pixmapName += QLatin1String("-") + QString::number(int(header->orientation));
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size());
+ pixmapName += QString::number(- int(header->position));
+ pixmapName += QString::number(- int(header->orientation));
QRect r = option->rect;
QColor gradientStopColor;
QColor gradientStartColor = option->palette.button().color();
@@ -1683,7 +1639,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
}
painter->fillRect(r, gradient);
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(r.size());
cache.fill(Qt::transparent);
QRect pixmapRect(0, 0, r.width(), r.height());
@@ -1702,8 +1658,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
cachePainter.drawLine(pixmapRect.topRight() + QPoint(-1, 3), pixmapRect.bottomRight() + QPoint(-1, -3)); cachePainter.setPen(QPen(option->palette.light().color()));
cachePainter.drawLine(pixmapRect.topRight() + QPoint(0, 3), pixmapRect.bottomRight() + QPoint(0, -3)); }
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(r.topLeft(), cache);
}
@@ -1758,18 +1713,16 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
// same rendering code for both orientations.
if (vertical) {
rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
- QTransform m;
- m.translate(rect.height()-1, -1.0);
+ QTransform m = QTransform::fromTranslate(rect.height()-1, -1.0);
m.rotate(90.0);
painter->setTransform(m, true);
}
int maxWidth = rect.width() - 4;
int minWidth = 4;
- qint64 progress = (qint64)qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar
- double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth);
- int progressBarWidth = (int(vc6_workaround) > minWidth ) ? int(vc6_workaround) : minWidth;
- int width = indeterminate ? maxWidth : progressBarWidth;
+ qreal progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar
+ int progressBarWidth = (progress - bar->minimum) * qreal(maxWidth) / qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum);
+ int width = indeterminate ? maxWidth : qMax(minWidth, progressBarWidth);
bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical;
if (inverted)
@@ -1864,7 +1817,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
if (!styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
- drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
+ proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
}
}
@@ -1891,7 +1844,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
int w = 0;
if (!menuItem->text.isEmpty()) {
painter->setFont(menuItem->font);
- drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
+ proxy()->drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
menuItem->palette, menuItem->state & State_Enabled, menuItem->text,
QPalette::Text);
w = menuItem->fontMetrics.width(menuItem->text) + 5;
@@ -1995,7 +1948,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
mode = QIcon::Active;
QPixmap pixmap;
- int smallIconSize = pixelMetric(PM_SmallIconSize, option, widget);
+ int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
QSize iconSize(smallIconSize, smallIconSize);
#ifndef QT_NO_COMBOBOX
if (const QComboBox *combo = qobject_cast<const QComboBox*>(widget))
@@ -2021,7 +1974,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
}
opt.state |= State_Sunken;
opt.rect = vCheckRect;
- drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
}
painter->drawPixmap(pmr.topLeft(), pixmap);
}
@@ -2054,7 +2007,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
if (t >= 0) {
QRect vShortcutRect = visualRect(opt->direction, menuitem->rect,
QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
- if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, s.mid(t + 1));
p->setPen(discol);
@@ -2063,12 +2016,18 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
s = s.left(t);
}
QFont font = menuitem->font;
+ // font may not have any "hard" flags set. We override
+ // the point size so that when it is resolved against the device, this font will win.
+ // This is mainly to handle cases where someone sets the font on the window
+ // and then the combo inherits it and passes it onward. At that point the resolve mask
+ // is very, very weak. This makes it stonger.
+ font.setPointSizeF(menuItem->font.pointSizeF());
if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
font.setBold(true);
p->setFont(font);
- if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, s.left(t));
p->setPen(discol);
@@ -2091,7 +2050,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
if (selected)
newMI.palette.setColor(QPalette::ButtonText,
newMI.palette.highlightedText().color());
- drawPrimitive(arrow, &newMI, painter, widget);
+ proxy()->drawPrimitive(arrow, &newMI, painter, widget);
}
}
painter->restore();
@@ -2152,7 +2111,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
if (button->features & QStyleOptionButton::HasMenu)
ir = ir.adjusted(0, 0, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0);
- drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled),
+ proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled),
button->text, QPalette::ButtonText);
}
break;
@@ -2207,7 +2166,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
|| (rtlHorTabs
&& tab->selectedPosition
== QStyleOptionTab::PreviousIsSelected));
- int tabBarAlignment = styleHint(SH_TabBar_Alignment, tab, widget);
+ int tabBarAlignment = proxy()->styleHint(SH_TabBar_Alignment, tab, widget);
bool leftAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignLeft)
|| (rtlHorTabs
&& tabBarAlignment == Qt::AlignRight);
@@ -2220,7 +2179,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
QColor midlight = tab->palette.midlight().color();
QColor background = tab->palette.background().color();
- int borderThinkness = pixelMetric(PM_TabBarBaseOverlap, tab, widget);
+ int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
if (selected)
borderThinkness /= 2;
QRect r2(option->rect);
@@ -2456,8 +2415,8 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
QPixmap cache;
- QString pixmapName = uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size());
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size());
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(spinBox->rect.size());
cache.fill(Qt::transparent);
QRect pixmapRect(0, 0, spinBox->rect.width(), spinBox->rect.height());
@@ -2473,10 +2432,10 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QRect rect = pixmapRect;
QStyleOptionSpinBox spinBoxCopy = *spinBox;
spinBoxCopy.rect = pixmapRect;
- QRect upRect = subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxUp, widget);
- QRect downRect = subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxDown, widget);
+ QRect upRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxUp, widget);
+ QRect downRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxDown, widget);
- int fw = spinBoxCopy.frame ? pixelMetric(PM_SpinBoxFrameWidth, &spinBoxCopy, widget) : 0;
+ int fw = spinBoxCopy.frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, &spinBoxCopy, widget) : 0;
cachePainter.fillRect(rect.adjusted(1, qMax(fw - 1, 0), -1, -fw),
option->palette.base());
@@ -2674,8 +2633,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
cachePainter.fillRect(downRect.adjusted(1, 0, 0, 0), disabledColor);
}
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(spinBox->rect.topLeft(), cache);
}
@@ -2699,7 +2657,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
if (widget && widget->inherits("Q3DockWindowTitleBar")) {
QStyleOptionDockWidgetV2 dockwidget;
dockwidget.QStyleOption::operator=(*option);
- drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget);
+ proxy()->drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget);
} else
#endif // QT3_SUPPORT
{
@@ -2742,7 +2700,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
painter->drawLine(fullRect.left() + 6, fullRect.top() + 1, fullRect.right() - 6, fullRect.top() + 1);
}
// draw title
- QRect textRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
+ QRect textRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
QFont font = painter->font();
font.setBold(true);
painter->setFont(font);
@@ -2757,7 +2715,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// min button
if ((titleBar->subControls & SC_TitleBarMinButton) && (titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
!(titleBar->titleBarState& Qt::WindowMinimized)) {
- QRect minButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
+ QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
if (minButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken);
@@ -2778,7 +2736,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// max button
if ((titleBar->subControls & SC_TitleBarMaxButton) && (titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
!(titleBar->titleBarState & Qt::WindowMaximized)) {
- QRect maxButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
+ QRect maxButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
if (maxButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken);
@@ -2800,7 +2758,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// close button
if ((titleBar->subControls & SC_TitleBarCloseButton) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
- QRect closeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
+ QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
if (closeButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken);
@@ -2834,7 +2792,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
(titleBar->titleBarState & Qt::WindowMinimized)) ||
((titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
(titleBar->titleBarState & Qt::WindowMaximized)))) {
- QRect normalButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
+ QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
if (normalButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver);
@@ -2874,7 +2832,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// context help button
if (titleBar->subControls & SC_TitleBarContextHelpButton
&& (titleBar->titleBarFlags & Qt::WindowContextHelpButtonHint)) {
- QRect contextHelpButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
+ QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
if (contextHelpButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken);
@@ -2893,7 +2851,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// shade button
if (titleBar->subControls & SC_TitleBarShadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
- QRect shadeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
+ QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
if (shadeButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken);
@@ -2906,7 +2864,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// unshade button
if (titleBar->subControls & SC_TitleBarUnshadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
- QRect unshadeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
+ QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
if (unshadeButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken);
@@ -2918,7 +2876,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
if ((titleBar->subControls & SC_TitleBarSysMenu) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
- QRect iconRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
+ QRect iconRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
if (iconRect.isValid()) {
if (!titleBar->icon.isNull()) {
titleBar->icon.paint(painter, iconRect);
@@ -2928,7 +2886,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QPixmap pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16);
tool.rect = iconRect;
painter->save();
- drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
painter->restore();
}
}
@@ -2948,10 +2906,10 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
painter->fillRect(option->rect, option->palette.background());
QRect rect = scrollBar->rect;
- QRect scrollBarSubLine = subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
- QRect scrollBarAddLine = subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
- QRect scrollBarSlider = subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
- QRect grooveRect = subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
+ QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
+ QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
+ QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
+ QRect grooveRect = proxy()->subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
// paint groove
if (scrollBar->subControls & SC_ScrollBarGroove) {
@@ -3086,7 +3044,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// The SubLine (up/left) buttons
if (scrollBar->subControls & SC_ScrollBarSubLine) {
- //int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, option, widget);
+ //int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, option, widget);
QRect pixmapRect = scrollBarSubLine;
if (isEnabled ) {
QRect fillRect = pixmapRect.adjusted(1, 1, -1, -1);
@@ -3132,12 +3090,12 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
arrow = PE_IndicatorArrowUp;
QStyleOption arrowOpt = *option;
arrowOpt.rect = scrollBarSubLine.adjusted(3, 3, -2, -2);
- drawPrimitive(arrow, &arrowOpt, painter, widget);
+ proxy()->drawPrimitive(arrow, &arrowOpt, painter, widget);
// The AddLine (down/right) button
if (scrollBar->subControls & SC_ScrollBarAddLine) {
- QString addLinePixmapName = uniqueName(QLatin1String("scrollbar_addline"), option, QSize(16, 16));
+ QString addLinePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_addline"), option, QSize(16, 16));
QRect pixmapRect = scrollBarAddLine;
if (isEnabled) {
QRect fillRect = pixmapRect.adjusted(1, 1, -1, -1);
@@ -3183,7 +3141,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QStyleOption arrowOpt = *option;
arrowOpt.rect = scrollBarAddLine.adjusted(3, 3, -2, -2);
- drawPrimitive(arrow, &arrowOpt, painter, widget);
+ proxy()->drawPrimitive(arrow, &arrowOpt, painter, widget);
}
}
}
@@ -3198,7 +3156,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
bool isEnabled = (comboBox->state & State_Enabled);
bool focus = isEnabled && (comboBox->state & State_HasFocus);
QPixmap cache;
- QString pixmapName = uniqueName(QLatin1String("combobox"), option, comboBox->rect.size());
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("combobox"), option, comboBox->rect.size());
if (sunken)
pixmapName += QLatin1String("-sunken");
if (comboBox->editable)
@@ -3206,7 +3164,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
if (isEnabled)
pixmapName += QLatin1String("-enabled");
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(comboBox->rect.size());
cache.fill(Qt::transparent);
QPainter cachePainter(&cache);
@@ -3215,9 +3173,9 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
comboBoxCopy.rect = pixmapRect;
QRect rect = pixmapRect;
- QRect downArrowRect = subControlRect(CC_ComboBox, &comboBoxCopy,
+ QRect downArrowRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
SC_ComboBoxArrow, widget);
- QRect editRect = subControlRect(CC_ComboBox, &comboBoxCopy,
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
SC_ComboBoxEditField, widget);
// Draw a push button
if (comboBox->editable) {
@@ -3231,7 +3189,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
buttonOption.state &= ~State_MouseOver;
}
- drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
//remove shadow from left side of edit field when pressed:
if (comboBox->direction != Qt::RightToLeft)
@@ -3273,7 +3231,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
buttonOption.state |= State_Sunken;
buttonOption.state &= ~State_MouseOver;
}
- drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
cachePainter.setPen(buttonShadow.darker(102));
int borderSize = 4;
@@ -3326,15 +3284,15 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
}
// Draw the focus rect
- if ((focus && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) {
+ if (focus && !comboBox->editable
+ && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) {
QStyleOptionFocusRect focus;
- focus.rect = subControlRect(CC_ComboBox, &comboBoxCopy, SC_ComboBoxEditField, widget)
+ focus.rect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy, SC_ComboBoxEditField, widget)
.adjusted(0, 2, option->direction == Qt::RightToLeft ? 1 : -1, -2);
- drawPrimitive(PE_FrameFocusRect, &focus, &cachePainter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focus, &cachePainter, widget);
}
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(comboBox->rect.topLeft(), cache);
}
@@ -3345,8 +3303,8 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
case CC_GroupBox:
painter->save();
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
- QRect textRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
- QRect checkBoxRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget);
+ QRect textRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
+ QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget);
bool flat = groupBox->features & QStyleOptionFrameV2::Flat;
if(!flat) {
@@ -3356,7 +3314,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
frame.features = groupBox->features;
frame.lineWidth = groupBox->lineWidth;
frame.midLineWidth = groupBox->midLineWidth;
- frame.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
+ frame.rect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
painter->save();
QRegion region(groupBox->rect);
@@ -3365,7 +3323,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
if (!groupBox->text.isEmpty() || groupBox->subControls & SC_GroupBoxCheckBox)
painter->setClipRegion(region);
frame.palette.setBrush(QPalette::Dark, option->palette.mid().color().lighter(110));
- drawPrimitive(PE_FrameGroupBox, &frame, painter);
+ proxy()->drawPrimitive(PE_FrameGroupBox, &frame, painter);
painter->restore();
}
}
@@ -3393,7 +3351,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QStyleOptionButton box;
box.QStyleOption::operator=(*groupBox);
box.rect = checkBoxRect;
- drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
}
}
painter->restore();
@@ -3402,9 +3360,9 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- QRect groove = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
- QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
+ QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
+ QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
@@ -3421,11 +3379,11 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
highlightAlpha.setAlpha(80);
if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
- QString groovePixmapName = uniqueName(QLatin1String("slider_groove"), option, groove.size());
+ QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_groove"), option, groove.size());
QRect pixmapRect(0, 0, groove.width(), groove.height());
// draw background groove
- if (!UsePixmapCache || !QPixmapCache::find(groovePixmapName, cache)) {
+ if (!QPixmapCache::find(groovePixmapName, cache)) {
cache = QPixmap(pixmapRect.size());
cache.fill(Qt::transparent);
QPainter groovePainter(&cache);
@@ -3452,15 +3410,14 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
groovePainter.setBrush(gradient);
groovePainter.drawRect(pixmapRect.adjusted(1, 1, -2, -2));
groovePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(groovePixmapName, cache);
+ QPixmapCache::insert(groovePixmapName, cache);
}
painter->drawPixmap(groove.topLeft(), cache);
// draw blue groove highlight
QRect clipRect;
groovePixmapName += QLatin1String("_blue");
- if (!UsePixmapCache || !QPixmapCache::find(groovePixmapName, cache)) {
+ if (!QPixmapCache::find(groovePixmapName, cache)) {
cache = QPixmap(pixmapRect.size());
cache.fill(Qt::transparent);
QPainter groovePainter(&cache);
@@ -3479,8 +3436,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
groovePainter.setBrush(gradient);
groovePainter.drawRect(pixmapRect.adjusted(1, 1, -2, -2));
groovePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(groovePixmapName, cache);
+ QPixmapCache::insert(groovePixmapName, cache);
}
if (horizontal) {
if (slider->upsideDown)
@@ -3501,8 +3457,8 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// draw handle
if ((option->subControls & SC_SliderHandle) ) {
- QString handlePixmapName = uniqueName(QLatin1String("slider_handle"), option, handle.size());
- if (!UsePixmapCache || !QPixmapCache::find(handlePixmapName, cache)) {
+ QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size());
+ if (!QPixmapCache::find(handlePixmapName, cache)) {
cache = QPixmap(handle.size());
cache.fill(Qt::transparent);
QRect pixmapRect(0, 0, handle.width(), handle.height());
@@ -3583,8 +3539,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
}
handlePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(handlePixmapName, cache);
+ QPixmapCache::insert(handlePixmapName, cache);
}
painter->drawPixmap(handle.topLeft(), cache);
@@ -3593,13 +3548,13 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*slider);
fropt.rect = slider->rect;
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
}
if (option->subControls & SC_SliderTickmarks) {
painter->setPen(darkOutline);
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
interval = slider->singleStep;
@@ -3613,7 +3568,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
interval = 1;
int v = slider->minimum;
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
while (v <= slider->maximum + 1) {
if (v == slider->maximum + 1 && interval == 1)
break;
@@ -3656,6 +3611,12 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
break;
#endif // QT_NO_SLIDER
+#ifndef QT_NO_DIAL
+ case CC_Dial:
+ if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
+ QStyleHelper::drawDial(dial, painter);
+ break;
+#endif // QT_NO_DIAL
default:
QWindowsStyle::drawComplexControl(control, option, painter, widget);
break;
@@ -3781,6 +3742,20 @@ QSize QCleanlooksStyle::sizeFromContents(ContentsType type, const QStyleOption *
}
break;
case CT_GroupBox:
+ // Since we use a bold font we have to recalculate base width
+ if (const QGroupBox *gb = qobject_cast<const QGroupBox*>(widget)) {
+ QFont font = gb->font();
+ font.setBold(true);
+ QFontMetrics metrics(font);
+ int baseWidth = metrics.width(gb->title()) + metrics.width(QLatin1Char(' '));
+ if (gb->isCheckable()) {
+ baseWidth += proxy()->pixelMetric(QStyle::PM_IndicatorWidth, option, widget);
+ baseWidth += proxy()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, option, widget);
+ }
+ newSize.setWidth(qMax(baseWidth, newSize.width()));
+ }
+ newSize += QSize(0, 1);
+ break;
case CT_RadioButton:
case CT_CheckBox:
newSize += QSize(0, 1);
@@ -3848,17 +3823,6 @@ QSize QCleanlooksStyle::sizeFromContents(ContentsType type, const QStyleOption *
void QCleanlooksStyle::polish(QApplication *app)
{
QWindowsStyle::polish(app);
-#ifdef Q_WS_X11
- Q_D(QCleanlooksStyle);
-
- QString dataDirs = QLatin1String(getenv("XDG_DATA_DIRS"));
-
- if (dataDirs.isEmpty())
- dataDirs = QLatin1String("/usr/local/share/:/usr/share/");
-
- dataDirs.prepend(QDir::homePath() + QLatin1String("/:"));
- d->iconDirs = dataDirs.split(QLatin1String(":"));
-#endif
}
/*!
@@ -3959,7 +3923,7 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
switch (subControl) {
case SC_SliderHandle: {
if (slider->orientation == Qt::Horizontal) {
@@ -4014,7 +3978,7 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
QSize bs;
int center = spinbox->rect.height() / 2;
- int fw = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
int y = fw;
bs.setHeight(qMax(8, spinbox->rect.height()/2 - y));
bs.setWidth(15);
@@ -4055,7 +4019,7 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
int topMargin = 0;
int topHeight = 0;
- int verticalAlignment = styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
+ int verticalAlignment = proxy()->styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
bool flat = groupBox->features & QStyleOptionFrameV2::Flat;
if (!groupBox->text.isEmpty()) {
topHeight = groupBox->fontMetrics.height();
@@ -4086,8 +4050,8 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
QSize textRect = fontMetrics.boundingRect(groupBoxWidget->title()).size() + QSize(2, 2);
if (subControl == SC_GroupBoxCheckBox) {
- int indicatorWidth = pixelMetric(PM_IndicatorWidth, option, widget);
- int indicatorHeight = pixelMetric(PM_IndicatorHeight, option, widget);
+ int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
+ int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget);
rect.setWidth(indicatorWidth);
rect.setHeight(indicatorHeight);
rect.moveTop((fontMetrics.height() - indicatorHeight) / 2 + 2);
@@ -4108,7 +4072,7 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
rect = visualRect(option->direction, option->rect, rect);
break;
case SC_ComboBoxEditField: {
- int frameWidth = pixelMetric(PM_DefaultFrameWidth);
+ int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth);
rect = visualRect(option->direction, option->rect, rect);
rect.setRect(option->rect.left() + frameWidth, option->rect.top() + frameWidth,
option->rect.width() - 19 - 2 * frameWidth,
@@ -4359,7 +4323,7 @@ QRect QCleanlooksStyle::subElementRect(SubElement sr, const QStyleOption *opt, c
if (verticalTitleBar) {
r.adjust(0, 0, 0, -4);
} else {
- if (QApplication::layoutDirection() == Qt::LeftToRight)
+ if (opt->direction == Qt::LeftToRight)
r.adjust(4, 0, 0, 0);
else
r.adjust(0, 0, -4, 0);
@@ -4376,44 +4340,6 @@ QRect QCleanlooksStyle::subElementRect(SubElement sr, const QStyleOption *opt, c
return r;
}
-void QCleanlooksStylePrivate::lookupIconTheme() const
-{
-#ifdef Q_WS_X11
-
- if (themeName.isEmpty()) {
- //resolve glib and gconf functions
- p_g_type_init = (Ptr_g_type_init)QLibrary::resolve(QLatin1String("gobject-2.0"), 0, "g_type_init");
- p_gconf_client_get_default = (Ptr_gconf_client_get_default)QLibrary::resolve(QLatin1String("gconf-2"), 4, "gconf_client_get_default");
- p_gconf_client_get_string = (Ptr_gconf_client_get_string)QLibrary::resolve(QLatin1String("gconf-2"), 4, "gconf_client_get_string");
- p_g_object_unref = (Ptr_g_object_unref)QLibrary::resolve(QLatin1String("gobject-2.0"), 0, "g_object_unref");
- p_g_error_free = (Ptr_g_error_free)QLibrary::resolve(QLatin1String("glib-2.0"), 0, "g_error_free");
- p_g_free = (Ptr_g_free)QLibrary::resolve(QLatin1String("glib-2.0"), 0, "g_free");
-
- if (p_g_type_init &&
- p_gconf_client_get_default &&
- p_gconf_client_get_string &&
- p_g_object_unref &&
- p_g_error_free &&
- p_g_free) {
-
- p_g_type_init();
- GConfClient* client = p_gconf_client_get_default();
- GError *err = 0;
- char *str = p_gconf_client_get_string(client, "/desktop/gnome/interface/icon_theme", &err);
- if (!err) {
- themeName = QString::fromUtf8(str);
- p_g_free(str);
- }
- p_g_object_unref(client);
- if (err)
- p_g_error_free (err);
- }
- if (themeName.isEmpty())
- themeName = QLatin1String("gnome");
- }
-#endif
-}
-
/*!
\internal
*/
@@ -4421,165 +4347,6 @@ QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon,
const QStyleOption *option,
const QWidget *widget) const
{
-#ifdef Q_WS_X11
- Q_D(const QCleanlooksStyle);
- if (!qApp->desktopSettingsAware())
- return QWindowsStyle::standardIconImplementation(standardIcon, option, widget);
- QIcon icon;
- QPixmap pixmap;
- QPixmap link;
- d->lookupIconTheme();
- switch (standardIcon) {
- case SP_DirIcon: {
- icon = QIcon(standardPixmap(standardIcon, option, widget));
- icon.addPixmap(standardPixmap(SP_DirClosedIcon, option, widget),
- QIcon::Normal, QIcon::Off);
- pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory.png"));
- if (!pixmap.isNull())
- icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off);
- pixmap = d->findIcon(48, QLatin1String("gnome-fs-directory.png"));
- if (!pixmap.isNull())
- icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off);
- pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory-accept.png"));
- if (!pixmap.isNull())
- icon.addPixmap(pixmap, QIcon::Normal, QIcon::On);
- pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory-accept.png"));
- if (!pixmap.isNull())
- icon.addPixmap(pixmap, QIcon::Normal, QIcon::On);
- }
- break;
- case SP_DirLinkIcon:
- {
- icon = QIcon(standardPixmap(standardIcon, option, widget));
- QPixmap link = d->findIcon(12, QLatin1String("emblem-symbolic-link.png"));
- if (!link.isNull()) {
- icon.addPixmap(standardPixmap(SP_DirLinkIcon, option, widget));
- pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory.png"));
- if (!pixmap.isNull()) {
- QPainter painter(&pixmap);
- painter.drawPixmap(8, 8, 8, 8, link);
- painter.end();
- icon.addPixmap(pixmap);
- }
- }
- break;
- }
- case SP_FileIcon:
- {
- icon = d->createIcon(QLatin1String("unknown.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("gnome-fs-regular.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("stock_new.png"));
- break;
- }
- case SP_DialogCloseButton:
- {
- icon = d->createIcon(QLatin1String("gtk-close.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("stock-close.png"));
- break;
- }
- case SP_DirHomeIcon:
- {
- icon = d->createIcon(QLatin1String("folder_home.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("gnome_home.png"));
- break;
- }
- case SP_DriveFDIcon:
- {
- icon = d->createIcon(QLatin1String("gnome-dev-floppy.png"));
- break;
- }
- case SP_ComputerIcon:
- {
- icon = d->createIcon(QLatin1String("gnome-fs-client.png"));
- break;
- }
- case SP_DesktopIcon:
- {
- icon = d->createIcon(QLatin1String("gnome-fs-desktop.png"));
- break;
- }
- case SP_TrashIcon:
- {
- icon = d->createIcon(QLatin1String("gnome-fs-trash-empty.png"));
- break;
- }
- case SP_DriveCDIcon:
- case SP_DriveDVDIcon:
- {
- icon = d->createIcon(QLatin1String("gnome-dev-cdrom.png"));
- break;
- }
- case SP_DriveHDIcon:
- {
- icon = d->createIcon(QLatin1String("gnome-dev-harddisk.png"));
- break;
- }
- case SP_ArrowUp:
- {
- icon = d->createIcon(QLatin1String("stock_up.png"));
- break;
- }
- case SP_ArrowDown:
- {
- icon = d->createIcon(QLatin1String("stock_down.png"));
- break;
- }
- case SP_ArrowRight:
- {
- icon = d->createIcon(QLatin1String("stock_right.png"));
- break;
- }
- case SP_ArrowLeft:
- {
- icon = d->createIcon(QLatin1String("stock_left.png"));
- break;
- }
- case SP_BrowserReload:
- {
- icon = d->createIcon(QLatin1String("view-refresh.png"));
- break;
- }
- case SP_BrowserStop:
- {
- pixmap = d->findIcon(24, QLatin1String("stop.png"));
- break;
- }
- case SP_FileLinkIcon:
- {
- icon = QIcon(standardPixmap(standardIcon, option, widget));
- QPixmap link = d->findIcon(12, QLatin1String("emblem-symbolic-link.png"));
- if (!link.isNull()) {
- icon.addPixmap(standardPixmap(SP_FileLinkIcon,option, widget));
- pixmap = d->findIcon(16, QLatin1String("unknown.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("stock_new.png"));
- if (!pixmap.isNull()) {
- QPainter painter(&pixmap);
- painter.drawPixmap(8, 8, 8, 8, link);
- painter.end();
- icon.addPixmap(pixmap);
- }
- }
- break;
- }
- case SP_ArrowForward:
- if (QApplication::layoutDirection() == Qt::RightToLeft)
- return standardIconImplementation(SP_ArrowLeft, option, widget);
- return standardIconImplementation(SP_ArrowRight, option, widget);
- case SP_ArrowBack:
- if (QApplication::layoutDirection() == Qt::RightToLeft)
- return standardIconImplementation(SP_ArrowRight, option, widget);
- return standardIconImplementation(SP_ArrowLeft, option, widget);
- default:
- icon = QIcon(standardPixmap(standardIcon, option, widget));
- }
- if (!icon.isNull())
- return icon;
-#endif // Q_WS_X11
return QWindowsStyle::standardIconImplementation(standardIcon, option, widget);
}
@@ -4589,341 +4356,10 @@ QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon,
QPixmap QCleanlooksStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
const QWidget *widget) const
{
-#ifdef Q_WS_X11
- Q_D(const QCleanlooksStyle);
QPixmap pixmap;
- if (!qApp->desktopSettingsAware())
- return QWindowsStyle::standardPixmap(standardPixmap, opt, widget);
- d->lookupIconTheme();
+
#ifndef QT_NO_IMAGEFORMAT_XPM
switch (standardPixmap) {
- case SP_MessageBoxInformation:
- {
- pixmap = d->findIcon(48, QLatin1String("dialog-info.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(48, QLatin1String("stock_dialog-info.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MessageBoxWarning:
- {
- pixmap = d->findIcon(48, QLatin1String("dialog-warning.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(48, QLatin1String("stock_dialog-warning.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MessageBoxCritical:
- {
- pixmap = d->findIcon(48, QLatin1String("dialog-error.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(48, QLatin1String("stock_dialog-error.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MessageBoxQuestion:
- {
- pixmap = d->findIcon(48, QLatin1String("dialog-question.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DirHomeIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("folder_home.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("gnome_home.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DialogOpenButton:
- case SP_DirOpenIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("stock_open.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_FileIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("unknown.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(24, QLatin1String("gnome-fs-regular.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(24, QLatin1String("stock_new.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_FileLinkIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("emblem-symbolic-link.png"));
- if (!pixmap.isNull()) {
- QPixmap fileIcon = d->findIcon(24, QLatin1String("unknown.png"));
- if (fileIcon.isNull())
- fileIcon = d->findIcon(24, QLatin1String("stock_new.png"));
- if (!fileIcon.isNull()) {
- QPainter painter(&fileIcon);
- painter.setRenderHint(QPainter::SmoothPixmapTransform);
- painter.drawPixmap(12, 12, 12, 12, pixmap);
- return fileIcon;
- }
- }
- break;
- }
- case SP_DirClosedIcon:
- case SP_DirIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("gnome-fs-directory.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DirLinkIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("emblem-symbolic-link.png"));
- if (!pixmap.isNull()) {
- QPixmap dirIcon = d->findIcon(24, QLatin1String("gnome-fs-directory.png"));
- if (!dirIcon.isNull()) {
- QPainter painter(&dirIcon);
- painter.setRenderHint(QPainter::SmoothPixmapTransform);
- painter.drawPixmap(12, 12, 12, 12, pixmap);
- return dirIcon;
- }
- }
- break;
- }
- case SP_DriveFDIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("gnome-dev-floppy.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_ComputerIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("gnome-fs-client.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DesktopIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("gnome-fs-desktop.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_TrashIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("gnome-fs-trash-empty.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DriveCDIcon:
- case SP_DriveDVDIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("gnome-dev-cdrom.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DriveHDIcon:
- {
- pixmap = d->findIcon(24, QLatin1String("gnome-dev-harddisk.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_FileDialogToParent:
- {
- pixmap = d->findIcon(16, QLatin1String("stock_up.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_FileDialogNewFolder:
- {
- pixmap = d->findIcon(16, QLatin1String("stock_new-dir.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_ArrowUp:
- {
- pixmap = d->findIcon(16, QLatin1String("stock_up.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_ArrowDown:
- {
- pixmap = d->findIcon(16, QLatin1String("stock_down.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_ArrowRight:
- {
- pixmap = d->findIcon(16, QLatin1String("stock_right.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_ArrowLeft:
- {
- pixmap = d->findIcon(16, QLatin1String("stock_left.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DialogCloseButton:
- {
- pixmap = d->findIcon(24, QLatin1String("gtk-close.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(24, QLatin1String("stock-close.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DialogApplyButton:
- {
- pixmap = d->findIcon(24, QLatin1String("dialog-apply.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(24, QLatin1String("stock-apply.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DialogResetButton:
- {
- pixmap = d->findIcon(24, QLatin1String("gtk-clear.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DialogHelpButton:
- {
- pixmap = d->findIcon(24, QLatin1String("gtk-help.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DialogOkButton:
- {
- pixmap = d->findIcon(24, QLatin1String("dialog-ok.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(24, QLatin1String("stock-ok.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DialogCancelButton:
- {
- pixmap = d->findIcon(24, QLatin1String("dialog-cancel.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(24, QLatin1String("stock-cancel.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(24, QLatin1String("process-stop.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_DialogSaveButton:
- {
- pixmap = d->findIcon(24, QLatin1String("stock_save.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_BrowserStop:
- {
- pixmap = d->findIcon(16, QLatin1String("process-stop.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_BrowserReload:
- {
- pixmap = d->findIcon(16, QLatin1String("view-refresh.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MediaPlay:
- {
- pixmap = d->findIcon(24, QLatin1String("media-playback-start.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MediaPause:
- {
- pixmap = d->findIcon(24, QLatin1String("media-playback-pause.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MediaStop:
- {
- pixmap = d->findIcon(24, QLatin1String("media-playback-stop.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MediaVolume:
- {
- pixmap = d->findIcon(16, QLatin1String("audio-volume-medium.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MediaVolumeMuted:
- {
- pixmap = d->findIcon(16, QLatin1String("audio-volume-muted.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MediaSeekForward:
- {
- pixmap = d->findIcon(24, QLatin1String("media-seek-forward.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MediaSeekBackward:
- {
- pixmap = d->findIcon(24, QLatin1String("media-seek-backward.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MediaSkipForward:
- {
- pixmap = d->findIcon(24, QLatin1String("media-skip-forward.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_MediaSkipBackward:
- {
- pixmap = d->findIcon(24, QLatin1String("media-skip-backward.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_TitleBarMenuButton:
- case SP_TitleBarShadeButton:
- case SP_TitleBarUnshadeButton:
- case SP_TitleBarMaxButton:
- case SP_TitleBarContextHelpButton:
- return QWindowsStyle::standardPixmap(standardPixmap, opt, widget);
case SP_TitleBarNormalButton:
return QPixmap((const char **)dock_widget_restore_xpm);
case SP_TitleBarMinButton:
@@ -4936,7 +4372,7 @@ QPixmap QCleanlooksStyle::standardPixmap(StandardPixmap standardPixmap, const QS
break;
}
#endif //QT_NO_IMAGEFORMAT_XPM
-#endif //Q_WS_X11
+
return QWindowsStyle::standardPixmap(standardPixmap, opt, widget);
}
diff --git a/src/gui/styles/qcleanlooksstyle_p.h b/src/gui/styles/qcleanlooksstyle_p.h
index c0348af..57401bb 100644
--- a/src/gui/styles/qcleanlooksstyle_p.h
+++ b/src/gui/styles/qcleanlooksstyle_p.h
@@ -71,8 +71,6 @@ public:
~QCleanlooksStylePrivate() {
}
-
- void lookupIconTheme() const;
};
QT_END_NAMESPACE
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index 14887ae..c9bdb7f 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -63,9 +63,10 @@
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qrubberband.h>
-#include <private/qapplication_p.h>
+#include <../kernel/qkde_p.h>
#include <private/qcommonstylepixmaps_p.h>
#include <private/qmath_p.h>
+#include <private/qstylehelper_p.h>
#include <qdebug.h>
#include <qtextformat.h>
#include <qwizard.h>
@@ -83,6 +84,8 @@
#ifdef Q_WS_X11
# include <private/qt_x11_p.h>
+#elif defined(Q_WS_MAC)
+# include <private/qt_cocoa_helpers_mac_p.h>
#endif
QT_BEGIN_NAMESPACE
@@ -124,9 +127,7 @@ QCommonStyle::QCommonStyle(QCommonStylePrivate &dd)
{ }
/*!
- \overload
-
- Destroys the style
+ Destroys the style.
*/
QCommonStyle::~QCommonStyle()
{ }
@@ -154,7 +155,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
&opt->palette.brush(QPalette::Button));
break;
case PE_IndicatorViewItemCheck:
- drawPrimitive(PE_IndicatorCheckBox, opt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, opt, p, widget);
break;
case PE_IndicatorCheckBox:
if (opt->state & State_NoChange) {
@@ -504,7 +505,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
QIcon::Active, QIcon::Off);
}
- int size = pixelMetric(QStyle::PM_SmallIconSize);
+ int size = proxy()->pixelMetric(QStyle::PM_SmallIconSize);
QIcon::Mode mode = opt->state & State_Enabled ?
(opt->state & State_Raised ? QIcon::Active : QIcon::Normal)
: QIcon::Disabled;
@@ -515,7 +516,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
QIcon::State state = opt->state & State_Sunken ? QIcon::On : QIcon::Off;
QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(size, mode, state);
- drawItemPixmap(p, opt->rect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(p, opt->rect, Qt::AlignCenter, pixmap);
break;
}
#endif // QT_NO_TABBAR
@@ -524,7 +525,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
qDrawWinPanel(p, opt->rect, opt->palette, false, 0);
break;
case PE_FrameLineEdit:
- drawPrimitive(PE_Frame, opt, p, widget);
+ proxy()->drawPrimitive(PE_Frame, opt, p, widget);
break;
#ifndef QT_NO_GROUPBOX
case PE_FrameGroupBox:
@@ -549,7 +550,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
int lw = frame->lineWidth;
if (lw <= 0)
- lw = pixelMetric(PM_DockWidgetFrameWidth);
+ lw = proxy()->pixelMetric(PM_DockWidgetFrameWidth);
qDrawShadePanel(p, frame->rect, frame->palette, false, lw);
}
@@ -561,7 +562,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
p->translate(opt->rect.x(), opt->rect.y());
if (opt->state & State_Horizontal) {
int x = opt->rect.width() / 3;
- if (QApplication::layoutDirection() == Qt::RightToLeft)
+ if (opt->direction == Qt::RightToLeft)
x -= 2;
if (opt->rect.height() > 4) {
qDrawShadePanel(p, x, 2, 3, opt->rect.height() - 4,
@@ -581,7 +582,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
p->restore();
break;
case PE_Q3DockWindowSeparator:
- drawPrimitive(PE_IndicatorToolBarSeparator, opt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorToolBarSeparator, opt, p, widget);
break;
case PE_IndicatorToolBarSeparator:
{
@@ -601,7 +602,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
case PE_IndicatorSpinPlus:
case PE_IndicatorSpinMinus: {
QRect r = opt->rect;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
QRect br = r.adjusted(fw, fw, -fw, -fw);
int offset = (opt->state & State_Sunken) ? 1 : 0;
@@ -618,7 +619,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
case PE_IndicatorSpinUp:
case PE_IndicatorSpinDown: {
QRect r = opt->rect;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
// QRect br = r.adjusted(fw, fw, -fw, -fw);
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
int sw = w-4;
@@ -643,8 +644,8 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
int bsx = 0;
int bsy = 0;
if (opt->state & State_Sunken) {
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
}
p->save();
p->translate(sx + bsx, sy + bsy);
@@ -693,7 +694,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
panel->palette.brush(QPalette::Base));
if (panel->lineWidth > 0)
- drawPrimitive(PE_FrameLineEdit, panel, p, widget);
+ proxy()->drawPrimitive(PE_FrameLineEdit, panel, p, widget);
}
break;
#endif // QT_NO_LINEEDIT
@@ -765,10 +766,12 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
cg = QPalette::Inactive;
- if ((vopt->state & QStyle::State_Selected) && styleHint(QStyle::SH_ItemView_ShowDecorationSelected, opt, widget))
+ if ((vopt->state & QStyle::State_Selected) && proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, opt, widget))
p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Highlight));
else if (vopt->features & QStyleOptionViewItemV2::Alternate)
p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase));
+ else if (!(vopt->state & QStyle::State_Enabled))
+ p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Base));
}
break;
case PE_PanelItemViewItem:
@@ -835,171 +838,36 @@ static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbut
#endif // QT_NO_TOOLBUTTON
-
#ifdef Q_WS_X11 // These functions are used to parse the X11 freedesktop icon spec
-void QCommonStylePrivate::lookupIconTheme() const
-{
- if (!themeName.isEmpty())
- return;
-
- QString dataDirs = QString::fromLocal8Bit(getenv("XDG_DATA_DIRS"));
- if (dataDirs.isEmpty())
- dataDirs = QLatin1String("/usr/local/share/:/usr/share/");
- dataDirs += QLatin1Char(':') + QApplicationPrivate::kdeHome() + QLatin1String("/share");
- dataDirs.prepend(QDir::homePath() + QLatin1String("/:"));
- QStringList kdeDirs = QString::fromLocal8Bit(getenv("KDEDIRS")).split(QLatin1Char(':'), QString::SkipEmptyParts);
- foreach (const QString &dirName, kdeDirs)
- dataDirs.append(QLatin1String(":") + dirName + QLatin1String("/share"));
- iconDirs = dataDirs.split(QLatin1Char(':'));
-
- QFileInfo fileInfo(QLatin1String("/usr/share/icons/default.kde"));
- QDir dir(fileInfo.canonicalFilePath());
- int kdeVersion = qgetenv("KDE_SESSION_VERSION").toInt();
- QString kdeDefault = kdeVersion >= 4 ? QString::fromLatin1("oxygen") : QString::fromLatin1("crystalsvg");
- QString defaultTheme = fileInfo.exists() ? dir.dirName() : kdeDefault;
- QSettings settings(QApplicationPrivate::kdeHome() +
- QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
- settings.beginGroup(QLatin1String("Icons"));
- themeName = settings.value(QLatin1String("Theme"), defaultTheme).toString();
-}
-
-QIconTheme QCommonStylePrivate::parseIndexFile(const QString &themeName) const
-{
- Q_Q(const QCommonStyle);
- QIconTheme theme;
- QFile themeIndex;
- QStringList parents;
- QHash <int, QString> dirList;
-
- for ( int i = 0 ; i < iconDirs.size() && !themeIndex.exists() ; ++i) {
- QString contentDir = QLatin1String(iconDirs[i].startsWith(QDir::homePath()) ?
- "/.icons/" : "/icons/");
- themeIndex.setFileName(iconDirs[i] + contentDir +
- themeName + QLatin1String("/index.theme"));
- }
-
- if (themeIndex.open(QIODevice::ReadOnly | QIODevice::Text)) {
-
- QTextStream in(&themeIndex);
+/*!internal
- while (!in.atEnd()) {
+Checks if you are running KDE and looks up the toolbar
+from the KDE configuration file
- QString line = in.readLine();
-
- if (line.startsWith(QLatin1String("Inherits="))) {
- line = line.right(line.length() - 9);
- parents = line.split(QLatin1Char(','));
- }
-
- if (line.startsWith(QLatin1String("["))) {
- line = line.trimmed();
- line.chop(1);
- QString dirName = line.right(line.length() - 1);
- if (!in.atEnd()) {
- line = in.readLine();
- int size;
- if (line.startsWith(QLatin1String("Size="))) {
- size = line.right(line.length() - 5).toInt();
- if (size)
- dirList.insertMulti(size, dirName);
- }
- }
- }
- }
- }
-
- if (q->inherits("QPlastiqueStyle")) {
- QFileInfo fileInfo(QLatin1String("/usr/share/icons/default.kde"));
- QDir dir(fileInfo.canonicalFilePath());
- QString defaultKDETheme = dir.exists() ? dir.dirName() : QString::fromLatin1("crystalsvg");
- if (!parents.contains(defaultKDETheme) && themeName != defaultKDETheme)
- parents.append(defaultKDETheme);
- } else if (parents.isEmpty() && themeName != QLatin1String("hicolor")) {
- parents.append(QLatin1String("hicolor"));
- }
- theme = QIconTheme(dirList, parents);
- return theme;
-}
-
-QPixmap QCommonStylePrivate::findIconHelper(int size,
- const QString &themeName,
- const QString &iconName,
- QStringList &visited) const
-{
- QPixmap pixmap;
-
- if (!themeName.isEmpty()) {
-
- visited << themeName;
- QIconTheme theme = themeList.value(themeName);
-
- if (!theme.isValid()) {
- theme = parseIndexFile(themeName);
- themeList.insert(themeName, theme);
- }
-
- if (!theme.isValid())
- return QPixmap();
-
- QList <QString> subDirs = theme.dirList().values(size);
-
- for ( int i = 0 ; i < iconDirs.size() ; ++i) {
- for ( int j = 0 ; j < subDirs.size() ; ++j) {
- QString contentDir = (iconDirs[i].startsWith(QDir::homePath())) ?
- QLatin1String("/.icons/") : QLatin1String("/icons/");
- QString fileName = iconDirs[i] + contentDir + themeName + QLatin1Char('/') + subDirs[j] + QLatin1Char('/') + iconName;
- QFile file(fileName);
- if (file.exists())
- pixmap.load(fileName);
- if (!pixmap.isNull())
- break;
- }
- }
-
- if (pixmap.isNull()) {
- QStringList parents = theme.parents();
- //search recursively through inherited themes
- for (int i = 0 ; pixmap.isNull() && i < parents.size() ; ++i) {
- QString parentTheme = parents[i].trimmed();
- if (!visited.contains(parentTheme)) //guard against endless recursion
- pixmap = findIconHelper(size, parentTheme, iconName, visited);
- }
- }
- }
- return pixmap;
-}
-
-QPixmap QCommonStylePrivate::findIcon(int size, const QString &name) const
+*/
+int QCommonStylePrivate::lookupToolButtonStyle() const
{
- QPixmap pixmap;
- QString pixmapName = QLatin1String("$qt") + name + QString::number(size);
-
- if (QPixmapCache::find(pixmapName, pixmap))
- return pixmap;
-
- if (!themeName.isEmpty()) {
- QStringList visited;
- pixmap = findIconHelper(size, themeName, name, visited);
+ int result = Qt::ToolButtonIconOnly;
+ if (X11->desktopEnvironment == DE_KDE && X11->desktopVersion >= 4) {
+ QSettings settings(QKde::kdeHome() +
+ QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ settings.beginGroup(QLatin1String("Toolbar style"));
+ QString toolbarStyle = settings.value(QLatin1String("ToolButtonStyle"), QLatin1String("TextBesideIcon")).toString();
+ if (toolbarStyle == QLatin1String("TextBesideIcon"))
+ result = Qt::ToolButtonTextBesideIcon;
+ else if (toolbarStyle == QLatin1String("TextOnly"))
+ result = Qt::ToolButtonTextOnly;
+ else if (toolbarStyle == QLatin1String("TextUnderIcon"))
+ result = Qt::ToolButtonTextUnderIcon;
}
- QPixmapCache::insert(pixmapName, pixmap);
- return pixmap;
-}
-
-QIcon QCommonStylePrivate::createIcon(const QString &name) const
-{
- QIcon icon;
- icon.addPixmap(findIcon(16, name));
- icon.addPixmap(findIcon(24, name));
- icon.addPixmap(findIcon(32, name));
- return icon;
+ return result;
}
#endif //Q_WS_X11
#ifndef QT_NO_ITEMVIEWS
-
QSize QCommonStylePrivate::viewItemSize(const QStyleOptionViewItemV4 *option, int role) const
{
Q_Q(const QCommonStyle);
@@ -1152,8 +1020,14 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt
}
}
-/* Set sizehint to false to layout the elements inside opt->rect. Set sizehint to true to ignore
- opt->rect and return rectangles in infinite space */
+/*! \internal
+ compute the position for the different component of an item (pixmap, text, checkbox)
+
+ Set sizehint to false to layout the elements inside opt->rect. Set sizehint to true to ignore
+ opt->rect and return rectangles in infinite space
+
+ Code duplicated in QItemDelegate::doLayout
+*/
void QCommonStylePrivate::viewItemLayout(const QStyleOptionViewItemV4 *opt, QRect *checkRect,
QRect *pixmapRect, QRect *textRect, bool sizehint) const
{
@@ -1174,8 +1048,10 @@ void QCommonStylePrivate::viewItemLayout(const QStyleOptionViewItemV4 *opt, QRe
int y = opt->rect.top();
int w, h;
- if (textRect->height() == 0 && !hasPixmap)
+ if (textRect->height() == 0 && (!hasPixmap || !sizehint)) {
+ //if there is no text, we still want to have a decent height for the item sizeHint and the editor size
textRect->setHeight(opt->fontMetrics.height());
+ }
QSize pm(0, 0);
if (hasPixmap) {
@@ -1279,6 +1155,75 @@ void QCommonStylePrivate::viewItemLayout(const QStyleOptionViewItemV4 *opt, QRe
}
#endif // QT_NO_ITEMVIEWS
+
+#ifndef QT_NO_TABBAR
+/*! \internal
+ Compute the textRect and the pixmapRect from the opt rect
+
+ Uses the same computation than in QTabBar::tabSizeHint
+ */
+void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const
+{
+ Q_ASSERT(textRect);
+ Q_ASSERT(iconRect);
+ QRect tr = opt->rect;
+ bool verticalTabs = opt->shape == QTabBar::RoundedEast
+ || opt->shape == QTabBar::RoundedWest
+ || opt->shape == QTabBar::TriangularEast
+ || opt->shape == QTabBar::TriangularWest;
+ if (verticalTabs)
+ tr.setRect(0, 0, tr.height(), tr.width()); //0, 0 as we will have a translate transform
+
+ int verticalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftVertical, opt, widget);
+ int horizontalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, opt, widget);
+ int hpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2;
+ int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2;
+ if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth)
+ verticalShift = -verticalShift;
+ tr.adjust(hpadding, vpadding, horizontalShift - hpadding, verticalShift - vpadding);
+ bool selected = opt->state & QStyle::State_Selected;
+ if (selected) {
+ tr.setBottom(tr.bottom() - verticalShift);
+ tr.setRight(tr.right() - horizontalShift);
+ }
+
+ // left widget
+ if (!opt->leftButtonSize.isEmpty()) {
+ tr.setLeft(tr.left() + 4 +
+ (verticalTabs ? opt->leftButtonSize.height() : opt->leftButtonSize.width()));
+ }
+ // right widget
+ if (!opt->rightButtonSize.isEmpty()) {
+ tr.setRight(tr.right() - 4 -
+ (verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width()));
+ }
+
+ // icon
+ if (!opt->icon.isNull()) {
+ QSize iconSize = opt->iconSize;
+ if (!iconSize.isValid()) {
+ int iconExtent = proxyStyle->pixelMetric(QStyle::PM_SmallIconSize);
+ iconSize = QSize(iconExtent, iconExtent);
+ }
+ QSize tabIconSize = opt->icon.actualSize(iconSize,
+ (opt->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled,
+ (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off );
+
+ *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2,
+ tabIconSize.width(), tabIconSize .height());
+ if (!verticalTabs)
+ *iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect);
+ tr.setLeft(tr.left() + tabIconSize.width() + 4);
+ }
+
+ if (!verticalTabs)
+ tr = proxyStyle->visualRect(opt->direction, opt->rect, tr);
+
+ *textRect = tr;
+}
+#endif //QT_NO_TABBAR
+
+
/*!
\reimp
*/
@@ -1290,24 +1235,24 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
case CE_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
- drawControl(CE_PushButtonBevel, btn, p, widget);
+ proxy()->drawControl(CE_PushButtonBevel, btn, p, widget);
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
- drawControl(CE_PushButtonLabel, &subopt, p, widget);
+ proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget);
if (btn->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
case CE_PushButtonBevel:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
QRect br = btn->rect;
- int dbi = pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
+ int dbi = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
if (btn->features & QStyleOptionButton::DefaultButton)
- drawPrimitive(PE_FrameDefaultButton, opt, p, widget);
+ proxy()->drawPrimitive(PE_FrameDefaultButton, opt, p, widget);
if (btn->features & QStyleOptionButton::AutoDefaultButton)
br.setCoords(br.left() + dbi, br.top() + dbi, br.right() - dbi, br.bottom() - dbi);
if (!(btn->features & (QStyleOptionButton::Flat | QStyleOptionButton::CommandLinkButton))
@@ -1315,14 +1260,14 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
|| (btn->features & QStyleOptionButton::CommandLinkButton && btn->state & State_MouseOver)) {
QStyleOptionButton tmpBtn = *btn;
tmpBtn.rect = br;
- drawPrimitive(PE_PanelButtonCommand, &tmpBtn, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &tmpBtn, p, widget);
}
if (btn->features & QStyleOptionButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, btn, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
QRect ir = btn->rect;
QStyleOptionButton newBtn = *btn;
newBtn.rect = QRect(ir.right() - mbi + 2, ir.height()/2 - mbi/2 + 3, mbi - 6, mbi - 6);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
break;
@@ -1330,7 +1275,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
QRect textRect = button->rect;
uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic;
- if (!styleHint(SH_UnderlineShortcut, button, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, button, widget))
tf |= Qt::TextHideMnemonic;
if (!button->icon.isNull()) {
@@ -1365,24 +1310,24 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
if (button->state & (State_On | State_Sunken))
- iconRect.translate(pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
- pixelMetric(PM_ButtonShiftVertical, opt, widget));
+ iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget));
p->drawPixmap(iconRect, pixmap);
} else {
tf |= Qt::AlignHCenter;
}
if (button->state & (State_On | State_Sunken))
- textRect.translate(pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
- pixelMetric(PM_ButtonShiftVertical, opt, widget));
+ textRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget));
if (button->features & QStyleOptionButton::HasMenu) {
- int indicatorSize = pixelMetric(PM_MenuButtonIndicator, button, widget);
+ int indicatorSize = proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget);
if (button->direction == Qt::LeftToRight)
textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
else
textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
}
- drawItemText(p, textRect, tf, button->palette, (button->state & State_Enabled),
+ proxy()->drawItemText(p, textRect, tf, button->palette, (button->state & State_Enabled),
button->text, QPalette::ButtonText);
}
break;
@@ -1393,17 +1338,17 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
: SE_CheckBoxIndicator, btn, widget);
- drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
+ proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
&subopt, p, widget);
subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
: SE_CheckBoxContents, btn, widget);
- drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget);
+ proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget);
if (btn->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
: SE_CheckBoxFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
@@ -1412,20 +1357,20 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
uint alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter);
- if (!styleHint(SH_UnderlineShortcut, btn, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget))
alignment |= Qt::TextHideMnemonic;
QPixmap pix;
QRect textRect = btn->rect;
if (!btn->icon.isNull()) {
pix = btn->icon.pixmap(btn->iconSize, btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled);
- drawItemPixmap(p, btn->rect, alignment, pix);
+ proxy()->drawItemPixmap(p, btn->rect, alignment, pix);
if (btn->direction == Qt::RightToLeft)
textRect.setRight(textRect.right() - btn->iconSize.width() - 4);
else
textRect.setLeft(textRect.left() + btn->iconSize.width() + 4);
}
if (!btn->text.isEmpty()){
- drawItemText(p, textRect, alignment | Qt::TextShowMnemonic,
+ proxy()->drawItemText(p, textRect, alignment | Qt::TextShowMnemonic,
btn->palette, btn->state & State_Enabled, btn->text, QPalette::WindowText);
}
}
@@ -1435,7 +1380,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->fillRect(opt->rect, opt->palette.background());
QStyleOption arrowOpt = *opt;
arrowOpt.state |= State_Enabled;
- drawPrimitive(((opt->state & State_DownArrow) ? PE_IndicatorArrowDown : PE_IndicatorArrowUp),
+ proxy()->drawPrimitive(((opt->state & State_DownArrow) ? PE_IndicatorArrowDown : PE_IndicatorArrowUp),
&arrowOpt, p, widget);
break; }
case CE_MenuTearoff:
@@ -1457,13 +1402,13 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip
| Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, mbi, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
- QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize), (mbi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
+ QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), (mbi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
if (!pix.isNull())
- drawItemPixmap(p,mbi->rect, alignment, pix);
+ proxy()->drawItemPixmap(p,mbi->rect, alignment, pix);
else
- drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled,
+ proxy()->drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled,
mbi->text, QPalette::ButtonText);
}
break;
@@ -1478,12 +1423,12 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
= qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
QStyleOptionProgressBarV2 subopt = *pb;
subopt.rect = subElementRect(SE_ProgressBarGroove, pb, widget);
- drawControl(CE_ProgressBarGroove, &subopt, p, widget);
+ proxy()->drawControl(CE_ProgressBarGroove, &subopt, p, widget);
subopt.rect = subElementRect(SE_ProgressBarContents, pb, widget);
- drawControl(CE_ProgressBarContents, &subopt, p, widget);
+ proxy()->drawControl(CE_ProgressBarContents, &subopt, p, widget);
if (pb->textVisible) {
subopt.rect = subElementRect(SE_ProgressBarLabel, pb, widget);
- drawControl(CE_ProgressBarLabel, &subopt, p, widget);
+ proxy()->drawControl(CE_ProgressBarLabel, &subopt, p, widget);
}
}
break;
@@ -1509,10 +1454,10 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
? QColor(255,255,255,160) : QColor(0,0,0,160);
QPalette shadowPalette = pb->palette;
shadowPalette.setColor(textRole, shadowColor);
- drawItemText(p, shadowRect, Qt::AlignCenter | Qt::TextSingleLine, shadowPalette,
+ proxy()->drawItemText(p, shadowRect, Qt::AlignCenter | Qt::TextSingleLine, shadowPalette,
pb->state & State_Enabled, pb->text, textRole);
}
- drawItemText(p, pb->rect, Qt::AlignCenter | Qt::TextSingleLine, pb->palette,
+ proxy()->drawItemText(p, pb->rect, Qt::AlignCenter | Qt::TextSingleLine, pb->palette,
pb->state & State_Enabled, pb->text, textRole);
}
}
@@ -1559,7 +1504,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->setPen(QPen(pal2.highlight().color(), 4));
p->drawLine(x, rect.y(), x, rect.height());
} else {
- const int unit_width = pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
+ const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
if (!unit_width)
return;
@@ -1601,7 +1546,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
for (int i = 0; i < nu; ++i) {
pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight);
pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
- drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
x += reverse ? -unit_width : unit_width;
}
@@ -1612,7 +1557,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
int offset = reverse ? x0 + x + unit_width-pixels_left : x0 + x;
pbBits.rect.setRect(offset, myY, pixels_left, myHeight);
pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
- drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
}
}
}
@@ -1623,7 +1568,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QRect rect = header->rect;
if (!header->icon.isNull()) {
QPixmap pixmap
- = header->icon.pixmap(pixelMetric(PM_SmallIconSize), (header->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
+ = header->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), (header->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
int pixw = pixmap.width();
QRect aligned = alignedRect(header->direction, QFlag(header->iconAlignment), pixmap.size(), rect);
@@ -1640,7 +1585,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
fnt.setBold(true);
p->setFont(fnt);
}
- drawItemText(p, rect, header->textAlignment, header->palette,
+ proxy()->drawItemText(p, rect, header->textAlignment, header->palette,
(header->state & State_Enabled), header->text, QPalette::ButtonText);
}
break;
@@ -1652,18 +1597,19 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
int shiftX = 0;
int shiftY = 0;
if (toolbutton->state & (State_Sunken | State_On)) {
- shiftX = pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
- shiftY = pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
+ shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
+ shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
}
// Arrow type always overrules and is always shown
bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow;
if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty())
|| toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) {
int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
- if (!styleHint(SH_UnderlineShortcut, opt, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
alignment |= Qt::TextHideMnemonic;
rect.translate(shiftX, shiftY);
- drawItemText(p, rect, alignment, toolbutton->palette,
+ p->setFont(toolbutton->font);
+ proxy()->drawItemText(p, rect, alignment, toolbutton->palette,
opt->state & State_Enabled, toolbutton->text,
QPalette::ButtonText);
} else {
@@ -1688,7 +1634,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QRect pr = rect,
tr = rect;
int alignment = Qt::TextShowMnemonic;
- if (!styleHint(SH_UnderlineShortcut, opt, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
alignment |= Qt::TextHideMnemonic;
if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
@@ -1696,7 +1642,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
tr.adjust(0, pr.height() - 1, 0, -3);
pr.translate(shiftX, shiftY);
if (!hasArrow) {
- drawItemPixmap(p, pr, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pm);
} else {
drawArrow(this, toolbutton, pr, p, widget);
}
@@ -1706,14 +1652,14 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
tr.adjust(pr.width(), 0, 0, 0);
pr.translate(shiftX, shiftY);
if (!hasArrow) {
- drawItemPixmap(p, QStyle::visualRect(opt->direction, rect, pr), Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, QStyle::visualRect(opt->direction, rect, pr), Qt::AlignCenter, pm);
} else {
drawArrow(this, toolbutton, pr, p, widget);
}
alignment |= Qt::AlignLeft | Qt::AlignVCenter;
}
tr.translate(shiftX, shiftY);
- drawItemText(p, QStyle::visualRect(opt->direction, rect, tr), alignment, toolbutton->palette,
+ proxy()->drawItemText(p, QStyle::visualRect(opt->direction, rect, tr), alignment, toolbutton->palette,
toolbutton->state & State_Enabled, toolbutton->text,
QPalette::ButtonText);
} else {
@@ -1721,7 +1667,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (hasArrow) {
drawArrow(this, toolbutton, rect, p, widget);
} else {
- drawItemPixmap(p, rect, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, rect, Qt::AlignCenter, pm);
}
}
}
@@ -1731,8 +1677,8 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
#ifndef QT_NO_TOOLBOX
case CE_ToolBoxTab:
if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) {
- drawControl(CE_ToolBoxTabShape, tb, p, widget);
- drawControl(CE_ToolBoxTabLabel, tb, p, widget);
+ proxy()->drawControl(CE_ToolBoxTabShape, tb, p, widget);
+ proxy()->drawControl(CE_ToolBoxTabLabel, tb, p, widget);
}
break;
case CE_ToolBoxTabShape:
@@ -1778,8 +1724,8 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
#ifndef QT_NO_TABBAR
case CE_TabBarTab:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
- drawControl(CE_TabBarTabShape, tab, p, widget);
- drawControl(CE_TabBarTabLabel, tab, p, widget);
+ proxy()->drawControl(CE_TabBarTabShape, tab, p, widget);
+ proxy()->drawControl(CE_TabBarTabLabel, tab, p, widget);
}
break;
case CE_TabBarTabShape:
@@ -1789,7 +1735,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QRect rect(tab->rect);
bool selected = tab->state & State_Selected;
bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
- int tabOverlap = onlyOne ? 0 : pixelMetric(PM_TabBarTabOverlap, opt, widget);
+ int tabOverlap = onlyOne ? 0 : proxy()->pixelMetric(PM_TabBarTabOverlap, opt, widget);
if (!selected) {
switch (tab->shape) {
@@ -1893,7 +1839,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) {
bool enabled = tb->state & State_Enabled;
bool selected = tb->state & State_Selected;
- QPixmap pm = tb->icon.pixmap(pixelMetric(QStyle::PM_SmallIconSize, tb, widget),
+ QPixmap pm = tb->icon.pixmap(proxy()->pixelMetric(QStyle::PM_SmallIconSize, tb, widget),
enabled ? QIcon::Normal : QIcon::Disabled);
QRect cr = subElementRect(QStyle::SE_ToolBoxTabContents, tb, widget);
@@ -1909,7 +1855,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
tr = QRect(ir.right(), cr.top(), cr.width() - ir.right() - 4, cr.height());
}
- if (selected && styleHint(QStyle::SH_ToolBox_SelectedPageTitleBold, tb, widget)) {
+ if (selected && proxy()->styleHint(QStyle::SH_ToolBox_SelectedPageTitleBold, tb, widget)) {
QFont f(p->font());
f.setBold(true);
p->setFont(f);
@@ -1921,16 +1867,16 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->drawPixmap(ir.left(), (tb->rect.height() - ih) / 2, pm);
int alignment = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic;
- if (!styleHint(QStyle::SH_UnderlineShortcut, tb, widget))
+ if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, tb, widget))
alignment |= Qt::TextHideMnemonic;
- drawItemText(p, tr, alignment, tb->palette, enabled, txt, QPalette::ButtonText);
+ proxy()->drawItemText(p, tr, alignment, tb->palette, enabled, txt, QPalette::ButtonText);
if (!txt.isEmpty() && opt->state & State_HasFocus) {
QStyleOptionFocusRect opt;
opt.rect = tr;
opt.palette = tb->palette;
opt.state = QStyle::State_None;
- drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, widget);
}
}
break;
@@ -1945,7 +1891,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
|| tabV2.shape == QTabBar::TriangularWest;
int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
- if (!styleHint(SH_UnderlineShortcut, opt, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
alignment |= Qt::TextHideMnemonic;
if (verticalTabs) {
@@ -1960,41 +1906,24 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
newY = tr.y() + tr.height();
newRot = -90;
}
- tr.setRect(0, 0, tr.height(), tr.width());
- QTransform m;
- m.translate(newX, newY);
+ QTransform m = QTransform::fromTranslate(newX, newY);
m.rotate(newRot);
p->setTransform(m, true);
}
- tr = subElementRect(SE_TabBarTabText, opt, widget);
+ QRect iconRect;
+ d->tabLayout(&tabV2, widget, &tr, &iconRect);
+ tr = proxy()->subElementRect(SE_TabBarTabText, opt, widget); //we compute tr twice because the style may override subElementRect
if (!tabV2.icon.isNull()) {
- QSize iconSize = tabV2.iconSize;
- if (!iconSize.isValid()) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
- iconSize = QSize(iconExtent, iconExtent);
- }
- QSize tabIconSize = tabV2.icon.actualSize(iconSize,
- (tabV2.state & State_Enabled) ? QIcon::Normal
- : QIcon::Disabled);
- QPixmap tabIcon = tabV2.icon.pixmap(iconSize,
+ QPixmap tabIcon = tabV2.icon.pixmap(tabV2.iconSize,
(tabV2.state & State_Enabled) ? QIcon::Normal
- : QIcon::Disabled);
-
- int offset = 4;
- int left = opt->rect.left();
- if (tabV2.leftButtonSize.isEmpty())
- offset += 2;
- else
- left += tabV2.leftButtonSize.width() + (6 + 2) + 2;
- QRect iconRect = QRect(left + offset, tr.center().y() - tabIcon.height() / 2,
- tabIconSize.width(), tabIconSize.height());
- if (!verticalTabs)
- iconRect = visualRect(opt->direction, opt->rect, iconRect);
+ : QIcon::Disabled,
+ (tabV2.state & State_Selected) ? QIcon::On
+ : QIcon::Off);
p->drawPixmap(iconRect.x(), iconRect.y(), tabIcon);
}
- drawItemText(p, tr, alignment, tab->palette, tab->state & State_Enabled, tab->text, QPalette::WindowText);
+ proxy()->drawItemText(p, tr, alignment, tab->palette, tab->state & State_Enabled, tab->text, QPalette::WindowText);
if (verticalTabs)
p->restore();
@@ -2105,7 +2034,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->save();
QRect r = opt->rect;
QStyleHintReturnMask mask;
- if (styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
+ if (proxy()->styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
p->setClipRegion(mask.region);
p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap);
p->setPen(opt->palette.color(QPalette::Active, QPalette::WindowText));
@@ -2143,7 +2072,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
}
const int indent = p->fontMetrics().descent();
- drawItemText(p, r.adjusted(indent + 1, 1, -indent - 1, -1),
+ proxy()->drawItemText(p, r.adjusted(indent + 1, 1, -indent - 1, -1),
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, dwOpt->title,
QPalette::WindowText);
@@ -2158,14 +2087,14 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
QRegion clipRegion = p->clipRegion();
p->setClipRect(opt->rect);
- drawControl(CE_HeaderSection, header, p, widget);
+ proxy()->drawControl(CE_HeaderSection, header, p, widget);
QStyleOptionHeader subopt = *header;
subopt.rect = subElementRect(SE_HeaderLabel, header, widget);
if (subopt.rect.isValid())
- drawControl(CE_HeaderLabel, &subopt, p, widget);
+ proxy()->drawControl(CE_HeaderLabel, &subopt, p, widget);
if (header->sortIndicator != QStyleOptionHeader::None) {
subopt.rect = subElementRect(SE_HeaderArrow, opt, widget);
- drawPrimitive(PE_IndicatorHeaderArrow, &subopt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorHeaderArrow, &subopt, p, widget);
}
p->setClipRegion(clipRegion);
}
@@ -2184,7 +2113,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
#ifndef QT_NO_COMBOBOX
case CE_ComboBoxLabel:
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
- QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
p->save();
p->setClipRect(editRect);
if (!cb->currentIcon.isNull()) {
@@ -2198,7 +2127,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
iconRect.size(), editRect);
if (cb->editable)
p->fillRect(iconRect, opt->palette.brush(QPalette::Base));
- drawItemPixmap(p, iconRect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(p, iconRect, Qt::AlignCenter, pixmap);
if (cb->direction == Qt::RightToLeft)
editRect.translate(-4 - cb->iconSize.width(), 0);
@@ -2206,7 +2135,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
editRect.translate(cb->iconSize.width() + 4, 0);
}
if (!cb->currentText.isEmpty() && !cb->editable) {
- drawItemText(p, editRect.adjusted(1, 0, -1, 0),
+ proxy()->drawItemText(p, editRect.adjusted(1, 0, -1, 0),
visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter),
cb->palette, cb->state & State_Enabled, cb->currentText);
}
@@ -2222,7 +2151,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
frame.QStyleOption::operator=(*toolBar);
frame.lineWidth = toolBar->lineWidth;
frame.midLineWidth = toolBar->midLineWidth;
- drawPrimitive(PE_PanelToolBar, opt, p, widget);
+ proxy()->drawPrimitive(PE_PanelToolBar, opt, p, widget);
if (widget && qobject_cast<QToolBar *>(widget->parentWidget()))
break;
@@ -2264,10 +2193,10 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QRect textRect = subElementRect(SE_ItemViewItemText, vopt, widget);
// draw the background
- drawPrimitive(PE_PanelItemViewItem, opt, p, widget);
+ proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, widget);
// draw the check mark
- if (checkRect.isValid()) {
+ if (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) {
QStyleOptionViewItemV4 option(*vopt);
option.rect = checkRect;
option.state = option.state & ~QStyle::State_HasFocus;
@@ -2283,7 +2212,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
option.state |= QStyle::State_On;
break;
}
- drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, p, widget);
}
// draw the icon
@@ -2326,7 +2255,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
? QPalette::Normal : QPalette::Disabled;
o.backgroundColor = vopt->palette.color(cg, (vopt->state & QStyle::State_Selected)
? QPalette::Highlight : QPalette::Window);
- drawPrimitive(QStyle::PE_FrameFocusRect, &o, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, p, widget);
}
p->restore();
@@ -2365,7 +2294,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (widget) {
widget->style()->drawPrimitive(QStyle::PE_Frame, opt, p, widget);
} else {
- drawPrimitive(QStyle::PE_Frame, opt, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_Frame, opt, p, widget);
}
break;
case QFrame::Panel:
@@ -2423,9 +2352,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_PushButtonContents:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
int dx1, dx2;
- dx1 = pixelMetric(PM_DefaultFrameWidth, btn, widget);
+ dx1 = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
if (btn->features & QStyleOptionButton::AutoDefaultButton)
- dx1 += pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
+ dx1 += proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
dx2 = dx1 * 2;
r.setRect(opt->rect.x() + dx1, opt->rect.y() + dx1, opt->rect.width() - dx2,
opt->rect.height() - dx2);
@@ -2436,11 +2365,11 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
int dbw1 = 0, dbw2 = 0;
if (btn->features & QStyleOptionButton::AutoDefaultButton){
- dbw1 = pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
+ dbw1 = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
dbw2 = dbw1 * 2;
}
- int dfw1 = pixelMetric(PM_DefaultFrameWidth, btn, widget) + 1,
+ int dfw1 = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget) + 1,
dfw2 = dfw1 * 2;
r.setRect(btn->rect.x() + dfw1 + dbw1, btn->rect.y() + dfw1 + dbw1,
@@ -2450,9 +2379,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
case SE_CheckBoxIndicator:
{
- int h = pixelMetric(PM_IndicatorHeight, opt, widget);
+ int h = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2),
- pixelMetric(PM_IndicatorWidth, opt, widget), h);
+ proxy()->pixelMetric(PM_IndicatorWidth, opt, widget), h);
r = visualRect(opt->direction, opt->rect, r);
}
break;
@@ -2462,7 +2391,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
// Deal with the logical first, then convert it back to screen coords.
QRect ir = visualRect(opt->direction, opt->rect,
subElementRect(SE_CheckBoxIndicator, opt, widget));
- int spacing = pixelMetric(PM_CheckBoxLabelSpacing, opt, widget);
+ int spacing = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget);
r.setRect(ir.right() + spacing, opt->rect.y(), opt->rect.width() - ir.width() - spacing,
opt->rect.height());
r = visualRect(opt->direction, opt->rect, r);
@@ -2502,9 +2431,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_RadioButtonIndicator:
{
- int h = pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget);
+ int h = proxy()->pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget);
r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2),
- pixelMetric(PM_ExclusiveIndicatorWidth, opt, widget), h);
+ proxy()->pixelMetric(PM_ExclusiveIndicatorWidth, opt, widget), h);
r = visualRect(opt->direction, opt->rect, r);
}
break;
@@ -2513,7 +2442,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
{
QRect ir = visualRect(opt->direction, opt->rect,
subElementRect(SE_RadioButtonIndicator, opt, widget));
- int spacing = pixelMetric(PM_RadioButtonLabelSpacing, opt, widget);
+ int spacing = proxy()->pixelMetric(PM_RadioButtonLabelSpacing, opt, widget);
r.setRect(ir.left() + ir.width() + spacing, opt->rect.y(), opt->rect.width() - ir.width() - spacing,
opt->rect.height());
r = visualRect(opt->direction, opt->rect, r);
@@ -2550,8 +2479,8 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
#ifndef QT_NO_SLIDER
case SE_SliderFocusRect:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget);
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
if (slider->orientation == Qt::Horizontal)
r.setRect(0, tickOffset - 1, slider->rect.width(), thickness + 2);
else
@@ -2622,7 +2551,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
#endif // QT_NO_TOOLBOX
case SE_HeaderLabel: {
- int margin = pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
r.setRect(opt->rect.x() + margin, opt->rect.y() + margin,
opt->rect.width() - margin * 2, opt->rect.height() - margin * 2);
@@ -2642,7 +2571,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
int w = opt->rect.width();
int x = opt->rect.x();
int y = opt->rect.y();
- int margin = pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
if (opt->state & State_Horizontal) {
int horiz_size = h / 2;
@@ -2678,7 +2607,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
r.setWidth(qMin(r.width(), twf->rect.width()
- twf->leftCornerWidgetSize.width()
- twf->rightCornerWidgetSize.width()));
- switch (styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
+ switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
default:
case Qt::AlignLeft:
r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width(), 0));
@@ -2700,7 +2629,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
r.setWidth(qMin(r.width(), twf->rect.width()
- twf->leftCornerWidgetSize.width()
- twf->rightCornerWidgetSize.width()));
- switch (styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
+ switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
default:
case Qt::AlignLeft:
r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width(),
@@ -2725,7 +2654,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
r.setHeight(qMin(r.height(), twf->rect.height()
- twf->leftCornerWidgetSize.height()
- twf->rightCornerWidgetSize.height()));
- switch (styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
+ switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
default:
case Qt::AlignLeft:
r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(),
@@ -2747,7 +2676,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
r.setHeight(qMin(r.height(), twf->rect.height()
- twf->leftCornerWidgetSize.height()
- twf->rightCornerWidgetSize.height()));
- switch (styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
+ switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
default:
case Qt::AlignLeft:
r.moveTopLeft(QPoint(0, twf->leftCornerWidgetSize.height()));
@@ -2769,7 +2698,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
QStyleOptionTab tabopt;
tabopt.shape = twf->shape;
- int overlap = pixelMetric(PM_TabBarBaseOverlap, &tabopt, widget);
+ int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &tabopt, widget);
if (twf->lineWidth == 0)
overlap = 0;
switch (twf->shape) {
@@ -2837,71 +2766,20 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
}
break;
case SE_TabBarTabText:
- // ### consider merging this with CE_TabBarTabLabel
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
- QStyleOptionTabV3 tabV2(*tab);
- QRect tr = tabV2.rect;
- bool verticalTabs = tabV2.shape == QTabBar::RoundedEast
- || tabV2.shape == QTabBar::RoundedWest
- || tabV2.shape == QTabBar::TriangularEast
- || tabV2.shape == QTabBar::TriangularWest;
- if (verticalTabs)
- tr.setRect(0, 0, tr.height(), tr.width());
- int verticalShift = pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);
- int horizontalShift = pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);
- if (tabV2.shape == QTabBar::RoundedSouth || tabV2.shape == QTabBar::TriangularSouth)
- verticalShift = -verticalShift;
- tr.adjust(0, 0, horizontalShift, verticalShift);
- bool selected = tabV2.state & State_Selected;
- if (selected) {
- tr.setBottom(tr.bottom() - verticalShift);
- tr.setRight(tr.right() - horizontalShift);
- }
-
- // left widget
- if (!tabV2.leftButtonSize.isEmpty()) {
- tr.setLeft(tr.left() + 6 + 2 +
- (verticalTabs ? tabV2.leftButtonSize.height() : tabV2.leftButtonSize.width()));
- }
-
- // icon
- if (!tabV2.icon.isNull()) {
- QSize iconSize = tabV2.iconSize;
- if (!iconSize.isValid()) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
- iconSize = QSize(iconExtent, iconExtent);
- }
- QSize tabIconSize = tabV2.icon.actualSize(iconSize,
- (tabV2.state & State_Enabled) ? QIcon::Normal
- : QIcon::Disabled);
- int offset = 4;
- if (tabV2.leftButtonSize.isEmpty())
- offset += 2;
-
- QRect iconRect = QRect(tr.left() + offset, tr.center().y() - tabIconSize.height() / 2,
- tabIconSize.width(), tabIconSize .height());
- if (!verticalTabs)
- iconRect = visualRect(opt->direction, opt->rect, iconRect);
- tr.setLeft(tr.left() + tabIconSize.width() + offset + 2);
- }
-
- // right widget
- if (!tabV2.rightButtonSize.isEmpty()) {
- tr.setRight(tr.right() - 6 - 2 -
- (verticalTabs ? tabV2.rightButtonSize.height() : tabV2.rightButtonSize.width()));
- }
-
- if (!verticalTabs)
- tr = visualRect(opt->direction, opt->rect, tr);
- r = tr;
+ QStyleOptionTabV3 tabV3(*tab);
+ QRect dummyIconRect;
+ d->tabLayout(&tabV3, widget, &r, &dummyIconRect);
}
break;
case SE_TabBarTabLeftButton:
case SE_TabBarTabRightButton:
if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) {
bool selected = tab->state & State_Selected;
- int verticalShift = pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);
- int horizontalShift = pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);
+ int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);
+ int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);
+ int hpadding = proxy()->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2;
+ hpadding = qMax(hpadding, 4); //workaround KStyle returning 0 because they workaround an old bug in Qt
bool verticalTabs = tab->shape == QTabBar::RoundedEast
|| tab->shape == QTabBar::RoundedWest
@@ -2916,6 +2794,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
horizontalShift *= -1;
verticalShift *= -1;
}
+ if (tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularWest)
+ horizontalShift = -horizontalShift;
+
tr.adjust(0, 0, horizontalShift, verticalShift);
if (selected)
{
@@ -2941,16 +2822,16 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
default:
if (sr == SE_TabBarTabLeftButton)
- r = QRect(6 + tab->rect.x(), midHeight, w, h);
+ r = QRect(tab->rect.x() + hpadding, midHeight, w, h);
else
- r = QRect(tab->rect.right() - 6 - w, midHeight, w, h);
+ r = QRect(tab->rect.right() - w - hpadding, midHeight, w, h);
r = visualRect(tab->direction, tab->rect, r);
}
if (verticalTabs) {
if (atTheTop)
- r = QRect(midWidth, tr.y() + tab->rect.height() - 6 - h, w, h);
+ r = QRect(midWidth, tr.y() + tab->rect.height() - hpadding - h, w, h);
else
- r = QRect(midWidth, tr.y() + 6, w, h);
+ r = QRect(midWidth, tr.y() + hpadding, w, h);
}
}
@@ -2990,7 +2871,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
case SE_FrameContents:
if (const QStyleOptionFrameV2 *f = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt)) {
- int fw = pixelMetric(PM_DefaultFrameWidth, f, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, f, widget);
r = opt->rect.adjusted(fw, fw, -fw, -fw);
r = visualRect(opt->direction, opt->rect, r);
}
@@ -3057,9 +2938,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_DockWidgetFloatButton:
case SE_DockWidgetTitleBarText:
case SE_DockWidgetIcon: {
- int iconSize = pixelMetric(PM_SmallIconSize, opt, widget);
- int buttonMargin = pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget);
- int margin = pixelMetric(QStyle::PM_DockWidgetTitleMargin, opt, widget);
+ int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
+ int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, opt, widget);
QRect rect = opt->rect;
const QStyleOptionDockWidget *dwOpt
@@ -3124,7 +3005,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
if (dw->isFloating())
icon = dw->windowIcon();
if (!icon.isNull()
- && icon.cacheKey() != qApp->windowIcon().cacheKey()) {
+ && icon.cacheKey() != QApplication::windowIcon().cacheKey()) {
QSize sz = icon.actualSize(QSize(r.height(), r.height()));
if (verticalTitleBar)
sz.transpose();
@@ -3169,8 +3050,10 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
if (!d->isViewItemCached(*vopt)) {
d->viewItemLayout(vopt, &d->checkRect, &d->decorationRect, &d->displayRect, false);
- if (d->cachedOption)
+ if (d->cachedOption) {
delete d->cachedOption;
+ d->cachedOption = 0;
+ }
d->cachedOption = new QStyleOptionViewItemV4(*vopt);
}
if (sr == SE_ViewItemCheckIndicator)
@@ -3182,6 +3065,25 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
}
break;
#endif //QT_NO_ITEMVIEWS
+#ifndef QT_NO_TOOLBAR
+ case SE_ToolBarHandle:
+ if (const QStyleOptionToolBar *tbopt = qstyleoption_cast<const QStyleOptionToolBar *>(opt)) {
+ if (tbopt->features & QStyleOptionToolBar::Movable) {
+ ///we need to access the widget here because the style option doesn't
+ //have all the information we need (ie. the layout's margin)
+ const QToolBar *tb = qobject_cast<const QToolBar*>(widget);
+ const int margin = tb && tb->layout() ? tb->layout()->margin() : 2;
+ const int handleExtent = pixelMetric(QStyle::PM_ToolBarHandleExtent, opt, tb);
+ if (tbopt->state & QStyle::State_Horizontal) {
+ r = QRect(margin, margin, handleExtent, tbopt->rect.height() - 2*margin);
+ r = QStyle::visualRect(tbopt->direction, tbopt->rect, r);
+ } else {
+ r = QRect(margin, margin, tbopt->rect.width() - 2*margin, handleExtent);
+ }
+ }
+ }
+ break;
+#endif //QT_NO_TOOLBAR
default:
break;
}
@@ -3189,47 +3091,6 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
}
#ifndef QT_NO_DIAL
-static qreal angle(const QPointF &p1, const QPointF &p2)
-{
- static const qreal rad_factor = 180 / Q_PI;
- qreal _angle = 0;
-
- if (p1.x() == p2.x()) {
- if (p1.y() < p2.y())
- _angle = 270;
- else
- _angle = 90;
- } else {
- qreal x1, x2, y1, y2;
-
- if (p1.x() <= p2.x()) {
- x1 = p1.x(); y1 = p1.y();
- x2 = p2.x(); y2 = p2.y();
- } else {
- x2 = p1.x(); y2 = p1.y();
- x1 = p2.x(); y1 = p2.y();
- }
-
- qreal m = -(y2 - y1) / (x2 - x1);
- _angle = atan(m) * rad_factor;
-
- if (p1.x() < p2.x())
- _angle = 180 - _angle;
- else
- _angle = -_angle;
- }
- return _angle;
-}
-
-static int calcBigLineSize(int radius)
-{
- int bigLineSize = radius / 6;
- if (bigLineSize < 4)
- bigLineSize = 4;
- if (bigLineSize > radius / 2)
- bigLineSize = radius / 2;
- return bigLineSize;
-}
static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a)
{
@@ -3250,7 +3111,7 @@ static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a)
int xc = width / 2;
int yc = height / 2;
- int len = r - calcBigLineSize(r) - 5;
+ int len = r - QStyleHelper::calcBigLineSize(r) - 5;
if (len < 5)
len = 5;
int back = len / 2;
@@ -3265,45 +3126,6 @@ static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a)
return arrow;
}
-static QPolygonF calcLines(const QStyleOptionSlider *dial, const QWidget *)
-{
- QPolygonF poly;
- int width = dial->rect.width();
- int height = dial->rect.height();
- qreal r = qMin(width, height) / 2;
- int bigLineSize = calcBigLineSize(int(r));
-
- qreal xc = width / 2;
- qreal yc = height / 2;
- int ns = dial->tickInterval;
- int notches = (dial->maximum + ns - 1 - dial->minimum) / ns;
- if (notches <= 0)
- return poly;
- if (dial->maximum < dial->minimum
- || dial->maximum - dial->minimum > 1000) {
- int maximum = dial->minimum + 1000;
- notches = (maximum + ns - 1 - dial->minimum) / ns;
- }
-
- poly.resize(2 + 2 * notches);
- int smallLineSize = bigLineSize / 2;
- for (int i = 0; i <= notches; ++i) {
- qreal angle = dial->dialWrapping ? Q_PI * 3 / 2 - i * 2 * Q_PI / notches
- : (Q_PI * 8 - i * 10 * Q_PI / notches) / 6;
- qreal s = qSin(angle);
- qreal c = qCos(angle);
- if (i == 0 || (((ns * i) % (dial->pageStep ? dial->pageStep : 1)) == 0)) {
- poly[2 * i] = QPointF(xc + (r - bigLineSize) * c,
- yc - (r - bigLineSize) * s);
- poly[2 * i + 1] = QPointF(xc + r * c, yc - r * s);
- } else {
- poly[2 * i] = QPointF(xc + (r - 1 - smallLineSize) * c,
- yc - (r - 1 - smallLineSize) * s);
- poly[2 * i + 1] = QPointF(xc + (r - 1) * c, yc -(r - 1) * s);
- }
- }
- return poly;
-}
#endif // QT_NO_DIAL
/*!
@@ -3317,11 +3139,11 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
if (slider->subControls == SC_SliderTickmarks) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
int ticks = slider->tickPosition;
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
- int len = pixelMetric(PM_SliderLength, slider, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
interval = slider->singleStep;
@@ -3379,71 +3201,71 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (scrollbar->subControls & SC_ScrollBarSubLine) {
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarSubLine, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubLine, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarSubLine))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarSubLine, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarSubLine, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarAddLine) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarAddLine, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarAddLine, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarAddLine))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarAddLine, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarAddLine, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarSubPage) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarSubPage, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubPage, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarSubPage))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarSubPage, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarSubPage, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarAddPage) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarAddPage, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarAddPage, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarAddPage))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarAddPage, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarAddPage, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarFirst) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarFirst, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarFirst, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarFirst))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarFirst, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarFirst, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarLast) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarLast, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarLast, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarLast))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarLast, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarLast, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarSlider) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarSlider, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSlider, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarSlider))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarSlider, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, widget);
if (scrollbar->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
@@ -3451,7 +3273,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
fropt.rect.setRect(newScrollbar.rect.x() + 2, newScrollbar.rect.y() + 2,
newScrollbar.rect.width() - 5,
newScrollbar.rect.height() - 5);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
}
@@ -3473,7 +3295,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
PrimitiveElement pe;
if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) {
- QRect r = subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget);
+ QRect r = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget);
qDrawWinPanel(p, r, sb->palette, true);
}
@@ -3497,10 +3319,10 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus
: PE_IndicatorSpinUp);
- copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
- drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
copy.rect.adjust(3, 0, -4, 0);
- drawPrimitive(pe, &copy, p, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
if (sb->subControls & SC_SpinBoxDown) {
@@ -3523,10 +3345,10 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus
: PE_IndicatorSpinDown);
- copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
- drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
copy.rect.adjust(3, 0, -4, 0);
- drawPrimitive(pe, &copy, p, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
}
break;
@@ -3536,8 +3358,8 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QRect button, menuarea;
- button = subControlRect(cc, toolbutton, SC_ToolButton, widget);
- menuarea = subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
State bflags = toolbutton->state & ~State_Sunken;
@@ -3559,7 +3381,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (bflags & (State_Sunken | State_On | State_Raised)) {
tool.rect = button;
tool.state = bflags;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
}
}
@@ -3568,28 +3390,28 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
fr.QStyleOption::operator=(*toolbutton);
fr.rect.adjust(3, 3, -3, -3);
if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup)
- fr.rect.adjust(0, 0, -pixelMetric(QStyle::PM_MenuButtonIndicator,
+ fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator,
toolbutton, widget), 0);
- drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
}
QStyleOptionToolButton label = *toolbutton;
label.state = bflags;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
label.rect = button.adjusted(fw, fw, -fw, -fw);
- drawControl(CE_ToolButtonLabel, &label, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;
tool.state = mflags;
if (mflags & (State_Sunken | State_On | State_Raised))
- drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
- drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
} else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
QRect ir = toolbutton->rect;
QStyleOptionToolButton newBtn = *toolbutton;
newBtn.rect = QRect(ir.right() + 5 - mbi, ir.y() + ir.height() - mbi + 4, mbi - 6, mbi - 6);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
break;
@@ -3613,7 +3435,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
p->fillRect(opt->rect, fillBrush);
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
p->setPen(tb->palette.highlightedText().color());
p->drawText(ir.x() + 2, ir.y(), ir.width() - 2, ir.height(),
@@ -3626,7 +3448,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
QStyleOption tool(0);
tool.palette = tb->palette;
if (tb->subControls & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, widget);
down = tb->activeSubControls & SC_TitleBarCloseButton && (opt->state & State_Sunken);
if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool
#ifndef QT_NO_DOCKWIDGET
@@ -3638,50 +3460,50 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
pm = standardIcon(SP_TitleBarCloseButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarMaxButton
&& tb->titleBarFlags & Qt::WindowMaximizeButtonHint
&& !(tb->titleBarState & Qt::WindowMaximized)) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, widget);
down = tb->activeSubControls & SC_TitleBarMaxButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarMaxButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarMinButton
&& tb->titleBarFlags & Qt::WindowMinimizeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, widget);
down = tb->activeSubControls & SC_TitleBarMinButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarMinButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
@@ -3692,81 +3514,81 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
&& (tb->titleBarState & Qt::WindowMaximized)));
if (drawNormalButton) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, widget);
down = tb->activeSubControls & SC_TitleBarNormalButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarNormalButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarShadeButton
&& tb->titleBarFlags & Qt::WindowShadeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, widget);
down = (tb->activeSubControls & SC_TitleBarShadeButton && (opt->state & State_Sunken));
pm = standardIcon(SP_TitleBarShadeButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarUnshadeButton
&& tb->titleBarFlags & Qt::WindowShadeButtonHint
&& tb->titleBarState & Qt::WindowMinimized) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, widget);
down = tb->activeSubControls & SC_TitleBarUnshadeButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarUnshadeButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarContextHelpButton
&& tb->titleBarFlags & Qt::WindowContextHelpButtonHint) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, widget);
down = tb->activeSubControls & SC_TitleBarContextHelpButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarContextHelpButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, widget);
if (!tb->icon.isNull()) {
tb->icon.paint(p, ir);
} else {
- int iconSize = pixelMetric(PM_SmallIconSize, tb, widget);
+ int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget);
pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(iconSize, iconSize);
tool.rect = ir;
p->save();
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
}
@@ -3794,11 +3616,11 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
// draw notches
if (dial->subControls & QStyle::SC_DialTickmarks) {
p->setPen(pal.foreground().color());
- p->drawLines(calcLines(dial, widget)); // ### calcLines could be cached...
+ p->drawLines(QStyleHelper::calcLines(dial));
}
if (dial->state & State_Enabled) {
- p->setBrush(pal.brush(QPalette::ColorRole(styleHint(SH_Dial_BackgroundRole,
+ p->setBrush(pal.brush(QPalette::ColorRole(proxy()->styleHint(SH_Dial_BackgroundRole,
dial, widget))));
p->setPen(Qt::NoPen);
p->drawEllipse(br);
@@ -3816,7 +3638,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
p->setBrush(pal.button());
p->drawPolygon(arrow);
- a = angle(QPointF(width / 2, height / 2), arrow[0]);
+ a = QStyleHelper::angle(QPointF(width / 2, height / 2), arrow[0]);
p->setBrush(Qt::NoBrush);
if (a <= 0 || a > 200) {
@@ -3859,7 +3681,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
br.setHeight(br.height() + r / 3);
}
fropt.rect = br.adjusted(-2, -2, 2, 2);
- drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, p, widget);
}
p->restore();
}
@@ -3869,15 +3691,15 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
case CC_GroupBox:
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
// Draw frame
- QRect textRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget);
- QRect checkBoxRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget);
+ QRect textRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget);
+ QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget);
if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
QStyleOptionFrameV2 frame;
frame.QStyleOption::operator=(*groupBox);
frame.features = groupBox->features;
frame.lineWidth = groupBox->lineWidth;
frame.midLineWidth = groupBox->midLineWidth;
- frame.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget);
+ frame.rect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget);
p->save();
QRegion region(groupBox->rect);
if (!groupBox->text.isEmpty()) {
@@ -3892,7 +3714,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
region -= finalRect;
}
p->setClipRegion(region);
- drawPrimitive(PE_FrameGroupBox, &frame, p, widget);
+ proxy()->drawPrimitive(PE_FrameGroupBox, &frame, p, widget);
p->restore();
}
@@ -3902,10 +3724,10 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (textColor.isValid())
p->setPen(textColor);
int alignment = int(groupBox->textAlignment);
- if (!styleHint(QStyle::SH_UnderlineShortcut, opt, widget))
+ if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, opt, widget))
alignment |= Qt::TextHideMnemonic;
- drawItemText(p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
+ proxy()->drawItemText(p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
groupBox->palette, groupBox->state & State_Enabled, groupBox->text,
textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
@@ -3913,7 +3735,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*groupBox);
fropt.rect = textRect;
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
@@ -3922,7 +3744,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
QStyleOptionButton box;
box.QStyleOption::operator=(*groupBox);
box.rect = checkBoxRect;
- drawPrimitive(PE_IndicatorCheckBox, &box, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, p, widget);
}
}
break;
@@ -3939,52 +3761,52 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (opt->activeSubControls & QStyle::SC_MdiCloseButton && (opt->state & State_Sunken)) {
btnOpt.state |= State_Sunken;
btnOpt.state &= ~State_Raised;
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
} else {
btnOpt.state |= State_Raised;
btnOpt.state &= ~State_Sunken;
bsx = 0;
bsy = 0;
}
- btnOpt.rect = subControlRect(CC_MdiControls, opt, SC_MdiCloseButton, widget);
- drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
+ btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiCloseButton, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
QPixmap pm = standardIcon(SP_TitleBarCloseButton).pixmap(16, 16);
- drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
}
if (opt->subControls & QStyle::SC_MdiNormalButton) {
if (opt->activeSubControls & QStyle::SC_MdiNormalButton && (opt->state & State_Sunken)) {
btnOpt.state |= State_Sunken;
btnOpt.state &= ~State_Raised;
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
} else {
btnOpt.state |= State_Raised;
btnOpt.state &= ~State_Sunken;
bsx = 0;
bsy = 0;
}
- btnOpt.rect = subControlRect(CC_MdiControls, opt, SC_MdiNormalButton, widget);
- drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
+ btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiNormalButton, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
QPixmap pm = standardIcon(SP_TitleBarNormalButton).pixmap(16, 16);
- drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
}
if (opt->subControls & QStyle::SC_MdiMinButton) {
if (opt->activeSubControls & QStyle::SC_MdiMinButton && (opt->state & State_Sunken)) {
btnOpt.state |= State_Sunken;
btnOpt.state &= ~State_Raised;
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
} else {
btnOpt.state |= State_Raised;
btnOpt.state &= ~State_Sunken;
bsx = 0;
bsy = 0;
}
- btnOpt.rect = subControlRect(CC_MdiControls, opt, SC_MdiMinButton, widget);
- drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
+ btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiMinButton, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
QPixmap pm = standardIcon(SP_TitleBarMinButton).pixmap(16, 16);
- drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
}
}
break;
@@ -4006,11 +3828,11 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- QRect r = subControlRect(cc, slider, SC_SliderHandle, widget);
+ QRect r = proxy()->subControlRect(cc, slider, SC_SliderHandle, widget);
if (r.isValid() && r.contains(pt)) {
sc = SC_SliderHandle;
} else {
- r = subControlRect(cc, slider, SC_SliderGroove ,widget);
+ r = proxy()->subControlRect(cc, slider, SC_SliderGroove ,widget);
if (r.isValid() && r.contains(pt))
sc = SC_SliderGroove;
}
@@ -4023,7 +3845,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_ScrollBarAddLine;
while (ctrl <= SC_ScrollBarGroove) {
- r = subControlRect(cc, scrollbar, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, scrollbar, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4039,7 +3861,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_ToolButton;
while (ctrl <= SC_ToolButtonMenu) {
- r = subControlRect(cc, toolbutton, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, toolbutton, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4063,7 +3885,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_SpinBoxUp;
while (ctrl <= SC_SpinBoxEditField) {
- r = subControlRect(cc, spinbox, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, spinbox, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4079,7 +3901,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
uint ctrl = SC_TitleBarSysMenu;
while (ctrl <= SC_TitleBarLabel) {
- r = subControlRect(cc, tb, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, tb, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4094,7 +3916,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_ComboBoxArrow; // Start here and go down.
while (ctrl > 0) {
- r = subControlRect(cc, cb, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, cb, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4110,7 +3932,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_GroupBoxCheckBox;
while (ctrl <= SC_GroupBoxFrame) {
- r = subControlRect(cc, groupBox, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, groupBox, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4125,7 +3947,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_MdiMinButton;
while (ctrl <= SC_MdiCloseButton) {
- r = subControlRect(CC_MdiControls, opt, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(CC_MdiControls, opt, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt) && (opt->subControls & ctrl)) {
sc = QStyle::SubControl(ctrl);
return sc;
@@ -4151,13 +3973,13 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget);
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
switch (sc) {
case SC_SliderHandle: {
int sliderPos = 0;
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum,
slider->sliderPosition,
@@ -4188,7 +4010,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
const QRect scrollBarRect = scrollbar->rect;
- int sbextent = pixelMetric(PM_ScrollBarExtent, scrollbar, widget);
+ int sbextent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollbar, widget);
int maxlen = ((scrollbar->orientation == Qt::Horizontal) ?
scrollBarRect.width() : scrollBarRect.height()) - (sbextent * 2);
int sliderlen;
@@ -4198,7 +4020,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
uint range = scrollbar->maximum - scrollbar->minimum;
sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep);
- int slidermin = pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget);
+ int slidermin = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget);
if (sliderlen < slidermin || range > INT_MAX / 2)
sliderlen = slidermin;
if (sliderlen > maxlen)
@@ -4271,7 +4093,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
QSize bs;
- int fw = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
bs.setHeight(qMax(8, spinbox->rect.height()/2 - fw));
// 1.6 -approximate golden mean
bs.setWidth(qMax(16, qMin(bs.height() * 8 / 5, spinbox->rect.width() / 4)));
@@ -4312,7 +4134,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
#ifndef QT_NO_TOOLBUTTON
case CC_ToolButton:
if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, tb, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, tb, widget);
ret = tb->rect;
switch (sc) {
case SC_ToolButton:
@@ -4452,7 +4274,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
case SC_GroupBoxContents: {
int topMargin = 0;
int topHeight = 0;
- int verticalAlignment = styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
+ int verticalAlignment = proxy()->styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
if (groupBox->text.size() || (groupBox->subControls & QStyle::SC_GroupBoxCheckBox)) {
topHeight = groupBox->fontMetrics.height();
if (verticalAlignment & Qt::AlignVCenter)
@@ -4472,7 +4294,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
int frameWidth = 0;
if (!(widget && widget->inherits("Q3GroupBox"))
&& ((groupBox->features & QStyleOptionFrameV2::Flat) == 0)) {
- frameWidth = pixelMetric(PM_DefaultFrameWidth, groupBox, widget);
+ frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth, groupBox, widget);
}
ret = frameRect.adjusted(frameWidth, frameWidth + topHeight - topMargin,
-frameWidth, -frameWidth);
@@ -4488,8 +4310,8 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
ret = groupBox->rect.adjusted(marg, 0, -marg, 0);
ret.setHeight(h);
- int indicatorWidth = pixelMetric(PM_IndicatorWidth, opt, widget);
- int indicatorSpace = pixelMetric(PM_CheckBoxLabelSpacing, opt, widget) - 1;
+ int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget);
+ int indicatorSpace = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget) - 1;
bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox;
int checkBoxSize = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0;
@@ -4503,7 +4325,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
int left = 0;
// Adjust for check box
if (sc == SC_GroupBoxCheckBox) {
- int indicatorHeight = pixelMetric(PM_IndicatorHeight, opt, widget);
+ int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth);
int top = totalRect.top() + (fontMetrics.height() - indicatorHeight) / 2;
totalRect.setRect(left, top, indicatorWidth, indicatorHeight);
@@ -4589,17 +4411,17 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
ret = 0;
break;
case PM_DialogButtonsSeparator:
- ret = 5;
+ ret = int(QStyleHelper::dpiScaled(5.));
break;
case PM_DialogButtonsButtonWidth:
- ret = 70;
+ ret = int(QStyleHelper::dpiScaled(70.));
break;
case PM_DialogButtonsButtonHeight:
- ret = 30;
+ ret = int(QStyleHelper::dpiScaled(30.));
break;
case PM_CheckListControllerSize:
case PM_CheckListButtonSize:
- ret = 16;
+ ret = int(QStyleHelper::dpiScaled(16.));
break;
case PM_TitleBarHeight: {
if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
@@ -4607,26 +4429,26 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
ret = qMax(widget ? widget->fontMetrics().lineSpacing() : opt->fontMetrics.lineSpacing(), 16);
#ifndef QT_NO_DOCKWIDGET
} else if (qobject_cast<const QDockWidget*>(widget)) {
- ret = qMax(widget->fontMetrics().lineSpacing(), 13);
+ ret = qMax(widget->fontMetrics().lineSpacing(), int(QStyleHelper::dpiScaled(13)));
#endif
} else {
ret = qMax(widget ? widget->fontMetrics().lineSpacing() : opt->fontMetrics.lineSpacing(), 18);
}
} else {
- ret = 18;
+ ret = int(QStyleHelper::dpiScaled(18.));
}
break; }
case PM_ScrollBarSliderMin:
- ret = 9;
+ ret = int(QStyleHelper::dpiScaled(9.));
break;
case PM_ButtonMargin:
- ret = 6;
+ ret = int(QStyleHelper::dpiScaled(6.));
break;
case PM_DockWidgetTitleBarButtonMargin:
- ret = 2;
+ ret = int(QStyleHelper::dpiScaled(2.));
break;
case PM_ButtonDefaultIndicator:
@@ -4634,7 +4456,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
break;
case PM_MenuButtonIndicator:
- ret = 12;
+ ret = int(QStyleHelper::dpiScaled(12.));
break;
case PM_ButtonShiftHorizontal:
@@ -4649,15 +4471,15 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
case PM_MenuPanelWidth:
case PM_TabBarBaseOverlap:
case PM_TabBarBaseHeight:
- ret = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ ret = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
break;
case PM_MdiSubWindowFrameWidth:
- ret = 4;
+ ret = int(QStyleHelper::dpiScaled(4.));
break;
case PM_MdiSubWindowMinimizedWidth:
- ret = 196;
+ ret = int(QStyleHelper::dpiScaled(196.));
break;
#ifndef QT_NO_SCROLLBAR
@@ -4668,7 +4490,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
: QApplication::globalStrut().width();
ret = qMax(16, s);
} else {
- ret = 16;
+ ret = int(QStyleHelper::dpiScaled(16.));
}
break;
#endif
@@ -4678,14 +4500,14 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
#ifndef QT_NO_SLIDER
case PM_SliderThickness:
- ret = 16;
+ ret = int(QStyleHelper::dpiScaled(16.));
break;
case PM_SliderTickmarkOffset:
if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height()
: sl->rect.width();
- int thickness = pixelMetric(PM_SliderControlThickness, sl, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, sl, widget);
int ticks = sl->tickPosition;
if (ticks == QSlider::TicksBothSides)
@@ -4702,9 +4524,9 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
case PM_SliderSpaceAvailable:
if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
if (sl->orientation == Qt::Horizontal)
- ret = sl->rect.width() - pixelMetric(PM_SliderLength, sl, widget);
+ ret = sl->rect.width() - proxy()->pixelMetric(PM_SliderLength, sl, widget);
else
- ret = sl->rect.height() - pixelMetric(PM_SliderLength, sl, widget);
+ ret = sl->rect.height() - proxy()->pixelMetric(PM_SliderLength, sl, widget);
} else {
ret = 0;
}
@@ -4712,11 +4534,11 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
#endif // QT_NO_SLIDER
#ifndef QT_NO_DOCKWIDGET
case PM_DockWidgetSeparatorExtent:
- ret = 6;
+ ret = int(QStyleHelper::dpiScaled(6.));
break;
case PM_DockWidgetHandleExtent:
- ret = 8;
+ ret = int(QStyleHelper::dpiScaled(8.));
break;
case PM_DockWidgetTitleMargin:
ret = 0;
@@ -4745,19 +4567,19 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
break;
case PM_ToolBarItemSpacing:
- ret = 4;
+ ret = int(QStyleHelper::dpiScaled(4.));
break;
case PM_ToolBarHandleExtent:
- ret = 8;
+ ret = int(QStyleHelper::dpiScaled(8.));
break;
case PM_ToolBarSeparatorExtent:
- ret = 6;
+ ret = int(QStyleHelper::dpiScaled(6.));
break;
case PM_ToolBarExtensionExtent:
- ret = 12;
+ ret = int(QStyleHelper::dpiScaled(12.));
break;
#endif // QT_NO_TOOLBAR
@@ -4767,7 +4589,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
break;
case PM_TabBarTabHSpace:
- ret = 24;
+ ret = int(QStyleHelper::dpiScaled(24.));
break;
case PM_TabBarTabShiftHorizontal:
@@ -4796,27 +4618,27 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
break;
case PM_IndicatorWidth:
- ret = 13;
+ ret = int(QStyleHelper::dpiScaled(13.));
break;
case PM_IndicatorHeight:
- ret = 13;
+ ret = int(QStyleHelper::dpiScaled(13.));
break;
case PM_ExclusiveIndicatorWidth:
- ret = 12;
+ ret = int(QStyleHelper::dpiScaled(12.));
break;
case PM_ExclusiveIndicatorHeight:
- ret = 12;
+ ret = int(QStyleHelper::dpiScaled(12.));
break;
case PM_MenuTearoffHeight:
- ret = 10;
+ ret = int(QStyleHelper::dpiScaled(10.));
break;
case PM_MenuScrollerHeight:
- ret = 10;
+ ret = int(QStyleHelper::dpiScaled(10.));
break;
case PM_MenuDesktopFrameWidth:
@@ -4826,16 +4648,16 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
break;
case PM_HeaderMargin:
- ret = 4;
+ ret = int(QStyleHelper::dpiScaled(4.));
break;
case PM_HeaderMarkSize:
- ret = 32;
+ ret = int(QStyleHelper::dpiScaled(32.));
break;
case PM_HeaderGripMargin:
- ret = 4;
+ ret = int(QStyleHelper::dpiScaled(4.));
break;
case PM_TabBarScrollButtonWidth:
- ret = 16;
+ ret = int(QStyleHelper::dpiScaled(16.));
break;
case PM_LayoutLeftMargin:
case PM_LayoutTopMargin:
@@ -4848,40 +4670,56 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
} else if (widget) {
isWindow = widget->isWindow();
}
- ret = pixelMetric(isWindow ? PM_DefaultTopLevelMargin : PM_DefaultChildMargin);
+ ret = proxy()->pixelMetric(isWindow ? PM_DefaultTopLevelMargin : PM_DefaultChildMargin);
}
break;
case PM_LayoutHorizontalSpacing:
case PM_LayoutVerticalSpacing:
- ret = pixelMetric(PM_DefaultLayoutSpacing);
+ ret = proxy()->pixelMetric(PM_DefaultLayoutSpacing);
break;
case PM_DefaultTopLevelMargin:
- ret = 11;
+ ret = int(QStyleHelper::dpiScaled(11.));
break;
case PM_DefaultChildMargin:
- ret = 9;
+ ret = int(QStyleHelper::dpiScaled(9.));
break;
case PM_DefaultLayoutSpacing:
- ret = 6;
+ ret = int(QStyleHelper::dpiScaled(6.));
break;
- case PM_TabBarIconSize:
case PM_ToolBarIconSize:
+#ifdef Q_WS_X11
+ if (X11->desktopVersion >= 4) {
+ static int iconSize = 0;
+ if (!iconSize) {
+ QSettings settings(QKde::kdeHome() +
+ QLatin1String("/share/config/kdeglobals"),
+ QSettings::IniFormat);
+ settings.beginGroup(QLatin1String("ToolbarIcons"));
+ iconSize = settings.value(QLatin1String("Size"), QLatin1String("22")).toInt();
+ }
+ ret = iconSize;
+ } else
+#endif
+ ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
+ break;
+
+ case PM_TabBarIconSize:
case PM_ListViewIconSize:
- ret = pixelMetric(PM_SmallIconSize, opt, widget);
+ ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
break;
case PM_ButtonIconSize:
case PM_SmallIconSize:
- ret = 16;
+ ret = int(QStyleHelper::dpiScaled(16.));
break;
case PM_IconViewIconSize:
- ret = pixelMetric(PM_LargeIconSize, opt, widget);
+ ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget);
break;
case PM_LargeIconSize:
- ret = 32;
+ ret = int(QStyleHelper::dpiScaled(32.));
break;
case PM_ToolTipLabelFrameWidth:
@@ -4889,13 +4727,20 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
break;
case PM_CheckBoxLabelSpacing:
case PM_RadioButtonLabelSpacing:
- ret = 6;
+ ret = int(QStyleHelper::dpiScaled(6.));
break;
case PM_SizeGripSize:
- ret = 13;
+ ret = int(QStyleHelper::dpiScaled(13.));
break;
case PM_MessageBoxIconSize:
- ret = 32;
+#ifdef Q_WS_MAC
+ if (QApplication::desktopSettingsAware()) {
+ ret = 64; // No DPI scaling, it's handled elsewhere.
+ } else
+#endif
+ {
+ ret = int(QStyleHelper::dpiScaled(32.));
+ }
break;
case PM_TextCursorWidth:
ret = 1;
@@ -4905,13 +4750,13 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
break;
case PM_TabCloseIndicatorWidth:
case PM_TabCloseIndicatorHeight:
- ret = 16;
+ ret = int(QStyleHelper::dpiScaled(16.));
break;
case PM_ScrollView_ScrollBarSpacing:
- ret = 2 * pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ ret = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
break;
case PM_SubMenuOverlap:
- ret = -pixelMetric(QStyle::PM_MenuPanelWidth, opt, widget);
+ ret = -proxy()->pixelMetric(QStyle::PM_MenuPanelWidth, opt, widget);
break;
default:
ret = 0;
@@ -4934,12 +4779,12 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
int w = csz.width(),
h = csz.height(),
- bm = pixelMetric(PM_ButtonMargin, btn, widget),
- fw = pixelMetric(PM_DefaultFrameWidth, btn, widget) * 2;
+ bm = proxy()->pixelMetric(PM_ButtonMargin, btn, widget),
+ fw = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget) * 2;
w += bm + fw;
h += bm + fw;
if (btn->features & QStyleOptionButton::AutoDefaultButton){
- int dbw = pixelMetric(PM_ButtonDefaultIndicator, btn, widget) * 2;
+ int dbw = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget) * 2;
w += dbw;
h += dbw;
}
@@ -4951,15 +4796,15 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
bool isRadio = (ct == CT_RadioButton);
- int w = pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth
+ int w = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth
: PM_IndicatorWidth, btn, widget);
- int h = pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight
+ int h = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight
: PM_IndicatorHeight, btn, widget);
int margins = 0;
// we add 4 pixels for label margins
if (btn->icon.isNull() || !btn->text.isEmpty())
- margins = 4 + pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
+ margins = 4 + proxy()->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
: PM_CheckBoxLabelSpacing, opt, widget);
sz += QSize(w + margins, 4);
sz.setHeight(qMax(sz.height(), h));
@@ -4977,7 +4822,7 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
} else {
h = mi->fontMetrics.height() + 8;
if (!mi->icon.isNull()) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
}
}
@@ -5002,10 +4847,10 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
#ifndef QT_NO_COMBOBOX
case CT_ComboBox:
if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
- int fw = cmb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0;
- const int textMargins = 2*(pixelMetric(PM_FocusFrameHMargin) + 1);
+ int fw = cmb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0;
+ const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1);
// QItemDelegate::sizeHint expands the textMargins two times, thus the 2*textMargins...
- int other = qMax(23, 2*textMargins + pixelMetric(QStyle::PM_ScrollBarExtent, opt, widget));
+ int other = qMax(23, 2*textMargins + proxy()->pixelMetric(QStyle::PM_ScrollBarExtent, opt, widget));
sz = QSize(sz.width() + fw + other, sz.height() + fw);
}
break;
@@ -5013,8 +4858,8 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_HeaderSection:
if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
bool nullIcon = hdr->icon.isNull();
- int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, widget);
- int iconSize = nullIcon ? 0 : pixelMetric(QStyle::PM_SmallIconSize, hdr, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, hdr, widget);
+ int iconSize = nullIcon ? 0 : proxy()->pixelMetric(QStyle::PM_SmallIconSize, hdr, widget);
QSize txt = hdr->fontMetrics.size(0, hdr->text);
sz.setHeight(margin + qMax(iconSize, txt.height()) + margin);
sz.setWidth((nullIcon ? 0 : margin) + iconSize
@@ -5212,8 +5057,8 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
if (widget) {
if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
mask->region = widget->rect();
- int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin),
- hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin);
+ int vmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin),
+ hmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin);
mask->region -= QRect(widget->rect().adjusted(hmargin, vmargin, -hmargin, -vmargin));
}
}
@@ -5226,7 +5071,7 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
ret = true;
if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
mask->region = opt->rect;
- int margin = pixelMetric(PM_DefaultFrameWidth) * 2;
+ int margin = proxy()->pixelMetric(PM_DefaultFrameWidth) * 2;
mask->region -= opt->rect.adjusted(margin, margin, -margin, -margin);
}
}
@@ -5344,6 +5189,18 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
case SH_DockWidget_ButtonsHaveFrame:
ret = true;
break;
+ case SH_ToolButtonStyle:
+ ret = Qt::ToolButtonIconOnly;
+#ifdef Q_WS_X11
+ {
+ static int buttonStyle = d_func()->lookupToolButtonStyle();
+ return buttonStyle;
+ }
+#endif
+ break;
+ case SH_RequestSoftwareInputPanel:
+ ret = RSIP_OnMouseClickAndAlreadyFocused;
+ break;
default:
ret = 0;
break;
@@ -5361,298 +5218,167 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
Q_UNUSED(widget);
Q_UNUSED(sp);
#else
-#ifdef Q_WS_X11
- Q_D(const QCommonStyle);
QPixmap pixmap;
- if (qApp->desktopSettingsAware()) {
- d->lookupIconTheme();
+ const bool rtl = (option && option->direction == Qt::RightToLeft) || !option && QApplication::isRightToLeft();
+
+ if (QApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) {
switch (sp) {
case SP_DirHomeIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("folder_home.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
+ pixmap = QIcon::fromTheme(QLatin1String("user-home")).pixmap(16);
+ break;
case SP_MessageBoxInformation:
- {
- pixmap = d->findIcon(32, QLatin1String("messagebox_info.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
+ pixmap = QIcon::fromTheme(QLatin1String("messagebox_info")).pixmap(16);
+ break;
case SP_MessageBoxWarning:
- {
- pixmap = d->findIcon(32, QLatin1String("messagebox_warning.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
+ pixmap = QIcon::fromTheme(QLatin1String("messagebox_warning")).pixmap(16);
+ break;
case SP_MessageBoxCritical:
- {
- pixmap = d->findIcon(32, QLatin1String("messagebox_critical.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
+ pixmap = QIcon::fromTheme(QLatin1String("messagebox_critical")).pixmap(16);
+ break;
case SP_MessageBoxQuestion:
- {
- pixmap = d->findIcon(32, QLatin1String("help.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
+ pixmap = QIcon::fromTheme(QLatin1String("help")).pixmap(16);
+ break;
case SP_DialogOpenButton:
case SP_DirOpenIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("folder-open.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("folder_open.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
+ pixmap = QIcon::fromTheme(QLatin1String("folder-open")).pixmap(16);
+ break;
case SP_FileIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("text-x-generic.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("empty.png"));
- if (!pixmap.isNull())
- return pixmap;
- break;
- }
- case SP_FileLinkIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("link_overlay.png"));
- if (!pixmap.isNull()) {
- QPixmap fileIcon = d->findIcon(16, QLatin1String("text-x-generic.png"));
- if (fileIcon.isNull())
- fileIcon = d->findIcon(16, QLatin1String("empty.png"));
- if (!fileIcon.isNull()) {
- QPainter painter(&fileIcon);
- painter.drawPixmap(0, 0, 16, 16, pixmap);
- return fileIcon;
- }
- }
- break;
- }
+ pixmap = QIcon::fromTheme(QLatin1String("text-x-generic"),
+ QIcon::fromTheme(QLatin1String("empty"))).pixmap(16);
+ break;
case SP_DirClosedIcon:
case SP_DirIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("folder.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("folder")).pixmap(16);
break;
- }
- case SP_DirLinkIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("link_overlay.png"));
- if (!pixmap.isNull()) {
- QPixmap dirIcon = d->findIcon(16, QLatin1String("folder.png"));
- if (!dirIcon.isNull()) {
- QPainter painter(&dirIcon);
- painter.drawPixmap(0, 0, 16, 16, pixmap);
- return dirIcon;
- }
- }
- break;
- }
case SP_DriveFDIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("media-floppy.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("3floppy_unmount.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("media-floppy"),
+ QIcon::fromTheme(QLatin1String("3floppy_unmount"))).pixmap(16);
break;
- }
case SP_ComputerIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("computer.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("system.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("computer"),
+ QIcon::fromTheme(QLatin1String("system"))).pixmap(16);
break;
- }
case SP_DesktopIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("user-desktop.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("desktop.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("user-desktop"),
+ QIcon::fromTheme(QLatin1String("desktop"))).pixmap(16);
break;
- }
case SP_TrashIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("user-trash.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("trashcan_empty.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("user-trash"),
+ QIcon::fromTheme(QLatin1String("trashcan_empty"))).pixmap(16);
break;
- }
case SP_DriveCDIcon:
case SP_DriveDVDIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("media-optical.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("cdrom_unmount.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("media-optical"),
+ QIcon::fromTheme(QLatin1String("cdrom_unmount"))).pixmap(16);
break;
- }
case SP_DriveHDIcon:
- {
- pixmap = d->findIcon(16, QLatin1String("drive-harddisk.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(16, QLatin1String("hdd_unmount.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("drive-harddisk"),
+ QIcon::fromTheme(QLatin1String("hdd_unmount"))).pixmap(16);
break;
- }
case SP_FileDialogToParent:
- {
- pixmap = d->findIcon(32, QLatin1String("go-up.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(32, QLatin1String("up.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("go-up"),
+ QIcon::fromTheme(QLatin1String("up"))).pixmap(16);
break;
- }
case SP_FileDialogNewFolder:
- {
- pixmap = d->findIcon(16, QLatin1String("folder_new.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("folder_new")).pixmap(16);
break;
- }
case SP_ArrowUp:
- {
- pixmap = d->findIcon(32, QLatin1String("go-up.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(32, QLatin1String("up.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("go-up"),
+ QIcon::fromTheme(QLatin1String("up"))).pixmap(16);
break;
- }
case SP_ArrowDown:
- {
- pixmap = d->findIcon(32, QLatin1String("go-down.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(32, QLatin1String("down.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("go-down"),
+ QIcon::fromTheme(QLatin1String("down"))).pixmap(16);
break;
- }
case SP_ArrowRight:
- {
- pixmap = d->findIcon(32, QLatin1String("go-next.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(32, QLatin1String("forward.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("go-next"),
+ QIcon::fromTheme(QLatin1String("forward"))).pixmap(16);
break;
- }
case SP_ArrowLeft:
- {
- pixmap = d->findIcon(32, QLatin1String("go-previous.png"));
- if (pixmap.isNull())
- pixmap = d->findIcon(32, QLatin1String("back.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("go-previous"),
+ QIcon::fromTheme(QLatin1String("back"))).pixmap(16);
break;
- }
case SP_FileDialogDetailedView:
- {
- pixmap = d->findIcon(16, QLatin1String("view_detailed.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("view_detailed")).pixmap(16);
break;
- }
-
case SP_FileDialogListView:
- {
- pixmap = d->findIcon(16, QLatin1String("view_icon.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("view_icon")).pixmap(16);
break;
- }
case SP_BrowserReload:
- {
- pixmap = d->findIcon(32, QLatin1String("reload.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("reload")).pixmap(16);
break;
- }
case SP_BrowserStop:
- {
- pixmap = d->findIcon(32, QLatin1String("stop.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("process-stop")).pixmap(16);
break;
- }
case SP_MediaPlay:
- {
- pixmap = d->findIcon(16, QLatin1String("player_play.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("media-playback-start")).pixmap(16);
break;
- }
case SP_MediaPause:
- {
- pixmap = d->findIcon(16, QLatin1String("player_pause.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("media-playback-pause")).pixmap(16);
break;
- }
case SP_MediaStop:
- {
- pixmap = d->findIcon(16, QLatin1String("player_stop.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("media-playback-stop")).pixmap(16);
break;
- }
case SP_MediaSeekForward:
- {
- pixmap = d->findIcon(16, QLatin1String("player_fwd.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("media-seek-forward")).pixmap(16);
break;
- }
case SP_MediaSeekBackward:
- {
- pixmap = d->findIcon(16, QLatin1String("player_rew.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("media-seek-backward")).pixmap(16);
break;
- }
case SP_MediaSkipForward:
- {
- pixmap = d->findIcon(16, QLatin1String("player_end.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("media-skip-backward")).pixmap(16);
break;
- }
case SP_MediaSkipBackward:
- {
- pixmap = d->findIcon(16, QLatin1String("player_start.png"));
- if (!pixmap.isNull())
- return pixmap;
+ pixmap = QIcon::fromTheme(QLatin1String("media-skip-backward")).pixmap(16);
+ break;
+ case SP_DialogResetButton:
+ pixmap = QIcon::fromTheme(QLatin1String("edit-clear")).pixmap(24);
+ break;
+ case SP_DialogHelpButton:
+ pixmap = QIcon::fromTheme(QLatin1String("help-contents")).pixmap(24);
+ break;
+ case SP_DialogCancelButton:
+ pixmap = QIcon::fromTheme(QLatin1String("process-stop")).pixmap(24);
break;
+ case SP_DialogSaveButton:
+ pixmap = QIcon::fromTheme(QLatin1String("document-save")).pixmap(24);
+ break;
+ case SP_FileLinkIcon:
+ pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16);
+ if (!pixmap.isNull()) {
+ QPixmap fileIcon = QIcon::fromTheme(QLatin1String("text-x-generic")).pixmap(16);
+ if (fileIcon.isNull())
+ fileIcon = QIcon::fromTheme(QLatin1String("empty")).pixmap(16);
+ if (!fileIcon.isNull()) {
+ QPainter painter(&fileIcon);
+ painter.drawPixmap(0, 0, 16, 16, pixmap);
+ return fileIcon;
+ }
}
-
+ break;
+ case SP_DirLinkIcon:
+ pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16);
+ if (!pixmap.isNull()) {
+ QPixmap dirIcon = QIcon::fromTheme(QLatin1String("folder")).pixmap(16);
+ if (!dirIcon.isNull()) {
+ QPainter painter(&dirIcon);
+ painter.drawPixmap(0, 0, 16, 16, pixmap);
+ return dirIcon;
+ }
+ }
+ break;
default:
break;
}
}
-#endif //Q_WS_X11
+
+ if (!pixmap.isNull())
+ return pixmap;
#endif //QT_NO_IMAGEFORMAT_PNG
switch (sp) {
#ifndef QT_NO_IMAGEFORMAT_XPM
case SP_ToolBarHorizontalExtensionButton:
- if (QApplication::layoutDirection() == Qt::RightToLeft) {
+ if (rtl) {
QImage im(tb_extension_arrow_h_xpm);
im = im.convertToFormat(QImage::Format_ARGB32).mirrored(true, false);
return QPixmap::fromImage(im);
@@ -5668,13 +5394,13 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
#ifndef QT_NO_IMAGEFORMAT_PNG
case SP_CommandLink:
case SP_ArrowForward:
- if (QApplication::layoutDirection() == Qt::RightToLeft)
- return standardPixmap(SP_ArrowLeft, option, widget);
- return standardPixmap(SP_ArrowRight, option, widget);
+ if (rtl)
+ return proxy()->standardPixmap(SP_ArrowLeft, option, widget);
+ return proxy()->standardPixmap(SP_ArrowRight, option, widget);
case SP_ArrowBack:
- if (QApplication::layoutDirection() == Qt::RightToLeft)
- return standardPixmap(SP_ArrowRight, option, widget);
- return standardPixmap(SP_ArrowLeft, option, widget);
+ if (rtl)
+ return proxy()->standardPixmap(SP_ArrowRight, option, widget);
+ return proxy()->standardPixmap(SP_ArrowLeft, option, widget);
case SP_ArrowLeft:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/left-16.png"));
case SP_ArrowRight:
@@ -5684,7 +5410,7 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
case SP_ArrowDown:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/down-16.png"));
case SP_FileDialogToParent:
- return standardPixmap(SP_ArrowUp, option, widget);
+ return proxy()->standardPixmap(SP_ArrowUp, option, widget);
case SP_FileDialogNewFolder:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-16.png"));
case SP_FileDialogDetailedView:
@@ -5696,7 +5422,7 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
case SP_FileDialogListView:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-16.png"));
case SP_FileDialogBack:
- return standardPixmap(SP_ArrowBack, option, widget);
+ return proxy()->standardPixmap(SP_ArrowBack, option, widget);
case SP_DriveHDIcon:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/harddrive-16.png"));
case SP_TrashIcon:
@@ -5783,254 +5509,271 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
const QWidget *widget) const
{
QIcon icon;
-#ifdef Q_WS_X11
- Q_D(const QCommonStyle);
- if (qApp->desktopSettingsAware()) {
- d->lookupIconTheme();
- QPixmap pixmap;
+ const bool rtl = (option && option->direction == Qt::RightToLeft) || !option && QApplication::isRightToLeft();
+ if (QApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) {
switch (standardIcon) {
case SP_DirHomeIcon:
- {
- icon = d->createIcon(QLatin1String("folder_home.png"));
+ icon = QIcon::fromTheme(QLatin1String("user-home"));
break;
- }
case SP_MessageBoxInformation:
- {
- icon = d->createIcon(QLatin1String("dialog-information.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("messagebox_info.png"));
+ icon = QIcon::fromTheme(QLatin1String("dialog-information"));
break;
- }
case SP_MessageBoxWarning:
- {
- icon = d->createIcon(QLatin1String("dialog-warning.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("messagebox_warning.png"));
+ icon = QIcon::fromTheme(QLatin1String("dialog-warning"));
break;
- }
case SP_MessageBoxCritical:
- {
- icon = d->createIcon(QLatin1String("dialog-error.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("messagebox_critical.png"));
+ icon = QIcon::fromTheme(QLatin1String("dialog-error"));
break;
- }
case SP_MessageBoxQuestion:
- {
- icon = d->createIcon(QLatin1String("help.png"));
+ icon = QIcon::fromTheme(QLatin1String("dialog-question"));
break;
- }
case SP_DialogOpenButton:
case SP_DirOpenIcon:
- {
- icon = d->createIcon(QLatin1String("folder-open.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("folder_open.png"));
+ icon = QIcon::fromTheme(QLatin1String("folder-open"));
break;
- }
case SP_FileIcon:
- {
- icon = d->createIcon(QLatin1String("text-x-generic.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("empty.png"));
+ icon = QIcon::fromTheme(QLatin1String("text-x-generic"));
break;
- }
case SP_DirClosedIcon:
case SP_DirIcon:
- {
- icon = d->createIcon(QLatin1String("folder.png"));
+ icon = QIcon::fromTheme(QLatin1String("folder"));
break;
- }
case SP_DriveFDIcon:
- {
- icon = d->createIcon(QLatin1String("floppy_unmount.png"));
+ icon = QIcon::fromTheme(QLatin1String("floppy_unmount"));
break;
- }
case SP_ComputerIcon:
- {
- icon = d->createIcon(QLatin1String("computer.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("system.png"));
+ icon = QIcon::fromTheme(QLatin1String("computer"),
+ QIcon::fromTheme(QLatin1String("system")));
break;
- }
case SP_DesktopIcon:
- {
- icon = d->createIcon(QLatin1String("user-desktop.png"));
+ icon = QIcon::fromTheme(QLatin1String("user-desktop"));
break;
- }
case SP_TrashIcon:
- {
- icon = d->createIcon(QLatin1String("user-trash.png"));
+ icon = QIcon::fromTheme(QLatin1String("user-trash"));
break;
- }
case SP_DriveCDIcon:
case SP_DriveDVDIcon:
- {
- icon = d->createIcon(QLatin1String("media-optical.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("cdrom_unmount.png"));
+ icon = QIcon::fromTheme(QLatin1String("media-optical"));
break;
- }
case SP_DriveHDIcon:
- {
- icon = d->createIcon(QLatin1String("drive-harddisk.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("hdd_unmount.png"));
+ icon = QIcon::fromTheme(QLatin1String("drive-harddisk"));
break;
- }
case SP_FileDialogToParent:
- {
- icon = d->createIcon(QLatin1String("go-up.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("up.png"));
+ icon = QIcon::fromTheme(QLatin1String("go-up"));
break;
- }
case SP_FileDialogNewFolder:
- {
- icon = d->createIcon(QLatin1String("folder_new.png"));
+ icon = QIcon::fromTheme(QLatin1String("folder-new"));
break;
- }
case SP_ArrowUp:
- {
- icon = d->createIcon(QLatin1String("go-up.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("up.png"));
+ icon = QIcon::fromTheme(QLatin1String("go-up"));
break;
- }
case SP_ArrowDown:
- {
- icon = d->createIcon(QLatin1String("go-down.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("down.png"));
+ icon = QIcon::fromTheme(QLatin1String("go-down"));
break;
- }
case SP_ArrowRight:
- {
- icon = d->createIcon(QLatin1String("go-next.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("forward.png"));
+ icon = QIcon::fromTheme(QLatin1String("go-next"));
break;
- }
case SP_ArrowLeft:
- {
- icon = d->createIcon(QLatin1String("go-previous.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("back.png"));
+ icon = QIcon::fromTheme(QLatin1String("go-previous"));
+ break;
+ case SP_DialogHelpButton:
+ icon = QIcon::fromTheme(QLatin1String("help-contents"));
+ break;
+ case SP_DialogCancelButton:
+ icon = QIcon::fromTheme(QLatin1String("process-stop"));
+ break;
+ case SP_DialogCloseButton:
+ icon = QIcon::fromTheme(QLatin1String("window-close"));
+ break;
+ case SP_DialogApplyButton:
+ icon = QIcon::fromTheme(QLatin1String("dialog-ok-apply"));
+ break;
+ case SP_DialogOkButton:
+ icon = QIcon::fromTheme(QLatin1String("dialog-ok"));
break;
- }
case SP_FileDialogDetailedView:
- {
- icon = d->createIcon(QLatin1String("view-list-details.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("view_detailed.png"));
+ icon = QIcon::fromTheme(QLatin1String("view-list-details"));
break;
- }
case SP_FileDialogListView:
- {
- icon = d->createIcon(QLatin1String("view-list-icons.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("view_icon.png"));
+ icon = QIcon::fromTheme(QLatin1String("view-list-icons"));
break;
- }
case SP_BrowserReload:
- {
- icon = d->createIcon(QLatin1String("view-refresh.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("reload.png"));
+ icon = QIcon::fromTheme(QLatin1String("view-refresh"));
break;
- }
case SP_BrowserStop:
- {
- icon = d->createIcon(QLatin1String("process-stop.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("stop.png"));
+ icon = QIcon::fromTheme(QLatin1String("process-stop"));
break;
- }
case SP_MediaPlay:
- {
- icon = d->createIcon(QLatin1String("media-playback-start.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("player_play.png"));
+ icon = QIcon::fromTheme(QLatin1String("media-playback-start"));
break;
- }
case SP_MediaPause:
- {
- icon = d->createIcon(QLatin1String("media-playback-pause.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("player_pause.png"));
+ icon = QIcon::fromTheme(QLatin1String("media-playback-pause"));
break;
- }
case SP_MediaStop:
- {
- icon = d->createIcon(QLatin1String("media-playback-stop.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("player_stop.png"));
+ icon = QIcon::fromTheme(QLatin1String("media-playback-stop"));
break;
- }
case SP_MediaSeekForward:
- {
- icon = d->createIcon(QLatin1String("media-skip-forward.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("player_fwd.png"));
+ icon = QIcon::fromTheme(QLatin1String("media-seek-forward"));
break;
- }
case SP_MediaSeekBackward:
- {
- icon = d->createIcon(QLatin1String("media-skip-backward.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("player_rew.png"));
+ icon = QIcon::fromTheme(QLatin1String("media-seek-backward"));
break;
- }
case SP_MediaSkipForward:
- {
- icon = d->createIcon(QLatin1String("media-skip-forward.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("player_end.png"));
+ icon = QIcon::fromTheme(QLatin1String("media-skip-forward"));
break;
- }
case SP_MediaSkipBackward:
- {
- icon = d->createIcon(QLatin1String("media-skip-backward.png"));
- if (icon.isNull())
- icon = d->createIcon(QLatin1String("player_start.png"));
+ icon = QIcon::fromTheme(QLatin1String("media-skip-backward"));
break;
- }
-
- case SP_FileLinkIcon: {
- icon = QIcon(standardPixmap(standardIcon, option, widget));
- QPixmap pixmap = d->findIcon(32, QLatin1String("link_overlay.png"));
- if (!pixmap.isNull()) {
- QPixmap fileIcon = d->findIcon(32, QLatin1String("text-x-generic.png"));
- if (fileIcon.isNull())
- fileIcon = d->findIcon(32, QLatin1String("empty.png"));
- if (!fileIcon.isNull()) {
- QPainter painter(&fileIcon);
- painter.drawPixmap(0, 0, 32, 32, pixmap);
- icon.addPixmap(fileIcon);
+ case SP_MediaVolume:
+ icon = QIcon::fromTheme(QLatin1String("audio-volume-medium"));
+ break;
+ case SP_MediaVolumeMuted:
+ icon = QIcon::fromTheme(QLatin1String("audio-volume-muted"));
+ break;
+ case SP_DialogResetButton:
+ icon = QIcon::fromTheme(QLatin1String("edit-clear"));
+ break;
+ case SP_ArrowForward:
+ if (rtl)
+ return standardIconImplementation(SP_ArrowLeft, option, widget);
+ return standardIconImplementation(SP_ArrowRight, option, widget);
+ case SP_ArrowBack:
+ if (rtl)
+ return standardIconImplementation(SP_ArrowRight, option, widget);
+ return standardIconImplementation(SP_ArrowLeft, option, widget);
+ case SP_FileLinkIcon:
+ {
+ QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link"));
+ if (!linkIcon.isNull()) {
+ QIcon baseIcon = standardIconImplementation(SP_FileIcon, option, widget);
+ const QList<QSize> sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off);
+ for (int i = 0 ; i < sizes.size() ; ++i) {
+ int size = sizes[i].width();
+ QPixmap basePixmap = baseIcon.pixmap(size);
+ QPixmap linkPixmap = linkIcon.pixmap(size/2);
+ QPainter painter(&basePixmap);
+ painter.drawPixmap(size/2, size/2, linkPixmap);
+ icon.addPixmap(basePixmap);
+ }
}
}
- }
- break;
- case SP_DirLinkIcon: {
- icon = QIcon(standardPixmap(standardIcon, option, widget));
- QPixmap pixmap = d->findIcon(32, QLatin1String("link_overlay.png"));
- if (!pixmap.isNull()) {
- QPixmap fileIcon = d->findIcon(32, QLatin1String("folder.png"));
- if (!fileIcon.isNull()) {
- QPainter painter(&fileIcon);
- painter.drawPixmap(0, 0, 32, 32, pixmap);
- icon.addPixmap(fileIcon);
+ break;
+ case SP_DirLinkIcon:
+ {
+ QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link"));
+ if (!linkIcon.isNull()) {
+ QIcon baseIcon = standardIconImplementation(SP_DirIcon, option, widget);
+ const QList<QSize> sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off);
+ for (int i = 0 ; i < sizes.size() ; ++i) {
+ int size = sizes[i].width();
+ QPixmap basePixmap = baseIcon.pixmap(size);
+ QPixmap linkPixmap = linkIcon.pixmap(size/2);
+ QPainter painter(&basePixmap);
+ painter.drawPixmap(size/2, size/2, linkPixmap);
+ icon.addPixmap(basePixmap);
+ }
}
- }
}
break;
default:
break;
}
+
if (!icon.isNull())
return icon;
+#if defined(Q_WS_MAC)
+ OSType iconType = 0;
+ switch (standardIcon) {
+ case QStyle::SP_MessageBoxQuestion:
+ case QStyle::SP_MessageBoxInformation:
+ case QStyle::SP_MessageBoxWarning:
+ case QStyle::SP_MessageBoxCritical:
+ iconType = kGenericApplicationIcon;
+ break;
+ case SP_DesktopIcon:
+ iconType = kDesktopIcon;
+ break;
+ case SP_TrashIcon:
+ iconType = kTrashIcon;
+ break;
+ case SP_ComputerIcon:
+ iconType = kComputerIcon;
+ break;
+ case SP_DriveFDIcon:
+ iconType = kGenericFloppyIcon;
+ break;
+ case SP_DriveHDIcon:
+ iconType = kGenericHardDiskIcon;
+ break;
+ case SP_DriveCDIcon:
+ case SP_DriveDVDIcon:
+ iconType = kGenericCDROMIcon;
+ break;
+ case SP_DriveNetIcon:
+ iconType = kGenericNetworkIcon;
+ break;
+ case SP_DirOpenIcon:
+ iconType = kOpenFolderIcon;
+ break;
+ case SP_DirClosedIcon:
+ case SP_DirLinkIcon:
+ iconType = kGenericFolderIcon;
+ break;
+ case SP_FileLinkIcon:
+ case SP_FileIcon:
+ iconType = kGenericDocumentIcon;
+ break;
+ case SP_DirIcon: {
+ // A rather special case
+ QIcon closeIcon = QStyle::standardIcon(SP_DirClosedIcon, option, widget);
+ QIcon openIcon = QStyle::standardIcon(SP_DirOpenIcon, option, widget);
+ closeIcon.addPixmap(openIcon.pixmap(16, 16), QIcon::Normal, QIcon::On);
+ closeIcon.addPixmap(openIcon.pixmap(32, 32), QIcon::Normal, QIcon::On);
+ closeIcon.addPixmap(openIcon.pixmap(64, 64), QIcon::Normal, QIcon::On);
+ closeIcon.addPixmap(openIcon.pixmap(128, 128), QIcon::Normal, QIcon::On);
+ return closeIcon;
+ }
+ case SP_TitleBarNormalButton:
+ case SP_TitleBarCloseButton: {
+ QIcon titleBarIcon;
+ if (standardIcon == SP_TitleBarCloseButton) {
+ titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-16.png"));
+ titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On);
+ } else {
+ titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-16.png"));
+ titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On);
+ }
+ return titleBarIcon;
+ }
+ default:
+ break;
+ }
+ if (iconType != 0) {
+ QIcon retIcon;
+ IconRef icon;
+ IconRef overlayIcon = 0;
+ if (iconType != kGenericApplicationIcon) {
+ GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon);
+ } else {
+ FSRef fsRef;
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ GetProcessBundleLocation(&psn, &fsRef);
+ GetIconRefFromFileInfo(&fsRef, 0, 0, 0, 0, kIconServicesNormalUsageFlag, &icon, 0);
+ if (standardIcon == SP_MessageBoxCritical) {
+ overlayIcon = icon;
+ GetIconRef(kOnSystemDisk, kSystemIconsCreator, kAlertCautionIcon, &icon);
+ }
+ }
+ if (icon) {
+ qt_mac_constructQIconFromIconRef(icon, overlayIcon, &retIcon, standardIcon);
+ ReleaseIconRef(icon);
+ }
+ if (overlayIcon)
+ ReleaseIconRef(overlayIcon);
+ return retIcon;
+ }
+#endif // Q_WS_MAC
}
-#endif//Q_WS_X11
switch (standardIcon) {
#ifndef QT_NO_IMAGEFORMAT_PNG
@@ -6119,11 +5862,11 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-128.png"));
break;
case SP_ArrowForward:
- if (QApplication::layoutDirection() == Qt::RightToLeft)
+ if (rtl)
return standardIconImplementation(SP_ArrowLeft, option, widget);
return standardIconImplementation(SP_ArrowRight, option, widget);
case SP_ArrowBack:
- if (QApplication::layoutDirection() == Qt::RightToLeft)
+ if (rtl)
return standardIconImplementation(SP_ArrowRight, option, widget);
return standardIconImplementation(SP_ArrowLeft, option, widget);
case SP_ArrowLeft:
@@ -6230,7 +5973,7 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
break;
#endif // QT_NO_IMAGEFORMAT_PNG
default:
- icon.addPixmap(standardPixmap(standardIcon, option, widget));
+ icon.addPixmap(proxy()->standardPixmap(standardIcon, option, widget));
break;
}
return icon;
diff --git a/src/gui/styles/qcommonstyle_p.h b/src/gui/styles/qcommonstyle_p.h
index 7f13c8b..ffc1324 100644
--- a/src/gui/styles/qcommonstyle_p.h
+++ b/src/gui/styles/qcommonstyle_p.h
@@ -122,19 +122,10 @@ public:
}
#endif
mutable QIcon tabBarcloseButtonIcon;
-
-//icon detection on X11
-#ifdef Q_WS_X11
- void lookupIconTheme() const;
- QIcon createIcon(const QString &) const;
- QPixmap findIcon(int size, const QString &) const;
- QPixmap findIconHelper(int size, const QString &, const QString &, QStringList &visited) const;
- QIconTheme parseIndexFile(const QString &themeName) const;
- mutable QString themeName;
- mutable QStringList iconDirs;
- mutable QHash <QString, QIconTheme> themeList;
+ int lookupToolButtonStyle() const;
+#ifndef QT_NO_TABBAR
+ void tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const;
#endif
-
};
QT_END_NAMESPACE
diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp
index 4d07c07..87fa322 100644
--- a/src/gui/styles/qgtkstyle.cpp
+++ b/src/gui/styles/qgtkstyle.cpp
@@ -1,4 +1,4 @@
-/******* *********************************************************************
+/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
@@ -70,6 +70,7 @@
#include <qpixmapcache.h>
#undef signals // Collides with GTK stymbols
#include "qgtkpainter_p.h"
+#include "qstylehelper_p.h"
#include <private/qcleanlooksstyle_p.h>
@@ -150,7 +151,6 @@ bool QGtkStyleFilter::eventFilter(QObject *obj, QEvent *e)
if (e->type() == QEvent::ApplicationPaletteChange) {
// Only do this the first time since this will also
// generate applicationPaletteChange events
- extern QHash<QByteArray, QPalette> *qt_app_palettes_hash(); //qapplication.cpp
if (!qt_app_palettes_hash() || qt_app_palettes_hash()->isEmpty()) {
QGtk::applyCustomPaletteHash();
}
@@ -176,7 +176,6 @@ public:
static const int groupBoxBottomMargin = 2; // space below the groupbox
static const int groupBoxTitleMargin = 6; // space between contents and title
static const int groupBoxTopMargin = 2;
-static bool UsePixmapCache = true;
// Get size of the arrow controls in a GtkSpinButton
static int spinboxArrowSize()
@@ -210,17 +209,6 @@ static GdkColor fromQColor(const QColor &color)
return retval;
}
-// Note this is different from uniqueName as used in QGtkPainter
-static QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size)
-{
- QString tmp;
- const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option);
- tmp.sprintf("%s-%d-%d-%d-%lld-%dx%d", key.toLatin1().constData(), uint(option->state),
- option->direction, complexOption ? uint(complexOption->activeSubControls) : uint(0),
- option->palette.cacheKey(), size.width(), size.height());
- return tmp;
-}
-
/*!
\class QGtkStyle
\brief The QGtkStyle class provides a widget style rendered by GTK+
@@ -611,6 +599,26 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg
break;
+ case SH_ToolButtonStyle:
+ {
+ if (QGtk::isKDE4Session())
+ return QCleanlooksStyle::styleHint(hint, option, widget, returnData);
+ GtkWidget *gtkToolbar = QGtk::gtkWidget(QLS("GtkToolbar"));
+ GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS;
+ g_object_get(gtkToolbar, "toolbar-style", &toolbar_style, NULL);
+ switch (toolbar_style) {
+ case GTK_TOOLBAR_TEXT:
+ return Qt::ToolButtonTextOnly;
+ case GTK_TOOLBAR_BOTH:
+ return Qt::ToolButtonTextUnderIcon;
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ return Qt::ToolButtonTextBesideIcon;
+ case GTK_TOOLBAR_ICONS:
+ default:
+ return Qt::ToolButtonIconOnly;
+ }
+ }
+ break;
case SH_SpinControls_DisableOnBounds:
return int(true);
@@ -675,14 +683,14 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
if (widget && widget->inherits("QComboBoxPrivateContainer")){
QStyleOption copy = *option;
copy.state |= State_Raised;
- drawPrimitive(PE_PanelMenu, &copy, painter, widget);
+ proxy()->drawPrimitive(PE_PanelMenu, &copy, painter, widget);
break;
}
// Drawing the entire itemview frame is very expensive, especially on the native X11 engine
// Instead we cheat a bit and draw a border image without the center part, hence only scaling
// thin rectangular images
const int pmSize = 64;
- const int border = pixelMetric(PM_DefaultFrameWidth, option, widget);
+ const int border = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
const QString pmKey = QString(QLS("windowframe %0")).arg(option->state);
QPixmap pixmap;
@@ -889,8 +897,8 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
int border = (size > 9) ? (size/4) : 0; //Allow small arrows to have exact dimensions
int bsx = 0, bsy = 0;
if (option->state & State_Sunken) {
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
}
QRect arrowRect = option->rect.adjusted(border + bsx, border + bsy, -border + bsx, -border + bsy);
GtkShadowType shadow = option->state & State_Sunken ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
@@ -970,7 +978,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
GtkWidget *gtkEntry = QGtk::gtkWidget(QLS("GtkEntry"));
if (panel->lineWidth > 0)
- drawPrimitive(PE_FrameLineEdit, option, painter, widget);
+ proxy()->drawPrimitive(PE_FrameLineEdit, option, painter, widget);
uint resolve_mask = option->palette.resolve();
QRect textRect = option->rect.adjusted(gtkEntry->style->xthickness, gtkEntry->style->ythickness,
-gtkEntry->style->xthickness, -gtkEntry->style->ythickness);
@@ -1241,8 +1249,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
painter->save();
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
- QRect textRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
- QRect checkBoxRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget);
+ QRect textRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
+ QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget);
// Draw title
if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
@@ -1257,7 +1265,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (!groupBox->text.isEmpty()) {
int alignment = int(groupBox->textAlignment);
- if (!styleHint(QStyle::SH_UnderlineShortcut, option, widget))
+ if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, option, widget))
alignment |= Qt::TextHideMnemonic;
QColor textColor = groupBox->textColor; // Note: custom textColor is currently ignored
int labelState = GTK_STATE_INSENSITIVE;
@@ -1282,7 +1290,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
QStyleOptionButton box;
box.QStyleOption::operator=(*groupBox);
box.rect = checkBoxRect;
- drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
}
}
@@ -1305,7 +1313,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
bool focus = isEnabled && (comboBox->state & State_HasFocus);
QColor buttonShadow = option->palette.dark().color();
GtkStateType state = gtkPainter.gtkState(option);
- int appears_as_list = !styleHint(QStyle::SH_ComboBox_Popup, comboBox, widget);
+ int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, comboBox, widget);
QPixmap cache;
QString pixmapName;
QStyleOptionComboBox comboBoxCopy = *comboBox;
@@ -1313,9 +1321,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
bool reverse = (option->direction == Qt::RightToLeft);
QRect rect = option->rect;
- QRect arrowButtonRect = subControlRect(CC_ComboBox, &comboBoxCopy,
+ QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
SC_ComboBoxArrow, widget);
- QRect editRect = subControlRect(CC_ComboBox, &comboBoxCopy,
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
SC_ComboBoxEditField, widget);
GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ?
@@ -1423,7 +1431,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
QGtk::gtk_widget_style_get(gtkToggleButton, "interior-focus", &interiorFocus, NULL);
int xt = interiorFocus ? gtkToggleButton->style->xthickness : 0;
int yt = interiorFocus ? gtkToggleButton->style->ythickness : 0;
- if ((focus && (option->state & State_KeyboardFocusChange)))
+ if (focus && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget)))
gtkCachedPainter.paintFocus(gtkToggleButton, "button",
option->rect.adjusted(xt, yt, -xt, -yt),
option->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL,
@@ -1494,8 +1502,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
QRect button, menuarea;
- button = subControlRect(control, toolbutton, SC_ToolButton, widget);
- menuarea = subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(control, toolbutton, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
State bflags = toolbutton->state & ~(State_Sunken | State_MouseOver);
if (bflags & State_AutoRaise)
@@ -1524,7 +1532,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (bflags & (State_Sunken | State_On | State_Raised | State_MouseOver)) {
tool.rect = button;
tool.state = bflags;
- drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
}
}
@@ -1535,9 +1543,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (toolbutton->state & State_HasFocus) {
QStyleOptionFocusRect fr;
fr.QStyleOption::operator=(*toolbutton);
- fr.rect = subControlRect(CC_ToolButton, toolbutton, SC_ToolButton, widget);
+ fr.rect = proxy()->subControlRect(CC_ToolButton, toolbutton, SC_ToolButton, widget);
fr.rect.adjust(1, 1, -1, -1);
- drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
}
QStyleOptionToolButton label = *toolbutton;
@@ -1553,21 +1561,21 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
}
label.rect = button.adjusted(style->xthickness, style->ythickness,
-style->xthickness - popupArrowSize, -style->ythickness);
- drawControl(CE_ToolButtonLabel, &label, painter, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, painter, widget);
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;
tool.state = mflags;
if ((mflags & State_Enabled && (mflags & (State_Sunken | State_Raised | State_MouseOver))) || !(mflags & State_AutoRaise))
- drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget);
- drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
} else if (drawMenuArrow) {
QRect ir = toolbutton->rect;
QStyleOptionToolButton newBtn = *toolbutton;
newBtn.rect = QRect(ir.right() - popupArrowSize - style->xthickness - 3, ir.height()/2 - 1, popupArrowSize, popupArrowSize);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
}
}
break;
@@ -1584,10 +1592,10 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
painter->fillRect(option->rect, option->palette.background());
QRect rect = scrollBar->rect;
- QRect scrollBarSubLine = subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
- QRect scrollBarAddLine = subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
- QRect scrollBarSlider = subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
- QRect grooveRect = subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
+ QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
+ QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
+ QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
+ QRect grooveRect = proxy()->subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
bool horizontal = scrollBar->orientation == Qt::Horizontal;
GtkWidget * scrollbarWidget = horizontal ? gtkHScrollBar : gtkVScrollBar;
style = scrollbarWidget->style;
@@ -1731,7 +1739,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
bool reverse = (spinBox->direction == Qt::RightToLeft);
//### Move this to subControlRect
- QRect upRect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
+ QRect upRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
upRect.setTop(option->rect.top());
if (reverse)
@@ -1739,8 +1747,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
else
upRect.setRight(option->rect.right());
- QRect editRect = subControlRect(CC_SpinBox, option, SC_SpinBoxEditField, widget);
- QRect downRect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
+ QRect editRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxEditField, widget);
+ QRect downRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
downRect.setBottom(option->rect.bottom());
if (reverse)
@@ -1772,8 +1780,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
QString key;
+
if (option->state & State_HasFocus) {
- key = QLS("f");
+ key += QLatin1Char('f');
GTK_WIDGET_SET_FLAGS(gtkSpinButton, GTK_HAS_FOCUS);
}
@@ -1871,9 +1880,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
GtkWidget *hScaleWidget = QGtk::gtkWidget(QLS("GtkHScale"));
GtkWidget *vScaleWidget = QGtk::gtkWidget(QLS("GtkVScale"));
- QRect groove = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
- QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
+ QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
+ QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
@@ -1928,8 +1937,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (option->subControls & SC_SliderTickmarks) {
painter->setPen(darkOutline);
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
@@ -1946,7 +1955,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
interval = 1;
int v = slider->minimum;
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
while (v <= slider->maximum + 1) {
if (v == slider->maximum + 1 && interval == 1)
break;
@@ -2007,7 +2016,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
fropt.rect.setLeft(handle.left() - 3);
fropt.rect.setRight(handle.right() + 3);
}
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
gtkPainter.paintSlider( scaleWidget, horizontal ? "hscale" : "vscale", handle, state, shadow, style,
@@ -2066,8 +2075,8 @@ void QGtkStyle::drawControl(ControlElement element,
}
if (vertical)
rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
- const int progressIndicatorPos = static_cast<int>((bar->progress - qint64(bar->minimum)) /
- qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * rect.width());
+ const int progressIndicatorPos = (bar->progress - qreal(bar->minimum)) * rect.width() /
+ qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum);
if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width())
leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height());
if (vertical)
@@ -2097,9 +2106,9 @@ void QGtkStyle::drawControl(ControlElement element,
if (option->state & State_Sunken)
buttonShift = QPoint(pixelMetric(PM_ButtonShiftHorizontal, option, widget),
- pixelMetric(PM_ButtonShiftVertical, option, widget));
+ proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
- if (styleHint(SH_UnderlineShortcut, button, widget))
+ if (proxy()->styleHint(SH_UnderlineShortcut, button, widget))
tf |= Qt::TextShowMnemonic;
else
tf |= Qt::TextHideMnemonic;
@@ -2160,7 +2169,7 @@ void QGtkStyle::drawControl(ControlElement element,
GdkColor gdkText = gtkButton->style->fg[labelState];
QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
pal.setBrush(QPalette::ButtonText, textColor);
- drawItemText(painter, ir, tf, pal, (button->state & State_Enabled),
+ proxy()->drawItemText(painter, ir, tf, pal, (button->state & State_Enabled),
button->text, QPalette::ButtonText);
}
break;
@@ -2181,7 +2190,7 @@ void QGtkStyle::drawControl(ControlElement element,
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
: SE_CheckBoxIndicator, btn, widget);
- drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
+ proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
&subopt, painter, widget);
subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
: SE_CheckBoxContents, btn, widget);
@@ -2195,14 +2204,14 @@ void QGtkStyle::drawControl(ControlElement element,
QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
pal.setBrush(QPalette::WindowText, textColor);
subopt.palette = pal;
- drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget);
+ proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget);
if (btn->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
: SE_CheckBoxFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
}
break;
@@ -2211,8 +2220,8 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_ComboBoxLabel:
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
- bool appearsAsList = !styleHint(QStyle::SH_ComboBox_Popup, cb, widget);
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
+ bool appearsAsList = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, cb, widget);
painter->save();
painter->setClipRect(editRect);
@@ -2230,7 +2239,7 @@ void QGtkStyle::drawControl(ControlElement element,
if (cb->editable)
painter->fillRect(iconRect, option->palette.brush(QPalette::Base));
- drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
if (cb->direction == Qt::RightToLeft)
editRect.translate(-4 - cb->iconSize.width(), 0);
@@ -2252,7 +2261,7 @@ void QGtkStyle::drawControl(ControlElement element,
pal.setBrush(QPalette::ButtonText, textColor);
- drawItemText(painter, editRect.adjusted(1, 0, -1, 0),
+ proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0),
visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter),
pal, cb->state & State_Enabled, cb->currentText, QPalette::ButtonText);
}
@@ -2298,7 +2307,7 @@ void QGtkStyle::drawControl(ControlElement element,
QString titleText
= painter->fontMetrics().elidedText(dwOpt->title,
Qt::ElideRight, titleRect.width());
- drawItemText(painter,
+ proxy()->drawItemText(painter,
titleRect,
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, titleText,
@@ -2419,10 +2428,10 @@ void QGtkStyle::drawControl(ControlElement element,
QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText;
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!QCleanlooksStyle::styleHint(SH_UnderlineShortcut, mbi, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
- drawItemText(painter, item.rect, alignment, item.palette, mbi->state & State_Enabled, mbi->text, textRole);
+ proxy()->drawItemText(painter, item.rect, alignment, item.palette, mbi->state & State_Enabled, mbi->text, textRole);
}
}
painter->restore();
@@ -2594,7 +2603,7 @@ void QGtkStyle::drawControl(ControlElement element,
mode = QIcon::Active;
QPixmap pixmap;
- int smallIconSize = pixelMetric(PM_SmallIconSize, option, widget);
+ int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
QSize iconSize(smallIconSize, smallIconSize);
#ifndef QT_NO_COMBOBOX
@@ -2622,7 +2631,7 @@ void QGtkStyle::drawControl(ControlElement element,
}
opt.state |= State_Sunken;
opt.rect = vCheckRect;
- drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
}
painter->drawPixmap(pmr.topLeft(), pixmap);
}
@@ -2662,7 +2671,7 @@ void QGtkStyle::drawControl(ControlElement element,
int t = s.indexOf(QLatin1Char('\t'));
int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
text_flags |= Qt::TextHideMnemonic;
// Draw shortcut right aligned
@@ -2695,7 +2704,7 @@ void QGtkStyle::drawControl(ControlElement element,
// Arrow
if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
QPoint buttonShift(pixelMetric(PM_ButtonShiftHorizontal, option, widget),
- pixelMetric(PM_ButtonShiftVertical, option, widget));
+ proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
QFontMetrics fm(menuitem->font);
int arrow_size = fm.ascent() + fm.descent() - 2 * gtkMenuItem->style->ythickness;
@@ -2723,7 +2732,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton"));
- drawControl(CE_PushButtonBevel, btn, painter, widget);
+ proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget);
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
gint interiorFocus = true;
@@ -2733,14 +2742,14 @@ void QGtkStyle::drawControl(ControlElement element,
if (btn->features & QStyleOptionButton::Flat && btn->state & State_HasFocus)
// The normal button focus rect does not work well for flat buttons in Clearlooks
- drawPrimitive(PE_FrameFocusRect, option, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, option, painter, widget);
else if (btn->state & State_HasFocus)
gtkPainter.paintFocus(gtkButton, "button",
option->rect.adjusted(xt, yt, -xt, -yt),
btn->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL,
gtkButton->style);
- drawControl(CE_PushButtonLabel, &subopt, painter, widget);
+ proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget);
}
break;
@@ -2847,8 +2856,7 @@ void QGtkStyle::drawControl(ControlElement element,
if (vertical) {
rect.translate(xt, -yt * 2);
rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // Flip width and height
- QTransform m;
- m.translate(rect.height(), 0);
+ QTransform m = QTransform::fromTranslate(rect.height(), 0);
m.rotate(90.0);
painter->setTransform(m);
}
@@ -2958,8 +2966,8 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple
font.setBold(true);
QFontMetrics fontMetrics(font);
QSize textRect = fontMetrics.boundingRect(groupBoxWidget->title()).size() + QSize(4, 4);
- int indicatorWidth = pixelMetric(PM_IndicatorWidth, option, widget);
- int indicatorHeight = pixelMetric(PM_IndicatorHeight, option, widget);
+ int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
+ int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget);
if (subControl == SC_GroupBoxCheckBox) {
rect.setWidth(indicatorWidth);
@@ -3040,7 +3048,7 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple
QGtk::gtk_widget_set_direction(gtkCombo, (option->direction == Qt::RightToLeft) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
GtkAllocation geometry = {0, 0, qMax(0, option->rect.width()), qMax(0, option->rect.height())};
QGtk::gtk_widget_size_allocate(gtkCombo, &geometry);
- int appears_as_list = !styleHint(QStyle::SH_ComboBox_Popup, option, widget);
+ int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, option, widget);
QString arrowPath = comboBoxPath + QLS(".GtkToggleButton");
if (!box->editable && !appears_as_list)
@@ -3204,7 +3212,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
case CT_ComboBox:
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
GtkWidget *gtkCombo = QGtk::gtkWidget(QLS("GtkComboBox"));
- QRect arrowButtonRect = subControlRect(CC_ComboBox, combo, SC_ComboBoxArrow, widget);
+ QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, combo, SC_ComboBoxArrow, widget);
newSize = size + QSize(12 + arrowButtonRect.width() + 2*gtkCombo->style->xthickness, 4 + 2*gtkCombo->style->ythickness);
if (!(widget && qobject_cast<QToolBar *>(widget->parentWidget())))
@@ -3231,6 +3239,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
return newSize;
}
+
/*! \reimp */
QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option,
const QWidget *widget) const
@@ -3263,65 +3272,80 @@ QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option,
}
break;
- case SP_DialogDiscardButton: {
+ case SP_DialogDiscardButton:
return QGtkPainter::getIcon(GTK_STOCK_DELETE);
- }
-
- case SP_DialogOkButton: {
+ case SP_DialogOkButton:
return QGtkPainter::getIcon(GTK_STOCK_OK);
- }
-
- case SP_DialogCancelButton: {
+ case SP_DialogCancelButton:
return QGtkPainter::getIcon(GTK_STOCK_CANCEL);
- }
-
- case SP_DialogYesButton: {
+ case SP_DialogYesButton:
return QGtkPainter::getIcon(GTK_STOCK_YES);
- }
-
- case SP_DialogNoButton: {
+ case SP_DialogNoButton:
return QGtkPainter::getIcon(GTK_STOCK_NO);
- }
-
- case SP_DialogOpenButton: {
+ case SP_DialogOpenButton:
return QGtkPainter::getIcon(GTK_STOCK_OPEN);
- }
-
- case SP_DialogCloseButton: {
+ case SP_DialogCloseButton:
return QGtkPainter::getIcon(GTK_STOCK_CLOSE);
- }
-
- case SP_DialogApplyButton: {
+ case SP_DialogApplyButton:
return QGtkPainter::getIcon(GTK_STOCK_APPLY);
- }
-
- case SP_DialogSaveButton: {
+ case SP_DialogSaveButton:
return QGtkPainter::getIcon(GTK_STOCK_SAVE);
- }
-
- case SP_MessageBoxWarning: {
+ case SP_MessageBoxWarning:
return QGtkPainter::getIcon(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
- }
-
- case SP_MessageBoxQuestion: {
+ case SP_MessageBoxQuestion:
return QGtkPainter::getIcon(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
- }
-
- case SP_MessageBoxInformation: {
+ case SP_MessageBoxInformation:
return QGtkPainter::getIcon(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
- }
-
- case SP_MessageBoxCritical: {
+ case SP_MessageBoxCritical:
return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
- }
-
default:
return QCleanlooksStyle::standardPixmap(sp, option, widget);
}
+ return pixmap;
+}
- return QPixmap();
+/*!
+ \internal
+*/
+QIcon QGtkStyle::standardIconImplementation(StandardPixmap standardIcon,
+ const QStyleOption *option,
+ const QWidget *widget) const
+{
+ if (!QGtk::isThemeAvailable())
+ return QCleanlooksStyle::standardIconImplementation(standardIcon, option, widget);
+ switch (standardIcon) {
+ case SP_DialogDiscardButton:
+ return QGtkPainter::getIcon(GTK_STOCK_DELETE);
+ case SP_DialogOkButton:
+ return QGtkPainter::getIcon(GTK_STOCK_OK);
+ case SP_DialogCancelButton:
+ return QGtkPainter::getIcon(GTK_STOCK_CANCEL);
+ case SP_DialogYesButton:
+ return QGtkPainter::getIcon(GTK_STOCK_YES);
+ case SP_DialogNoButton:
+ return QGtkPainter::getIcon(GTK_STOCK_NO);
+ case SP_DialogOpenButton:
+ return QGtkPainter::getIcon(GTK_STOCK_OPEN);
+ case SP_DialogCloseButton:
+ return QGtkPainter::getIcon(GTK_STOCK_CLOSE);
+ case SP_DialogApplyButton:
+ return QGtkPainter::getIcon(GTK_STOCK_APPLY);
+ case SP_DialogSaveButton:
+ return QGtkPainter::getIcon(GTK_STOCK_SAVE);
+ case SP_MessageBoxWarning:
+ return QGtkPainter::getIcon(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
+ case SP_MessageBoxQuestion:
+ return QGtkPainter::getIcon(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
+ case SP_MessageBoxInformation:
+ return QGtkPainter::getIcon(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
+ case SP_MessageBoxCritical:
+ return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
+ default:
+ return QCleanlooksStyle::standardIconImplementation(standardIcon, option, widget);
+ }
}
+
/*! \reimp */
QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
{
diff --git a/src/gui/styles/qgtkstyle.h b/src/gui/styles/qgtkstyle.h
index 61c2ed7..cd81e3b 100644
--- a/src/gui/styles/qgtkstyle.h
+++ b/src/gui/styles/qgtkstyle.h
@@ -106,6 +106,10 @@ public:
void unpolish(QWidget *widget);
void unpolish(QApplication *app);
+
+protected Q_SLOTS:
+ QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option,
+ const QWidget *widget = 0) const;
};
diff --git a/src/gui/styles/qmacstyle.qdoc b/src/gui/styles/qmacstyle.qdoc
new file mode 100644
index 0000000..943f7c8
--- /dev/null
+++ b/src/gui/styles/qmacstyle.qdoc
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+/*!
+ \class QMacStyle
+ \brief The QMacStyle class provides a Mac OS X style using the Apple Appearance Manager.
+
+ \ingroup appearance
+
+ This class is implemented as a wrapper to the HITheme
+ APIs, allowing applications to be styled according to the current
+ theme in use on Mac OS X. This is done by having primitives
+ in QStyle implemented in terms of what Mac OS X would normally theme.
+
+ \warning This style is only available on Mac OS X because it relies on the
+ HITheme APIs.
+
+ There are additional issues that should be taken
+ into consideration to make an application compatible with the
+ \link http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/index.html
+ Apple Human Interface Guidelines \endlink. Some of these issues are outlined
+ below.
+
+ \list
+
+ \i Layout - The restrictions on window layout are such that some
+ aspects of layout that are style-dependent cannot be achieved
+ using QLayout. Changes are being considered (and feedback would be
+ appreciated) to make layouts QStyle-able. Some of the restrictions
+ involve horizontal and vertical widget alignment and widget size
+ (covered below).
+
+ \i Widget size - Mac OS X allows widgets to have specific fixed sizes. Qt
+ does not fully implement this behavior so as to maintain cross-platform
+ compatibility. As a result some widgets sizes may be inappropriate (and
+ subsequently not rendered correctly by the HITheme APIs).The
+ QWidget::sizeHint() will return the appropriate size for many
+ managed widgets (widgets enumerated in \l QStyle::ContentsType).
+
+ \i Effects - QMacStyle uses HITheme for performing most of the drawing, but
+ also uses emulation in a few cases where HITheme does not provide the
+ required functionality (for example, tab bars on Panther, the toolbar
+ separator, etc). We tried to make the emulation as close to the original as
+ possible. Please report any issues you see in effects or non-standard
+ widgets.
+
+ \endlist
+
+ There are other issues that need to be considered in the feel of
+ your application (including the general color scheme to match the
+ Aqua colors). The Guidelines mentioned above will remain current
+ with new advances and design suggestions for Mac OS X.
+
+ Note that the functions provided by QMacStyle are
+ reimplementations of QStyle functions; see QStyle for their
+ documentation.
+
+ \img qmacstyle.png
+ \sa QWindowsXPStyle, QWindowsStyle, QPlastiqueStyle, QCDEStyle, QMotifStyle
+*/
+
+
+/*!
+ \enum QMacStyle::WidgetSizePolicy
+
+ \value SizeSmall
+ \value SizeLarge
+ \value SizeMini
+ \value SizeDefault
+ \omitvalue SizeNone
+*/
+
+/*! \fn QMacStyle::QMacStyle()
+ Constructs a QMacStyle object.
+*/
+
+/*! \fn QMacStyle::~QMacStyle()
+ Destructs a QMacStyle object.
+*/
+
+/*! \fn void QMacStyle::polish(QPalette &pal)
+ \reimp
+*/
+
+/*! \fn void QMacStyle::polish(QApplication *)
+ \reimp
+*/
+
+/*! \fn void QMacStyle::unpolish(QApplication *)
+ \reimp
+*/
+
+/*! \fn void QMacStyle::polish(QWidget* w)
+ \reimp
+*/
+
+/*! \fn void QMacStyle::unpolish(QWidget* w)
+ \reimp
+*/
+
+/*! \fn int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const
+ \reimp
+*/
+
+/*! \fn QPalette QMacStyle::standardPalette() const
+ \reimp
+*/
+
+/*! \fn int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, QStyleHintReturn *hret) const
+ \reimp
+*/
+
+/*! \fn QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
+ \reimp
+*/
+
+/*! \fn QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
+ \reimp
+*/
+
+/*!
+ \enum QMacStyle::FocusRectPolicy
+
+ This type is used to signify a widget's focus rectangle policy.
+
+ \value FocusEnabled show a focus rectangle when the widget has focus.
+ \value FocusDisabled never show a focus rectangle for the widget.
+ \value FocusDefault show a focus rectangle when the widget has
+ focus and the widget is a QSpinWidget, QDateTimeEdit, QLineEdit,
+ QListBox, QListView, editable QTextEdit, or one of their
+ subclasses.
+*/
+
+/*! \fn void QMacStyle::setFocusRectPolicy(QWidget *w, FocusRectPolicy policy)
+ \obsolete
+ Sets the focus rectangle policy of \a w. The \a policy can be one of
+ \l{QMacStyle::FocusRectPolicy}.
+
+ This is now simply an interface to the Qt::WA_MacShowFocusRect attribute and the
+ FocusDefault value does nothing anymore. If you want to set a widget back
+ to its default value, you must save the old value of the attribute before
+ you change it.
+
+ \sa focusRectPolicy() QWidget::setAttribute()
+*/
+
+/*! \fn QMacStyle::FocusRectPolicy QMacStyle::focusRectPolicy(const QWidget *w)
+ \obsolete
+ Returns the focus rectangle policy for the widget \a w.
+
+ The focus rectangle policy can be one of \l{QMacStyle::FocusRectPolicy}.
+
+ In 4.3 and up this function will simply test for the
+ Qt::WA_MacShowFocusRect attribute and will never return
+ QMacStyle::FocusDefault.
+
+ \sa setFocusRectPolicy(), QWidget::testAttribute()
+*/
+
+/*! \fn void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy)
+
+ \obsolete
+
+ Call QWidget::setAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize,
+ or Qt::WA_MacNormalSize instead.
+*/
+
+/*! \fn QMacStyle::WidgetSizePolicy QMacStyle::widgetSizePolicy(const QWidget *widget)
+ \obsolete
+
+ Call QWidget::testAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize,
+ or Qt::WA_MacNormalSize instead.
+*/
+
+/*! \fn void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const
+
+ \reimp
+*/
+
+/*! \fn void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, const QWidget *w) const
+
+ \reimp
+*/
+
+/*! \fn QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *widget) const
+
+ \reimp
+*/
+
+/*! \fn void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const
+ \reimp
+*/
+
+/*! \fn QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, const QPoint &pt, const QWidget *widget) const
+ \reimp
+*/
+
+/*! \fn QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const
+ \reimp
+*/
+
+/*! \fn QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &csz, const QWidget *widget) const
+ \reimp
+*/
+
+/*! \fn void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole) const
+ \reimp
+*/
+
+/*! \fn bool QMacStyle::event(QEvent *e)
+ \reimp
+*/
+
+/*! \fn QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt, const QWidget *widget) const
+ \internal
+*/
+
+/*! \fn int QMacStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget) const
+
+ \internal
+*/
+
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm
index 194c244..ef1818d 100644
--- a/src/gui/styles/qmacstyle_mac.mm
+++ b/src/gui/styles/qmacstyle_mac.mm
@@ -50,11 +50,13 @@
#define QMAC_QAQUASTYLE_SIZE_CONSTRAIN
//#define DEBUG_SIZE_CONSTRAINT
+#include <private/qapplication_p.h>
#include <private/qcombobox_p.h>
#include <private/qmacstylepixmaps_mac_p.h>
#include <private/qpaintengine_mac_p.h>
#include <private/qpainter_p.h>
#include <private/qprintengine_mac_p.h>
+#include <private/qstylehelper_p.h>
#include <qapplication.h>
#include <qbitmap.h>
#include <qcheckbox.h>
@@ -102,7 +104,6 @@
QT_BEGIN_NAMESPACE
extern QRegion qt_mac_convert_mac_region(RgnHandle); //qregion_mac.cpp
-extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp
// The following constants are used for adjusting the size
// of push buttons so that they are drawn inside their bounds.
@@ -130,6 +131,20 @@ static const QColor titlebarSeparatorLineInactive(131, 131, 131);
static const QColor mainWindowGradientBegin(240, 240, 240);
static const QColor mainWindowGradientEnd(200, 200, 200);
+#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
+enum {
+ kThemePushButtonTextured = 31,
+ kThemePushButtonTexturedSmall = 32,
+ kThemePushButtonTexturedMini = 33
+};
+
+/* Search fields */
+enum {
+ kHIThemeFrameTextFieldRound = 1000,
+ kHIThemeFrameTextFieldRoundSmall = 1001,
+ kHIThemeFrameTextFieldRoundMini = 1002
+};
+#endif
// Resolve these at run-time, since the functions was moved in Leopard.
typedef HIRect * (*PtrHIShapeGetBounds)(HIShapeRef, HIRect *);
@@ -488,11 +503,9 @@ public:
inline int animateSpeed(Animates) const { return 33; }
// Utility functions
- void drawColorlessButton(const QRect &macRect, HIThemeButtonDrawInfo *bdi,
+ void drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi,
QPainter *p, const QStyleOption *opt) const;
- void drawPantherTab(const QStyleOptionTab *tab, QPainter *p, const QWidget *w = 0) const;
-
QSize pushButtonSizeFromContents(const QStyleOptionButton *btn) const;
HIRect pushButtonContentBounds(const QStyleOptionButton *btn,
@@ -505,7 +518,7 @@ public:
static QRect comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi);
- static void drawCombobox(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p);
+ static void drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p);
static void drawTableHeader(const HIRect &outerBounds, bool drawTopBorder, bool drawLeftBorder,
const HIThemeButtonDrawInfo &bdi, QPainter *p);
bool contentFitsInPushButton(const QStyleOptionButton *btn, HIThemeButtonDrawInfo *bdi,
@@ -545,7 +558,6 @@ QT_END_INCLUDE_NAMESPACE
External functions
*****************************************************************************/
extern CGContextRef qt_mac_cg_context(const QPaintDevice *); //qpaintdevice_mac.cpp
-extern QPixmap qt_mac_convert_iconref(const IconRef, int, int); //qpixmap_mac.cpp
extern QRegion qt_mac_convert_mac_region(HIShapeRef); //qregion_mac.cpp
void qt_mac_dispose_rgn(RgnHandle r); //qregion_mac.cpp
extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp
@@ -566,11 +578,7 @@ QPixmap *qt_mac_backgroundPattern = 0; // stores the standard widget background.
*****************************************************************************/
static inline int qt_mac_hitheme_tab_version()
{
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- return 1;
-#endif
- return 0;
+ return 1;
}
static inline HIRect qt_hirectForQRect(const QRect &convertRect, const QRect &rect = QRect())
@@ -836,7 +844,7 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
}
break;
case QStyle::CT_HeaderSection:
- if (sz == QAquaSizeLarge && isTreeView(widg))
+ if (isTreeView(widg))
ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricListHeaderHeight));
break;
case QStyle::CT_MenuBar:
@@ -1020,13 +1028,6 @@ HIRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn,
HIRect contentBounds;
HIThemeGetButtonContentBounds(&outerBounds, bdi, &contentBounds);
-
- // Return the button rect if the rect returned by HIThemeGetButtonContentBounds
- // is invalid. This avoids passing around bad rects to code that does not expect it.
- if (contentBounds.size.height == 0 && contentBounds.size.width == 0) {
- return qt_hirectForQRect(btn->rect);
- }
-
return contentBounds;
}
@@ -1043,7 +1044,7 @@ QSize QMacStylePrivate::pushButtonSizeFromContents(const QStyleOptionButton *btn
: btn->fontMetrics.boundingRect(QRect(), Qt::AlignCenter, btn->text);
csz.setWidth(iconSize.width() + textRect.width()
+ ((btn->features & QStyleOptionButton::HasMenu)
- ? q->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0));
+ ? q->proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0));
csz.setHeight(qMax(iconSize.height(), textRect.height()));
return csz;
}
@@ -1287,12 +1288,11 @@ QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThe
create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop
it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly.
*/
-void QMacStylePrivate::drawCombobox(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p)
+void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p)
{
- if (!(bdi.kind == kThemeComboBox && outerBounds.height() > 28)){
+ if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){
// We have an unscaled combobox, or popup-button; use Carbon directly.
- const HIRect hiOuterBounds = qt_hirectForQRect(outerBounds);
- HIRect innerBounds = QMacStylePrivate::comboboxInnerBounds(hiOuterBounds, bdi.kind);
+ HIRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, bdi.kind);
HIThemeDrawButton(&innerBounds, &bdi, QMacCGContext(p), kHIThemeOrientationNormal, 0);
} else {
QPixmap buffer;
@@ -1307,50 +1307,31 @@ void QMacStylePrivate::drawCombobox(const QRect &outerBounds, const HIThemeButto
QPixmapCache::insert(key, buffer);
}
- const int widgetX = outerBounds.x();
- const int widgetY = outerBounds.y();
- const int widgetWidth = outerBounds.width();
- const int widgetHeight = outerBounds.height();
-
- const int buttonWidth = 20;
- const int frameWidth = 10;
- const int frameHeight = 10; // frame height
- const int bstart = widgetWidth - buttonWidth;
- const int flower = widgetHeight - frameHeight;
+ const int bwidth = 20;
+ const int fwidth = 10;
+ const int fheight = 10;
+ int w = qRound(outerBounds.size.width);
+ int h = qRound(outerBounds.size.height);
+ int bstart = w - bwidth;
+ int blower = fheight + 1;
+ int flower = h - fheight;
+ int sheight = flower - fheight;
+ int center = qRound(outerBounds.size.height + outerBounds.origin.y) / 2;
// Draw upper and lower gap
- p->drawPixmap(widgetX + frameWidth, widgetY, bstart - frameWidth, frameHeight,
- buffer, frameWidth, 0, 1, frameHeight); // upper
- p->drawPixmap(widgetX + frameWidth, widgetY + flower, bstart - frameWidth, frameHeight,
- buffer, frameWidth, buffer.height() - frameHeight, 1, frameHeight); // lower
-
- const int center = widgetY + widgetHeight / 2;
- const int sheight = flower - frameHeight;
-
+ p->drawPixmap(fwidth, 0, bstart - fwidth, fheight, buffer, fwidth, 0, 1, fheight);
+ p->drawPixmap(fwidth, flower, bstart - fwidth, fheight, buffer, fwidth, buffer.height() - fheight, 1, fheight);
// Draw left and right gap. Right gap is drawn top and bottom separatly
- p->drawPixmap(widgetX, widgetY + frameHeight, frameWidth, sheight,
- buffer, 0, frameHeight, frameWidth, 1); // right
- p->drawPixmap(widgetX + bstart, widgetY + frameHeight, buttonWidth, widgetHeight / 2 - frameHeight,
- buffer, buffer.width() - buttonWidth, frameHeight - 1, buttonWidth, 1); // top left
- p->drawPixmap(widgetX + bstart, center, buttonWidth, sheight / 2,
- buffer, buffer.width() - buttonWidth, frameHeight + 6, buttonWidth, 1); // bottom left
-
+ p->drawPixmap(0, fheight, fwidth, sheight, buffer, 0, fheight, fwidth, 1);
+ p->drawPixmap(bstart, fheight, bwidth, center - fheight, buffer, buffer.width() - bwidth, fheight - 1, bwidth, 1);
+ p->drawPixmap(bstart, center, bwidth, sheight / 2, buffer, buffer.width() - bwidth, fheight + 6, bwidth, 1);
// Draw arrow
- p->drawPixmap(widgetX + bstart, center - 4, buttonWidth - 3, 6,
- buffer, buffer.width() - buttonWidth, frameHeight, buttonWidth - 3, 6);
-
+ p->drawPixmap(bstart, center - 4, bwidth - 3, 6, buffer, buffer.width() - bwidth, fheight, bwidth - 3, 6);
// Draw corners
- p->drawPixmap(widgetX, widgetY, frameWidth, frameHeight,
- buffer, 0, 0, frameWidth, frameHeight); // top left
- p->drawPixmap(widgetX + bstart, widgetY, buttonWidth, frameHeight,
- buffer, buffer.width() - buttonWidth, 0, buttonWidth, frameHeight); // top right
- p->drawPixmap(widgetX, widgetY + flower, frameWidth, frameHeight,
- buffer, 0, buffer.height() - frameHeight, frameWidth, frameHeight); // bottom left
-
- const int blower = frameHeight + 1;
- p->drawPixmap(widgetX + bstart, widgetY + widgetHeight - blower, buttonWidth, blower,
- buffer,
- buffer.width() - buttonWidth, buffer.height() - blower, buttonWidth, blower); // bottom right
+ p->drawPixmap(0, 0, fwidth, fheight, buffer, 0, 0, fwidth, fheight);
+ p->drawPixmap(bstart, 0, bwidth, fheight, buffer, buffer.width() - bwidth, 0, bwidth, fheight);
+ p->drawPixmap(0, flower, fwidth, fheight, buffer, 0, buffer.height() - fheight, fwidth, fheight);
+ p->drawPixmap(bstart, h - blower, bwidth, blower, buffer, buffer.width() - bwidth, buffer.height() - blower, bwidth, blower);
}
}
@@ -1483,8 +1464,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti
}
// Tiger broke reverse scroll bars so put them back and "fake it"
- if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)
- && QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
+ if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)) {
tdi->attributes &= ~kThemeTrackRightToLeft;
tdi->value = tdi->max - slider->sliderPosition;
}
@@ -1567,166 +1547,6 @@ void QMacStylePrivate::startAnimationTimer()
timerID = startTimer(animateSpeed(AquaListViewItemOpen));
}
-enum { TabNormalLeft, TabNormalMid, TabNormalRight, TabSelectedActiveLeft,
- TabSelectedActiveMid, TabSelectedActiveRight, TabSelectedInactiveLeft,
- TabSelectedInactiveMid, TabSelectedInactiveRight, TabSelectedActiveGraphiteLeft,
- TabSelectedActiveGraphiteMid, TabSelectedActiveGraphiteRight,
- TabPressedLeft, TabPressedMid, TabPressedRight };
-
-static const char * const * const PantherTabXpms[] = {
- qt_mac_tabnrm_left,
- qt_mac_tabnrm_mid,
- qt_mac_tabnrm_right,
- qt_mac_tabselected_active_left,
- qt_mac_tabselected_active_mid,
- qt_mac_tabselected_active_right,
- qt_mac_tabselected_inactive_left,
- qt_mac_tabselected_inactive_mid,
- qt_mac_tabselected_inactive_right,
- qt_mac_tab_selected_active_graph_left,
- qt_mac_tab_selected_active_graph_mid,
- qt_mac_tab_selected_active_graph_right,
- qt_mac_tab_press_left,
- qt_mac_tab_press_mid,
- qt_mac_tab_press_right};
-
-void QMacStylePrivate::drawPantherTab(const QStyleOptionTab *tabOpt, QPainter *p,
- const QWidget *) const
-{
- QString tabKey = QLatin1String("$qt_mac_style_tab_");
- int pantherTabStart;
- int pantherTabMid;
- int pantherTabEnd;
-
- ThemeTabDirection ttd = getTabDirection(tabOpt->shape);
-
- if (tabOpt->state & QStyle::State_Selected) {
- if (!(tabOpt->state & QStyle::State_Active)) {
- pantherTabStart = TabSelectedInactiveLeft;
- } else {
- // Draw into a pixmap to determine which version we use, Aqua or Graphite.
- QPixmap tabPix(20, 20);
- QPainter pixPainter(&tabPix);
- HIThemeTabDrawInfo tdi;
- tdi.version = 0;
- tdi.style = kThemeTabFront;
- tdi.direction = kThemeTabNorth;
- tdi.size = kHIThemeTabSizeNormal;
- tdi.adornment = kHIThemeTabAdornmentNone;
- HIRect inRect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f);
- HIThemeDrawTab(&inRect, &tdi, QMacCGContext(&pixPainter), kHIThemeOrientationNormal, 0);
- pixPainter.end();
- const QRgb GraphiteColor = 0xffa7b0ba;
- QRgb pmColor = tabPix.toImage().pixel(10, 10);
- if (qAbs(qRed(pmColor) - qRed(GraphiteColor)) < 3 &&
- qAbs(qGreen(pmColor) - qGreen(GraphiteColor)) < 3
- && qAbs(qBlue(pmColor) - qBlue(GraphiteColor)) < 3)
- pantherTabStart = TabSelectedActiveGraphiteLeft;
- else
- pantherTabStart = TabSelectedActiveLeft;
- }
- } else if (tabOpt->state & QStyle::State_Sunken) {
- pantherTabStart = TabPressedLeft;
- } else {
- pantherTabStart = TabNormalLeft;
- }
-
-
- bool doLine;
- bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;
-
- QStyleOptionTab::TabPosition tp = tabOpt->position;
- if (ttd == kThemeTabWest
- || ((ttd == kThemeTabNorth || ttd == kThemeTabSouth)
- && tabOpt->direction == Qt::RightToLeft)) {
- if (tp == QStyleOptionTab::Beginning)
- tp = QStyleOptionTab::End;
- else if (tp == QStyleOptionTab::End)
- tp = QStyleOptionTab::Beginning;
- }
-
- switch (tp) {
- default: // Stupid GCC, being overly pedantic
- case QStyleOptionTab::Beginning:
- doLine = false;
- pantherTabMid = pantherTabEnd = pantherTabStart + 1;
- break;
- case QStyleOptionTab::Middle:
- doLine = true;
- pantherTabMid = pantherTabEnd = ++pantherTabStart;
- break;
- case QStyleOptionTab::End:
- doLine = true;
- pantherTabMid = ++pantherTabStart;
- pantherTabEnd = pantherTabMid + 1;
- break;
- case QStyleOptionTab::OnlyOneTab:
- doLine = false;
- pantherTabMid = pantherTabStart + 1;
- pantherTabEnd = pantherTabMid + 1;
- break;
- }
-
- QPixmap pmStart;
- if (!QPixmapCache::find(tabKey + QString::number(pantherTabStart), pmStart)) {
- pmStart = QPixmap(PantherTabXpms[pantherTabStart]);
- QPixmapCache::insert(tabKey + QString::number(pantherTabStart), pmStart);
- }
-
- QPixmap pmMid;
- if (!QPixmapCache::find(tabKey + QString::number(pantherTabMid), pmMid)) {
- pmMid = QPixmap(PantherTabXpms[pantherTabMid]);
- QPixmapCache::insert(tabKey + QString::number(pantherTabMid), pmMid);
- }
-
- QPixmap pmEnd;
- if (!QPixmapCache::find(tabKey + QString::number(pantherTabEnd), pmEnd)) {
- pmEnd = QPixmap(PantherTabXpms[pantherTabEnd]);
- QPixmapCache::insert(tabKey + QString::number(pantherTabEnd), pmEnd);
- }
- QRect tr = tabOpt->rect;
- if (verticalTabs) {
- p->save();
- int newX, newY, newRot;
- if (tabOpt->shape == QTabBar::RoundedEast || tabOpt->shape == QTabBar::TriangularEast) {
- newX = tr.width();
- newY = tr.y();
- newRot = 90;
- } else {
- newX = 0;
- newY = tr.y() + tr.height();
- newRot = -90;
- }
- tr.setRect(0, 0, tr.height(), tr.width());
- QMatrix m;
- if (ttd == kThemeTabEast) {
- // It's lame but Apple inverts these on the East side.
- m.scale(-1, 1);
- m.translate(-tabOpt->rect.width(), 0);
- }
- m.translate(newX, newY);
- m.rotate(newRot);
- p->setMatrix(m, true);
- }
-
- int x = tr.x();
- int y = tr.y();
- int endX = x + tr.width() - pmEnd.width();
-
- p->drawPixmap(x, y, pmStart.width(), tr.height(), pmStart);
- if (doLine) {
- QPen oldPen = p->pen();
- p->setPen(QColor(0, 0, 0, 0x35));
- p->drawLine(x, y + (verticalTabs ? 0 : 1), x, tr.height() - 2);
- }
-
- for (x = x + pmStart.width(); x < endX; x += pmMid.width())
- p->drawPixmap(x, y, pmMid.width(), tr.height(), pmMid);
- p->drawPixmap(endX, y, pmEnd.width(), tr.height(), pmEnd);
- if (verticalTabs)
- p->restore();
-}
-
bool QMacStylePrivate::addWidget(QWidget *w)
{
//already knew of it
@@ -1915,7 +1735,7 @@ bool QMacStylePrivate::doAnimate(QMacStylePrivate::Animates as)
return true;
}
-void QMacStylePrivate::drawColorlessButton(const QRect &outerBounds, HIThemeButtonDrawInfo *bdi,
+void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi,
QPainter *p, const QStyleOption *opt) const
{
int xoff = 0,
@@ -1925,8 +1745,8 @@ void QMacStylePrivate::drawColorlessButton(const QRect &outerBounds, HIThemeButt
finalyoff = 0;
const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt);
- const int width = outerBounds.width() + extraWidth;
- const int height = outerBounds.height() + extraHeight;
+ int width = int(macRect.size.width) + extraWidth;
+ int height = int(macRect.size.height) + extraHeight;
if (width <= 0 || height <= 0)
return; // nothing to draw
@@ -1943,11 +1763,11 @@ void QMacStylePrivate::drawColorlessButton(const QRect &outerBounds, HIThemeButt
// Carbon combos don't scale. Therefore we draw it
// ourselves, if a scaled version is needed.
QPainter tmpPainter(&activePixmap);
- QMacStylePrivate::drawCombobox(outerBounds, *bdi, &tmpPainter);
+ QMacStylePrivate::drawCombobox(macRect, *bdi, &tmpPainter);
}
else {
QMacCGContext cg(&activePixmap);
- HIRect newRect = CGRectMake(xoff, yoff, outerBounds.width(), outerBounds.height());
+ HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0);
}
}
@@ -1987,7 +1807,7 @@ void QMacStylePrivate::drawColorlessButton(const QRect &outerBounds, HIThemeButt
colorlessPixmap.fill(Qt::transparent);
QMacCGContext cg(&colorlessPixmap);
- HIRect newRect = CGRectMake(xoff, yoff, outerBounds.width(), outerBounds.height());
+ HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
int oldValue = bdi->value;
bdi->value = kThemeButtonOff;
HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0);
@@ -2017,7 +1837,7 @@ void QMacStylePrivate::drawColorlessButton(const QRect &outerBounds, HIThemeButt
}
QPixmapCache::insert(key, pm);
}
- p->drawPixmap(outerBounds.x(), outerBounds.y() + finalyoff, width, height, pm);
+ p->drawPixmap(int(macRect.origin.x), int(macRect.origin.y) + finalyoff, width, height, pm);
}
QMacStyle::QMacStyle()
@@ -2039,22 +1859,10 @@ QMacStyle::~QMacStyle()
QPixmap QMacStylePrivate::generateBackgroundPattern() const
{
QPixmap px(4, 4);
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- QMacCGContext cg(&px);
- HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal);
- const CGRect cgRect = CGRectMake(0, 0, px.width(), px.height());
- CGContextFillRect(cg, cgRect);
- } else
-#endif
- {
-#ifndef QT_MAC_NO_QUICKDRAW
- QMacSavedPortInfo port(&px);
- SetThemeBackground(kThemeBrushDialogBackgroundActive, px.depth(), true);
- const Rect qdRect = { 0, 0, px.width(), px.height() };
- EraseRect(&qdRect);
-#endif
- }
+ QMacCGContext cg(&px);
+ HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal);
+ const CGRect cgRect = CGRectMake(0, 0, px.width(), px.height());
+ CGContextFillRect(cg, cgRect);
return px;
}
@@ -2062,25 +1870,23 @@ QPixmap QMacStylePrivate::generateBackgroundPattern() const
Fills the given \a rect with the pattern stored in \a brush. As an optimization,
HIThemeSetFill us used directly if we are filling with the standard background.
*/
-void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QPoint &offset, const QBrush &brush)
+void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush)
{
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
QPoint dummy;
const QPaintDevice *target = painter->device();
const QPaintDevice *redirected = QPainter::redirected(target, &dummy);
const bool usePainter = redirected && redirected != target;
- const QRegion translated = rgn.translated(offset);
- if (!usePainter && QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 && qt_mac_backgroundPattern
+ if (!usePainter && qt_mac_backgroundPattern
&& qt_mac_backgroundPattern->cacheKey() == brush.texture().cacheKey()) {
- painter->setClipRegion(translated);
+ painter->setClipRegion(rgn);
CGContextRef cg = qt_mac_cg_context(target);
CGContextSaveGState(cg);
HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationInverted);
- const QVector<QRect> &rects = translated.rects();
+ const QVector<QRect> &rects = rgn.rects();
for (int i = 0; i < rects.size(); ++i) {
const QRect rect(rects.at(i));
// Anchor the pattern to the top so it stays put when the window is resized.
@@ -2090,11 +1896,9 @@ void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QPoint
}
CGContextRestoreGState(cg);
- } else
-#endif
- {
- const QRect rect(translated.boundingRect());
- painter->setClipRegion(translated);
+ } else {
+ const QRect rect(rgn.boundingRect());
+ painter->setClipRegion(rgn);
painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
}
}
@@ -2162,18 +1966,6 @@ void QMacStyle::polish(QWidget* w)
}
}
- // Adjust the lineedit of the editable combo box
- if (QSysInfo::MacintoshVersion == QSysInfo::MV_10_3) {
- if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(w)) {
- if (qobject_cast<QComboBox *>(lineEdit->parentWidget())
- && !lineEdit->testAttribute(Qt::WA_SetFont)) {
- QFont font = lineEdit->font();
- font.setPointSize(font.pointSize() - 1);
- lineEdit->setFont(font);
- }
- }
- }
-
if (QTabBar *tb = qobject_cast<QTabBar*>(w)) {
if (tb->documentMode()) {
w->setAttribute(Qt::WA_Hover);
@@ -2234,7 +2026,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
ret = closeButtonSize;
break;
case PM_ToolBarIconSize:
- ret = pixelMetric(PM_LargeIconSize);
+ ret = proxy()->pixelMetric(PM_LargeIconSize);
break;
case PM_FocusFrameVMargin:
case PM_FocusFrameHMargin:
@@ -2408,12 +2200,6 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
GetThemeMetric(kThemeMetricScrollBarWidth, &ret);
break;
case QAquaSizeMini:
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3) && 0
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3) {
- GetThemeMetric(kThemeMetricMiniScrollBarWidth, &ret);
- break;
- }
-#endif
case QAquaSizeSmall:
GetThemeMetric(kThemeMetricSmallScrollBarWidth, &ret);
break;
@@ -2516,9 +2302,6 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
case PM_ToolBarItemSpacing:
ret = 4;
break;
- case PM_MessageBoxIconSize:
- ret = 64;
- break;
case PM_SplitterWidth:
ret = qMax(7, QApplication::globalStrut().width());
break;
@@ -2594,6 +2377,9 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
case PM_MenuHMargin:
ret = 0;
break;
+ case PM_ToolBarFrameWidth:
+ ret = 0;
+ break;
default:
ret = QWindowsStyle::pixelMetric(metric, opt, widget);
break;
@@ -2755,7 +2541,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
QPixmap pix(pixmapSize);
pix.fill(QColor(fillR, fillG, fillB));
QPainter pix_paint(&pix);
- drawControl(CE_FocusFrame, opt, &pix_paint, w);
+ proxy()->drawControl(CE_FocusFrame, opt, &pix_paint, w);
pix_paint.end();
img = pix.toImage();
}
@@ -3070,7 +2856,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
twf.rect = twf.rect.adjusted(0, -10, 0, 0);
break;
}
- drawPrimitive(PE_FrameTabWidget, &twf, p, w);
+ proxy()->drawPrimitive(PE_FrameTabWidget, &twf, p, w);
p->restore();
}
break;
@@ -3168,7 +2954,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
// In HITheme, up is down, down is up and hamburgers eat people.
if (header->sortIndicator != QStyleOptionHeader::None)
- drawPrimitive(
+ proxy()->drawPrimitive(
(header->sortIndicator == QStyleOptionHeader::SortDown) ?
PE_IndicatorArrowUp : PE_IndicatorArrowDown, header, p, w);
}
@@ -3241,13 +3027,15 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
bdi.value = kThemeButtonOn;
else
bdi.value = kThemeButtonOff;
-
- if (!drawColorless) {
- const HIRect macRect = qt_hirectForQRect(opt->rect);
+ HIRect macRect;
+ if (pe == PE_Q3CheckListExclusiveIndicator || pe == PE_Q3CheckListIndicator)
+ macRect = qt_hirectForQRect(opt->rect);
+ else
+ macRect = qt_hirectForQRect(opt->rect);
+ if (!drawColorless)
HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0);
- } else {
- d->drawColorlessButton(opt->rect, &bdi, p, opt);
- }
+ else
+ d->drawColorlessButton(macRect, &bdi, p, opt);
break; }
case PE_FrameFocusRect:
// Use the our own focus widget stuff.
@@ -3300,7 +3088,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
fdi.isFocused = (frame->state & State_HasFocus);
int lw = frame->lineWidth;
if (lw <= 0)
- lw = pixelMetric(PM_DefaultFrameWidth, frame, w);
+ lw = proxy()->pixelMetric(PM_DefaultFrameWidth, frame, w);
{ //clear to base color
p->save();
p->setPen(QPen(baseColor, lw));
@@ -3325,27 +3113,14 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
if (const QStyleOptionTabWidgetFrame *twf
= qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
HIRect hirect = qt_hirectForQRect(twf->rect);
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- HIThemeTabPaneDrawInfo tpdi;
- tpdi.version = qt_mac_hitheme_tab_version();
- tpdi.state = tds;
- tpdi.direction = getTabDirection(twf->shape);
- tpdi.size = kHIThemeTabSizeNormal;
- if (tpdi.version == 1) {
- tpdi.kind = kHIThemeTabKindNormal;
- tpdi.adornment = kHIThemeTabPaneAdornmentNormal;
- }
- HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal);
- } else
-#endif
- {
- HIThemeGroupBoxDrawInfo gdi;
- gdi.version = qt_mac_hitheme_version;
- gdi.state = tds;
- gdi.kind = kHIThemeGroupBoxKindSecondary;
- HIThemeDrawGroupBox(&hirect, &gdi, cg, kHIThemeOrientationNormal);
- }
+ HIThemeTabPaneDrawInfo tpdi;
+ tpdi.version = qt_mac_hitheme_tab_version();
+ tpdi.state = tds;
+ tpdi.direction = getTabDirection(twf->shape);
+ tpdi.size = kHIThemeTabSizeNormal;
+ tpdi.kind = kHIThemeTabKindNormal;
+ tpdi.adornment = kHIThemeTabPaneAdornmentNormal;
+ HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal);
}
break;
case PE_PanelScrollAreaCorner: {
@@ -3369,7 +3144,6 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
QWindowsStyle::drawPrimitive(pe, opt, p, w);
break;
}
-
// Use the Leopard style only if the status bar is the status bar for a
// QMainWindow with a unifed toolbar.
if (w == 0 || w->parent() == 0 || qobject_cast<QMainWindow *>(w->parent()) == 0 ||
@@ -3513,16 +3287,16 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QIcon::Mode mode = QIcon::Disabled;
if (opt->state & State_Enabled)
mode = QIcon::Normal;
- QPixmap pixmap = header->icon.pixmap(pixelMetric(PM_SmallIconSize), mode);
+ QPixmap pixmap = header->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), mode);
QRect pixr = header->rect;
pixr.setY(header->rect.center().y() - (pixmap.height() - 1) / 2);
- drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap);
+ proxy()->drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap);
textr.translate(pixmap.width() + 2, 0);
}
- drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette,
- header->state & State_Enabled, header->text, QPalette::ButtonText);
+ proxy()->drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette,
+ header->state & State_Enabled, header->text, QPalette::ButtonText);
}
break;
case CE_ToolButtonLabel:
@@ -3533,58 +3307,89 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QRect cr = tb->rect;
int shiftX = 0;
int shiftY = 0;
- if (tb->state & (State_Sunken | State_On)) {
- shiftX = pixelMetric(PM_ButtonShiftHorizontal, tb, w);
- shiftY = pixelMetric(PM_ButtonShiftVertical, tb, w);
+ bool needText = false;
+ int alignment = 0;
+ bool down = tb->state & (State_Sunken | State_On);
+ if (down) {
+ shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, w);
+ shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, tb, w);
}
// The down state is special for QToolButtons in a toolbar on the Mac
// The text is a bit bolder and gets a drop shadow and the icons are also darkened.
// This doesn't really fit into any particular case in QIcon, so we
// do the majority of the work ourselves.
- if (tb->state & State_Sunken
- && !(tb->features & QStyleOptionToolButton::Arrow)) {
+ if (!(tb->features & QStyleOptionToolButton::Arrow)) {
Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle;
if (tb->icon.isNull() && !tb->text.isEmpty())
tbstyle = Qt::ToolButtonTextOnly;
switch (tbstyle) {
- case Qt::ToolButtonTextOnly:
- drawItemText(p, cr, Qt::AlignCenter, tb->palette,
- tb->state & State_Enabled, tb->text);
- break;
+ case Qt::ToolButtonTextOnly: {
+ needText = true;
+ alignment = Qt::AlignCenter;
+ break; }
case Qt::ToolButtonIconOnly:
case Qt::ToolButtonTextBesideIcon:
case Qt::ToolButtonTextUnderIcon: {
QRect pr = cr;
QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal
- : QIcon::Disabled;
+ : QIcon::Disabled;
QIcon::State iconState = (tb->state & State_On) ? QIcon::On
- : QIcon::Off;
+ : QIcon::Off;
QPixmap pixmap = tb->icon.pixmap(tb->rect.size().boundedTo(tb->iconSize), iconMode, iconState);
// Draw the text if it's needed.
if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) {
- int alignment = 0;
+ needText = true;
if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
- pr.setHeight(pixmap.size().height() + 6);
- cr.adjust(0, pr.bottom(), 0, -3);
+ pr.setHeight(pixmap.size().height());
+ cr.adjust(0, pr.bottom() + 1, 0, 1);
alignment |= Qt::AlignCenter;
} else {
pr.setWidth(pixmap.width() + 8);
cr.adjust(pr.right(), 0, 0, 0);
alignment |= Qt::AlignLeft | Qt::AlignVCenter;
}
- cr.translate(shiftX, shiftY);
- drawItemText(p, cr, alignment, tb->palette,
- tb->state & State_Enabled, tb->text);
- cr.adjust(0, 3, 0, -3); // the drop shadow
- drawItemText(p, cr, alignment, tb->palette,
- tb->state & State_Enabled, tb->text);
}
- pr.translate(shiftX, shiftY);
- pixmap = darkenPixmap(pixmap);
- drawItemPixmap(p, pr, Qt::AlignCenter, pixmap);
+ if (opt->state & State_Sunken) {
+ pr.translate(shiftX, shiftY);
+ pixmap = darkenPixmap(pixmap);
+ }
+ proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap);
break; }
+ default:
+ Q_ASSERT(false);
+ break;
+ }
+
+ if (needText) {
+ QPalette pal = tb->palette;
+ QPalette::ColorRole role = QPalette::NoRole;
+ if (down)
+ cr.translate(shiftX, shiftY);
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5
+ && (tbstyle == Qt::ToolButtonTextOnly
+ || (tbstyle != Qt::ToolButtonTextOnly && !down))) {
+ QPen pen = p->pen();
+ QColor light = down ? Qt::black : Qt::white;
+ light.setAlphaF(0.375f);
+ p->setPen(light);
+ p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text);
+ p->setPen(pen);
+ if (down && tbstyle == Qt::ToolButtonTextOnly) {
+ pal = QApplication::palette("QMenu");
+ pal.setCurrentColorGroup(tb->palette.currentColorGroup());
+ role = QPalette::HighlightedText;
+ }
+ }
+ drawItemText(p, cr, alignment, pal,
+ tb->state & State_Enabled, tb->text, role);
+ if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 &&
+ (tb->state & State_Sunken)) {
+ // Draw a "drop shadow" in earlier versions.
+ drawItemText(p, cr.adjusted(0, 1, 0, 1), alignment,
+ tb->palette, tb->state & State_Enabled, tb->text);
+ }
}
} else {
QWindowsStyle::drawControl(ce, &myTb, p, w);
@@ -3634,7 +3439,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0);
if (btn->features & QStyleOptionButton::HasMenu) {
- int mbi = pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
+ int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
QRect ir = btn->rect;
HIRect arrowRect = CGRectMake(ir.right() - mbi - PushButtonRightOffset,
ir.height() / 2 - 4, mbi, ir.height() / 2);
@@ -3721,7 +3526,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (hasIcon) {
int contentW = textRect.width();
if (hasMenu)
- contentW += pixelMetric(PM_MenuButtonIndicator) + 4;
+ contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4;
QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
if (mode == QIcon::Normal && btn->state & State_HasFocus)
mode = QIcon::Active;
@@ -3735,7 +3540,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmap.height()) / 2;
QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmap.width(), pixmap.height());
QRect visualIconDestRect = visualRect(btn->direction, freeContentRect, iconDestRect);
- drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap);
+ proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap);
int newOffset = iconDestRect.x() + iconDestRect.width()
+ PushButtonContentPadding - textRect.x();
textRect.adjust(newOffset, 0, newOffset, 0);
@@ -3743,8 +3548,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// Draw the text:
if (hasText) {
textRect = visualRect(btn->direction, freeContentRect, textRect);
- drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn->palette,
- (btn->state & State_Enabled), btn->text, QPalette::ButtonText);
+ proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn->palette,
+ (btn->state & State_Enabled), btn->text, QPalette::ButtonText);
}
}
}
@@ -3769,104 +3574,104 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
return;
}
}
-
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_3) {
- HIThemeTabDrawInfo tdi;
- tdi.version = 1;
- tdi.style = kThemeTabNonFront;
- tdi.direction = getTabDirection(tabOpt->shape);
- switch (d->aquaSizeConstrain(opt, w)) {
- default:
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- tdi.size = kHIThemeTabSizeNormal;
- break;
- case QAquaSizeSmall:
- tdi.size = kHIThemeTabSizeSmall;
+ HIThemeTabDrawInfo tdi;
+ tdi.version = 1;
+ tdi.style = kThemeTabNonFront;
+ tdi.direction = getTabDirection(tabOpt->shape);
+ switch (d->aquaSizeConstrain(opt, w)) {
+ default:
+ case QAquaSizeUnknown:
+ case QAquaSizeLarge:
+ tdi.size = kHIThemeTabSizeNormal;
+ break;
+ case QAquaSizeSmall:
+ tdi.size = kHIThemeTabSizeSmall;
+ break;
+ case QAquaSizeMini:
+ tdi.size = kHIThemeTabSizeMini;
+ break;
+ }
+ bool verticalTabs = tdi.direction == kThemeTabWest || tdi.direction == kThemeTabEast;
+ QRect tabRect = tabOpt->rect;
+
+ bool selected = tabOpt->state & State_Selected;
+ if (selected) {
+ if (!(tabOpt->state & State_Active))
+ tdi.style = kThemeTabFrontUnavailable;
+ else if (!(tabOpt->state & State_Enabled))
+ tdi.style = kThemeTabFrontInactive;
+ else
+ tdi.style = kThemeTabFront;
+ } else if (!(tabOpt->state & State_Active)) {
+ tdi.style = kThemeTabNonFrontUnavailable;
+ } else if (!(tabOpt->state & State_Enabled)) {
+ tdi.style = kThemeTabNonFrontInactive;
+ } else if (tabOpt->state & State_Sunken) {
+ tdi.style = kThemeTabFrontInactive; // (should be kThemeTabNonFrontPressed)
+ }
+ if (tabOpt->state & State_HasFocus)
+ tdi.adornment = kHIThemeTabAdornmentFocus;
+ else
+ tdi.adornment = kHIThemeTabAdornmentNone;
+ tdi.kind = kHIThemeTabKindNormal;
+ if (!verticalTabs)
+ tabRect.setY(tabRect.y() - 1);
+ else
+ tabRect.setX(tabRect.x() - 1);
+ QStyleOptionTab::TabPosition tp = tabOpt->position;
+ QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition;
+ if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) {
+ if (sp == QStyleOptionTab::NextIsSelected)
+ sp = QStyleOptionTab::PreviousIsSelected;
+ else if (sp == QStyleOptionTab::PreviousIsSelected)
+ sp = QStyleOptionTab::NextIsSelected;
+ switch (tp) {
+ case QStyleOptionTab::Beginning:
+ tp = QStyleOptionTab::End;
break;
- case QAquaSizeMini:
- tdi.size = kHIThemeTabSizeMini;
+ case QStyleOptionTab::End:
+ tp = QStyleOptionTab::Beginning;
break;
- }
- bool verticalTabs = tdi.direction == kThemeTabWest || tdi.direction == kThemeTabEast;
- QRect tabRect = tabOpt->rect;
-
- if ((!verticalTabs && tabRect.height() > 21 || verticalTabs && tabRect.width() > 21)) {
- d->drawPantherTab(tabOpt, p, w);
+ default:
break;
}
+ }
+ switch (tp) {
+ case QStyleOptionTab::Beginning:
+ tdi.position = kHIThemeTabPositionFirst;
+ if (sp != QStyleOptionTab::NextIsSelected)
+ tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
+ break;
+ case QStyleOptionTab::Middle:
+ tdi.position = kHIThemeTabPositionMiddle;
+ if (selected)
+ tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;
+ if (sp != QStyleOptionTab::NextIsSelected) // Also when we're selected.
+ tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
+ break;
+ case QStyleOptionTab::End:
+ tdi.position = kHIThemeTabPositionLast;
+ if (selected)
+ tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;
+ break;
+ case QStyleOptionTab::OnlyOneTab:
+ tdi.position = kHIThemeTabPositionOnly;
+ break;
+ }
- bool selected = tabOpt->state & State_Selected;
- if (selected) {
- if (!(tabOpt->state & State_Active))
- tdi.style = kThemeTabFrontUnavailable;
- else if (!(tabOpt->state & State_Enabled))
- tdi.style = kThemeTabFrontInactive;
- else
- tdi.style = kThemeTabFront;
- } else if (!(tabOpt->state & State_Active)) {
- tdi.style = kThemeTabNonFrontUnavailable;
- } else if (!(tabOpt->state & State_Enabled)) {
- tdi.style = kThemeTabNonFrontInactive;
- } else if (tabOpt->state & State_Sunken) {
- tdi.style = kThemeTabFrontInactive; // (should be kThemeTabNonFrontPressed)
- }
- if (tabOpt->state & State_HasFocus)
- tdi.adornment = kHIThemeTabAdornmentFocus;
- else
- tdi.adornment = kHIThemeTabAdornmentNone;
- tdi.kind = kHIThemeTabKindNormal;
- if (!verticalTabs)
- tabRect.setY(tabRect.y() - 1);
- else
- tabRect.setX(tabRect.x() - 1);
- QStyleOptionTab::TabPosition tp = tabOpt->position;
- QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition;
- if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) {
- if (sp == QStyleOptionTab::NextIsSelected)
- sp = QStyleOptionTab::PreviousIsSelected;
- else if (sp == QStyleOptionTab::PreviousIsSelected)
- sp = QStyleOptionTab::NextIsSelected;
- switch (tp) {
- case QStyleOptionTab::Beginning:
- tp = QStyleOptionTab::End;
- break;
- case QStyleOptionTab::End:
- tp = QStyleOptionTab::Beginning;
- break;
- default:
- break;
- }
- }
- switch (tp) {
- case QStyleOptionTab::Beginning:
- tdi.position = kHIThemeTabPositionFirst;
- if (sp != QStyleOptionTab::NextIsSelected)
- tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
- break;
- case QStyleOptionTab::Middle:
- tdi.position = kHIThemeTabPositionMiddle;
- if (selected)
- tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;
- if (sp != QStyleOptionTab::NextIsSelected) // Also when we're selected.
- tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
- break;
- case QStyleOptionTab::End:
- tdi.position = kHIThemeTabPositionLast;
- if (selected)
- tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;
- break;
- case QStyleOptionTab::OnlyOneTab:
- tdi.position = kHIThemeTabPositionOnly;
- break;
+ // HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves.
+ if ((!verticalTabs && tabRect.height() > 21 || verticalTabs && tabRect.width() > 21)) {
+ HIRect hirect = CGRectMake(0, 0, 23, 23);
+ QPixmap pm(23, 23);
+ pm.fill(Qt::transparent);
+ {
+ QMacCGContext pmcg(&pm);
+ HIThemeDrawTab(&hirect, &tdi, pmcg, kHIThemeOrientationNormal, 0);
}
+ QStyleHelper::drawBorderPixmap(pm, p, tabRect, 7, 7, 7, 7);
+ } else {
HIRect hirect = qt_hirectForQRect(tabRect);
HIThemeDrawTab(&hirect, &tdi, cg, kHIThemeOrientationNormal, 0);
- } else
-#endif
- {
- d->drawPantherTab(tabOpt, p, w);
}
}
break;
@@ -3901,7 +3706,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QRect nr = subElementRect(SE_TabBarTabText, opt, w);
nr.moveTop(+1);
int alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextHideMnemonic;
- drawItemText(p, nr, alignment, np, tab->state & State_Enabled, tab->text, QPalette::WindowText);
+ proxy()->drawItemText(p, nr, alignment, np, tab->state & State_Enabled,
+ tab->text, QPalette::WindowText);
p->restore();
}
@@ -4024,8 +3830,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
break;
case CE_FocusFrame: {
- int xOff = pixelMetric(PM_FocusFrameHMargin, opt, w) + 1;
- int yOff = pixelMetric(PM_FocusFrameVMargin, opt, w) + 1;
+ int xOff = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, w) + 1;
+ int yOff = proxy()->pixelMetric(PM_FocusFrameVMargin, opt, w) + 1;
HIRect hirect = CGRectMake(xOff+opt->rect.x(), yOff+opt->rect.y(), opt->rect.width() - 2 * xOff,
opt->rect.height() - 2 * yOff);
HIThemeDrawFocusRect(&hirect, true, QMacCGContext(p), kHIThemeOrientationNormal);
@@ -4148,7 +3954,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal
: QIcon::Disabled;
// Always be normal or disabled to follow the Mac style.
- int smallIconSize = pixelMetric(PM_SmallIconSize);
+ int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize);
QSize iconSize(smallIconSize, smallIconSize);
if (const QComboBox *comboBox = qobject_cast<const QComboBox *>(w)) {
iconSize = comboBox->iconSize();
@@ -4183,8 +3989,12 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const int xm = macItemFrame + maxpmw + macItemHMargin;
QFont myFont = mi->font;
- if (mi->state & QStyle::State_Mini)
- myFont.setPointSize(mi->font.pointSize());
+ // myFont may not have any "hard" flags set. We override
+ // the point size so that when it is resolved against the device, this font will win.
+ // This is mainly to handle cases where someone sets the font on the window
+ // and then the combo inherits it and passes it onward. At that point the resolve mask
+ // is very, very weak. This makes it stonger.
+ myFont.setPointSizeF(mi->font.pointSizeF());
p->setFont(myFont);
p->drawText(xpos, yPos, contentRect.width() - xm - tabwidth + 1,
contentRect.height(), text_flags ^ Qt::AlignRight, s);
@@ -4258,7 +4068,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
drawItemPixmap(p, mi->rect,
Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip
| Qt::TextSingleLine,
- mi->icon.pixmap(pixelMetric(PM_SmallIconSize),
+ mi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize),
(mi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled));
} else {
drawItemText(p, mi->rect,
@@ -4318,7 +4128,19 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
tdi.enableState = kThemeTrackDisabled;
else
tdi.enableState = kThemeTrackActive;
- HIThemeDrawTrack(&tdi, 0, cg, kHIThemeOrientationNormal);
+ HIThemeOrientation drawOrientation = kHIThemeOrientationNormal;
+ if (reverse) {
+ if (vertical) {
+ drawOrientation = kHIThemeOrientationInverted;
+ } else {
+ CGContextSaveGState(cg);
+ CGContextTranslateCTM(cg, pb->rect.width(), 0);
+ CGContextScaleCTM(cg, -1, 1);
+ }
+ }
+ HIThemeDrawTrack(&tdi, 0, cg, drawOrientation);
+ if (reverse && !vertical)
+ CGContextRestoreGState(cg);
}
break;
case CE_ProgressBarLabel:
@@ -4406,9 +4228,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
case CE_ToolBar: {
// For unified tool bars, draw nothing.
if (w) {
- if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window()))
+ if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) {
if (mainWindow->unifiedTitleAndToolBarOnMac())
break;
+ }
}
// draw background gradient
@@ -4777,10 +4600,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
// similar when I have an upside down scroll bar
// because on Tiger I only "fake" the reverse stuff.
bool reverseHorizontal = (slider->direction == Qt::RightToLeft
- && slider->orientation == Qt::Horizontal
- && (!slider->upsideDown
- || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4
- && slider->upsideDown)));
+ && slider->orientation == Qt::Horizontal);
if ((reverseHorizontal
&& slider->activeSubControls == SC_ScrollBarAddLine)
|| (!reverseHorizontal
@@ -4815,12 +4635,12 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
// no longer possible to move it, second the up/down buttons are removed when
// there is not enough space for them.
if (cc == CC_ScrollBar) {
- const int scrollBarLenght = (slider->orientation == Qt::Horizontal)
+ const int scrollBarLength = (slider->orientation == Qt::Horizontal)
? slider->rect.width() : slider->rect.height();
const QMacStyle::WidgetSizePolicy sizePolicy = widgetSizePolicy(widget);
- if (scrollBarLenght < scrollButtonsCutoffSize(thumbIndicatorCutoff, sizePolicy))
+ if (scrollBarLength < scrollButtonsCutoffSize(thumbIndicatorCutoff, sizePolicy))
tdi.attributes &= ~kThemeTrackShowThumb;
- if (scrollBarLenght < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy))
+ if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy))
tdi.enableState = kThemeTrackNothingToScroll;
}
@@ -4882,7 +4702,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
treeOpt.state |= State_Children;
if (item.state & State_Open)
treeOpt.state |= State_Open;
- drawPrimitive(PE_IndicatorBranch, &treeOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorBranch, &treeOpt, p, widget);
}
y += item.totalHeight;
}
@@ -4896,7 +4716,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
SInt32 frame_size;
GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size);
- QRect lineeditRect = subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget);
+ QRect lineeditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget);
lineeditRect.adjust(-frame_size, -frame_size, +frame_size, +frame_size);
HIThemeFrameDrawInfo fdi;
@@ -4940,9 +4760,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
bdi.value = kThemeButtonOff;
bdi.adornment = kThemeAdornmentNone;
- QRect updown = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
+ QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
- updown |= subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
+ updown |= proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
HIRect newRect = qt_hirectForQRect(updown);
QRect off_rct;
HIRect outRect;
@@ -4963,9 +4783,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state));
bool drawColorless = combo->palette.currentColorGroup() == QPalette::Active && tds == kThemeStateInactive;
if (!drawColorless)
- QMacStylePrivate::drawCombobox(combo->rect, bdi, p);
+ QMacStylePrivate::drawCombobox(qt_hirectForQRect(combo->rect), bdi, p);
else
- d->drawColorlessButton(combo->rect, &bdi, p, opt);
+ d->drawColorlessButton(qt_hirectForQRect(combo->rect), &bdi, p, opt);
}
break;
case CC_TitleBar:
@@ -5055,7 +4875,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
&titleRegion2);
ptrHIShapeGetBounds(titleRegion2, &tmpRect);
if (tmpRect.size.width != 1) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
iw = titlebar->icon.actualSize(QSize(iconExtent, iconExtent)).width();
}
}
@@ -5073,7 +4893,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
else
x += br.width() / 2 - p->fontMetrics().width(titlebar->text) / 2;
if (iw)
- p->drawPixmap(x - iw, y, titlebar->icon.pixmap(pixelMetric(PM_SmallIconSize), QIcon::Normal));
+ p->drawPixmap(x - iw, y,
+ titlebar->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), QIcon::Normal));
drawItemText(p, br, Qt::AlignCenter, opt->palette, tds == kThemeStateActive,
titlebar->text, QPalette::Text);
p->restore();
@@ -5110,7 +4931,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
tti.truncationPosition = kHIThemeTextTruncationNone;
tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n'));
QCFString groupText = qt_mac_removeMnemonics(groupBox->text);
- QRect r = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
+ QRect r = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
HIRect bounds = qt_hirectForQRect(r);
HIThemeDrawTextBox(groupText, &bounds, &tti, cg, kHIThemeOrientationNormal);
p->restore();
@@ -5123,29 +4944,35 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) {
if (tb->subControls & SC_ToolButtonMenu) {
QStyleOption arrowOpt(0);
- arrowOpt.rect = subControlRect(cc, tb, SC_ToolButtonMenu, widget);
+ arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2);
arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2);
arrowOpt.state = tb->state;
arrowOpt.palette = tb->palette;
- drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
} else if ((tb->features & QStyleOptionToolButton::HasMenu)
&& (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) {
drawToolbarButtonArrow(tb->rect, tds, cg);
}
if (tb->state & State_On) {
- QPen oldPen = p->pen();
- p->setPen(QColor(0, 0, 0, 0x3a));
- p->fillRect(tb->rect.adjusted(1, 1, -1, -1), QColor(0, 0, 0, 0x12));
- p->drawLine(tb->rect.left() + 1, tb->rect.top(),
- tb->rect.right() - 1, tb->rect.top());
- p->drawLine(tb->rect.left() + 1, tb->rect.bottom(),
- tb->rect.right() - 1, tb->rect.bottom());
- p->drawLine(tb->rect.topLeft(), tb->rect.bottomLeft());
- p->drawLine(tb->rect.topRight(), tb->rect.bottomRight());
- p->setPen(oldPen);
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
+ static QPixmap pm(QLatin1String(":/trolltech/mac/style/images/leopard-unified-toolbar-on.png"));
+ p->setRenderHint(QPainter::SmoothPixmapTransform);
+ QStyleHelper::drawBorderPixmap(pm, p, tb->rect, 2, 2, 2, 2);
+ } else {
+ QPen oldPen = p->pen();
+ p->setPen(QColor(0, 0, 0, 0x3a));
+ p->fillRect(tb->rect.adjusted(1, 1, -1, -1), QColor(0, 0, 0, 0x12));
+ p->drawLine(tb->rect.left() + 1, tb->rect.top(),
+ tb->rect.right() - 1, tb->rect.top());
+ p->drawLine(tb->rect.left() + 1, tb->rect.bottom(),
+ tb->rect.right() - 1, tb->rect.bottom());
+ p->drawLine(tb->rect.topLeft(), tb->rect.bottomLeft());
+ p->drawLine(tb->rect.topRight(), tb->rect.bottomRight());
+ p->setPen(oldPen);
+ }
}
- drawControl(CE_ToolButtonLabel, opt, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget);
} else {
ThemeButtonKind bkind = kThemeBevelButton;
switch (d->aquaSizeConstrain(opt, widget)) {
@@ -5154,20 +4981,14 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
bkind = kThemeBevelButton;
break;
case QAquaSizeMini:
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3) && 0
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3) {
- bkind = kThemeMiniBevelButton;
- break;
- }
-#endif
case QAquaSizeSmall:
bkind = kThemeSmallBevelButton;
break;
}
QRect button, menuarea;
- button = subControlRect(cc, tb, SC_ToolButton, widget);
- menuarea = subControlRect(cc, tb, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(cc, tb, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
State bflags = tb->state,
mflags = tb->state;
if (tb->subControls & SC_ToolButton)
@@ -5230,14 +5051,18 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
} else if (tb->features & QStyleOptionToolButton::HasMenu) {
drawToolbarButtonArrow(tb->rect, tds, cg);
}
- QRect buttonRect = subControlRect(CC_ToolButton, tb, SC_ToolButton, widget);
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
QStyleOptionToolButton label = *tb;
label.rect = buttonRect.adjusted(fw, fw, -fw, -fw);
- drawControl(CE_ToolButtonLabel, &label, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
}
}
break;
+ case CC_Dial:
+ if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt))
+ QStyleHelper::drawDial(dial, p);
+ break;
default:
QWindowsStyle::drawComplexControl(cc, opt, p, widget);
break;
@@ -5253,6 +5078,8 @@ QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc,
case CC_ComboBox:
if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
sc = QWindowsStyle::hitTestComplexControl(cc, cmb, pt, widget);
+ if (!cmb->editable && sc != QStyle::SC_None)
+ sc = SC_ComboBoxArrow; // A bit of a lie, but what we want
}
break;
case CC_Slider:
@@ -5282,9 +5109,9 @@ QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc,
// The arrow buttons are not drawn if the scroll bar is to short,
// exclude them from the hit test.
- const int scrollBarLenght = (sb->orientation == Qt::Horizontal)
+ const int scrollBarLength = (sb->orientation == Qt::Horizontal)
? sb->rect.width() : sb->rect.height();
- if (scrollBarLenght < scrollButtonsCutoffSize(scrollButtonsCutoff, widgetSizePolicy(widget)))
+ if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, widgetSizePolicy(widget)))
sbi.enableState = kThemeTrackNothingToScroll;
sbi.viewsize = sb->pageStep;
@@ -5402,11 +5229,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
cpc = sc == SC_ScrollBarSubLine ? kControlUpButtonPart
: kControlDownButtonPart;
if (slider->direction == Qt::RightToLeft
- && slider->orientation == Qt::Horizontal
- && (!slider->upsideDown
- || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4
- && slider->upsideDown))
- ) {
+ && slider->orientation == Qt::Horizontal) {
if (cpc == kControlDownButtonPart)
cpc = kControlUpButtonPart;
else if (cpc == kControlUpButtonPart)
@@ -5459,7 +5282,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
else if (sc == SC_TitleBarLabel)
wrc = kWindowTitleTextRgn;
else if (sc == SC_TitleBarSysMenu)
- ret.setRect(-1024, -1024, 10, pixelMetric(PM_TitleBarHeight,
+ ret.setRect(-1024, -1024, 10, proxy()->pixelMetric(PM_TitleBarHeight,
titlebar, widget));
if (wrc != kWindowGlobalPortRgn) {
QCFType<HIShapeRef> region;
@@ -5563,7 +5386,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment,
QSize(tw, h), ret);
- int indicatorWidth = pixelMetric(PM_IndicatorWidth, opt, widget);
+ int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget);
bool rtl = groupBox->direction == Qt::RightToLeft;
if (sc == SC_GroupBoxLabel) {
if (checkable) {
@@ -5585,7 +5408,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
if (sc == SC_GroupBoxCheckBox) {
int left = rtl ? labelRect.right() - indicatorWidth : labelRect.left();
ret.setRect(left, ret.top(),
- indicatorWidth, pixelMetric(PM_IndicatorHeight, opt, widget));
+ indicatorWidth, proxy()->pixelMetric(PM_IndicatorHeight, opt, widget));
}
break;
}
@@ -5623,7 +5446,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
QAquaWidgetSize aquaSize = d->aquaSizeConstrain(spin, widget);
int spinner_w;
int spinBoxSep;
- int fw = pixelMetric(PM_SpinBoxFrameWidth, spin, widget);
+ int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget);
switch (aquaSize) {
default:
case QAquaSizeUnknown:
@@ -5700,7 +5523,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
spin->rect.height() - fw * 2);
} else {
ret.setRect(fw, fw,
- spin->rect.width() - spinner_w - fw * 2 - spinBoxSep,
+ spin->rect.width() - fw * 2 - spinBoxSep - spinner_w,
spin->rect.height() - fw * 2);
}
ret = visualRect(spin->direction, spin->rect, ret);
@@ -5737,11 +5560,6 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
break;
case QStyle::CT_TabBarTab:
if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) {
- bool newStyleTabs =
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 ? true :
-#endif
- false;
const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget);
const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont))
|| !QApplication::desktopSettingsAware();
@@ -5749,86 +5567,61 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
bool vertTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;
if (vertTabs)
sz.transpose();
- if (newStyleTabs) {
- int defaultTabHeight;
- int defaultExtraSpace = pixelMetric(PM_TabBarTabHSpace, tab, widget); // Remove spurious gcc warning (AFAIK)
- QFontMetrics fm = opt->fontMetrics;
- switch (AquaSize) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- if (tab->documentMode)
- defaultTabHeight = 23;
- else
- defaultTabHeight = 21;
- break;
- case QAquaSizeSmall:
- defaultTabHeight = 18;
- break;
- case QAquaSizeMini:
- defaultTabHeight = 16;
- break;
- }
-
- bool setWidth = false;
- if (differentFont || !tab->icon.isNull()) {
- sz.rheight() = qMax(defaultTabHeight, sz.height());
- } else {
- QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text);
- sz.rheight() = qMax(defaultTabHeight, textSize.height());
- sz.rwidth() = textSize.width() + defaultExtraSpace;
- setWidth = true;
- }
+ int defaultTabHeight;
+ int defaultExtraSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); // Remove spurious gcc warning (AFAIK)
+ QFontMetrics fm = opt->fontMetrics;
+ switch (AquaSize) {
+ case QAquaSizeUnknown:
+ case QAquaSizeLarge:
+ if (tab->documentMode)
+ defaultTabHeight = 23;
+ else
+ defaultTabHeight = 21;
+ break;
+ case QAquaSizeSmall:
+ defaultTabHeight = 18;
+ break;
+ case QAquaSizeMini:
+ defaultTabHeight = 16;
+ break;
+ }
+ bool setWidth = false;
+ if (differentFont || !tab->icon.isNull()) {
+ sz.rheight() = qMax(defaultTabHeight, sz.height());
+ } else {
+ QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text);
+ sz.rheight() = qMax(defaultTabHeight, textSize.height());
+ sz.rwidth() = textSize.width() + defaultExtraSpace;
+ setWidth = true;
+ }
- if (vertTabs)
- sz.transpose();
+ if (vertTabs)
+ sz.transpose();
- int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height());
- int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width());
+ int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height());
+ int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width());
- int widgetWidth = 0;
- int widgetHeight = 0;
- int padding = 0;
- if (tab->leftButtonSize.isValid()) {
- padding += 8;
- widgetWidth += tab->leftButtonSize.width();
- widgetHeight += tab->leftButtonSize.height();
- }
- if (tab->rightButtonSize.isValid()) {
- padding += 8;
- widgetWidth += tab->rightButtonSize.width();
- widgetHeight += tab->rightButtonSize.height();
- }
+ int widgetWidth = 0;
+ int widgetHeight = 0;
+ int padding = 0;
+ if (tab->leftButtonSize.isValid()) {
+ padding += 8;
+ widgetWidth += tab->leftButtonSize.width();
+ widgetHeight += tab->leftButtonSize.height();
+ }
+ if (tab->rightButtonSize.isValid()) {
+ padding += 8;
+ widgetWidth += tab->rightButtonSize.width();
+ widgetHeight += tab->rightButtonSize.height();
+ }
- if (vertTabs) {
- sz.setHeight(sz.height() + widgetHeight + padding);
- sz.setWidth(qMax(sz.width(), maxWidgetWidth));
- } else {
- if (setWidth)
- sz.setWidth(sz.width() + widgetWidth + padding);
- sz.setHeight(qMax(sz.height(), maxWidgetHeight));
- }
+ if (vertTabs) {
+ sz.setHeight(sz.height() + widgetHeight + padding);
+ sz.setWidth(qMax(sz.width(), maxWidgetWidth));
} else {
- SInt32 tabh = sz.height();
- SInt32 overlap = 0;
- switch (AquaSize) {
- default:
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- GetThemeMetric(kThemeLargeTabHeight, &tabh);
- GetThemeMetric(kThemeMetricTabFrameOverlap, &overlap);
- break;
- case QAquaSizeMini:
- GetThemeMetric(kThemeMetricMiniTabHeight, &tabh);
- GetThemeMetric(kThemeMetricMiniTabFrameOverlap, &overlap);
- break;
- case QAquaSizeSmall:
- GetThemeMetric(kThemeSmallTabHeight, &tabh);
- GetThemeMetric(kThemeMetricSmallTabFrameOverlap, &overlap);
- break;
- }
- tabh += overlap;
- if (sz.height() < tabh)
- sz.rheight() = tabh;
+ if (setWidth)
+ sz.setWidth(sz.width() + widgetWidth + padding);
+ sz.setHeight(qMax(sz.height(), maxWidgetHeight));
}
}
break;
@@ -5858,7 +5651,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
h = qMax(h, iconSize.height() + 4);
maxpmw = qMax(maxpmw, iconSize.width());
} else {
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
}
}
@@ -5887,6 +5680,14 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
}
break;
case CT_ToolButton:
+ if (widget && qobject_cast<const QToolBar *>(widget->parentWidget())) {
+ sz.rwidth() += 4;
+ if (sz.height() <= 32) {
+ // Workaround strange HIToolBar bug when getting constraints.
+ sz.rheight() += 1;
+ }
+ return sz;
+ }
sz.rwidth() += 10;
sz.rheight() += 10;
return sz;
@@ -5897,7 +5698,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
QStyleHintReturnMask menuMask;
QStyleOption myOption = *opt;
myOption.rect.setSize(sz);
- if (styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) {
+ if (proxy()->styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) {
sz = menuMask.region.boundingRect().size();
}
break; }
@@ -6066,78 +5867,12 @@ bool QMacStyle::event(QEvent *e)
return false;
}
-void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayIcon, QIcon *retIcon, QStyle::StandardPixmap standardIcon = QStyle::SP_CustomBase)
-{
- int size = 16;
- while (size <= 128) {
-
- const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size);
- QPixmap mainIcon;
- if (standardIcon >= QStyle::SP_CustomBase) {
- mainIcon = qt_mac_convert_iconref(icon, size, size);
- } else if (QPixmapCache::find(cacheKey, mainIcon) == false) {
- mainIcon = qt_mac_convert_iconref(icon, size, size);
- QPixmapCache::insert(cacheKey, mainIcon);
- }
-
- if (overlayIcon) {
- int littleSize = size / 2;
- QPixmap overlayPix = qt_mac_convert_iconref(overlayIcon, littleSize, littleSize);
- QPainter painter(&mainIcon);
- painter.drawPixmap(size - littleSize, size - littleSize, overlayPix);
- }
-
- retIcon->addPixmap(mainIcon);
- size += size; // 16 -> 32 -> 64 -> 128
- }
-}
-
QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt,
const QWidget *widget) const
{
- OSType iconType = 0;
switch (standardIcon) {
- case QStyle::SP_MessageBoxQuestion:
- case QStyle::SP_MessageBoxInformation:
- case QStyle::SP_MessageBoxWarning:
- case QStyle::SP_MessageBoxCritical:
- iconType = kGenericApplicationIcon;
- break;
- case SP_DesktopIcon:
- iconType = kDesktopIcon;
- break;
- case SP_TrashIcon:
- iconType = kTrashIcon;
- break;
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
- case SP_ComputerIcon:
- iconType = kComputerIcon;
- break;
-#endif
- case SP_DriveFDIcon:
- iconType = kGenericFloppyIcon;
- break;
- case SP_DriveHDIcon:
- iconType = kGenericHardDiskIcon;
- break;
- case SP_DriveCDIcon:
- case SP_DriveDVDIcon:
- iconType = kGenericCDROMIcon;
- break;
- case SP_DriveNetIcon:
- iconType = kGenericNetworkIcon;
- break;
- case SP_DirOpenIcon:
- iconType = kOpenFolderIcon;
- break;
- case SP_DirClosedIcon:
- case SP_DirLinkIcon:
- iconType = kGenericFolderIcon;
- break;
- case SP_FileLinkIcon:
- case SP_FileIcon:
- iconType = kGenericDocumentIcon;
- break;
+ default:
+ return QWindowsStyle::standardIconImplementation(standardIcon, opt, widget);
case SP_ToolBarHorizontalExtensionButton:
case SP_ToolBarVerticalExtensionButton: {
QPixmap pixmap(qt_mac_toolbar_ext);
@@ -6151,58 +5886,8 @@ QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const Q
return pix2;
}
return pixmap;
- }
- break;
- case SP_DirIcon: {
- // A rather special case
- QIcon closeIcon = QStyle::standardIcon(SP_DirClosedIcon, opt, widget);
- QIcon openIcon = QStyle::standardIcon(SP_DirOpenIcon, opt, widget);
- closeIcon.addPixmap(openIcon.pixmap(16, 16), QIcon::Normal, QIcon::On);
- closeIcon.addPixmap(openIcon.pixmap(32, 32), QIcon::Normal, QIcon::On);
- closeIcon.addPixmap(openIcon.pixmap(64, 64), QIcon::Normal, QIcon::On);
- closeIcon.addPixmap(openIcon.pixmap(128, 128), QIcon::Normal, QIcon::On);
- return closeIcon;
- }
- case SP_TitleBarNormalButton:
- case SP_TitleBarCloseButton: {
- QIcon titleBarIcon;
- if (standardIcon == SP_TitleBarCloseButton) {
- titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-16.png"));
- titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/closedock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On);
- } else {
- titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-16.png"));
- titleBarIcon.addFile(QLatin1String(":/trolltech/styles/macstyle/images/dockdock-down-16.png"), QSize(16, 16), QIcon::Normal, QIcon::On);
- }
- return titleBarIcon;
}
- default:
- break;
- }
- if (iconType != 0) {
- QIcon retIcon;
- IconRef icon;
- IconRef overlayIcon = 0;
- if (iconType != kGenericApplicationIcon) {
- GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon);
- } else {
- FSRef fsRef;
- ProcessSerialNumber psn = { 0, kCurrentProcess };
- GetProcessBundleLocation(&psn, &fsRef);
- GetIconRefFromFileInfo(&fsRef, 0, 0, 0, 0, kIconServicesNormalUsageFlag, &icon, 0);
- if (standardIcon == SP_MessageBoxCritical) {
- overlayIcon = icon;
- GetIconRef(kOnSystemDisk, kSystemIconsCreator, kAlertCautionIcon, &icon);
- }
- }
- if (icon) {
- qt_mac_constructQIconFromIconRef(icon, overlayIcon, &retIcon, standardIcon);
- ReleaseIconRef(icon);
- }
- if (overlayIcon)
- ReleaseIconRef(overlayIcon);
- return retIcon;
}
- return QWindowsStyle::standardIconImplementation(standardIcon, opt, widget);
}
int QMacStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1,
diff --git a/src/gui/styles/qmacstylepixmaps_mac_p.h b/src/gui/styles/qmacstylepixmaps_mac_p.h
index 66b7aa4..6399b5e 100644
--- a/src/gui/styles/qmacstylepixmaps_mac_p.h
+++ b/src/gui/styles/qmacstylepixmaps_mac_p.h
@@ -50,1406 +50,6 @@
// We mean it.
//
-static const char *const qt_mac_tabnrm_left[]={
-"6 22 71 2",
-"#a c #5f5f5f",
-"## c #6d6d6d",
-".c c #737373",
-".d c #757575",
-".b c #7c7c7c",
-".n c #7d7d7d",
-".r c #828282",
-".f c #838383",
-"#. c #878787",
-".7 c #8c8c8c",
-".v c #8e8e8e",
-".4 c #939393",
-".1 c #969696",
-".j c #979797",
-".a c #9a9a9a",
-".6 c #9b9b9b",
-".A c #a0a0a0",
-".Z c #a6a6a6",
-".C c #aaaaaa",
-".3 c #aeaeae",
-".E c #afafaf",
-".J c #b3b3b3",
-".8 c #b7b7b7",
-".o c #b8b8b8",
-".g c #b9b9b9",
-".P c #bcbcbc",
-".R c #bfbfbf",
-".T c #c2c2c2",
-".s c #c4c4c4",
-"#e c #c6c6c6",
-".V c #c7c7c7",
-".w c #c9c9c9",
-".B c #cacaca",
-"#d c #cbcbcb",
-".z c #cecece",
-".F c #cfcfcf",
-".5 c #d1d1d1",
-"#c c #d3d3d3",
-".K c #d4d4d4",
-".G c #d5d5d5",
-".Q c #d6d6d6",
-".S c #d8d8d8",
-".U c #dadada",
-".2 c #dbdbdb",
-".L c #dcdcdc",
-".H c #dedede",
-".I c #dfdfdf",
-".M c #e0e0e0",
-".X c #e1e1e1",
-".D c #e2e2e2",
-"#b c #e3e3e3",
-".O c #e4e4e4",
-".N c #e6e6e6",
-".9 c #e7e7e7",
-".e c #e8e8e8",
-".# c #e9e9e9",
-".t c #ebebeb",
-"Qt c #ececec",
-".p c #ededed",
-".x c #eeeeee",
-".y c #efefef",
-".u c #f1f1f1",
-".k c #f2f2f2",
-".q c #f3f3f3",
-".W c #f6f6f6",
-".l c #f7f7f7",
-".m c #f8f8f8",
-".Y c #f9f9f9",
-".h c #fcfcfc",
-".i c #fdfdfd",
-".0 c #ffffff",
-"Qt.#.a.b.c.d",
-".e.f.gQt.h.i",
-".j.a.k.l.m.m",
-".n.o.p.k.q.q",
-".r.s.t.u.u.u",
-".v.w.t.x.y.y",
-".a.z.#.p.x.x",
-".A.B.#.t.x.p",
-".C.B.D.t.x.x",
-".E.F.G.H.I.I",
-".J.K.L.M.N.O",
-".P.Q.D.#.e.#",
-".R.S.O.p.x.p",
-".T.U.#.u.u.k",
-".V.I.t.q.W.W",
-".P.X.k.W.Y.Y",
-".Z.M.u.Y.0.0",
-".1.2.l.0.0.0",
-".3.4.m.0.0.0",
-".5.6.7.8.9.0",
-".X.5.3#.###a",
-".O#b.L#c#d#e"};
-
-static const char *const qt_mac_tabnrm_mid[]={
-"6 22 18 1",
-"n c #585858",
-". c #777777",
-"p c #c2c2c2",
-"o c #c3c3c3",
-"g c #dedede",
-"h c #e5e5e5",
-"i c #e8e8e8",
-"f c #ededed",
-"e c #eeeeee",
-"d c #efefef",
-"c c #f1f1f1",
-"b c #f3f3f3",
-"j c #f6f6f6",
-"a c #f8f8f8",
-"k c #f9f9f9",
-"# c #fdfdfd",
-"l c #fefefe",
-"m c #ffffff",
-"......",
-"######",
-"aaaaaa",
-"bbbbbb",
-"cccccc",
-"dddddd",
-"eeeeee",
-"ffffff",
-"eeeeee",
-"gggggg",
-"hhhhhh",
-"iiiiii",
-"eeeeee",
-"cccccc",
-"jjjjjj",
-"kkkkkk",
-"llllll",
-"mmmmmm",
-"mmmmmm",
-"mmmmmm",
-"nnnnnn",
-"oppooo"};
-
-static const char *const qt_mac_tabnrm_right[]={
-"6 22 70 2",
-".9 c #5f5f5f",
-"#. c #6d6d6d",
-".# c #747474",
-"Qt c #757575",
-".a c #7c7c7c",
-".p c #7d7d7d",
-".t c #828282",
-".h c #838383",
-"## c #888888",
-".6 c #8c8c8c",
-".x c #8e8e8e",
-".3 c #929292",
-".2 c #969696",
-".l c #979797",
-".b c #9a9a9a",
-".7 c #9b9b9b",
-".A c #a0a0a0",
-".0 c #a6a6a6",
-".C c #aaaaaa",
-"#a c #aeaeae",
-".H c #afafaf",
-".N c #b3b3b3",
-".5 c #b7b7b7",
-".o c #b8b8b8",
-".g c #b9b9b9",
-".Q c #bcbcbc",
-".S c #bfbfbf",
-".U c #c2c2c2",
-".s c #c4c4c4",
-"#b c #c6c6c6",
-".W c #c7c7c7",
-".w c #c9c9c9",
-".z c #cacaca",
-".y c #cecece",
-".G c #cfcfcf",
-".8 c #d1d1d1",
-"#c c #d3d3d3",
-".M c #d4d4d4",
-".F c #d5d5d5",
-".P c #d6d6d6",
-".R c #d8d8d8",
-".T c #dadada",
-".1 c #dbdbdb",
-".L c #dcdcdc",
-".E c #dedede",
-".D c #dfdfdf",
-".K c #e0e0e0",
-".Y c #e1e1e1",
-".B c #e2e2e2",
-".I c #e4e4e4",
-"#d c #e5e5e5",
-".J c #e6e6e6",
-".4 c #e7e7e7",
-".O c #e8e8e8",
-".c c #e9e9e9",
-".r c #ebebeb",
-".d c #ececec",
-".n c #ededed",
-".v c #eeeeee",
-".u c #efefef",
-".q c #f1f1f1",
-".k c #f2f2f2",
-".m c #f3f3f3",
-".V c #f6f6f6",
-".j c #f7f7f7",
-".i c #f8f8f8",
-".X c #f9f9f9",
-".f c #fcfcfc",
-".e c #fdfdfd",
-".Z c #ffffff",
-"Qt.#.a.b.c.d",
-".e.f.d.g.h.c",
-".i.i.j.k.b.l",
-".m.m.k.n.o.p",
-".q.q.q.r.s.t",
-".u.u.v.r.w.x",
-".v.v.n.c.y.b",
-".n.v.r.c.z.A",
-".v.v.r.B.z.C",
-".D.D.E.F.G.H",
-".I.J.K.L.M.N",
-".c.O.c.B.P.Q",
-".n.v.n.I.R.S",
-".k.q.q.c.T.U",
-".V.V.m.r.D.W",
-".X.X.V.k.Y.Q",
-".Z.Z.X.q.K.0",
-".Z.Z.Z.j.1.2",
-".Z.Z.Z.i.3.H",
-".Z.4.5.6.7.8",
-".9#.###a.8.B",
-"#b.z#c.L.I#d"};
-
-static const char *const qt_mac_tabselected_active_left[]={
-"6 22 130 2",
-".d c #000069",
-".C c #0042b4",
-".I c #0157bb",
-".w c #0c28a0",
-".l c #101094",
-".O c #1163c4",
-".c c #1a1a6e",
-".U c #1e6ec9",
-".r c #214eb7",
-".x c #256cc9",
-".0 c #2877ce",
-".6 c #347fd1",
-".D c #3981d2",
-"#a c #3a81d2",
-"#g c #418ad7",
-".J c #4288d4",
-".q c #45459b",
-".V c #458cd5",
-".g c #46469f",
-".P c #4a8dd7",
-".1 c #4a90db",
-"#m c #4b91db",
-"#s c #4e91dc",
-"#y c #4f8dcd",
-".7 c #5195df",
-".b c #525280",
-"#E c #5984b2",
-"#b c #5b9be1",
-"#R c #5c7e9f",
-".2 c #5d9de6",
-"#5 c #5f5f5f",
-"#Y c #627c8d",
-"#h c #65a4e7",
-".3 c #65a6e8",
-".8 c #67a6eb",
-"#n c #69a6e8",
-"#c c #6cabed",
-"#4 c #6d6d6d",
-".4 c #6dacee",
-".5 c #6eabee",
-"#K c #6f87a1",
-"#L c #70aff1",
-".9 c #70aff2",
-"#t c #71aced",
-"#z c #72afee",
-"#F c #72afef",
-".f c #757592",
-"#i c #75b3f4",
-"#d c #75b4f3",
-"#Z c #77a6b3",
-"#. c #77b1f4",
-"## c #7ab4f4",
-".W c #7cb0e7",
-"#o c #7cb8f9",
-"#f c #80bdf9",
-"#e c #81bbf9",
-"#j c #81bbfc",
-"#u c #86c1ff",
-"#3 c #878787",
-"#k c #89c2fd",
-"#A c #89c3ff",
-".Q c #8bb9e8",
-"#l c #8bc4ff",
-"#p c #8bc6ff",
-"#G c #8dc7ff",
-".K c #8ebae8",
-"#S c #8ecbff",
-"#q c #91c8ff",
-"#M c #92ccff",
-"#v c #93ccff",
-".k c #9494b0",
-"#r c #94caff",
-".E c #96bde8",
-".X c #96c3ee",
-"#w c #96cfff",
-"#B c #97cfff",
-".Y c #99c4ee",
-"#x c #99d0ff",
-".a c #9a9aa4",
-"#X c #9b9b9b",
-".s c #9bbee8",
-".R c #9bc4ee",
-".T c #9cc5ee",
-".Z c #9dc7ef",
-"#C c #9dd3ff",
-".y c #9ec3e8",
-".L c #9ec3ed",
-".M c #9ec5ed",
-"#H c #9ed6ff",
-".S c #9fc5ee",
-"#D c #a1d7ff",
-".N c #a3c8ed",
-"#N c #a3daff",
-".F c #a5c8ed",
-".G c #a7c9ed",
-"#J c #a7ddff",
-"#I c #a7deff",
-".H c #a8caee",
-"#T c #a8e0ff",
-"#0 c #a8e2e6",
-".z c #a9caed",
-"#O c #abe3ff",
-".A c #adcbed",
-"#P c #ade3ff",
-"#Q c #aeaeae",
-".m c #afbbe7",
-".B c #afccee",
-"#U c #b0e9ff",
-".t c #b3d1ed",
-"#V c #b5ebff",
-".u c #bad4ee",
-".v c #bbd4ef",
-".h c #bfc2e8",
-"#1 c #bffdff",
-"a# c #c6c6c6",
-"a. c #cbcbcb",
-".n c #cbddf2",
-".o c #cce0f3",
-".p c #cfe1f4",
-"#W c #d1d1d1",
-"#9 c #d3d3d3",
-"#8 c #dcdcdc",
-"#2 c #e1e1e1",
-"#7 c #e3e3e3",
-"#6 c #e4e4e4",
-".i c #e6e9f6",
-".e c #e8e8e8",
-".# c #e9e9e9",
-".j c #e9edf8",
-"Qt c #ececec",
-"Qt.#.a.b.c.d",
-".e.f.g.h.i.j",
-".k.l.m.n.o.p",
-".q.r.s.t.u.v",
-".w.x.y.z.A.B",
-".C.D.E.F.G.H",
-".I.J.K.L.M.N",
-".O.P.Q.R.S.T",
-".U.V.W.X.Y.Z",
-".0.1.2.3.4.5",
-".6.7.8.9#.##",
-"#a#b#c#d#e#f",
-"#g#h#i#j#k#l",
-"#m#n#o#p#q#r",
-"#s#t#u#v#w#x",
-"#y#z#A#B#C#D",
-"#E#F#G#H#I#J",
-"#K#L#M#N#O#P",
-"#Q#R#S#T#U#V",
-"#W#X#Y#Z#0#1",
-"#2#W#Q#3#4#5",
-"#6#7#8#9a.a#"};
-
-static const char *const qt_mac_tabselected_active_mid[]={
-"6 22 23 1",
-". c #00006d",
-"s c #585858",
-"h c #70adef",
-"i c #7bb5f5",
-"j c #83bcf9",
-"k c #8bc3ff",
-"l c #93c9ff",
-"m c #9ad1ff",
-"f c #9ec5ef",
-"g c #9ec7f0",
-"n c #a0d6ff",
-"e c #a2c7ed",
-"d c #a8caee",
-"o c #a8deff",
-"p c #ade2ff",
-"c c #afceee",
-"q c #b6ecff",
-"b c #bbd5f0",
-"r c #c1feff",
-"u c #c2c2c2",
-"t c #c3c3c3",
-"a c #cfe1f3",
-"# c #e9edf8",
-"......",
-"######",
-"aaaaaa",
-"bbbbbb",
-"cccccc",
-"dddddd",
-"eeeeee",
-"ffffff",
-"gggggg",
-"hhhhhh",
-"iiiiii",
-"jjjjjj",
-"kkkkkk",
-"llllll",
-"mmmmmm",
-"nnnnnn",
-"oooooo",
-"pppppp",
-"qqqqqq",
-"rrrrrr",
-"ssssss",
-"ttttuu"};
-
-static const char *const qt_mac_tabselected_active_right[]={
-"6 22 128 2",
-"Qt c #000069",
-".G c #0042b4",
-".M c #0157bb",
-".A c #0c28a0",
-".n c #101094",
-".S c #1163c4",
-".# c #1b1b6e",
-".Y c #1e6ec9",
-".t c #214eb7",
-".z c #256cc9",
-".4 c #2877ce",
-"#. c #347fd1",
-".F c #3981d2",
-"#e c #3a81d2",
-"#k c #418ad7",
-".L c #4288d4",
-".u c #45459b",
-".X c #458cd5",
-".h c #46469f",
-".R c #4a8dd7",
-".3 c #4a90db",
-"#q c #4b91db",
-"#w c #4e91dc",
-"#C c #4f8dcd",
-".9 c #5195df",
-".a c #525280",
-"#I c #5984b2",
-"#T c #5b7d9f",
-"#d c #5b9be1",
-".2 c #5d9de6",
-"#1 c #5f5f5f",
-"#Y c #627c8d",
-"#j c #65a4e7",
-".1 c #65a6e8",
-".8 c #67a6eb",
-"#p c #69a6e8",
-"#c c #6cabed",
-"#2 c #6d6d6d",
-".0 c #6dacee",
-".Z c #6eabee",
-"#O c #6f87a1",
-"#N c #70aff1",
-".7 c #70aff2",
-"#v c #71aced",
-"#B c #72afee",
-"#H c #72afef",
-".i c #757592",
-"#i c #75b3f4",
-"#b c #75b4f3",
-"#X c #77a6b3",
-".6 c #77b1f4",
-".5 c #7ab4f4",
-".W c #7cb0e7",
-"#o c #7cb8f9",
-"## c #80bdf9",
-"#a c #81bbf9",
-"#h c #81bbfc",
-"#u c #86c1ff",
-"#3 c #888888",
-"#g c #89c2fd",
-"#A c #89c3ff",
-".Q c #8bb9e8",
-"#f c #8bc4ff",
-"#n c #8bc6ff",
-"#G c #8dc7ff",
-".K c #8ebae8",
-"#S c #8ecbff",
-"#m c #91c8ff",
-"#M c #92ccff",
-"#t c #93ccff",
-".o c #9494b0",
-"#l c #94caff",
-".E c #96bde8",
-".V c #96c3ee",
-"#s c #96cfff",
-"#z c #97cfff",
-".U c #99c4ee",
-"#r c #99d0ff",
-".b c #9a9aa4",
-"#Z c #9b9b9b",
-".s c #9bbee8",
-".P c #9bc4ee",
-".N c #9cc5ee",
-".T c #9dc7ef",
-"#y c #9dd3ff",
-".y c #9ec3e8",
-".J c #9ec3ed",
-".I c #9ec5ed",
-"#F c #9ed6ff",
-".O c #9fc5ee",
-"#x c #a1d7ff",
-".H c #a3c8ed",
-"#L c #a3daff",
-".D c #a5c8ed",
-".C c #a7c9ed",
-"#D c #a7ddff",
-"#E c #a7deff",
-".B c #a8caee",
-"#R c #a8e0ff",
-"#W c #a8e2e6",
-".x c #a9caed",
-"#K c #abe3ff",
-".w c #adcbed",
-"#J c #ade3ff",
-"#U c #aeaeae",
-".m c #afbbe7",
-".v c #afccee",
-"#Q c #b0e9ff",
-".r c #b3d1ed",
-"#P c #b5ebff",
-".q c #bad4ee",
-".p c #bbd4ef",
-".g c #bfc2e8",
-"#V c #bffdff",
-"#5 c #c6c6c6",
-"#6 c #cacaca",
-".l c #cbddf2",
-".k c #cce0f3",
-".j c #cfe1f4",
-"#0 c #d1d1d1",
-"#7 c #d3d3d3",
-"#8 c #dcdcdc",
-"#4 c #e2e2e2",
-"#9 c #e4e4e4",
-".f c #e6e9f6",
-".c c #e9e9e9",
-".e c #e9edf8",
-".d c #ececec",
-"Qt.#.a.b.c.d",
-".e.f.g.h.i.c",
-".j.k.l.m.n.o",
-".p.q.r.s.t.u",
-".v.w.x.y.z.A",
-".B.C.D.E.F.G",
-".H.I.J.K.L.M",
-".N.O.P.Q.R.S",
-".T.U.V.W.X.Y",
-".Z.0.1.2.3.4",
-".5.6.7.8.9#.",
-"###a#b#c#d#e",
-"#f#g#h#i#j#k",
-"#l#m#n#o#p#q",
-"#r#s#t#u#v#w",
-"#x#y#z#A#B#C",
-"#D#E#F#G#H#I",
-"#J#K#L#M#N#O",
-"#P#Q#R#S#T#U",
-"#V#W#X#Y#Z#0",
-"#1#2#3#U#0#4",
-"#5#6#7#8#9#9"};
-
-static const char *const qt_mac_tabselected_inactive_left[]={
-"6 22 64 1",
-"9 c #656565",
-"8 c #737373",
-"c c #767676",
-"b c #808080",
-"n c #818181",
-"q c #828282",
-"e c #888888",
-"7 c #8b8b8b",
-"u c #8d8d8d",
-"3 c #939393",
-"k c #979797",
-"0 c #989898",
-"j c #9b9b9b",
-"A c #9d9d9d",
-"a c #9e9e9e",
-"4 c #9f9f9f",
-"Y c #a3a3a3",
-"C c #a6a6a6",
-"E c #aaaaaa",
-"J c #aeaeae",
-"6 c #b0b0b0",
-"2 c #b1b1b1",
-"o c #b2b2b2",
-"f c #b3b3b3",
-"O c #b6b6b6",
-"Q c #b9b9b9",
-"S c #bbbbbb",
-"r c #bdbdbd",
-"U c #c0c0c0",
-"v c #c2c2c2",
-"B c #c3c3c3",
-"y c #c6c6c6",
-"F c #c7c7c7",
-"K c #cccccc",
-"G c #cdcdcd",
-"R c #cfcfcf",
-"T c #d1d1d1",
-"1 c #d2d2d2",
-"L c #d3d3d3",
-"H c #d5d5d5",
-"I c #d6d6d6",
-"W c #d7d7d7",
-"D c #d8d8d8",
-"N c #dadada",
-"M c #dcdcdc",
-"5 c #dddddd",
-"P c #dedede",
-"z c #dfdfdf",
-"s c #e0e0e0",
-"g c #e1e1e1",
-"p c #e2e2e2",
-"w c #e3e3e3",
-"x c #e4e4e4",
-"t c #e6e6e6",
-"l c #e7e7e7",
-"d c #e8e8e8",
-"# c #e9e9e9",
-"V c #eaeaea",
-"m c #ebebeb",
-". c #ececec",
-"X c #ededed",
-"h c #f0f0f0",
-"i c #f1f1f1",
-"Z c #f2f2f2",
-".#abcc",
-"defghi",
-"jklm..",
-"nopldd",
-"qrsttt",
-"uvswxx",
-"kyzpww",
-"ABzswp",
-"CBDsww",
-"EFGHII",
-"JKLIMN",
-"OGDzPz",
-"QRNpwp",
-"STzttl",
-"UIsdVV",
-"OWlVXX",
-"YItXZZ",
-"01mZZZ",
-"23.ZZZ",
-"T4uo5Z",
-"gT6789",
-"xwMLKF"};
-
-static const char *const qt_mac_tabselected_inactive_mid[]={
-"6 22 17 1",
-"m c #5f5f5f",
-". c #787878",
-"o c #c3c3c3",
-"n c #c4c4c4",
-"g c #d5d5d5",
-"h c #dbdbdb",
-"i c #dedede",
-"f c #e2e2e2",
-"e c #e3e3e3",
-"d c #e4e4e4",
-"c c #e6e6e6",
-"b c #e8e8e8",
-"j c #eaeaea",
-"a c #ececec",
-"k c #ededed",
-"# c #f1f1f1",
-"l c #f2f2f2",
-"......",
-"######",
-"aaaaaa",
-"bbbbbb",
-"cccccc",
-"dddddd",
-"eeeeee",
-"ffffff",
-"eeeeee",
-"gggggg",
-"hhhhhh",
-"iiiiii",
-"eeeeee",
-"cccccc",
-"jjjjjj",
-"kkkkkk",
-"llllll",
-"llllll",
-"llllll",
-"llllll",
-"mmmmmm",
-"nnnnno"};
-
-static const char *const qt_mac_tabselected_inactive_right[]={
-"6 22 65 2",
-".6 c #656565",
-".7 c #737373",
-"Qt c #767676",
-".# c #808080",
-".p c #818181",
-".t c #828282",
-".h c #888888",
-".8 c #8c8c8c",
-".x c #8d8d8d",
-".2 c #929292",
-".k c #979797",
-".1 c #989898",
-".l c #9b9b9b",
-".B c #9d9d9d",
-".a c #9e9e9e",
-".5 c #9f9f9f",
-".Z c #a3a3a3",
-".D c #a6a6a6",
-".I c #aaaaaa",
-".N c #aeaeae",
-".9 c #b0b0b0",
-".3 c #b1b1b1",
-".o c #b2b2b2",
-".g c #b3b3b3",
-".P c #b6b6b6",
-".R c #b9b9b9",
-".T c #bbbbbb",
-".s c #bdbdbd",
-".V c #c0c0c0",
-".w c #c2c2c2",
-".A c #c3c3c3",
-".z c #c6c6c6",
-".H c #c7c7c7",
-"#. c #cbcbcb",
-".M c #cccccc",
-".G c #cdcdcd",
-".Q c #cfcfcf",
-".S c #d1d1d1",
-".0 c #d2d2d2",
-".L c #d3d3d3",
-".F c #d5d5d5",
-".E c #d6d6d6",
-".X c #d7d7d7",
-".C c #d8d8d8",
-".J c #dadada",
-".K c #dcdcdc",
-".4 c #dddddd",
-".O c #dedede",
-".y c #dfdfdf",
-".r c #e0e0e0",
-".f c #e1e1e1",
-".n c #e2e2e2",
-".v c #e3e3e3",
-".u c #e4e4e4",
-".q c #e6e6e6",
-".j c #e7e7e7",
-".m c #e8e8e8",
-".b c #e9e9e9",
-".U c #eaeaea",
-".i c #ebebeb",
-".c c #ececec",
-".W c #ededed",
-".e c #f0f0f0",
-".d c #f1f1f1",
-".Y c #f2f2f2",
-"QtQt.#.a.b.c",
-".d.e.f.g.h.b",
-".c.c.i.j.k.l",
-".m.m.j.n.o.p",
-".q.q.q.r.s.t",
-".u.u.v.r.w.x",
-".v.v.n.y.z.k",
-".n.v.r.y.A.B",
-".v.v.r.C.A.D",
-".E.E.F.G.H.I",
-".J.K.E.L.M.N",
-".y.O.y.C.G.P",
-".n.v.n.J.Q.R",
-".j.q.q.y.S.T",
-".U.U.m.r.E.V",
-".W.W.U.j.X.P",
-".Y.Y.W.q.E.Z",
-".Y.Y.Y.i.0.1",
-".Y.Y.Y.c.2.3",
-".Y.4.o.x.5.S",
-".6.7.8.9.S.n",
-".H#..L.K.u.u"};
-
-static const char * const qt_mac_tab_selected_active_graph_left[]={
-"6 22 126 2",
-".d c #15283d",
-".c c #283348",
-".w c #374459",
-".l c #435364",
-".B c #465568",
-".q c #4d5367",
-".b c #525763",
-".H c #536271",
-".N c #5d6a79",
-"#1 c #5f5f5f",
-".T c #647181",
-"#N c #656e77",
-".r c #677282",
-"#B c #687380",
-"#U c #697077",
-".Z c #6c7885",
-".5 c #6c7988",
-"#0 c #6d6d6d",
-"#H c #6f767f",
-".x c #727e8a",
-"## c #757f8d",
-".f c #76767d",
-"#v c #76838f",
-"#e c #778292",
-"#k c #7b8694",
-".U c #7b8794",
-".C c #7b8795",
-".O c #7c8893",
-".I c #7d8896",
-".g c #7e8895",
-".0 c #7e8b99",
-"#q c #818c98",
-".6 c #85909e",
-"#Z c #878787",
-"#a c #8a96a3",
-"#f c #8d99a7",
-".1 c #8e99a6",
-"#V c #929ca5",
-"#l c #939daa",
-".k c #949499",
-".7 c #96a0ad",
-".2 c #98a3af",
-"#r c #99a5b0",
-".a c #9a9a9b",
-"#I c #9aa4b1",
-"#T c #9b9b9b",
-".3 c #9ba6b1",
-"#b c #9ba6b3",
-".8 c #9ca7b4",
-".4 c #9da6b1",
-"#w c #9da7b5",
-"#C c #9ea9b5",
-".V c #a0a9b4",
-"#g c #a0abb8",
-"#. c #a3acb8",
-".9 c #a4adba",
-"#c c #a6afbc",
-"#m c #a8b1bd",
-"#d c #a9b3bf",
-".J c #abb3bc",
-".P c #adb4bb",
-"#h c #adb8c3",
-"#M c #aeaeae",
-"#j c #aeb8c4",
-".W c #b0b8c2",
-"#i c #b0bac6",
-".D c #b3bac3",
-"#x c #b3bcc8",
-"#n c #b3bdc9",
-".Q c #b4bac2",
-"#D c #b5bfc9",
-".y c #b6bdc5",
-"#o c #b6becb",
-"#s c #b7c2ce",
-".K c #b8bdc6",
-".X c #b8bfc8",
-"#p c #b8c1ce",
-".S c #b9bec7",
-".R c #b9bfc8",
-".Y c #b9c1c7",
-".M c #b9c1c8",
-"#J c #bac5cf",
-".L c #bbbfc8",
-"#O c #bbc7d4",
-".s c #bcc3ca",
-"#t c #bcc5d1",
-"#u c #bcc6d2",
-".E c #bdc3ca",
-"#y c #bdc7d2",
-".G c #bec3cb",
-".F c #bec5cb",
-".z c #c2c7ce",
-"#E c #c2cad6",
-".A c #c3c9d0",
-"#z c #c3ccd7",
-"#A c #c3ced7",
-".m c #c5c9d0",
-"#7 c #c6c6c6",
-"#K c #c7d2dd",
-".t c #c8ced3",
-"#F c #c8d3de",
-"#G c #c9d3df",
-"#6 c #cbcbcb",
-".u c #cbd1d6",
-".v c #ccd2d7",
-".h c #ced2d6",
-"#W c #ced8e4",
-"#L c #d0dae3",
-"#S c #d1d1d1",
-"#P c #d1dbe6",
-"#5 c #d3d3d3",
-".n c #d5dadc",
-"#Q c #d5deea",
-".o c #d7dbdf",
-"#R c #d7e1ec",
-".p c #dadde0",
-"#4 c #dcdcdc",
-".i c #e0e2e6",
-"#Y c #e1e1e1",
-"#3 c #e3e3e3",
-"#2 c #e4e4e4",
-".j c #e6e8ea",
-".e c #e8e8e8",
-".# c #e9e9e9",
-"#X c #e9f4ff",
-"Qt c #ececec",
-"Qt.#.a.b.c.d",
-".e.f.g.h.i.j",
-".k.l.m.n.o.p",
-".q.r.s.t.u.v",
-".w.x.y.z.A.A",
-".B.C.D.E.F.G",
-".H.I.J.K.L.M",
-".N.O.P.Q.R.S",
-".T.U.V.W.X.Y",
-".Z.0.1.2.3.4",
-".5.6.7.8.9#.",
-"###a#b#c#d#d",
-"#e#f#g#h#i#j",
-"#k#l#m#n#o#p",
-"#q#r#h#s#t#u",
-"#v#w#x#y#z#A",
-"#B#C#D#E#F#G",
-"#H#I#J#K#L#L",
-"#M#N#O#P#Q#R",
-"#S#T#U#V#W#X",
-"#Y#S#M#Z#0#1",
-"#2#3#4#5#6#7"};
-
-static const char * const qt_mac_tab_selected_active_graph_mid[]={
-"6 22 41 1",
-". c #15273d",
-"# c #16283e",
-"a c #17293e",
-"b c #192a3f",
-"c c #1a2b40",
-"K c #585858",
-"p c #9ea8b4",
-"q c #a4adb9",
-"r c #aab4bf",
-"s c #afb9c6",
-"o c #b6bcc6",
-"n c #b8bec6",
-"t c #b8c2ce",
-"m c #bbc2c8",
-"u c #bbc5d0",
-"l c #bec4cb",
-"v c #bfcad4",
-"L c #c2c2c2",
-"k c #c2c9ce",
-"M c #c3c3c3",
-"w c #c7d1dd",
-"i c #cad0d5",
-"j c #cbd0d5",
-"x c #ccd5e1",
-"y c #cdd6e2",
-"z c #ced6e2",
-"A c #d5dfeb",
-"B c #d6e0ec",
-"C c #d7e1ed",
-"e c #d8dbe0",
-"f c #d8dce0",
-"g c #d9dce0",
-"D c #d9e2ee",
-"h c #dadce0",
-"E c #dae2ef",
-"d c #e7e9eb",
-"J c #e9f2ff",
-"I c #eaf3ff",
-"H c #ebf5ff",
-"G c #ecf6ff",
-"F c #edf6ff",
-"..#abc",
-"dddddd",
-"eeefgh",
-"iiiiij",
-"kkkkkk",
-"llllll",
-"mmmmmm",
-"nnnnnn",
-"oooooo",
-"pppppp",
-"qqqqqq",
-"rrrrrr",
-"ssssss",
-"tttttt",
-"uuuuuu",
-"vvvvvv",
-"wwwwww",
-"xxxxyz",
-"AABCDE",
-"FFGHIJ",
-"KKKKKK",
-"LLLLMM"};
-
-static const char * const qt_mac_tab_selected_active_graph_right[]={
-"6 22 124 2",
-"Qt c #15283d",
-".# c #293448",
-".z c #374459",
-".n c #435364",
-".F c #465568",
-".u c #4d5367",
-".a c #525763",
-".L c #536271",
-".R c #5d6a79",
-"#X c #5f5f5f",
-"#P c #646d77",
-".X c #647181",
-".t c #677282",
-"#F c #687380",
-"#U c #697077",
-".3 c #6c7885",
-".9 c #6c7988",
-"#Y c #6d6d6d",
-"#K c #6f767f",
-".y c #727e8a",
-"#c c #757f8d",
-".i c #76767d",
-"#z c #76838f",
-"#i c #778292",
-"#o c #7b8694",
-".W c #7b8794",
-".E c #7b8795",
-".Q c #7c8893",
-".K c #7d8896",
-".h c #7e8895",
-".2 c #7e8b99",
-"#t c #818c98",
-".8 c #85909e",
-"#Z c #888888",
-"#b c #8a96a3",
-"#h c #8d99a7",
-".1 c #8e99a6",
-"#T c #929ca5",
-"#n c #939daa",
-".o c #949499",
-".7 c #96a0ad",
-".0 c #98a3af",
-"#s c #99a5b0",
-".b c #9a9a9b",
-"#J c #9aa4b1",
-"#V c #9b9b9b",
-".Z c #9ba6b1",
-"#a c #9ba6b3",
-".6 c #9ca7b4",
-".Y c #9da6b1",
-"#y c #9da7b5",
-"#E c #9ea9b5",
-".V c #a0a9b4",
-"#g c #a0abb8",
-".4 c #a3acb8",
-".5 c #a4adba",
-"## c #a6afbc",
-"#m c #a8b1bd",
-"#. c #a9b3bf",
-".J c #abb3bc",
-".P c #adb4bb",
-"#f c #adb8c3",
-"#Q c #aeaeae",
-"#d c #aeb8c4",
-".U c #b0b8c2",
-"#e c #b0bac6",
-".D c #b3bac3",
-"#x c #b3bcc8",
-"#l c #b3bdc9",
-".O c #b4bac2",
-"#D c #b5bfc9",
-".x c #b6bdc5",
-"#k c #b6becb",
-"#r c #b7c2ce",
-".I c #b8bdc6",
-".T c #b8bfc8",
-"#j c #b8c1ce",
-".M c #b9bec7",
-".N c #b9bfc8",
-".S c #b9c1c7",
-".G c #b9c1c8",
-"#I c #bac5cf",
-".H c #bbbfc8",
-"#O c #bbc7d4",
-".s c #bcc3ca",
-"#q c #bcc5d1",
-"#p c #bcc6d2",
-".C c #bdc3ca",
-"#w c #bdc7d2",
-".A c #bec3cb",
-".B c #bec5cb",
-".w c #c2c7ce",
-"#C c #c2cad6",
-".v c #c3c9d0",
-"#v c #c3ccd7",
-"#u c #c3ced7",
-".m c #c5c9d0",
-"#1 c #c6c6c6",
-"#H c #c7d2dd",
-".r c #c8ced3",
-"#B c #c8d3de",
-"#A c #c9d3df",
-"#2 c #cacaca",
-".q c #cbd1d6",
-".p c #ccd2d7",
-".g c #ced2d6",
-"#S c #ced8e4",
-"#G c #d0dae3",
-"#W c #d1d1d1",
-"#N c #d1dbe6",
-"#3 c #d3d3d3",
-".l c #d5dadc",
-"#M c #d5deea",
-".k c #d7dbdf",
-"#L c #d7e1ec",
-".j c #dadde0",
-"#4 c #dcdcdc",
-".f c #e0e2e6",
-"#0 c #e2e2e2",
-"#5 c #e4e4e4",
-".e c #e6e8ea",
-".c c #e9e9e9",
-"#R c #e9f4ff",
-".d c #ececec",
-"Qt.#.a.b.c.d",
-".e.f.g.h.i.c",
-".j.k.l.m.n.o",
-".p.q.r.s.t.u",
-".v.v.w.x.y.z",
-".A.B.C.D.E.F",
-".G.H.I.J.K.L",
-".M.N.O.P.Q.R",
-".S.T.U.V.W.X",
-".Y.Z.0.1.2.3",
-".4.5.6.7.8.9",
-"#.#.###a#b#c",
-"#d#e#f#g#h#i",
-"#j#k#l#m#n#o",
-"#p#q#r#f#s#t",
-"#u#v#w#x#y#z",
-"#A#B#C#D#E#F",
-"#G#G#H#I#J#K",
-"#L#M#N#O#P#Q",
-"#R#S#T#U#V#W",
-"#X#Y#Z#Q#W#0",
-"#1#2#3#4#5#5"};
-
-static const char * const qt_mac_tab_press_left[]={
-"6 22 65 2",
-".8 c #5c5c5c",
-".c c #696969",
-".d c #6a6a6a",
-".b c #767676",
-".f c #7e7e7e",
-".t c #808080",
-".4 c #828282",
-".7 c #838383",
-".2 c #888888",
-".k c #8b8b8b",
-".0 c #8c8c8c",
-".z c #909090",
-".j c #919191",
-".a c #959595",
-".Y c #989898",
-".B c #999999",
-".D c #9e9e9e",
-".I c #a1a1a1",
-".n c #a6a6a6",
-".g c #a7a7a7",
-".6 c #a8a8a8",
-".O c #aaaaaa",
-".1 c #ababab",
-".R c #acacac",
-".T c #afafaf",
-".q c #b1b1b1",
-".V c #b3b3b3",
-".u c #b5b5b5",
-".A c #b6b6b6",
-".x c #bababa",
-".E c #bbbbbb",
-"#. c #bebebe",
-".J c #bfbfbf",
-".F c #c0c0c0",
-".P c #c1c1c1",
-".S c #c3c3c3",
-".U c #c5c5c5",
-".K c #c6c6c6",
-".G c #c8c8c8",
-".H c #c9c9c9",
-".L c #cacaca",
-".X c #cbcbcb",
-".C c #cccccc",
-".3 c #cdcdcd",
-".N c #cecece",
-".M c #cfcfcf",
-".5 c #d0d0d0",
-".Q c #d1d1d1",
-".y c #d2d2d2",
-".r c #d4d4d4",
-".h c #d5d5d5",
-".o c #d6d6d6",
-".v c #d7d7d7",
-".w c #d8d8d8",
-".s c #d9d9d9",
-".l c #dadada",
-".p c #dbdbdb",
-".9 c #dcdcdc",
-".W c #dedede",
-".m c #dfdfdf",
-".e c #e0e0e0",
-".# c #e1e1e1",
-".i c #e3e3e3",
-"Qt c #e4e4e4",
-".Z c #e6e6e6",
-"Qt.#.a.b.c.d",
-".e.f.g.h.iQt",
-".j.k.l.m.e.e",
-".b.n.o.l.p.p",
-".b.q.r.s.s.s",
-".t.u.r.v.w.w",
-".k.x.y.o.v.v",
-".z.A.y.r.v.o",
-".B.A.C.r.v.v",
-".D.E.F.G.H.H",
-".I.J.K.L.M.N",
-".O.P.C.y.Q.y",
-".R.S.N.o.v.o",
-".T.U.y.s.s.l",
-".V.H.r.p.W.W",
-".O.X.l.W.#.#",
-".Y.L.s.#.Z.Z",
-".0.K.m.Z.Z.Z",
-".1.2.e.Z.Z.Z",
-".3.Y.4.n.5.Z",
-".s.H.6.7.d.8",
-".9.l.r.L.S#."};
-
-static const char * const qt_mac_tab_press_mid[]={
-"7 22 19 1",
-"o c #555555",
-". c #6b6b6b",
-"p c #bbbbbb",
-"q c #bcbcbc",
-"g c #c8c8c8",
-"h c #cecece",
-"i c #d1d1d1",
-"f c #d6d6d6",
-"e c #d7d7d7",
-"d c #d8d8d8",
-"c c #d9d9d9",
-"j c #dadada",
-"b c #dbdbdb",
-"k c #dedede",
-"a c #e0e0e0",
-"l c #e1e1e1",
-"# c #e4e4e4",
-"m c #e5e5e5",
-"n c #e6e6e6",
-".......",
-"#######",
-"aaaaaaa",
-"bbbbbbb",
-"ccccccc",
-"ddddddd",
-"eeeeeee",
-"fffffff",
-"eeeeeee",
-"ggggggg",
-"hhhhhhh",
-"iiiiiii",
-"eeeeeee",
-"jjjjjjj",
-"kkkkkkk",
-"lllllll",
-"mmmmmmm",
-"nnnnnnn",
-"nnnnnnn",
-"nnnnnnn",
-"ooooooo",
-"ppppqqq"};
-
-static const char * const qt_mac_tab_press_right[]={
-"6 22 64 1",
-"5 c #5c5c5c",
-". c #6a6a6a",
-"# c #767676",
-"g c #7e7e7e",
-"v c #808080",
-"3 c #828282",
-"6 c #848484",
-"0 c #888888",
-"k c #8b8b8b",
-"Z c #8c8c8c",
-"z c #909090",
-"l c #919191",
-"a c #959595",
-"Y c #989898",
-"B c #999999",
-"G c #9e9e9e",
-"M c #a1a1a1",
-"o c #a6a6a6",
-"f c #a7a7a7",
-"7 c #a8a8a8",
-"P c #aaaaaa",
-"1 c #ababab",
-"R c #acacac",
-"T c #afafaf",
-"r c #b1b1b1",
-"V c #b3b3b3",
-"u c #b5b5b5",
-"y c #b6b6b6",
-"x c #bababa",
-"F c #bbbbbb",
-"8 c #bebebe",
-"L c #bfbfbf",
-"E c #c0c0c0",
-"O c #c1c1c1",
-"9 c #c2c2c2",
-"Q c #c3c3c3",
-"S c #c5c5c5",
-"K c #c6c6c6",
-"D c #c8c8c8",
-"C c #c9c9c9",
-"J c #cacaca",
-"W c #cbcbcb",
-"A c #cccccc",
-"4 c #cdcdcd",
-"H c #cecece",
-"I c #cfcfcf",
-"2 c #d0d0d0",
-"N c #d1d1d1",
-"w c #d2d2d2",
-"q c #d4d4d4",
-"e c #d5d5d5",
-"n c #d6d6d6",
-"t c #d7d7d7",
-"s c #d8d8d8",
-"p c #d9d9d9",
-"j c #dadada",
-"m c #dbdbdb",
-"U c #dedede",
-"i c #dfdfdf",
-"h c #e0e0e0",
-"b c #e1e1e1",
-"d c #e3e3e3",
-"c c #e4e4e4",
-"X c #e6e6e6",
-"..#abc",
-"cdefgb",
-"hhijkl",
-"mmjno#",
-"pppqr#",
-"sstquv",
-"ttnwxk",
-"ntqwyz",
-"ttqAyB",
-"CCDEFG",
-"HIJKLM",
-"wNwAOP",
-"ntnHQR",
-"jppwST",
-"UUmqCV",
-"bbUjWP",
-"XXbpJY",
-"XXXiKZ",
-"XXXh01",
-"X2o3Y4",
-"5.67Cj",
-"89Jqmm"};
-
static const char * const qt_mac_toolbar_ext[]={
"14 9 4 1",
"# c #858585",
diff --git a/src/gui/styles/qmotifstyle.cpp b/src/gui/styles/qmotifstyle.cpp
index 092673c..3550408 100644
--- a/src/gui/styles/qmotifstyle.cpp
+++ b/src/gui/styles/qmotifstyle.cpp
@@ -386,7 +386,7 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
case PE_FrameTabWidget:
case PE_FrameWindow:
- qDrawShadePanel(p, opt->rect, opt->palette, QStyle::State_None, pixelMetric(PM_DefaultFrameWidth));
+ qDrawShadePanel(p, opt->rect, opt->palette, QStyle::State_None, proxy()->pixelMetric(PM_DefaultFrameWidth));
break;
case PE_FrameFocusRect:
if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt)) {
@@ -475,7 +475,7 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
fill = opt->palette.brush(QPalette::Button);
if ((opt->state & State_Enabled || opt->state & State_On) || !(opt->state & State_AutoRaise))
qDrawShadePanel(p, opt->rect, opt->palette, bool(opt->state & (State_Sunken | State_On)),
- pixelMetric(PM_DefaultFrameWidth), &fill);
+ proxy()->pixelMetric(PM_DefaultFrameWidth), &fill);
break; }
case PE_IndicatorCheckBox: {
@@ -490,9 +490,9 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
opt->rect.x(), opt->rect.y() + opt->rect.height() - 1);
} else {
qDrawShadePanel(p, opt->rect, opt->palette, !showUp,
- pixelMetric(PM_DefaultFrameWidth), &fill);
+ proxy()->pixelMetric(PM_DefaultFrameWidth), &fill);
}
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern));
break; }
@@ -545,7 +545,7 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
a.setPoints(INTARRLEN(bottom_pts), bottom_pts);
a.translate(opt->rect.x(), opt->rect.y());
p->drawPolyline(a);
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern));
p->setPen(oldPen);
p->setBrush(oldBrush);
@@ -736,13 +736,13 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
#undef CLEFT
#undef CTOP
#undef CBOT
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern));
break; }
case PE_IndicatorDockWidgetResizeHandle: {
const int motifOffset = 10;
- int sw = pixelMetric(PM_SplitterWidth);
+ int sw = proxy()->pixelMetric(PM_SplitterWidth);
if (opt->state & State_Horizontal) {
int yPos = opt->rect.y() + opt->rect.height() / 2;
int kPos = opt->rect.right() - motifOffset - sw;
@@ -769,7 +769,7 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
const int markH = 6;
int posX = opt->rect.x() + (opt->rect.width() - markW) / 2 - 1;
int posY = opt->rect.y() + (opt->rect.height() - markH) / 2;
- int dfw = pixelMetric(PM_DefaultFrameWidth);
+ int dfw = proxy()->pixelMetric(PM_DefaultFrameWidth);
if (dfw < 2) {
// Could do with some optimizing/caching...
@@ -843,7 +843,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
handleOpt.state &= ~State_Horizontal;
else
handleOpt.state |= State_Horizontal;
- drawPrimitive(PE_IndicatorDockWidgetResizeHandle, &handleOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorDockWidgetResizeHandle, &handleOpt, p, widget);
break; }
case CE_ScrollBarSubLine:
@@ -855,9 +855,9 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
pe = (opt->state & State_Horizontal) ? (opt->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight) : PE_IndicatorArrowUp;
QStyleOption arrowOpt = *opt;
arrowOpt.state |= State_Enabled;
- drawPrimitive(pe, &arrowOpt, p, widget);
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText)) {
- int fw = pixelMetric(PM_DefaultFrameWidth);
+ proxy()->drawPrimitive(pe, &arrowOpt, p, widget);
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) {
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth);
p->fillRect(opt->rect.adjusted(fw, fw, -fw, -fw), QBrush(p->background().color(), Qt::Dense5Pattern));
}
}break;
@@ -873,9 +873,9 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
bevelOpt.state &= ~(State_Sunken | State_On);
p->save();
p->setBrushOrigin(bevelOpt.rect.topLeft());
- drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget);
p->restore();
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern));
break; }
@@ -886,31 +886,31 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
: SE_CheckBoxIndicator, btn, widget);
- drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
+ proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
&subopt, p, widget);
subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
: SE_CheckBoxContents, btn, widget);
- drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget);
+ proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget);
if ((btn->state & State_HasFocus) && (!focus || !focus->isVisible())) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
: SE_CheckBoxFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
case CE_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
- drawControl(CE_PushButtonBevel, btn, p, widget);
+ proxy()->drawControl(CE_PushButtonBevel, btn, p, widget);
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
- drawControl(CE_PushButtonLabel, &subopt, p, widget);
+ proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget);
if ((btn->state & State_HasFocus) && (!focus || !focus->isVisible())) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
@@ -919,7 +919,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
int diw, x1, y1, x2, y2;
p->setPen(opt->palette.foreground().color());
p->setBrush(QBrush(opt->palette.button().color(), Qt::NoBrush));
- diw = pixelMetric(PM_ButtonDefaultIndicator);
+ diw = proxy()->pixelMetric(PM_ButtonDefaultIndicator);
opt->rect.getCoords(&x1, &y1, &x2, &y2);
if (btn->features & (QStyleOptionButton::AutoDefaultButton|QStyleOptionButton::DefaultButton)) {
x1 += diw;
@@ -948,14 +948,14 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
QStyleOptionButton newOpt = *btn;
newOpt.rect = QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
p->setBrushOrigin(p->brushOrigin());
- drawPrimitive(PE_PanelButtonCommand, &newOpt, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &newOpt, p, widget);
}
if (btn->features & QStyleOptionButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, btn, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
QRect ir = btn->rect;
QStyleOptionButton newBtn = *btn;
newBtn.rect = QRect(ir.right() - mbi - 3, ir.y() + 4, mbi, ir.height() - 8);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
break;
}
@@ -963,7 +963,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
#ifndef QT_NO_TABBAR
case CE_TabBarTabShape:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
- const int default_frame = pixelMetric(PM_DefaultFrameWidth, tab, widget);
+ const int default_frame = proxy()->pixelMetric(PM_DefaultFrameWidth, tab, widget);
const int frame_offset = (default_frame > 1) ? 1 : 0;
if (tab->shape == QTabBar::RoundedNorth || tab->shape == QTabBar::RoundedEast ||
@@ -1081,7 +1081,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
}
p->setTransform(m, true);
}
- const int unit_width = pixelMetric(PM_ProgressBarChunkWidth, opt, widget);
+ const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, opt, widget);
int u = rect.width() / unit_width;
int p_v = pb->progress - pb->minimum;
int t_s = qMax(0, pb->maximum - pb->minimum);
@@ -1150,7 +1150,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
QFont oldFont = p->font();
p->setFont(menuitem->font);
p->fillRect(x, y, w, h, opt->palette.brush(QPalette::Button));
- drawItemText(p, menuitem->rect.adjusted(10, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
+ proxy()->drawItemText(p, menuitem->rect.adjusted(10, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
menuitem->palette, menuitem->state & State_Enabled, menuitem->text,
QPalette::Text);
textWidth = menuitem->fontMetrics.width(menuitem->text) + 10;
@@ -1220,10 +1220,10 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
}
if (menuitem->checkType & QStyleOptionMenuItem::Exclusive) {
newMenuItem.rect.setRect(xvis + 2, y + motifItemFrame + mh / 4, 11, 11);
- drawPrimitive(PE_IndicatorRadioButton, &newMenuItem, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorRadioButton, &newMenuItem, p, widget);
} else {
newMenuItem.rect.setRect(xvis + 5, y + motifItemFrame + mh / 4, 9, 9);
- drawPrimitive(PE_IndicatorCheckBox, &newMenuItem, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &newMenuItem, p, widget);
}
}
@@ -1258,14 +1258,14 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
int xv = vr.x();
QRect tr(xv, y+m, menuitem->tabWidth, h-2*m);
p->drawText(tr, text_flags, s.mid(t+1));
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(tr, QBrush(p->background().color(), Qt::Dense5Pattern));
s = s.left(t);
}
QRect tr(xvis, y+m, w - xm - menuitem->tabWidth + 1, h-2*m);
p->drawText(tr, text_flags, s.left(t));
p->setFont(oldFont);
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(tr, QBrush(p->background().color(), Qt::Dense5Pattern));
}
if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) { // draw sub menu arrow
@@ -1279,7 +1279,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
arrowOpt.state = (State_Sunken | ((opt->state & State_Enabled) ? State_Enabled : State_None));
else
arrowOpt.state = ((opt->state & State_Enabled) ? State_Enabled : State_None);
- drawPrimitive(arrow, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(arrow, &arrowOpt, p, widget);
}
break; }
@@ -1296,7 +1296,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
p->save();
p->setBrushOrigin(opt->rect.topLeft());
qDrawShadePanel(p, opt->rect, opt->palette, bool(opt->state & (State_Sunken|State_On)),
- pixelMetric(PM_DefaultFrameWidth),
+ proxy()->pixelMetric(PM_DefaultFrameWidth),
&opt->palette.brush((opt->state & State_Sunken) ? QPalette::Mid : QPalette::Button));
p->restore();
break;
@@ -1431,8 +1431,8 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QRect button, menuarea;
- button = subControlRect(cc, toolbutton, SC_ToolButton, widget);
- menuarea = subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
State bflags = toolbutton->state & ~State_Sunken;
if (bflags & State_AutoRaise) {
@@ -1453,7 +1453,7 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
if (bflags & (State_Sunken | State_On | State_Raised)) {
tool.rect = button;
tool.state = bflags;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
}
}
@@ -1461,26 +1461,26 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
QStyleOptionFocusRect fr;
fr.QStyleOption::operator=(*toolbutton);
fr.rect = toolbutton->rect.adjusted(3, 3, -3, -3);
- drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
}
QStyleOptionToolButton label = *toolbutton;
label.state = bflags;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
label.rect = button.adjusted(fw, fw, -fw, -fw);
- drawControl(CE_ToolButtonLabel, &label, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;
tool.state = mflags;
if (mflags & (State_Sunken | State_On | State_Raised))
- drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
- drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
} else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
QRect ir = toolbutton->rect;
QStyleOptionToolButton newBtn = *toolbutton;
newBtn.rect = QRect(ir.right() + 5 - mbi, ir.height() - mbi + 4, mbi - 6, mbi - 6);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
break;
@@ -1491,18 +1491,18 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
PrimitiveElement pe;
if (spinbox->frame && (spinbox->subControls & SC_SpinBoxFrame)) {
- QRect r = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxFrame, widget);
- qDrawShadePanel(p, r, opt->palette, false, pixelMetric(PM_SpinBoxFrameWidth));
+ QRect r = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxFrame, widget);
+ qDrawShadePanel(p, r, opt->palette, false, proxy()->pixelMetric(PM_SpinBoxFrameWidth));
- int fw = pixelMetric(QStyle::PM_DefaultFrameWidth);
- r = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxEditField, widget).adjusted(-fw,-fw,fw,fw);
+ int fw = proxy()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ r = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxEditField, widget).adjusted(-fw,-fw,fw,fw);
QStyleOptionFrame lineOpt;
lineOpt.QStyleOption::operator=(*opt);
lineOpt.rect = r;
lineOpt.lineWidth = fw;
lineOpt.midLineWidth = 0;
lineOpt.state |= QStyle::State_Sunken;
- drawPrimitive(QStyle::PE_FrameLineEdit, &lineOpt, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_FrameLineEdit, &lineOpt, p, widget);
}
if (spinbox->subControls & SC_SpinBoxUp) {
@@ -1525,8 +1525,8 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
pe = (spinbox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus
: PE_IndicatorSpinUp);
- copy.rect = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxUp, widget);
- drawPrimitive(pe, &copy, p, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxUp, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
if (spinbox->subControls & SC_SpinBoxDown) {
@@ -1549,8 +1549,8 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
pe = (spinbox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus
: PE_IndicatorSpinDown);
- copy.rect = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxDown, widget);
- drawPrimitive(pe, &copy, p, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxDown, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
}
break;
@@ -1558,16 +1558,16 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- QRect groove = subControlRect(CC_Slider, opt, SC_SliderGroove, widget),
- handle = subControlRect(CC_Slider, opt, SC_SliderHandle, widget);
+ QRect groove = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, widget),
+ handle = proxy()->subControlRect(CC_Slider, opt, SC_SliderHandle, widget);
if ((opt->subControls & SC_SliderGroove) && groove.isValid()) {
- qDrawShadePanel(p, groove, opt->palette, true, pixelMetric(PM_DefaultFrameWidth),
+ qDrawShadePanel(p, groove, opt->palette, true, proxy()->pixelMetric(PM_DefaultFrameWidth),
&opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window));
if ((opt->state & State_HasFocus) && (!focus || !focus->isVisible())) {
QStyleOption focusOpt = *opt;
focusOpt.rect = subElementRect(SE_SliderFocusRect, opt, widget);
- drawPrimitive(PE_FrameFocusRect, &focusOpt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focusOpt, p, widget);
}
}
@@ -1577,7 +1577,7 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
bevelOpt.rect = handle;
p->save();
p->setBrushOrigin(bevelOpt.rect.topLeft());
- drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget);
p->restore();
if (slider->orientation == Qt::Horizontal) {
@@ -1589,14 +1589,14 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
qDrawShadeLine(p, handle.x(), mid, handle.x() + handle.width() - 2, mid, opt->palette,
true, 1);
}
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(handle, QBrush(p->background().color(), Qt::Dense5Pattern));
}
if (slider->subControls & SC_SliderTickmarks) {
QStyleOptionSlider tmpSlider = *slider;
tmpSlider.subControls = SC_SliderTickmarks;
- int frameWidth = pixelMetric(PM_DefaultFrameWidth);
+ int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth);
tmpSlider.rect.translate(frameWidth - 1, 0);
QCommonStyle::drawComplexControl(cc, &tmpSlider, p, widget);
}
@@ -1607,13 +1607,13 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
if (opt->subControls & SC_ComboBoxArrow) {
int awh, ax, ay, sh, sy, dh, ew;
- int fw = cb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
+ int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
if (cb->frame) {
QStyleOptionButton btn;
btn.QStyleOption::operator=(*cb);
btn.state |= QStyle::State_Raised;
- drawPrimitive(PE_PanelButtonCommand, &btn, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &btn, p, widget);
} else {
p->fillRect(opt->rect, opt->palette.brush(QPalette::Button));
}
@@ -1627,7 +1627,7 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
QStyleOption arrowOpt = *opt;
arrowOpt.rect = ar;
arrowOpt.state |= State_Enabled;
- drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
// draws the shaded line under the arrow
@@ -1643,13 +1643,13 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
focus.QStyleOption::operator=(*opt);
focus.rect = subElementRect(SE_ComboBoxFocusRect, opt, widget);
focus.backgroundColor = opt->palette.button().color();
- drawPrimitive(PE_FrameFocusRect, &focus, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focus, p, widget);
}
}
if (opt->subControls & SC_ComboBoxEditField) {
if (cb->editable) {
- QRect er = subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, widget);
+ QRect er = proxy()->subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, widget);
er.adjust(-1, -1, 1, 1);
qDrawShadePanel(p, er, opt->palette, true, 1,
&opt->palette.brush(QPalette::Base));
@@ -1663,7 +1663,7 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
case CC_ScrollBar: {
if (opt->subControls & SC_ScrollBarGroove)
qDrawShadePanel(p, opt->rect, opt->palette, true,
- pixelMetric(PM_DefaultFrameWidth, opt, widget),
+ proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget),
&opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window));
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
@@ -1798,7 +1798,7 @@ int QMotifStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt,
break;
case PM_ToolBarFrameWidth:
- ret = pixelMetric(PM_DefaultFrameWidth);
+ ret = proxy()->pixelMetric(PM_DefaultFrameWidth);
break;
case PM_ToolBarItemMargin:
@@ -1819,7 +1819,7 @@ int QMotifStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt,
break;
case PM_SliderThickness:
- ret = 16 + 4 * pixelMetric(PM_DefaultFrameWidth);
+ ret = 16 + 4 * proxy()->pixelMetric(PM_DefaultFrameWidth);
break;
#ifndef QT_NO_SLIDER
case PM_SliderControlThickness:
@@ -1849,9 +1849,9 @@ int QMotifStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt,
case PM_SliderSpaceAvailable:
if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
if (sl->orientation == Qt::Horizontal)
- ret = sl->rect.width() - pixelMetric(PM_SliderLength, opt, widget) - 2 * pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ ret = sl->rect.width() - proxy()->pixelMetric(PM_SliderLength, opt, widget) - 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
else
- ret = sl->rect.height() - pixelMetric(PM_SliderLength, opt, widget) - 2 * pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ ret = sl->rect.height() - proxy()->pixelMetric(PM_SliderLength, opt, widget) - 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
}
break;
#endif // QT_NO_SLIDER
@@ -1901,7 +1901,7 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
#ifndef QT_NO_SPINBOX
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
- int fw = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
QSize bs;
bs.setHeight(opt->rect.height()/2 - fw);
bs.setWidth(qMin(bs.height() * 8 / 5, opt->rect.width() / 4)); // 1.6 -approximate golden mean
@@ -1944,11 +1944,11 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
if (sc == SC_SliderHandle) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, opt, widget);
- int thickness = pixelMetric(PM_SliderControlThickness, opt, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, opt, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, opt, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
- int len = pixelMetric(PM_SliderLength, opt, widget);
- int motifBorder = pixelMetric(PM_DefaultFrameWidth);
+ int len = proxy()->pixelMetric(PM_SliderLength, opt, widget);
+ int motifBorder = proxy()->pixelMetric(PM_DefaultFrameWidth);
int sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, slider->sliderPosition,
horizontal ? slider->rect.width() - len - 2 * motifBorder
: slider->rect.height() - len - 2 * motifBorder,
@@ -1967,7 +1967,7 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
#ifndef QT_NO_SCROLLBAR
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- int dfw = pixelMetric(PM_DefaultFrameWidth);
+ int dfw = proxy()->pixelMetric(PM_DefaultFrameWidth);
QRect rect = visualRect(scrollbar->direction, scrollbar->rect,
QCommonStyle::subControlRect(cc, scrollbar, sc, widget));
if (sc == SC_ScrollBarSlider) {
@@ -1991,7 +1991,7 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
switch (sc) {
case SC_ComboBoxArrow: {
int ew, awh, sh, dh, ax, ay, sy;
- int fw = cb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
+ int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
QRect cr = opt->rect;
cr.adjust(fw, fw, -fw, -fw);
get_combo_parameters(cr, ew, awh, ax, ay, sh, dh, sy);
@@ -1999,7 +1999,7 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
}
case SC_ComboBoxEditField: {
- int fw = cb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
+ int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
QRect rect = opt->rect;
rect.adjust(fw, fw, -fw, -fw);
int ew = get_combo_extra_width(rect.height(), rect.width());
@@ -2029,10 +2029,6 @@ QMotifStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
QSize sz(contentsSize);
switch(ct) {
- case CT_Splitter:
- sz = QSize(10, 10);
- break;
-
case CT_RadioButton:
case CT_CheckBox:
sz = QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget);
@@ -2119,7 +2115,7 @@ QMotifStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidge
case SE_ComboBoxFocusRect:
{
int awh, ax, ay, sh, sy, dh, ew;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
QRect tr = opt->rect;
tr.adjust(fw, fw, -fw, -fw);
diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp
index f7044d0..8250013 100644
--- a/src/gui/styles/qplastiquestyle.cpp
+++ b/src/gui/styles/qplastiquestyle.cpp
@@ -43,7 +43,6 @@
#if !defined(QT_NO_STYLE_PLASTIQUE) || defined(QT_PLUGIN)
-static bool UsePixmapCache = true;
static const bool AnimateBusyProgressBar = true;
static const bool AnimateProgressBar = false;
// #define QPlastique_MaskButtons
@@ -51,6 +50,7 @@ static const int ProgressBarFps = 25;
static const int blueFrameWidth = 2; // with of line edit focus frame
#include "qwindowsstyle_p.h"
+#include <private/qstylehelper_p.h>
#include <qapplication.h>
#include <qbitmap.h>
#include <qabstractitemview.h>
@@ -98,7 +98,6 @@ static const int windowsItemHMargin = 3; // menu item hor text margin
static const int windowsItemVMargin = 2; // menu item ver text margin
static const int windowsArrowHMargin = 6; // arrow horizontal margin
static const int windowsTabSpacing = 12; // space between text and tab
-static const int windowsCheckMarkHMargin = 2; // horiz. margins of check mark
static const int windowsRightBorder = 15; // right border on windows
static const int windowsCheckMarkWidth = 12; // checkmarks width on windows
@@ -490,7 +489,7 @@ static void qBrushSetAlphaF(QBrush *brush, qreal alpha)
QPixmap texture = brush->texture();
QPixmap pixmap;
QString name = QString::fromLatin1("qbrushtexture-alpha-%1-%2").arg(alpha).arg(texture.cacheKey());
- if (UsePixmapCache && !QPixmapCache::find(name, pixmap)) {
+ if (!QPixmapCache::find(name, pixmap)) {
QImage image = texture.toImage();
QRgb *rgb = reinterpret_cast<QRgb *>(image.bits());
int pixels = image.width() * image.height();
@@ -551,7 +550,7 @@ static QBrush qBrushLight(QBrush brush, int light)
QPixmap texture = brush.texture();
QPixmap pixmap;
QString name = QString::fromLatin1("qbrushtexture-light-%1-%2").arg(light).arg(texture.cacheKey());
- if (UsePixmapCache && !QPixmapCache::find(name, pixmap)) {
+ if (!QPixmapCache::find(name, pixmap)) {
QImage image = texture.toImage();
QRgb *rgb = reinterpret_cast<QRgb *>(image.bits());
int pixels = image.width() * image.height();
@@ -610,7 +609,7 @@ static QBrush qBrushDark(QBrush brush, int dark)
QPixmap texture = brush.texture();
QPixmap pixmap;
QString name = QString::fromLatin1("qbrushtexture-dark-%1-%2").arg(dark).arg(brush.texture().cacheKey());
- if (UsePixmapCache && !QPixmapCache::find(name, pixmap)) {
+ if (!QPixmapCache::find(name, pixmap)) {
QImage image = texture.toImage();
QRgb *rgb = reinterpret_cast<QRgb *>(image.bits());
int pixels = image.width() * image.height();
@@ -730,16 +729,6 @@ static QColor mergedColors(const QColor &colorA, const QColor &colorB, int facto
return tmp;
}
-static QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size)
-{
- QString tmp;
- const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option);
- tmp.sprintf("%s-%d-%d-%d-%lld-%dx%d", key.toLatin1().constData(), uint(option->state),
- option->direction, complexOption ? uint(complexOption->activeSubControls) : uint(0),
- option->palette.cacheKey(), size.width(), size.height());
- return tmp;
-}
-
static void qt_plastique_draw_gradient(QPainter *painter, const QRect &rect, const QColor &gradientStart,
const QColor &gradientStop)
{
@@ -749,8 +738,7 @@ static void qt_plastique_draw_gradient(QPainter *painter, const QRect &rect, con
QPainter *p = painter;
QRect r = rect;
- bool doPixmapCache = UsePixmapCache
- && painter->deviceTransform().isIdentity()
+ bool doPixmapCache = painter->deviceTransform().isIdentity()
&& painter->worldMatrix().isIdentity();
if (doPixmapCache && QPixmapCache::find(gradientName, cache)) {
painter->drawPixmap(rect, cache);
@@ -1005,8 +993,6 @@ QPlastiqueStylePrivate::QPlastiqueStylePrivate() :
, progressBarAnimateTimer(0)
#endif
{
- if (!qgetenv("QT_STYLE_NO_PIXMAPCACHE").isNull())
- UsePixmapCache = false;
}
/*!
@@ -1132,7 +1118,7 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
switch (element) {
case PE_IndicatorButtonDropDown:
- drawPrimitive(PE_PanelButtonTool, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, option, painter, widget);
break;
case PE_FrameDefaultButton: {
if (!(option->state & QStyle::State_Enabled))
@@ -1178,7 +1164,7 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
break;
}
- int borderThickness = pixelMetric(PM_TabBarBaseOverlap, twf, widget);
+ int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, twf, widget);
bool reverse = (twf->direction == Qt::RightToLeft);
painter->save();
@@ -1357,7 +1343,7 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
painter->setPen(oldPen);
} else {
frameV2.state &= ~(State_Sunken | State_HasFocus);
- drawPrimitive(PE_Frame, &frameV2, painter, widget);
+ proxy()->drawPrimitive(PE_Frame, &frameV2, painter, widget);
}
}
break;
@@ -1515,8 +1501,8 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
rect.adjust(2, 0, -2, 0);
}
#endif
- QString pixmapName = uniqueName(QLatin1String("toolbarhandle"), option, rect.size());
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("toolbarhandle"), option, rect.size());
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(rect.size());
cache.fill(Qt::transparent);
QPainter cachePainter(&cache);
@@ -1546,8 +1532,7 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
handle);
}
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(rect.topLeft(), cache);
break;
@@ -1857,13 +1842,13 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
QStyleOptionButton button;
button.QStyleOption::operator=(*option);
button.state &= ~State_MouseOver;
- drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
break;
}
case PE_FrameWindow: {
painter->save();
bool active = (option->state & State_Active);
- int titleBarStop = option->rect.top() + pixelMetric(PM_TitleBarHeight, option, widget);
+ int titleBarStop = option->rect.top() + proxy()->pixelMetric(PM_TitleBarHeight, option, widget);
QPalette palette = option->palette;
if (!active)
@@ -2073,7 +2058,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
&& !leftCornerWidget;
bool reverseShadow = false;
- int borderThickness = pixelMetric(PM_TabBarBaseOverlap, tab, widget);
+ int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
int marginLeft = 0;
if ((atBeginning && !selected) || (selected && leftCornerWidget && ((tab->position == QStyleOptionTab::Beginning) || onlyTab))) {
marginLeft = 1;
@@ -2585,8 +2570,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
painter->setTransform(m, true);
}
- double vc6_workaround = ((bar->progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * rect.width());
- int progressIndicatorPos = int(vc6_workaround);
+ int progressIndicatorPos = (bar->progress - qreal(bar->minimum)) / qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum) * rect.width();
bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted)
|| ((bar->direction == Qt::LeftToRight) && inverted))) || (vertical && ((!inverted && !bottomToTop) || (inverted && bottomToTop)));
@@ -2646,8 +2630,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
// same rendering code for both orientations.
if (vertical) {
rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
- QTransform m;
- m.translate(rect.height()-1, 0);
+ QTransform m = QTransform::fromTranslate(rect.height()-1, 0);
m.rotate(90.0);
painter->setTransform(m, true);
}
@@ -2782,10 +2765,10 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
// contents
painter->setPen(QPen());
- QString progressBarName = uniqueName(QLatin1String("progressBarContents"),
+ QString progressBarName = QStyleHelper::uniqueName(QLatin1String("progressBarContents"),
option, rect.size());
QPixmap cache;
- if ((!UsePixmapCache || !QPixmapCache::find(progressBarName, cache)) && rect.height() > 7) {
+ if (!QPixmapCache::find(progressBarName, cache) && rect.height() > 7) {
QSize size = rect.size();
cache = QPixmap(QSize(size.width() - 6 + 30, size.height() - 6));
cache.fill(Qt::white);
@@ -2818,8 +2801,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
leftEdge += 10;
}
- if (UsePixmapCache)
- QPixmapCache::insert(progressBarName, cache);
+ QPixmapCache::insert(progressBarName, cache);
}
painter->setClipRect(progressBar.adjusted(1, 0, -1, -1));
@@ -2843,11 +2825,11 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
// Draws the header in tables.
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QPixmap cache;
- QString pixmapName = uniqueName(QLatin1String("headersection"), option, option->rect.size());
- pixmapName += QLatin1String("-") + QString::number(int(header->position));
- pixmapName += QLatin1String("-") + QString::number(int(header->orientation));
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size());
+ pixmapName += QString::number(- int(header->position));
+ pixmapName += QString::number(- int(header->orientation));
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, option->rect.width(), option->rect.height());
@@ -2891,8 +2873,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
cachePainter.drawLines(lines, 2);
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
@@ -2915,7 +2896,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
int w = 0;
if (!menuItem->text.isEmpty()) {
painter->setFont(menuItem->font);
- drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
+ proxy()->drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
menuItem->palette, menuItem->state & State_Enabled, menuItem->text,
QPalette::Text);
w = menuItem->fontMetrics.width(menuItem->text) + 5;
@@ -2958,7 +2939,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
if (checked)
button.state |= State_On;
button.palette = menuItem->palette;
- drawPrimitive(PE_IndicatorRadioButton, &button, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorRadioButton, &button, painter, widget);
} else {
if (menuItem->icon.isNull()) {
QStyleOptionButton button;
@@ -2967,7 +2948,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
if (checked)
button.state |= State_On;
button.palette = menuItem->palette;
- drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
} else if (checked) {
int iconSize = qMax(menuItem->maxIconWidth, 20);
QRect sunkenRect(option->rect.left() + 1,
@@ -3079,7 +3060,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
newMI.palette.highlightedText().color());
else
newMI.palette.setColor(QPalette::ButtonText, textBrush.color());
- drawPrimitive(arrow, &newMI, painter, widget);
+ proxy()->drawPrimitive(arrow, &newMI, painter, widget);
}
painter->restore();
@@ -3091,8 +3072,8 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
// Draws a menu bar item; File, Edit, Help etc..
if ((option->state & State_Selected)) {
QPixmap cache;
- QString pixmapName = uniqueName(QLatin1String("menubaritem"), option, option->rect.size());
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("menubaritem"), option, option->rect.size());
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, option->rect.width(), option->rect.height());
@@ -3142,8 +3123,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
lines[1] = QLine(rect.right() - 1, rect.top() + 1, rect.right() - 1, rect.bottom() - 2);
cachePainter.drawLines(lines, 2);
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
} else {
@@ -3455,9 +3435,9 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
bool reverse = scrollBar->direction == Qt::RightToLeft;
bool sunken = scrollBar->state & State_Sunken;
- QString addLinePixmapName = uniqueName(QLatin1String("scrollbar_addline"), option, option->rect.size());
+ QString addLinePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_addline"), option, option->rect.size());
QPixmap cache;
- if (!UsePixmapCache || !QPixmapCache::find(addLinePixmapName, cache)) {
+ if (!QPixmapCache::find(addLinePixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, cache.width(), cache.height());
@@ -3516,8 +3496,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
addLinePainter.drawImage(QPoint(pixmapRect.center().x() - 3, pixmapRect.center().y() - 2), arrow);
}
addLinePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(addLinePixmapName, cache);
+ QPixmapCache::insert(addLinePixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
}
@@ -3528,14 +3507,14 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
bool sunken = scrollBar->state & State_Sunken;
bool horizontal = scrollBar->orientation == Qt::Horizontal;
- QString groovePixmapName = uniqueName(QLatin1String("scrollbar_groove"), option, option->rect.size());
+ QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_groove"), option, option->rect.size());
if (sunken)
groovePixmapName += QLatin1String("-sunken");
if (element == CE_ScrollBarAddPage)
groovePixmapName += QLatin1String("-addpage");
QPixmap cache;
- if (!UsePixmapCache || !QPixmapCache::find(groovePixmapName, cache)) {
+ if (!QPixmapCache::find(groovePixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(option->palette.background().color());
QPainter groovePainter(&cache);
@@ -3561,8 +3540,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
}
groovePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(groovePixmapName, cache);
+ QPixmapCache::insert(groovePixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
}
@@ -3579,7 +3557,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
// The SubLine (up/left) buttons
QRect button1;
QRect button2;
- int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, option, widget);
+ int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, option, widget);
if (horizontal) {
button1.setRect(scrollBarSubLine.left(), scrollBarSubLine.top(), scrollBarExtent, scrollBarSubLine.height());
button2.setRect(scrollBarSubLine.right() - (scrollBarExtent - 1), scrollBarSubLine.top(), scrollBarExtent, scrollBarSubLine.height());
@@ -3588,9 +3566,9 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
button2.setRect(scrollBarSubLine.left(), scrollBarSubLine.bottom() - (scrollBarExtent - 1), scrollBarSubLine.width(), scrollBarExtent);
}
- QString subLinePixmapName = uniqueName(QLatin1String("scrollbar_subline"), option, button1.size());
+ QString subLinePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_subline"), option, button1.size());
QPixmap cache;
- if (!UsePixmapCache || !QPixmapCache::find(subLinePixmapName, cache)) {
+ if (!QPixmapCache::find(subLinePixmapName, cache)) {
cache = QPixmap(button1.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, cache.width(), cache.height());
@@ -3650,8 +3628,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
subLinePainter.drawImage(QPoint(pixmapRect.center().x() - 3, pixmapRect.center().y() - 2), arrow);
}
subLinePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(subLinePixmapName, cache);
+ QPixmapCache::insert(subLinePixmapName, cache);
}
painter->drawPixmap(button1.topLeft(), cache);
painter->drawPixmap(button2.topLeft(), cache);
@@ -3664,12 +3641,12 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
// The slider
if (option->rect.isValid()) {
- QString sliderPixmapName = uniqueName(QLatin1String("scrollbar_slider"), option, option->rect.size());
+ QString sliderPixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_slider"), option, option->rect.size());
if (horizontal)
sliderPixmapName += QLatin1String("-horizontal");
QPixmap cache;
- if (!UsePixmapCache || !QPixmapCache::find(sliderPixmapName, cache)) {
+ if (!QPixmapCache::find(sliderPixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, cache.width(), cache.height());
@@ -3720,7 +3697,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
pixmapRect.right() - 1, pixmapRect.bottom() - 1);
sliderPainter.drawLines(lines, 2);
- int sliderMinLength = pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget);
+ int sliderMinLength = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget);
if ((horizontal && scrollBar->rect.width() > sliderMinLength)
|| (!horizontal && scrollBar->rect.height() > sliderMinLength)) {
QImage pattern(horizontal ? qt_scrollbar_slider_pattern_horizontal
@@ -3740,8 +3717,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
}
sliderPainter.end();
// insert the slider into the cache
- if (UsePixmapCache)
- QPixmapCache::insert(sliderPixmapName, cache);
+ QPixmapCache::insert(sliderPixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
}
@@ -3760,7 +3736,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
QWindowsStyle::drawControl(element, option, painter, widget);
} else if (!comboBox->currentIcon.isNull()) {
{
- QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget);
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget);
if (comboBox->direction == Qt::RightToLeft)
editRect.adjust(0, 2, -2, -2);
else
@@ -3773,11 +3749,11 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode);
QRect iconRect(editRect);
iconRect.setWidth(comboBox->iconSize.width() + 5);
- iconRect = alignedRect(QApplication::layoutDirection(),
+ iconRect = alignedRect(comboBox->direction,
Qt::AlignLeft | Qt::AlignVCenter,
iconRect.size(), editRect);
painter->fillRect(iconRect, option->palette.brush(QPalette::Base));
- drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
}
painter->restore();
}
@@ -3820,9 +3796,9 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- QRect grooveRegion = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
- QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
+ QRect grooveRegion = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
+ QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
@@ -3885,13 +3861,13 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
if ((option->subControls & SC_SliderHandle) && handle.isValid()) {
- QString handlePixmapName = uniqueName(QLatin1String("slider_handle"), option, handle.size());
+ QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size());
if (ticksAbove && !ticksBelow)
handlePixmapName += QLatin1String("-flipped");
if ((option->activeSubControls & SC_SliderHandle) && (option->state & State_Sunken))
handlePixmapName += QLatin1String("-sunken");
- if (!UsePixmapCache || !QPixmapCache::find(handlePixmapName, cache)) {
+ if (!QPixmapCache::find(handlePixmapName, cache)) {
cache = QPixmap(handle.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, handle.width(), handle.height());
@@ -3974,8 +3950,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
handlePainter.drawImage(pixmapRect, image);
handlePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(handlePixmapName, cache);
+ QPixmapCache::insert(handlePixmapName, cache);
}
painter->drawPixmap(handle.topLeft(), cache);
@@ -3984,15 +3959,15 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*slider);
fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
}
if (option->subControls & SC_SliderTickmarks) {
QPen oldPen = painter->pen();
painter->setPen(borderColor);
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
interval = slider->singleStep;
@@ -4006,7 +3981,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
interval = 1;
int v = slider->minimum;
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
QVarLengthArray<QLine, 32> lines;
while (v <= slider->maximum + 1) {
if (v == slider->maximum + 1 && interval == 1)
@@ -4061,8 +4036,8 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool reverse = (spinBox->direction == Qt::RightToLeft);
// Rects
- QRect upRect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
- QRect downRect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
+ QRect upRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
+ QRect downRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
QRect buttonRect = upRect | downRect;
// Brushes
@@ -4083,7 +4058,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
} else {
d->drawPartialFrame(painter,
option,
- subControlRect(CC_SpinBox, spinBox, SC_SpinBoxEditField, widget),
+ proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxEditField, widget),
widget);
}
// Paint buttons
@@ -4423,7 +4398,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
Q_D(const QPlastiqueStyle);
d->drawPartialFrame(painter,
option,
- subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget),
+ proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget),
widget);
QBrush border = qMapBrushToRect(option->palette.shadow(), buttonRect);
@@ -4547,7 +4522,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
if (!sunken) {
buttonOption.state &= ~State_Sunken;
}
- drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget);
// Draw the menu button separator line
QBrush border = qMapBrushToRect(option->palette.shadow(), rect);
@@ -4580,11 +4555,12 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
// Draw the focus rect
- if (((option->state & State_HasFocus) && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) {
+ if ((option->state & State_HasFocus) && !comboBox->editable
+ && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) {
QStyleOptionFocusRect focus;
- focus.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget)
+ focus.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget)
.adjusted(-2, 0, 2, 0);
- drawPrimitive(PE_FrameFocusRect, &focus, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focus, painter, widget);
}
painter->setPen(oldPen);
@@ -4614,7 +4590,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
QStyleOptionDockWidgetV2 dockwidget;
dockwidget.QStyleOption::operator=(*option);
dockwidget.title = titleBar->text;
- drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget);
+ proxy()->drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget);
} else
#endif // QT3_SUPPORT
@@ -4687,7 +4663,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
}
// draw title
- QRect textRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
+ QRect textRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
QFont font = painter->font();
font.setBold(true);
@@ -4714,7 +4690,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken);
- QRect minButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
+ QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, minButtonRect, hover, sunken);
int xoffset = minButtonRect.width() / 3;
@@ -4758,7 +4734,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken);
- QRect maxButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
+ QRect maxButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, maxButtonRect, hover, sunken);
int xoffset = maxButtonRect.width() / 3;
@@ -4783,7 +4759,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken);
- QRect closeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
+ QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, closeButtonRect, hover, sunken);
int xoffset = closeButtonRect.width() / 3;
@@ -4829,7 +4805,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_Sunken);
- QRect normalButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
+ QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, normalButtonRect, hover, sunken);
int xoffset = int(normalButtonRect.width() / 3.5);
int yoffset = int(normalButtonRect.height() / 3.5);
@@ -4875,7 +4851,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken);
- QRect contextHelpButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
+ QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, contextHelpButtonRect, hover, sunken);
@@ -4902,7 +4878,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken);
- QRect shadeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
+ QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, shadeButtonRect, hover, sunken);
int xoffset = shadeButtonRect.width() / 3;
@@ -4926,7 +4902,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken);
- QRect unshadeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
+ QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, unshadeButtonRect, hover, sunken);
int xoffset = unshadeButtonRect.width() / 3;
@@ -4951,7 +4927,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarSysMenu) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarSysMenu) && (titleBar->state & State_Sunken);
- QRect iconRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
+ QRect iconRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
if (hover)
qt_plastique_draw_mdibutton(painter, titleBar, iconRect, hover, sunken);
@@ -4963,13 +4939,19 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
QPixmap pm = standardPixmap(SP_TitleBarMenuButton, &tool, widget);
tool.rect = iconRect;
painter->save();
- drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
painter->restore();
}
}
painter->restore();
}
break;
+#ifndef QT_NO_DIAL
+ case CC_Dial:
+ if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
+ QStyleHelper::drawDial(dial, painter);
+ break;
+#endif // QT_NO_DIAL
default:
QWindowsStyle::drawComplexControl(control, option, painter, widget);
break;
@@ -4992,7 +4974,7 @@ QSize QPlastiqueStyle::sizeFromContents(ContentsType type, const QStyleOption *o
#ifndef QT_NO_SLIDER
case CT_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
if (slider->tickPosition & QSlider::TicksBelow) {
if (slider->orientation == Qt::Horizontal)
newSize.rheight() += tickSize;
@@ -5011,8 +4993,8 @@ QSize QPlastiqueStyle::sizeFromContents(ContentsType type, const QStyleOption *o
#ifndef QT_NO_SCROLLBAR
case CT_ScrollBar:
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, option, widget);
- int scrollBarSliderMinimum = pixelMetric(PM_ScrollBarSliderMin, option, widget);
+ int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, option, widget);
+ int scrollBarSliderMinimum = proxy()->pixelMetric(PM_ScrollBarSliderMin, option, widget);
if (scrollBar->orientation == Qt::Horizontal) {
newSize = QSize(scrollBarExtent * 3 + scrollBarSliderMinimum, scrollBarExtent);
} else {
@@ -5093,7 +5075,7 @@ QRect QPlastiqueStyle::subControlRect(ComplexControl control, const QStyleOption
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
switch (subControl) {
case SC_SliderHandle:
@@ -5146,10 +5128,10 @@ QRect QPlastiqueStyle::subControlRect(ComplexControl control, const QStyleOption
#ifndef QT_NO_SCROLLBAR
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, scrollBar, widget);
+ int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollBar, widget);
int sliderMaxLength = ((scrollBar->orientation == Qt::Horizontal) ?
scrollBar->rect.width() : scrollBar->rect.height()) - (scrollBarExtent * 3);
- int sliderMinLength = pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget);
+ int sliderMinLength = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget);
int sliderLength;
// calculate slider length
@@ -5271,7 +5253,7 @@ QRect QPlastiqueStyle::subControlRect(ComplexControl control, const QStyleOption
break;
case SC_ComboBoxEditField: {
if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- int frameWidth = pixelMetric(PM_DefaultFrameWidth);
+ int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth);
rect = visualRect(option->direction, option->rect, rect);
if (box->editable) {
@@ -5453,6 +5435,11 @@ int QPlastiqueStyle::styleHint(StyleHint hint, const QStyleOption *option, const
case SH_Menu_SubMenuPopupDelay:
ret = 96; // from Plastik
break;
+#ifndef Q_OS_WIN
+ case SH_Menu_AllowActiveAndDisabled:
+ ret = false;
+ break;
+#endif
default:
ret = QWindowsStyle::styleHint(hint, option, widget, returnData);
break;
@@ -5471,31 +5458,31 @@ QStyle::SubControl QPlastiqueStyle::hitTestComplexControl(ComplexControl control
#ifndef QT_NO_SCROLLBAR
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- QRect slider = subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
+ QRect slider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
if (slider.contains(pos)) {
ret = SC_ScrollBarSlider;
break;
}
- QRect scrollBarAddLine = subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
+ QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
if (scrollBarAddLine.contains(pos)) {
ret = SC_ScrollBarAddLine;
break;
}
- QRect scrollBarSubPage = subControlRect(control, scrollBar, SC_ScrollBarSubPage, widget);
+ QRect scrollBarSubPage = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubPage, widget);
if (scrollBarSubPage.contains(pos)) {
ret = SC_ScrollBarSubPage;
break;
}
- QRect scrollBarAddPage = subControlRect(control, scrollBar, SC_ScrollBarAddPage, widget);
+ QRect scrollBarAddPage = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddPage, widget);
if (scrollBarAddPage.contains(pos)) {
ret = SC_ScrollBarAddPage;
break;
}
- QRect scrollBarSubLine = subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
+ QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
if (scrollBarSubLine.contains(pos)) {
ret = SC_ScrollBarSubLine;
break;
diff --git a/src/gui/styles/qproxystyle.cpp b/src/gui/styles/qproxystyle.cpp
new file mode 100644
index 0000000..df9bb9e
--- /dev/null
+++ b/src/gui/styles/qproxystyle.cpp
@@ -0,0 +1,420 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qstyle.h>
+#include <private/qstyle_p.h>
+#include <private/qproxystyle_p.h>
+#include <private/qapplication_p.h>
+#include "qproxystyle.h"
+#include "qstylefactory.h"
+
+#if !defined(QT_NO_STYLE_PROXY) || defined(QT_PLUGIN)
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QProxyStyle
+
+ \brief The QProxyStyle class is a convenience class that simplifies
+ dynamically overriding QStyle elements.
+
+ \since 4.6
+
+ A QProxyStyle wraps a QStyle (usually the default system style) for the
+ purpose of dynamically overriding painting or other specific style behavior.
+
+ The following example shows how to override the shortcut underline
+ behavior on any platform:
+
+ \snippet doc/src/snippets/code/src_gui_qproxystyle.cpp 1
+
+ Warning: The \l {QCommonStyle} {common styles} provided by Qt will
+ respect this hint, because they call QStyle::proxy(), but there is
+ no guarantee that QStyle::proxy() will be called for user defined
+ or system controlled styles. It would not work on a Mac, for
+ example, where menus are handled by the operating system.
+
+ \sa QStyle
+*/
+
+void QProxyStylePrivate::ensureBaseStyle() const
+{
+ Q_Q(const QProxyStyle);
+
+ if (baseStyle)
+ return;
+
+ if (!baseStyle && !QApplicationPrivate::styleOverride.isEmpty()) {
+ baseStyle = QStyleFactory::create(QApplicationPrivate::styleOverride);
+ if (baseStyle) {
+ // If baseStyle is an instance of the same proxyStyle
+ // we destroy it and fall back to the desktop style
+ if (qstrcmp(baseStyle->metaObject()->className(),
+ q->metaObject()->className()) == 0) {
+ delete baseStyle;
+ baseStyle = 0;
+ }
+ }
+ }
+
+ if (!baseStyle) // Use application desktop style
+ baseStyle = QStyleFactory::create(QApplicationPrivate::desktopStyleKey());
+
+ if (!baseStyle) // Fallback to windows style
+ baseStyle = QStyleFactory::create(QLatin1String("windows"));
+
+ baseStyle->setProxy(const_cast<QProxyStyle*>(q));
+ baseStyle->setParent(const_cast<QProxyStyle*>(q)); // Take ownership
+}
+
+/*!
+ Constructs a QProxyStyle object for overriding behavior in \a style
+ or in the current application \l{QStyle}{style} if \a style is 0
+ (default). Normally \a style is 0, because you want to override
+ behavior in the system style.
+
+ Ownership of \a style is transferred to QProxyStyle.
+*/
+QProxyStyle::QProxyStyle(QStyle *style) :
+ QCommonStyle(*new QProxyStylePrivate())
+{
+ Q_D(QProxyStyle);
+ if (style) {
+ style->setProxy(this);
+ style->setParent(this); // Take ownership
+ d->baseStyle = style;
+ }
+}
+
+/*!
+ Destroys the QProxyStyle object.
+*/
+QProxyStyle::~QProxyStyle()
+{
+}
+
+/*!
+ Returns the proxy base style object. If no base style
+ is set on the proxy style, QProxyStyle will create
+ an instance of the application style instead.
+
+ \sa setBaseStyle(), QStyle
+*/
+QStyle *QProxyStyle::baseStyle() const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle;
+}
+
+/*!
+ Sets the base style that should be proxied.
+
+ Ownership of \a style is transferred to QProxyStyle.
+
+ If style is zero, a desktop-dependant style will be
+ assigned automatically.
+*/
+void QProxyStyle::setBaseStyle(QStyle *style)
+{
+ Q_D (QProxyStyle);
+
+ if (d->baseStyle && d->baseStyle->parent() == this)
+ d->baseStyle->deleteLater();
+
+ d->baseStyle = style;
+
+ if (d->baseStyle) {
+ d->baseStyle->setProxy(this);
+ d->baseStyle->setParent(this);
+ }
+}
+
+/*! \reimp
+ */
+void QProxyStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawPrimitive(element, option, painter, widget);
+}
+
+/*!
+ \reimp
+ */
+void QProxyStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawControl(element, option, painter, widget);
+}
+
+/*! \reimp
+ */
+void QProxyStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawComplexControl(control, option, painter, widget);
+}
+
+/*! \reimp
+ */
+void QProxyStyle::drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled,
+ const QString &text, QPalette::ColorRole textRole) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawItemText(painter, rect, flags, pal, enabled, text, textRole);
+}
+
+/*! \reimp
+ */
+void QProxyStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawItemPixmap(painter, rect, alignment, pixmap);
+}
+
+/*! \reimp
+ */
+QSize QProxyStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->sizeFromContents(type, option, size, widget);
+}
+
+/*! \reimp
+ */
+QRect QProxyStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->subElementRect(element, option, widget);
+}
+
+/*! \reimp
+ */
+QRect QProxyStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->subControlRect(cc, option, sc, widget);
+}
+
+/*! \reimp
+ */
+QRect QProxyStyle::itemTextRect(const QFontMetrics &fm, const QRect &r, int flags, bool enabled, const QString &text) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->itemTextRect(fm, r, flags, enabled, text);
+}
+
+/*! \reimp
+ */
+QRect QProxyStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->itemPixmapRect(r, flags, pixmap);
+}
+
+/*! \reimp
+ */
+QStyle::SubControl QProxyStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->hitTestComplexControl(control, option, pos, widget);
+}
+
+/*! \reimp
+ */
+int QProxyStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->styleHint(hint, option, widget, returnData);
+}
+
+/*! \reimp
+ */
+int QProxyStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->pixelMetric(metric, option, widget);
+}
+
+/*! \reimp
+ */
+QPixmap QProxyStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->standardPixmap(standardPixmap, opt, widget);
+}
+
+/*! \reimp
+ */
+QPixmap QProxyStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->generatedIconPixmap(iconMode, pixmap, opt);
+}
+
+/*! \reimp
+ */
+QPalette QProxyStyle::standardPalette() const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->standardPalette();
+}
+
+/*! \reimp
+ */
+void QProxyStyle::polish(QWidget *widget)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->polish(widget);
+}
+
+/*! \reimp
+ */
+void QProxyStyle::polish(QPalette &pal)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->polish(pal);
+}
+
+/*! \reimp
+ */
+void QProxyStyle::polish(QApplication *app)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->polish(app);
+}
+
+/*! \reimp
+ */
+void QProxyStyle::unpolish(QWidget *widget)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->unpolish(widget);
+}
+
+/*! \reimp
+ */
+void QProxyStyle::unpolish(QApplication *app)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->unpolish(app);
+}
+
+/*! \reimp
+ */
+bool QProxyStyle::event(QEvent *e)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->event(e);
+}
+
+/*!
+ Returns an icon for the given \a standardIcon.
+
+ Reimplement this slot to provide your own icons in a QStyle
+ subclass. The \a option argument can be used to pass extra
+ information required to find the appropriate icon. The \a widget
+ argument is optional and can also be used to help find the icon.
+
+ \note Because of binary compatibility constraints, standardIcon()
+ introduced in Qt 4.1 is not virtual. Therefore it must dynamically
+ detect and call \e this slot. This default implementation simply
+ calls standardIcon() with the given parameters.
+
+ \sa standardIcon()
+ */
+QIcon QProxyStyle::standardIconImplementation(StandardPixmap standardIcon,
+ const QStyleOption *option,
+ const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->standardIcon(standardIcon, option, widget);
+}
+
+/*!
+ This slot is called by layoutSpacing() to determine the spacing that
+ should be used between \a control1 and \a control2 in a layout. \a
+ orientation specifies whether the controls are laid out side by side
+ or stacked vertically. The \a option parameter can be used to pass
+ extra information about the parent widget. The \a widget parameter
+ is optional and can also be used if \a option is 0.
+
+ The default implementation returns -1.
+
+ \sa layoutSpacing(), combinedLayoutSpacing()
+ */
+int QProxyStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation,
+ const QStyleOption *option,
+ const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->layoutSpacing(control1, control2, orientation, option, widget);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STYLE_PROXY
diff --git a/src/gui/styles/qproxystyle.h b/src/gui/styles/qproxystyle.h
new file mode 100644
index 0000000..4f344b0
--- /dev/null
+++ b/src/gui/styles/qproxystyle.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROXYSTYLE_H
+#define QPROXYSTYLE_H
+
+#include <QtGui/QCommonStyle>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_STYLE_PROXY)
+
+class QProxyStylePrivate;
+class Q_GUI_EXPORT QProxyStyle : public QCommonStyle
+{
+ Q_OBJECT
+
+public:
+ QProxyStyle(QStyle *baseStyle = 0);
+ ~QProxyStyle();
+
+ QStyle *baseStyle() const;
+ void setBaseStyle(QStyle *style);
+
+ void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled,
+ const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const;
+ virtual void drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const;
+
+ QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const;
+
+ QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const;
+ QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const;
+ QRect itemTextRect(const QFontMetrics &fm, const QRect &r, int flags, bool enabled, const QString &text) const;
+ QRect itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const;
+
+ SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget = 0) const;
+ int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const;
+ int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const;
+
+ QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget = 0) const;
+ QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const;
+ QPalette standardPalette() const;
+
+ void polish(QWidget *widget);
+ void polish(QPalette &pal);
+ void polish(QApplication *app);
+
+ void unpolish(QWidget *widget);
+ void unpolish(QApplication *app);
+
+protected:
+ bool event(QEvent *e);
+
+protected Q_SLOTS:
+ QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const;
+ int layoutSpacingImplementation(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2,
+ Qt::Orientation orientation, const QStyleOption *option = 0, const QWidget *widget = 0) const;
+private:
+ Q_DISABLE_COPY(QProxyStyle)
+ Q_DECLARE_PRIVATE(QProxyStyle)
+};
+
+#endif // QT_NO_STYLE_PROXY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPROXYSTYLE_H
diff --git a/src/gui/styles/qproxystyle_p.h b/src/gui/styles/qproxystyle_p.h
new file mode 100644
index 0000000..9c0493b
--- /dev/null
+++ b/src/gui/styles/qproxystyle_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROXYSTYLE_P_H
+#define QPROXYSTYLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qcommonstyle.h"
+#include "qcommonstyle_p.h"
+#include "qproxystyle.h"
+
+#ifndef QT_NO_STYLE_PROXY
+
+QT_BEGIN_NAMESPACE
+
+class QProxyStylePrivate : public QCommonStylePrivate
+{
+ Q_DECLARE_PUBLIC(QProxyStyle)
+public:
+ void ensureBaseStyle() const;
+private:
+ QProxyStylePrivate() :
+ QCommonStylePrivate(), baseStyle(0) {}
+ mutable QPointer <QStyle> baseStyle;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STYLE_PROXY
+
+#endif //QPROXYSTYLE_P_H
diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp
new file mode 100644
index 0000000..bd27c8d
--- /dev/null
+++ b/src/gui/styles/qs60style.cpp
@@ -0,0 +1,2882 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qs60style_p.h"
+
+#include "qapplication.h"
+#include "qpainter.h"
+#include "qstyleoption.h"
+#include "qevent.h"
+#include "qpixmapcache.h"
+
+#include "qcalendarwidget.h"
+#include "qdial.h"
+#include "qdialog.h"
+#include "qgroupbox.h"
+#include "qheaderview.h"
+#include "qlist.h"
+#include "qlistwidget.h"
+#include "qlistview.h"
+#include "qmenu.h"
+#include "qmenubar.h"
+#include "qpushbutton.h"
+#include "qscrollarea.h"
+#include "qscrollbar.h"
+#include "qtabbar.h"
+#include "qtablewidget.h"
+#include "qtableview.h"
+#include "qtextedit.h"
+#include "qtoolbar.h"
+#include "qtoolbutton.h"
+#include "qtreeview.h"
+#include "qfocusframe.h"
+
+#include "private/qtoolbarextension_p.h"
+#include "private/qcombobox_p.h"
+#include "private/qwidget_p.h"
+#include "private/qapplication_p.h"
+
+#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
+
+QT_BEGIN_NAMESPACE
+
+// from text/qfont.cpp
+extern Q_GUI_EXPORT int qt_defaultDpiY();
+
+const QS60StylePrivate::SkinElementFlags QS60StylePrivate::KDefaultSkinElementFlags =
+ SkinElementFlags(SF_PointNorth | SF_StateEnabled);
+
+static const QByteArray propertyKeyLayouts = "layouts";
+static const QByteArray propertyKeyCurrentlayout = "currentlayout";
+
+static const qreal goldenRatio = 1.618;
+
+const layoutHeader QS60StylePrivate::m_layoutHeaders[] = {
+// *** generated layout data ***
+{240,320,1,14,true,"QVGA Landscape Mirrored"},
+{240,320,1,14,false,"QVGA Landscape"},
+{320,240,1,14,true,"QVGA Portrait Mirrored"},
+{320,240,1,14,false,"QVGA Portrait"},
+{360,640,1,14,true,"NHD Landscape Mirrored"},
+{360,640,1,14,false,"NHD Landscape"},
+{640,360,1,14,true,"NHD Portrait Mirrored"},
+{640,360,1,14,false,"NHD Portrait"},
+{352,800,1,12,true,"E90 Landscape Mirrored"},
+{352,800,1,12,false,"E90 Landscape"}
+// *** End of generated data ***
+};
+const int QS60StylePrivate::m_numberOfLayouts =
+ (int)sizeof(QS60StylePrivate::m_layoutHeaders)/sizeof(QS60StylePrivate::m_layoutHeaders[0]);
+
+const short QS60StylePrivate::data[][MAX_PIXELMETRICS] = {
+// *** generated pixel metrics ***
+{5,0,-909,0,0,1,0,0,-1,8,15,22,15,15,7,198,-909,-909,-909,19,15,2,0,0,21,-909,21,-909,4,4,1,-909,-909,0,2,0,0,13,23,17,17,21,21,2,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,51,27,51,4,4,5,10,15,-909,5,58,12,5,0,7,4,4,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1},
+{5,0,-909,0,0,1,0,0,-1,8,15,22,15,15,7,198,-909,-909,-909,19,15,2,0,0,21,-909,21,-909,4,4,1,-909,-909,0,2,0,0,13,23,17,17,21,21,2,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,51,27,51,4,4,5,10,15,-909,5,58,12,5,0,4,4,7,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1},
+{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,-909,27,-909,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,4,4,5,10,15,-909,5,58,13,5,0,7,4,4,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1},
+{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,-909,27,-909,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,4,4,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1},
+{7,0,-909,0,0,2,0,0,-1,20,53,28,19,19,9,258,-909,-909,-909,29,19,26,0,0,32,-909,72,-909,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,5,5,6,8,19,-909,7,74,19,7,0,8,5,5,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1},
+{7,0,-909,0,0,2,0,0,-1,20,53,28,19,19,9,258,-909,-909,-909,29,19,26,0,0,32,-909,72,-909,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,5,5,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1},
+{7,0,-909,0,0,2,0,0,-1,20,52,28,19,19,9,258,-909,-909,-909,29,19,6,0,0,32,-909,60,-909,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,98,35,98,5,5,6,8,19,-909,7,74,22,7,0,8,5,5,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1},
+{7,0,-909,0,0,2,0,0,-1,20,52,28,19,19,9,258,-909,-909,-909,29,19,6,0,0,32,-909,60,-909,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,98,35,98,5,5,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1},
+{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,-909,32,-909,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,5,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,8,6,5,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1},
+{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,-909,32,-909,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1}
+// *** End of generated data ***
+};
+
+const short *QS60StylePrivate::m_pmPointer = QS60StylePrivate::data[0];
+
+// theme background texture
+QPixmap *QS60StylePrivate::m_background = 0;
+
+// theme palette
+QPalette *QS60StylePrivate::m_themePalette = 0;
+
+const struct QS60StylePrivate::frameElementCenter QS60StylePrivate::m_frameElementsData[] = {
+ {SE_ButtonNormal, QS60StyleEnums::SP_QsnFrButtonTbCenter},
+ {SE_ButtonPressed, QS60StyleEnums::SP_QsnFrButtonTbCenterPressed},
+ {SE_FrameLineEdit, QS60StyleEnums::SP_QsnFrInputCenter},
+ {SE_ListHighlight, QS60StyleEnums::SP_QsnFrListCenter},
+ {SE_OptionsMenu, QS60StyleEnums::SP_QsnFrPopupCenter},
+ {SE_SettingsList, QS60StyleEnums::SP_QsnFrSetOptCenter},
+ {SE_TableItem, QS60StyleEnums::SP_QsnFrCaleCenter},
+ {SE_TableHeaderItem, QS60StyleEnums::SP_QsnFrCaleHeadingCenter},
+ {SE_ToolTip, QS60StyleEnums::SP_QsnFrPopupPreviewCenter},
+ {SE_ToolBar, QS60StyleEnums::SP_QsnFrPopupSubCenter},
+ {SE_ToolBarButton, QS60StyleEnums::SP_QsnFrSctrlButtonCenter},
+ {SE_ToolBarButtonPressed, QS60StyleEnums::SP_QsnFrSctrlButtonCenterPressed},
+ {SE_PanelBackground, QS60StyleEnums::SP_QsnFrSetOptCenter},
+ {SE_ButtonInactive, QS60StyleEnums::SP_QsnFrButtonCenterInactive},
+ {SE_Editor, QS60StyleEnums::SP_QsnFrNotepadCenter},
+};
+
+static const int frameElementsCount =
+ int(sizeof(QS60StylePrivate::m_frameElementsData)/sizeof(QS60StylePrivate::m_frameElementsData[0]));
+
+const int KNotFound = -909;
+const double KTabFontMul = 0.72;
+
+QS60StylePrivate::~QS60StylePrivate()
+{
+ clearCaches(); //deletes also background image
+ deleteThemePalette();
+}
+
+void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags)
+{
+ switch (element) {
+ case SE_ButtonNormal:
+ drawFrame(SF_ButtonNormal, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ButtonPressed:
+ drawFrame(SF_ButtonPressed, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_FrameLineEdit:
+ drawFrame(SF_FrameLineEdit, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ProgressBarGrooveHorizontal:
+ drawRow(QS60StyleEnums::SP_QgnGrafBarFrameSideL, QS60StyleEnums::SP_QgnGrafBarFrameCenter,
+ QS60StyleEnums::SP_QgnGrafBarFrameSideR, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ProgressBarGrooveVertical:
+ drawRow(QS60StyleEnums::SP_QgnGrafBarFrameSideL, QS60StyleEnums::SP_QgnGrafBarFrameCenter,
+ QS60StyleEnums::SP_QgnGrafBarFrameSideR, Qt::Vertical, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_ProgressBarIndicatorHorizontal:
+ drawPart(QS60StyleEnums::SP_QgnGrafBarProgress, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ProgressBarIndicatorVertical:
+ drawPart(QS60StyleEnums::SP_QgnGrafBarProgress, painter, rect, flags | SF_PointWest);
+ break;
+ case SE_ScrollBarGrooveHorizontal:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollBgBottom, QS60StyleEnums::SP_QsnCpScrollBgMiddle,
+ QS60StyleEnums::SP_QsnCpScrollBgTop, Qt::Horizontal, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_ScrollBarGrooveVertical:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollBgTop, QS60StyleEnums::SP_QsnCpScrollBgMiddle,
+ QS60StyleEnums::SP_QsnCpScrollBgBottom, Qt::Vertical, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ScrollBarHandleHorizontal:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollHandleBottom, QS60StyleEnums::SP_QsnCpScrollHandleMiddle,
+ QS60StyleEnums::SP_QsnCpScrollHandleTop, Qt::Horizontal, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_ScrollBarHandleVertical:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollHandleTop, QS60StyleEnums::SP_QsnCpScrollHandleMiddle,
+ QS60StyleEnums::SP_QsnCpScrollHandleBottom, Qt::Vertical, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_SliderHandleHorizontal:
+ drawPart(QS60StyleEnums::SP_QgnIndiSliderEdit, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_SliderHandleVertical:
+ drawPart(QS60StyleEnums::SP_QgnIndiSliderEdit, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_TabBarTabEastActive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabActiveL, QS60StyleEnums::SP_QgnGrafTabActiveM,
+ QS60StyleEnums::SP_QgnGrafTabActiveR, Qt::Vertical, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_TabBarTabEastInactive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveL, QS60StyleEnums::SP_QgnGrafTabPassiveM,
+ QS60StyleEnums::SP_QgnGrafTabPassiveR, Qt::Vertical, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_TabBarTabNorthActive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabActiveL, QS60StyleEnums::SP_QgnGrafTabActiveM,
+ QS60StyleEnums::SP_QgnGrafTabActiveR, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_TabBarTabNorthInactive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveL, QS60StyleEnums::SP_QgnGrafTabPassiveM,
+ QS60StyleEnums::SP_QgnGrafTabPassiveR, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_TabBarTabSouthActive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabActiveR, QS60StyleEnums::SP_QgnGrafTabActiveM,
+ QS60StyleEnums::SP_QgnGrafTabActiveL, Qt::Horizontal, painter, rect, flags | SF_PointSouth);
+ break;
+ case SE_TabBarTabSouthInactive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveR, QS60StyleEnums::SP_QgnGrafTabPassiveM,
+ QS60StyleEnums::SP_QgnGrafTabPassiveL, Qt::Horizontal, painter, rect, flags | SF_PointSouth);
+ break;
+ case SE_TabBarTabWestActive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabActiveR, QS60StyleEnums::SP_QgnGrafTabActiveM,
+ QS60StyleEnums::SP_QgnGrafTabActiveL, Qt::Vertical, painter, rect, flags | SF_PointWest);
+ break;
+ case SE_TabBarTabWestInactive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveR, QS60StyleEnums::SP_QgnGrafTabPassiveM,
+ QS60StyleEnums::SP_QgnGrafTabPassiveL, Qt::Vertical, painter, rect, flags | SF_PointWest);
+ break;
+ case SE_ListHighlight:
+ drawFrame(SF_ListHighlight, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_OptionsMenu:
+ drawFrame(SF_OptionsMenu, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_SettingsList:
+ drawFrame(SF_SettingsList, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_TableItem:
+ drawFrame(SF_TableItem, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_TableHeaderItem:
+ drawFrame(SF_TableHeaderItem, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ToolTip:
+ drawFrame(SF_ToolTip, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ToolBar:
+ drawFrame(SF_ToolBar, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ToolBarButton:
+ drawFrame(SF_ToolBarButton, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ToolBarButtonPressed:
+ drawFrame(SF_ToolBarButtonPressed, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_PanelBackground:
+ drawFrame(SF_PanelBackground, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ScrollBarHandlePressedHorizontal:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed, QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed,
+ QS60StyleEnums::SP_QsnCpScrollHandleTopPressed, Qt::Horizontal, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_ScrollBarHandlePressedVertical:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollHandleTopPressed, QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed,
+ QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed, Qt::Vertical, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ButtonInactive:
+ drawFrame(SF_ButtonInactive, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_Editor:
+ drawFrame(SF_Editor, painter, rect, flags | SF_PointNorth);
+ break;
+ default:
+ break;
+ }
+}
+
+void QS60StylePrivate::drawSkinPart(QS60StyleEnums::SkinParts part,
+ QPainter *painter, const QRect &rect, SkinElementFlags flags)
+{
+ drawPart(part, painter, rect, flags);
+}
+
+short QS60StylePrivate::pixelMetric(int metric)
+{
+ Q_ASSERT(metric < MAX_PIXELMETRICS);
+ const short returnValue = m_pmPointer[metric];
+ return returnValue;
+}
+
+void QS60StylePrivate::setStyleProperty(const char *name, const QVariant &value)
+{
+ if (name == propertyKeyCurrentlayout) {
+ static const QStringList layouts = styleProperty(propertyKeyLayouts).toStringList();
+ const QString layout = value.toString();
+ Q_ASSERT(layouts.contains(layout));
+ const int layoutIndex = layouts.indexOf(layout);
+ setCurrentLayout(layoutIndex);
+ QApplication::setLayoutDirection(m_layoutHeaders[layoutIndex].mirroring ? Qt::RightToLeft : Qt::LeftToRight);
+ clearCaches();
+ refreshUI();
+ }
+}
+
+QVariant QS60StylePrivate::styleProperty(const char *name) const
+{
+ if (name == propertyKeyLayouts) {
+ static QStringList layouts;
+ if (layouts.isEmpty())
+ for (int i = 0; i < m_numberOfLayouts; i++)
+ layouts.append(QLatin1String(m_layoutHeaders[i].layoutName));
+ return layouts;
+ }
+ return QVariant();
+}
+
+QColor QS60StylePrivate::stateColor(const QColor &color, const QStyleOption *option)
+{
+ QColor retColor (color);
+ if (option && !(option->state & QStyle::State_Enabled)) {
+ QColor hsvColor = retColor.toHsv();
+ int colorSat = hsvColor.saturation();
+ int colorVal = hsvColor.value();
+ colorSat = (colorSat!=0) ? (colorSat>>1) : 128;
+ colorVal = (colorVal!=0) ? (colorVal>>1) : 128;
+ hsvColor.setHsv(hsvColor.hue(), colorSat, colorVal);
+ retColor = hsvColor.toRgb();
+ }
+ return retColor;
+}
+
+QColor QS60StylePrivate::lighterColor(const QColor &baseColor)
+{
+ QColor result(baseColor);
+ bool modifyColor = false;
+ if (result.saturation() == 0) {
+ result.setHsv(result.hue(), 128, result.value());
+ modifyColor = true;
+ }
+ if (result.value() == 0) {
+ result.setHsv(result.hue(), result.saturation(), 128);
+ modifyColor = true;
+ }
+ if (modifyColor)
+ result = result.lighter(175);
+ else
+ result = result.lighter(225);
+ return result;
+}
+
+bool QS60StylePrivate::drawsOwnThemeBackground(const QWidget *widget)
+{
+ return qobject_cast<const QDialog *> (widget);
+}
+
+QFont QS60StylePrivate::s60Font(
+ QS60StyleEnums::FontCategories fontCategory, int pointSize) const
+{
+ QFont result;
+ int actualPointSize = pointSize;
+ if (actualPointSize <= 0) {
+ const QFont appFont = QApplication::font();
+ actualPointSize = appFont.pointSize();
+ if (actualPointSize <= 0)
+ actualPointSize = appFont.pixelSize() * 72 / qt_defaultDpiY();
+ }
+ Q_ASSERT(actualPointSize > 0);
+ const QPair<QS60StyleEnums::FontCategories, int> key(fontCategory, actualPointSize);
+ if (!m_mappedFontsCache.contains(key)) {
+ result = s60Font_specific(fontCategory, actualPointSize);
+ m_mappedFontsCache.insert(key, result);
+ } else {
+ result = m_mappedFontsCache.value(key);
+ if (result.pointSize() != actualPointSize)
+ result.setPointSize(actualPointSize);
+ }
+ return result;
+}
+
+void QS60StylePrivate::clearCaches(CacheClearReason reason)
+{
+ switch(reason){
+ case CC_LayoutChange:
+ // when layout changes, the colors remain in cache, but graphics and fonts can change
+ m_mappedFontsCache.clear();
+ deleteBackground();
+ QPixmapCache::clear();
+ break;
+ case CC_ThemeChange:
+ m_colorCache.clear();
+ QPixmapCache::clear();
+ deleteBackground();
+ break;
+ case CC_UndefinedChange:
+ default:
+ m_colorCache.clear();
+ m_mappedFontsCache.clear();
+ QPixmapCache::clear();
+ deleteBackground();
+ break;
+ }
+}
+
+// Since S60Style has 'button' and 'tooltip' as a graphic, we don't have any native color which to use
+// for QPalette::Button and QPalette::ToolTipBase. Therefore S60Style needs to guesstimate
+// palette colors by calculating average rgb values for button pixels.
+// Returns Qt::black if there is an issue with the graphics (image is NULL, or no bits() found).
+QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const
+{
+ const bool cachedColorExists = m_colorCache.contains(frame);
+ if (!cachedColorExists) {
+ const int frameCornerWidth = pixelMetric(PM_Custom_FrameCornerWidth);
+ const int frameCornerHeight = pixelMetric(PM_Custom_FrameCornerHeight);
+ Q_ASSERT(2*frameCornerWidth<32);
+ Q_ASSERT(2*frameCornerHeight<32);
+
+ const QImage frameImage = QS60StylePrivate::frame(frame, QSize(32,32)).toImage();
+ Q_ASSERT(frameImage.bytesPerLine() > 0);
+ if (frameImage.isNull())
+ return Qt::black;
+
+ const QRgb *pixelRgb = (const QRgb*)frameImage.bits();
+ const int pixels = frameImage.numBytes()/sizeof(QRgb);
+
+ int estimatedRed = 0;
+ int estimatedGreen = 0;
+ int estimatedBlue = 0;
+
+ int skips = 0;
+ int estimations = 0;
+
+ const int topBorderLastPixel = frameCornerHeight*frameImage.width()-1;
+ const int bottomBorderFirstPixel = frameImage.width()*frameImage.height()-frameCornerHeight*frameImage.width()-1;
+ const int rightBorderFirstPixel = frameImage.width()-frameCornerWidth;
+ const int leftBorderLastPixel = frameCornerWidth;
+
+ while ((skips + estimations) < pixels) {
+ if ((skips+estimations) > topBorderLastPixel &&
+ (skips+estimations) < bottomBorderFirstPixel) {
+ for (int rowIndex = 0; rowIndex < frameImage.width(); rowIndex++) {
+ if (rowIndex > leftBorderLastPixel &&
+ rowIndex < rightBorderFirstPixel) {
+ estimatedRed += qRed(*pixelRgb);
+ estimatedGreen += qGreen(*pixelRgb);
+ estimatedBlue += qBlue(*pixelRgb);
+ }
+ pixelRgb++;
+ estimations++;
+ }
+ } else {
+ pixelRgb++;
+ skips++;
+ }
+ }
+ QColor frameColor(estimatedRed/estimations, estimatedGreen/estimations, estimatedBlue/estimations);
+ m_colorCache.insert(frame, frameColor);
+ return !estimations ? Qt::black : frameColor;
+ } else {
+ return m_colorCache.value(frame);
+ }
+
+}
+
+void QS60StylePrivate::setThemePalette(QApplication *app) const
+{
+ Q_UNUSED(app)
+ QPalette widgetPalette = QPalette(Qt::white);
+ setThemePalette(&widgetPalette);
+ QApplication::setPalette(widgetPalette); //calling QApplication::setPalette clears palette hash
+ setThemePaletteHash(&widgetPalette);
+ storeThemePalette(&widgetPalette);
+}
+
+void QS60StylePrivate::setThemePalette(QStyleOption *option) const
+{
+ setThemePalette(&option->palette);
+}
+
+QPalette* QS60StylePrivate::themePalette()
+{
+ return m_themePalette;
+}
+
+void QS60StylePrivate::setBackgroundTexture(QApplication *app) const
+{
+ Q_UNUSED(app)
+ QPalette applicationPalette = QApplication::palette();
+ applicationPalette.setBrush(QPalette::Window, backgroundTexture());
+ QApplication::setPalette(applicationPalette);
+}
+
+void QS60StylePrivate::deleteBackground()
+{
+ if (m_background) {
+ delete m_background;
+ m_background = 0;
+ }
+}
+
+void QS60StylePrivate::setCurrentLayout(int index)
+{
+ m_pmPointer = data[index];
+}
+
+void QS60StylePrivate::drawPart(QS60StyleEnums::SkinParts skinPart,
+ QPainter *painter, const QRect &rect, SkinElementFlags flags)
+{
+ static const bool doCache =
+#if defined(Q_WS_S60)
+ // Freezes on 3.1. Anyways, caching is only really needed on touch UI
+ !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
+#else
+ true;
+#endif
+ const QPixmap skinPartPixMap((doCache ? cachedPart : part)(skinPart, rect.size(), flags));
+ if (!skinPartPixMap.isNull())
+ painter->drawPixmap(rect.topLeft(), skinPartPixMap);
+}
+
+void QS60StylePrivate::drawFrame(SkinFrameElements frameElement, QPainter *painter, const QRect &rect, SkinElementFlags flags)
+{
+ static const bool doCache =
+#if defined(Q_WS_S60)
+ // Freezes on 3.1. Anyways, caching is only really needed on touch UI
+ !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
+#else
+ true;
+#endif
+ const QPixmap frameElementPixMap((doCache ? cachedFrame : frame)(frameElement, rect.size(), flags));
+ if (!frameElementPixMap.isNull())
+ painter->drawPixmap(rect.topLeft(), frameElementPixMap);
+}
+
+void QS60StylePrivate::drawRow(QS60StyleEnums::SkinParts start,
+ QS60StyleEnums::SkinParts middle, QS60StyleEnums::SkinParts end,
+ Qt::Orientation orientation, QPainter *painter, const QRect &rect,
+ SkinElementFlags flags)
+{
+ QSize startEndSize(partSize(start, flags));
+ startEndSize.scale(rect.size(), Qt::KeepAspectRatio);
+
+ QRect startRect = QRect(rect.topLeft(), startEndSize);
+ QRect middleRect = rect;
+ QRect endRect;
+
+ if (orientation == Qt::Horizontal) {
+ startRect.setWidth(qMin((rect.width() >> 1) - 1, startRect.width()));
+ endRect = startRect.translated(rect.width() - startRect.width(), 0);
+ middleRect.adjust(startRect.width(), 0, -startRect.width(), 0);
+ if (startRect.bottomRight().x() > endRect.topLeft().x()) {
+ const int overlap = (startRect.bottomRight().x() - endRect.topLeft().x())>>1;
+ startRect.setWidth(startRect.width()-overlap);
+ endRect.adjust(overlap,0,0,0);
+ }
+ } else {
+ startRect.setHeight(qMin((rect.height() >> 1) - 1, startRect.height()));
+ endRect = startRect.translated(0, rect.height() - startRect.height());
+ middleRect.adjust(0, startRect.height(), 0, -startRect.height());
+ if (startRect.topRight().y() > endRect.bottomLeft().y()) {
+ const int overlap = (startRect.topRight().y() - endRect.bottomLeft().y())>>1;
+ startRect.setHeight(startRect.height()-overlap);
+ endRect.adjust(0,overlap,0,0);
+ }
+ }
+
+#if 0
+ painter->save();
+ painter->setOpacity(.3);
+ painter->fillRect(startRect, Qt::red);
+ painter->fillRect(middleRect, Qt::green);
+ painter->fillRect(endRect, Qt::blue);
+ painter->restore();
+#else
+ drawPart(start, painter, startRect, flags);
+ if (middleRect.isValid())
+ drawPart(middle, painter, middleRect, flags);
+ drawPart(end, painter, endRect, flags);
+#endif
+}
+
+QPixmap QS60StylePrivate::cachedPart(QS60StyleEnums::SkinParts part,
+ const QSize &size, SkinElementFlags flags)
+{
+ QPixmap result;
+ const QString cacheKey =
+ QString::fromLatin1("S60Style: SkinParts=%1 QSize=%2|%3 SkinPartFlags=%4")
+ .arg((int)part).arg(size.width()).arg(size.height()).arg((int)flags);
+ if (!QPixmapCache::find(cacheKey, result)) {
+ result = QS60StylePrivate::part(part, size, flags);
+ QPixmapCache::insert(cacheKey, result);
+ }
+ return result;
+}
+
+QPixmap QS60StylePrivate::cachedFrame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags)
+{
+ QPixmap result;
+ const QString cacheKey =
+ QString::fromLatin1("S60Style: SkinFrameElements=%1 QSize=%2|%3 SkinElementFlags=%4")
+ .arg((int)frame).arg(size.width()).arg(size.height()).arg((int)flags);
+ if (!QPixmapCache::find(cacheKey, result)) {
+ result = QS60StylePrivate::frame(frame, size, flags);
+ QPixmapCache::insert(cacheKey, result);
+ }
+ return result;
+}
+
+void QS60StylePrivate::refreshUI()
+{
+ QList<QWidget *> widgets = QApplication::allWidgets();
+
+ for (int i = 0; i < widgets.size(); ++i) {
+ QWidget *widget = widgets.at(i);
+ if (widget == 0)
+ continue;
+
+ if (widget->style()) {
+ widget->style()->polish(widget);
+ QEvent event(QEvent::StyleChange);
+ qApp->sendEvent(widget, &event);
+ }
+ widget->update();
+ widget->updateGeometry();
+ }
+}
+
+void QS60StylePrivate::setFont(QWidget *widget) const
+{
+ QS60StyleEnums::FontCategories fontCategory = QS60StyleEnums::FC_Undefined;
+ if (!widget)
+ return;
+ if (qobject_cast<QPushButton *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Primary;
+ } else if (qobject_cast<QToolButton *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Primary;
+ } else if (qobject_cast<QHeaderView *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Secondary;
+ } else if (qobject_cast<QGroupBox *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Title;
+ }
+ if (fontCategory != QS60StyleEnums::FC_Undefined) {
+ const QFont suggestedFont =
+ s60Font(fontCategory, widget->font().pointSizeF());
+ widget->setFont(suggestedFont);
+ }
+}
+
+void QS60StylePrivate::setThemePalette(QWidget *widget) const
+{
+ if(!widget)
+ return;
+ QPalette widgetPalette = QApplication::palette(widget);
+
+ //header view and its viewport need to be set 100% transparent button color, since drawing code will
+ //draw transparent theme graphics to table column and row headers.
+ if (qobject_cast<QHeaderView *>(widget)){
+ widgetPalette.setColor(QPalette::Active, QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 23, 0));
+ QHeaderView* header = qobject_cast<QHeaderView *>(widget);
+ widgetPalette.setColor(QPalette::Button, Qt::transparent );
+ if ( header->viewport() )
+ header->viewport()->setPalette(widgetPalette);
+ QApplication::setPalette(widgetPalette, "QHeaderView");
+ }
+}
+
+void QS60StylePrivate::setThemePalette(QPalette *palette) const
+{
+ if (!palette)
+ return;
+
+ // basic colors
+ palette->setColor(QPalette::WindowText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0));
+ palette->setColor(QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0));
+ palette->setColor(QPalette::Text,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0));
+ palette->setColor(QPalette::ToolTipText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 55, 0));
+ palette->setColor(QPalette::BrightText, palette->color(QPalette::WindowText).lighter());
+ palette->setColor(QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0));
+ palette->setColor(QPalette::Link,
+ s60Color(QS60StyleEnums::CL_QsnHighlightColors, 3, 0));
+ palette->setColor(QPalette::LinkVisited, palette->color(QPalette::Link).darker());
+ palette->setColor(QPalette::Highlight,
+ s60Color(QS60StyleEnums::CL_QsnHighlightColors, 2, 0));
+ // set background image as a texture brush
+ palette->setBrush(QPalette::Window, backgroundTexture());
+ // set these as transparent so that styled full screen theme background is visible
+ palette->setColor(QPalette::AlternateBase, Qt::transparent);
+ palette->setBrush(QPalette::Base, Qt::transparent);
+ // set button and tooltipbase based on pixel colors
+ const QColor buttonColor = this->colorFromFrameGraphics(SF_ButtonNormal);
+ palette->setColor(QPalette::Button, buttonColor );
+ const QColor toolTipColor = this->colorFromFrameGraphics(SF_ToolTip);
+ palette->setColor(QPalette::ToolTipBase, toolTipColor );
+ palette->setColor(QPalette::Light, palette->color(QPalette::Button).lighter());
+ palette->setColor(QPalette::Dark, palette->color(QPalette::Button).darker());
+ palette->setColor(QPalette::Midlight, palette->color(QPalette::Button).lighter(125));
+ palette->setColor(QPalette::Mid, palette->color(QPalette::Button).darker(150));
+ palette->setColor(QPalette::Shadow, Qt::black);
+}
+
+void QS60StylePrivate::deleteThemePalette()
+{
+ if (m_themePalette) {
+ delete m_themePalette;
+ m_themePalette = 0;
+ }
+}
+
+void QS60StylePrivate::storeThemePalette(QPalette *palette)
+{
+ deleteThemePalette();
+ //store specified palette for latter use.
+ m_themePalette = new QPalette(*palette);
+}
+
+// set widget specific palettes
+void QS60StylePrivate::setThemePaletteHash(QPalette *palette) const
+{
+ if (!palette)
+ return;
+
+ //store the original palette
+ QPalette widgetPalette = *palette;
+ const QColor mainAreaTextColor =
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0);
+
+ widgetPalette.setColor(QPalette::All, QPalette::WindowText,
+ s60Color(QS60StyleEnums::CL_QsnLineColors, 8, 0));
+ QApplication::setPalette(widgetPalette, "QSlider");
+ // return to original palette after each widget
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, mainAreaTextColor);
+ widgetPalette.setColor(QPalette::Inactive, QPalette::ButtonText, mainAreaTextColor);
+ const QStyleOption opt;
+ widgetPalette.setColor(QPalette::Disabled, QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, &opt));
+ QApplication::setPalette(widgetPalette, "QPushButton");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, mainAreaTextColor);
+ widgetPalette.setColor(QPalette::Inactive, QPalette::ButtonText, mainAreaTextColor);
+ QApplication::setPalette(widgetPalette, "QToolButton");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::Active, QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 23, 0));
+ QApplication::setPalette(widgetPalette, "QHeaderView");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 8, 0));
+ QApplication::setPalette(widgetPalette, "QMenuBar");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::Active, QPalette::WindowText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 4, 0));
+ QApplication::setPalette(widgetPalette, "QTabBar");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::Text,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0));
+ QApplication::setPalette(widgetPalette, "QTableView");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0));
+ QApplication::setPalette(widgetPalette, "QLineEdit");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::Text,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 34, 0));
+ widgetPalette.setColor(QPalette::All, QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0));
+ QApplication::setPalette(widgetPalette, "QTextEdit");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0));
+ QApplication::setPalette(widgetPalette, "QComboBox");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::WindowText, mainAreaTextColor);
+ widgetPalette.setColor(QPalette::Button, QApplication::palette().color(QPalette::Button));
+ widgetPalette.setColor(QPalette::Dark, mainAreaTextColor.darker());
+ widgetPalette.setColor(QPalette::Light, mainAreaTextColor.lighter());
+ QApplication::setPalette(widgetPalette, "QDial");
+ widgetPalette = *palette;
+
+ widgetPalette.setBrush(QPalette::Window, QBrush());
+ QApplication::setPalette(widgetPalette, "QScrollArea");
+ widgetPalette = *palette;
+}
+
+QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlags flags)
+{
+ QSize result(20, 20);
+ switch (part)
+ {
+ case QS60StyleEnums::SP_QgnGrafBarProgress:
+ result.setWidth(pixelMetric(QStyle::PM_ProgressBarChunkWidth));
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabActiveM:
+ case QS60StyleEnums::SP_QgnGrafTabPassiveM:
+ case QS60StyleEnums::SP_QgnGrafTabActiveR:
+ case QS60StyleEnums::SP_QgnGrafTabPassiveR:
+ case QS60StyleEnums::SP_QgnGrafTabPassiveL:
+ case QS60StyleEnums::SP_QgnGrafTabActiveL:
+ break;
+ case QS60StyleEnums::SP_QgnIndiSliderEdit:
+ result.scale(pixelMetric(QStyle::PM_SliderLength),
+ pixelMetric(QStyle::PM_SliderControlThickness), Qt::IgnoreAspectRatio);
+ break;
+
+ case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed:
+ case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed:
+ case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed:
+ case QS60StyleEnums::SP_QsnCpScrollBgBottom:
+ case QS60StyleEnums::SP_QsnCpScrollBgMiddle:
+ case QS60StyleEnums::SP_QsnCpScrollBgTop:
+ case QS60StyleEnums::SP_QsnCpScrollHandleBottom:
+ case QS60StyleEnums::SP_QsnCpScrollHandleMiddle:
+ case QS60StyleEnums::SP_QsnCpScrollHandleTop:
+ result.setHeight(pixelMetric(QStyle::PM_ScrollBarExtent));
+ result.setWidth(pixelMetric(QStyle::PM_ScrollBarSliderMin));
+ break;
+ default:
+ // Generic frame part size gathering.
+ for (int i = 0; i < frameElementsCount; ++i)
+ {
+ switch (m_frameElementsData[i].center - part) {
+ case 8: /* CornerTl */
+ case 7: /* CornerTr */
+ case 6: /* CornerBl */
+ case 5: /* CornerBr */
+ result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ // Falltrough intended...
+ case 4: /* SideT */
+ case 3: /* SideB */
+ result.setHeight(pixelMetric(PM_Custom_FrameCornerHeight));
+ break;
+ case 2: /* SideL */
+ case 1: /* SideR */
+ result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ break;
+ case 0: /* center */
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ if (flags & (SF_PointEast | SF_PointWest)) {
+ const int temp = result.width();
+ result.setWidth(result.height());
+ result.setHeight(temp);
+ }
+ return result;
+}
+
+/*!
+ \class QS60Style
+ \brief The QS60Style class provides a look and feel suitable for applications on S60.
+ \since 4.6
+ \ingroup appearance
+
+ \sa QMacStyle, QWindowsStyle, QWindowsXPStyle, QWindowsVistaStyle, QPlastiqueStyle, QCleanlooksStyle, QMotifStyle
+*/
+
+
+/*!
+ Destroys the style.
+*/
+QS60Style::~QS60Style()
+{
+}
+
+/*!
+ \reimp
+*/
+void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
+{
+ const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled;
+ SubControls sub = option->subControls;
+
+ switch (control) {
+#ifndef QT_NO_SCROLLBAR
+ case CC_ScrollBar:
+ if (const QStyleOptionSlider *optionSlider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ const bool horizontal = optionSlider->orientation == Qt::Horizontal;
+
+ const QRect scrollBarSlider = subControlRect(control, optionSlider, SC_ScrollBarSlider, widget);
+ const QRect grooveRect = subControlRect(control, optionSlider, SC_ScrollBarGroove, widget);
+
+ const QS60StylePrivate::SkinElements grooveElement =
+ horizontal ? QS60StylePrivate::SE_ScrollBarGrooveHorizontal : QS60StylePrivate::SE_ScrollBarGrooveVertical;
+ QS60StylePrivate::drawSkinElement(grooveElement, painter, grooveRect, flags);
+
+ const QStyle::SubControls subControls = optionSlider->subControls;
+
+ // select correct slider (horizontal/vertical/pressed)
+ const bool sliderPressed = ((optionSlider->state & QStyle::State_Sunken) && (subControls & SC_ScrollBarSlider));
+ const QS60StylePrivate::SkinElements handleElement =
+ horizontal ?
+ ( sliderPressed ?
+ QS60StylePrivate::SE_ScrollBarHandlePressedHorizontal :
+ QS60StylePrivate::SE_ScrollBarHandleHorizontal ) :
+ ( sliderPressed ?
+ QS60StylePrivate::SE_ScrollBarHandlePressedVertical :
+ QS60StylePrivate::SE_ScrollBarHandleVertical);
+ QS60StylePrivate::drawSkinElement(handleElement, painter, scrollBarSlider, flags);
+ }
+ break;
+#endif // QT_NO_SCROLLBAR
+#ifndef QT_NO_SLIDER
+ case CC_Slider:
+ if (const QStyleOptionSlider *optionSlider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+
+ // The groove is just a centered line. Maybe a qgn_graf_line_* at some point
+ const QRect sliderGroove = subControlRect(control, optionSlider, SC_SliderGroove, widget);
+ const QPoint sliderGrooveCenter = sliderGroove.center();
+ const bool horizontal = optionSlider->orientation == Qt::Horizontal;
+ painter->save();
+ if (widget)
+ painter->setPen(widget->palette().windowText().color());
+ if (horizontal)
+ painter->drawLine(0, sliderGrooveCenter.y(), sliderGroove.right(), sliderGrooveCenter.y());
+ else
+ painter->drawLine(sliderGrooveCenter.x(), 0, sliderGrooveCenter.x(), sliderGroove.bottom());
+ painter->restore();
+
+ const QRect sliderHandle = subControlRect(control, optionSlider, SC_SliderHandle, widget);
+ const QS60StylePrivate::SkinElements handleElement =
+ horizontal ? QS60StylePrivate::SE_SliderHandleHorizontal : QS60StylePrivate::SE_SliderHandleVertical;
+ QS60StylePrivate::drawSkinElement(handleElement, painter, sliderHandle, flags);
+ }
+ break;
+#endif // QT_NO_SLIDER
+#ifndef QT_NO_COMBOBOX
+ case CC_ComboBox:
+ if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
+ const QRect cmbxEditField = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget);
+ const QRect cmbxFrame = subControlRect(CC_ComboBox, option, SC_ComboBoxFrame, widget);
+ const bool direction = cmb->direction == Qt::LeftToRight;
+
+ // Button frame
+ QStyleOptionFrame buttonOption;
+ buttonOption.QStyleOption::operator=(*cmb);
+ const int maxHeight = cmbxFrame.height();
+ const int maxWidth = cmbxFrame.width() - cmbxEditField.width();
+ const int topLeftPoint = direction ? cmbxEditField.right()+1 : cmbxEditField.left()+1-maxWidth;
+ const QRect buttonRect(topLeftPoint, cmbxEditField.top(), maxWidth, maxHeight);
+ buttonOption.rect = buttonRect;
+ buttonOption.state = cmb->state & (State_Enabled | State_MouseOver);
+ drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget);
+
+ // draw label background - label itself is drawn separately
+ const QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_FrameLineEdit;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, cmbxEditField, flags);
+
+ // Draw the combobox arrow
+ if (sub & SC_ComboBoxArrow) {
+ // Make rect slightly smaller
+ buttonOption.rect.adjust(1, 1, -1, -1);
+ painter->save();
+ painter->setPen(option->palette.buttonText().color());
+ drawPrimitive(PE_IndicatorSpinDown, &buttonOption, painter, widget);
+ painter->restore();
+ }
+ }
+ break;
+#endif // QT_NO_COMBOBOX
+#ifndef QT_NO_TOOLBUTTON
+ case CC_ToolButton:
+ if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
+ const State bflags = toolBtn->state;
+ const QRect button(subControlRect(control, toolBtn, SC_ToolButton, widget));
+ QStyleOptionToolButton toolButton = *toolBtn;
+
+ if (sub&SC_ToolButton) {
+ QStyleOption tool(0);
+ tool.palette = toolBtn->palette;
+
+ // Check if toolbutton is in toolbar.
+ QToolBar *toolBar = 0;
+ if (widget)
+ toolBar = qobject_cast<QToolBar *>(widget->parentWidget());
+
+ if (bflags & (State_Sunken | State_On | State_Raised)) {
+ tool.rect = button;
+ tool.state = bflags;
+
+ // todo: I'd like to move extension button next to where last button is
+ // however, the painter seems to want to clip the button rect even if I turn of the clipping.
+ if (toolBar && (qobject_cast<const QToolBarExtension *>(widget))){
+ /*QList<QAction *> actionList = toolBar->actions();
+ const int actionCount = actionList.count();
+ const int toolbarWidth = toolBar->width();
+ const int extButtonWidth = pixelMetric(PM_ToolBarExtensionExtent, option, widget);
+ const int toolBarButtonWidth = pixelMetric(PM_ToolBarIconSize, option, widget);
+ const int frame = pixelMetric(PM_ToolBarFrameWidth, option, widget);
+ const int margin = pixelMetric(PM_ToolBarItemMargin, option, widget);
+ const int border = frame + margin;
+ const int spacing = pixelMetric(PM_ToolBarItemSpacing, option, widget);
+ const int toolBarButtonArea = toolbarWidth - extButtonWidth - spacing - 2*border;
+ const int numberOfVisibleButtons = toolBarButtonArea / toolBarButtonWidth;
+ // new extension button place is after border and all the other visible buttons (with spacings)
+ const int newXForExtensionButton = numberOfVisibleButtons * toolBarButtonWidth + (numberOfVisibleButtons-1)*spacing + border;
+ painter->save();
+ painter->setClipping(false);
+ tool.rect.translate(-newXForExtensionButton,0);
+ painter->restore();*/
+ }
+
+ if (toolBar){
+ /*if (toolBar->orientation() == Qt::Vertical){
+ // todo: I'd like to make all vertical buttons the same size, but again the painter
+ // prefers to use clipping for button rects, even though clipping has been set off.
+ painter->save();
+ painter->setClipping(false);
+
+ const int origWidth = tool.rect.width();
+ const int newWidth = toolBar->width()-2*pixelMetric(PM_ToolBarFrameWidth, option, widget);
+ painter->translate(origWidth-newWidth,0);
+ tool.rect.translate(origWidth-tool.rect.width(),0);
+ tool.rect.setWidth(newWidth);
+
+ if (option->state & QStyle::State_Sunken)
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButtonPressed, painter, tool.rect, flags);
+ else
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButton, painter, tool.rect, flags);
+
+ }*/
+ if (option->state & QStyle::State_Sunken)
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButtonPressed, painter, tool.rect, flags);
+ else
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButton, painter, tool.rect, flags);
+ /*
+ if (toolBar->orientation() == Qt::Vertical)
+ painter->restore();
+ */
+ } else {
+ drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
+ }
+ }
+ }
+
+ if (toolBtn->features & QStyleOptionToolButton::Arrow) {
+ QStyle::PrimitiveElement pe;
+ switch (toolBtn->arrowType) {
+ case Qt::LeftArrow:
+ pe = QStyle::PE_IndicatorArrowLeft;
+ break;
+ case Qt::RightArrow:
+ pe = QStyle::PE_IndicatorArrowRight;
+ break;
+ case Qt::UpArrow:
+ pe = QStyle::PE_IndicatorArrowUp;
+ break;
+ case Qt::DownArrow:
+ pe = QStyle::PE_IndicatorArrowDown;
+ break;
+ default:
+ break; }
+ toolButton.rect = button;
+ drawPrimitive(pe, &toolButton, painter, widget);
+ }
+
+ if (toolBtn->text.length()>0 ||
+ !toolBtn->icon.isNull()) {
+ const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget);
+ toolButton.rect = button.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth);
+ drawControl(CE_ToolButtonLabel, &toolButton, painter, widget);
+ }
+ }
+ break;
+#endif //QT_NO_TOOLBUTTON
+#ifndef QT_NO_SPINBOX
+ case CC_SpinBox:
+ if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ QStyleOptionSpinBox copy = *spinBox;
+ PrimitiveElement pe;
+
+ if (spinBox->subControls & SC_SpinBoxUp) {
+ copy.subControls = SC_SpinBoxUp;
+ QPalette spinBoxPal = spinBox->palette;
+ if (!(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled)) {
+ spinBoxPal.setCurrentColorGroup(QPalette::Disabled);
+ copy.state &= ~State_Enabled;
+ copy.palette = spinBoxPal;
+ }
+
+ if (spinBox->activeSubControls == SC_SpinBoxUp && (spinBox->state & State_Sunken)) {
+ copy.state |= State_On;
+ copy.state |= State_Sunken;
+ } else {
+ copy.state |= State_Raised;
+ copy.state &= ~State_Sunken;
+ }
+ pe = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) ?
+ PE_IndicatorSpinPlus :
+ PE_IndicatorSpinUp;
+
+ copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxUp, widget);
+ drawPrimitive(PE_PanelButtonBevel, &copy, painter, widget);
+ copy.rect.adjust(1, 1, -1, -1);
+ drawPrimitive(pe, &copy, painter, widget);
+ }
+
+ if (spinBox->subControls & SC_SpinBoxDown) {
+ copy.subControls = SC_SpinBoxDown;
+ copy.state = spinBox->state;
+ QPalette spinBoxPal = spinBox->palette;
+ if (!(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled)) {
+ spinBoxPal.setCurrentColorGroup(QPalette::Disabled);
+ copy.state &= ~State_Enabled;
+ copy.palette = spinBoxPal;
+ }
+
+ if (spinBox->activeSubControls == SC_SpinBoxDown && (spinBox->state & State_Sunken)) {
+ copy.state |= State_On;
+ copy.state |= State_Sunken;
+ } else {
+ copy.state |= State_Raised;
+ copy.state &= ~State_Sunken;
+ }
+ pe = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) ?
+ PE_IndicatorSpinMinus :
+ PE_IndicatorSpinDown;
+
+ copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxDown, widget);
+ drawPrimitive(PE_PanelButtonBevel, &copy, painter, widget);
+ copy.rect.adjust(1, 1, -1, -1);
+ drawPrimitive(pe, &copy, painter, widget);
+ }
+ }
+ break;
+#endif //QT_NO_SPINBOX
+#ifndef QT_NO_GROUPBOX
+ case CC_GroupBox:
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
+ // Draw frame
+ const QRect textRect = subControlRect(CC_GroupBox, option, SC_GroupBoxLabel, widget);
+ const QRect checkBoxRect = subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget);
+ if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
+ QStyleOptionFrameV2 frame;
+ frame.QStyleOption::operator=(*groupBox);
+ frame.features = groupBox->features;
+ frame.lineWidth = groupBox->lineWidth;
+ frame.midLineWidth = groupBox->midLineWidth;
+ frame.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
+ drawPrimitive(PE_FrameGroupBox, &frame, painter, widget);
+ }
+
+ // Draw title
+ if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
+ const QColor textColor = groupBox->textColor;
+ painter->save();
+
+ if (textColor.isValid())
+ painter->setPen(textColor);
+ int alignment = int(groupBox->textAlignment);
+ if (!styleHint(QStyle::SH_UnderlineShortcut, option, widget))
+ alignment |= Qt::TextHideMnemonic;
+
+ drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | Qt::AlignVCenter | alignment,
+ groupBox->palette, groupBox->state & State_Enabled, groupBox->text,
+ textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
+ painter->restore();
+ }
+
+ // Draw checkbox
+ if (groupBox->subControls & SC_GroupBoxCheckBox) {
+ QStyleOptionButton box;
+ box.QStyleOption::operator=(*groupBox);
+ box.rect = checkBoxRect;
+ drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
+ }
+ }
+ break;
+#endif //QT_NO_GROUPBOX
+ default:
+ QCommonStyle::drawComplexControl(control, option, painter, widget);
+ }
+}
+
+/*!
+ \reimp
+*/
+void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
+{
+ Q_D(const QS60Style);
+ const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled;
+ switch (element) {
+ case CE_PushButton:
+ if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
+
+ drawControl(CE_PushButtonBevel, btn, painter, widget);
+ QStyleOptionButton subopt = *btn;
+ subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
+
+ drawControl(CE_PushButtonLabel, &subopt, painter, widget);
+ }
+ break;
+ case CE_PushButtonBevel:
+ if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
+ const bool isDisabled = !(option->state & QStyle::State_Enabled);
+ const bool isFlat = button->features & QStyleOptionButton::Flat;
+ QS60StyleEnums::SkinParts skinPart;
+ QS60StylePrivate::SkinElements skinElement;
+ if (!isDisabled) {
+ const bool isPressed = (option->state & QStyle::State_Sunken) ||
+ (option->state & QStyle::State_On);
+ if (isFlat) {
+ skinPart =
+ isPressed ? QS60StyleEnums::SP_QsnFrButtonTbCenterPressed : QS60StyleEnums::SP_QsnFrButtonTbCenter;
+ } else {
+ skinElement =
+ isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal;
+ }
+ } else {
+ if (isFlat)
+ skinPart =QS60StyleEnums::SP_QsnFrButtonCenterInactive;
+ else
+ skinElement = QS60StylePrivate::SE_ButtonInactive;
+ }
+ if (isFlat)
+ QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags);
+ else
+ QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
+ }
+ break;
+#ifndef QT_NO_TOOLBUTTON
+ case CE_ToolButtonLabel:
+ if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
+ QStyleOptionToolButton optionToolButton = *toolBtn;
+
+ if (!optionToolButton.icon.isNull() && (optionToolButton.state & QStyle::State_Sunken)
+ && (optionToolButton.state & State_Enabled)) {
+
+ const QIcon::State state = optionToolButton.state & State_On ? QIcon::On : QIcon::Off;
+ const QPixmap pm(optionToolButton.icon.pixmap(optionToolButton.rect.size().boundedTo(optionToolButton.iconSize),
+ QIcon::Normal, state));
+ optionToolButton.icon = generatedIconPixmap(QIcon::Selected, pm, &optionToolButton);
+ }
+
+ QCommonStyle::drawControl(element, &optionToolButton, painter, widget);
+ }
+ break;
+#endif //QT_NO_TOOLBUTTON
+#ifndef QT_NO_COMBOBOX
+ case CE_ComboBoxLabel:
+ if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
+ QStyleOption optionComboBox = *comboBox;
+ optionComboBox.palette.setColor(QPalette::Active, QPalette::WindowText,
+ optionComboBox.palette.text().color() );
+ optionComboBox.palette.setColor(QPalette::Inactive, QPalette::WindowText,
+ optionComboBox.palette.text().color() );
+ QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget);
+ painter->save();
+ painter->setClipRect(editRect);
+
+ if (!comboBox->currentIcon.isNull()) {
+ QIcon::Mode mode = comboBox->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
+ QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode);
+ QRect iconRect(editRect);
+ iconRect.setWidth(comboBox->iconSize.width() + 4);
+ iconRect = alignedRect(comboBox->direction,
+ Qt::AlignLeft | Qt::AlignVCenter,
+ iconRect.size(), editRect);
+ if (comboBox->editable)
+ painter->fillRect(iconRect, optionComboBox.palette.brush(QPalette::Base));
+ drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
+
+ if (comboBox->direction == Qt::RightToLeft)
+ editRect.translate(-4 - comboBox->iconSize.width(), 0);
+ else
+ editRect.translate(comboBox->iconSize.width() + 4, 0);
+ }
+ if (!comboBox->currentText.isEmpty() && !comboBox->editable) {
+ QCommonStyle::drawItemText(painter,
+ editRect.adjusted(QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth), 0, -1, 0),
+ visualAlignment(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter),
+ comboBox->palette, comboBox->state & State_Enabled, comboBox->currentText);
+ }
+ painter->restore();
+ }
+ break;
+#endif //QT_NO_COMBOBOX
+#ifndef QT_NO_ITEMVIEWS
+ case CE_ItemViewItem:
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
+ QStyleOptionViewItemV4 voptAdj = *vopt;
+ painter->save();
+
+ painter->setClipRect(voptAdj.rect);
+ const bool isSelected = (voptAdj.state & QStyle::State_HasFocus);
+
+ bool isVisible = false;
+ int scrollBarWidth = 0;
+ QList<QScrollBar *> scrollBars = qFindChildren<QScrollBar *>(widget);
+ for (int i = 0; i < scrollBars.size(); ++i) {
+ QScrollBar *scrollBar = scrollBars.at(i);
+ if (scrollBar && scrollBar->orientation() == Qt::Vertical) {
+ isVisible = scrollBar->isVisible();
+ scrollBarWidth = scrollBar->size().width();
+ break;
+ }
+ }
+
+ int rightValue = widget ? widget->contentsRect().right() : 0;
+
+ if (isVisible)
+ rightValue -= scrollBarWidth;
+
+ if (voptAdj.rect.right() > rightValue)
+ voptAdj.rect.setRight(rightValue);
+
+ const QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &voptAdj, widget);
+ QRect textRect = subElementRect(SE_ItemViewItemText, &voptAdj, widget);
+
+ // draw themed background for table unless background brush has been defined.
+ if (vopt->backgroundBrush == Qt::NoBrush) {
+ const QStyleOptionViewItemV4 *tableOption = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option);
+ const QTableView *table = qobject_cast<const QTableView *>(widget);
+ if (table && tableOption) {
+ const QModelIndex index = tableOption->index;
+ //todo: Draw cell background only once - for the first cell.
+ QStyleOptionViewItemV4 voptAdj2 = voptAdj;
+ const QModelIndex indexFirst = table->model()->index(0,0);
+ const QModelIndex indexLast = table->model()->index(
+ table->model()->rowCount()-1,table->model()->columnCount()-1);
+ if (table->viewport())
+ voptAdj2.rect = QRect( table->visualRect(indexFirst).topLeft(),
+ table->visualRect(indexLast).bottomRight()).intersect(table->viewport()->rect());
+ drawPrimitive(PE_PanelItemViewItem, &voptAdj2, painter, widget);
+ }
+ } else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget);}
+
+ // draw the focus rect
+ if (isSelected) {
+ const QRect highlightRect = option->rect.adjusted(1,1,-1,-1);
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, highlightRect, flags);
+ }
+
+ // draw the icon
+ const QIcon::Mode mode = (voptAdj.state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled;
+ const QIcon::State state = voptAdj.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
+ voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state);
+
+ // Draw selection check mark. Show check mark only in multi selection modes.
+ if (const QListView *listView = (qobject_cast<const QListView *>(widget))) {
+ const bool singleSelection =
+ listView &&
+ (listView->selectionMode() == QAbstractItemView::SingleSelection ||
+ listView->selectionMode() == QAbstractItemView::NoSelection);
+ const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, &voptAdj, widget);
+ if (voptAdj.state & QStyle::State_Selected && !singleSelection) {
+ QStyleOptionViewItemV4 option(voptAdj);
+ option.rect = selectionRect;
+ // Draw selection mark.
+ drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, painter, widget);
+ if ( textRect.right() > selectionRect.left() )
+ textRect.setRight(selectionRect.left());
+ } else if (singleSelection &&
+ voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator) {
+ // draw the check mark
+ if (selectionRect.isValid()) {
+ QStyleOptionViewItemV4 option(*vopt);
+ option.rect = selectionRect;
+ option.state = option.state & ~QStyle::State_HasFocus;
+
+ switch (vopt->checkState) {
+ case Qt::Unchecked:
+ option.state |= QStyle::State_Off;
+ break;
+ case Qt::PartiallyChecked:
+ option.state |= QStyle::State_NoChange;
+ break;
+ case Qt::Checked:
+ option.state |= QStyle::State_On;
+ break;
+ }
+ drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, painter, widget);
+ }
+ }
+ }
+
+ // draw the text
+ if (!voptAdj.text.isEmpty()) {
+ const QStyleOptionViewItemV4 *tableOption = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option);
+ if (isSelected) {
+ if (qobject_cast<const QTableView *>(widget) && tableOption)
+ voptAdj.palette.setColor(
+ QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0));
+ else
+ voptAdj.palette.setColor(
+ QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0));
+ }
+ painter->setPen(voptAdj.palette.text().color());
+ d->viewItemDrawText(painter, &voptAdj, textRect);
+ }
+ painter->restore();
+ }
+ break;
+#endif // QT_NO_ITEMVIEWS
+#ifndef QT_NO_TABBAR
+ case CE_TabBarTabShape:
+ if (const QStyleOptionTabV3 *optionTab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) {
+ QStyleOptionTabV3 optionTabAdj = *optionTab;
+ const bool isSelected = optionTab->state & QStyle::State_Selected;
+ const bool directionMirrored = (optionTab->direction == Qt::RightToLeft);
+ QS60StylePrivate::SkinElements skinElement;
+ switch (optionTab->shape) {
+ case QTabBar::TriangularEast:
+ case QTabBar::RoundedEast:
+ skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabEastActive:
+ QS60StylePrivate::SE_TabBarTabEastInactive;
+ break;
+ case QTabBar::TriangularSouth:
+ case QTabBar::RoundedSouth:
+ skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabSouthActive:
+ QS60StylePrivate::SE_TabBarTabSouthInactive;
+ break;
+ case QTabBar::TriangularWest:
+ case QTabBar::RoundedWest:
+ skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabWestActive:
+ QS60StylePrivate::SE_TabBarTabWestInactive;
+ break;
+ case QTabBar::TriangularNorth:
+ case QTabBar::RoundedNorth:
+ default:
+ skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabNorthActive:
+ QS60StylePrivate::SE_TabBarTabNorthInactive;
+ break;
+ }
+ if (skinElement==QS60StylePrivate::SE_TabBarTabEastInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabNorthInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabSouthInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabWestInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabEastActive||
+ skinElement==QS60StylePrivate::SE_TabBarTabNorthActive||
+ skinElement==QS60StylePrivate::SE_TabBarTabSouthActive||
+ skinElement==QS60StylePrivate::SE_TabBarTabWestActive) {
+ const int borderThickness =
+ QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const int tabOverlap =
+ QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap) - borderThickness;
+ //todo: draw navi wipe behind tabbar - must be drawn with first draw
+
+ if (skinElement==QS60StylePrivate::SE_TabBarTabEastInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabEastActive||
+ skinElement==QS60StylePrivate::SE_TabBarTabWestInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabWestActive){
+ optionTabAdj.rect.adjust(0, 0, 0, tabOverlap);
+ } else {
+ if (directionMirrored)
+ optionTabAdj.rect.adjust(-tabOverlap, 0, 0, 0);
+ else
+ optionTabAdj.rect.adjust(0, 0, tabOverlap, 0);
+ }
+ }
+ QS60StylePrivate::drawSkinElement(skinElement, painter, optionTabAdj.rect, flags);
+ }
+ break;
+ case CE_TabBarTabLabel:
+ if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) {
+ QStyleOptionTabV3 optionTab = *tab;
+ QRect tr = optionTab.rect;
+ const bool directionMirrored = (optionTab.direction == Qt::RightToLeft);
+ const int borderThickness = QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const int tabOverlap =
+ QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap) - borderThickness;
+ const QRect windowRect = painter->window();
+
+ switch (tab->shape) {
+ case QTabBar::TriangularWest:
+ case QTabBar::RoundedWest:
+ case QTabBar::TriangularEast:
+ case QTabBar::RoundedEast:
+ tr.adjust(0, 0, 0, tabOverlap);
+ break;
+ case QTabBar::TriangularSouth:
+ case QTabBar::RoundedSouth:
+ case QTabBar::TriangularNorth:
+ case QTabBar::RoundedNorth:
+ default:
+ if (directionMirrored)
+ tr.adjust(-tabOverlap, 0, 0, 0);
+ else
+ tr.adjust(0, 0, tabOverlap, 0);
+ break;
+ }
+ painter->save();
+ QFont f = painter->font();
+ f.setPointSizeF(f.pointSizeF() * KTabFontMul);
+ painter->setFont(f);
+
+ if (option->state & QStyle::State_Selected){
+ optionTab.palette.setColor(QPalette::Active, QPalette::WindowText,
+ QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 3, option));
+ }
+
+ const bool verticalTabs = optionTab.shape == QTabBar::RoundedEast
+ || optionTab.shape == QTabBar::RoundedWest
+ || optionTab.shape == QTabBar::TriangularEast
+ || optionTab.shape == QTabBar::TriangularWest;
+ const bool selected = optionTab.state & State_Selected;
+ if (verticalTabs) {
+ painter->save();
+ int newX, newY, newRotation;
+ if (optionTab.shape == QTabBar::RoundedEast || optionTab.shape == QTabBar::TriangularEast) {
+ newX = tr.width();
+ newY = tr.y();
+ newRotation = 90;
+ } else {
+ newX = 0;
+ newY = tr.y() + tr.height();
+ newRotation = -90;
+ }
+ tr.setRect(0, 0, tr.height(), tr.width());
+ QTransform m;
+ m.translate(newX, newY);
+ m.rotate(newRotation);
+ painter->setTransform(m, true);
+ }
+ tr.adjust(0, 0, pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget),
+ pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget));
+
+ if (selected) {
+ tr.setBottom(tr.bottom() - pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget));
+ tr.setRight(tr.right() - pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget));
+ }
+
+ int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
+ if (!styleHint(SH_UnderlineShortcut, &optionTab, widget))
+ alignment |= Qt::TextHideMnemonic;
+ if (!optionTab.icon.isNull()) {
+ QSize iconSize = optionTab.iconSize;
+ int iconExtent = pixelMetric(PM_TabBarIconSize);
+ if (iconSize.height() > iconExtent || iconSize.width() > iconExtent)
+ iconSize = QSize(iconExtent, iconExtent);
+ QPixmap tabIcon = optionTab.icon.pixmap(iconSize,
+ (optionTab.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
+ if (tab->text.isEmpty())
+ painter->drawPixmap(tr.center().x() - (tabIcon.height() >>1),
+ tr.center().y() - (tabIcon.height() >>1),
+ tabIcon);
+ else
+ painter->drawPixmap(tr.left() + tabOverlap,
+ tr.center().y() - (tabIcon.height() >>1),
+ tabIcon);
+ tr.setLeft(tr.left() + iconSize.width() + 4);
+ }
+
+ QCommonStyle::drawItemText(painter, tr, alignment, optionTab.palette, tab->state & State_Enabled, tab->text, QPalette::WindowText);
+ if (verticalTabs)
+ painter->restore();
+
+ painter->restore();
+ }
+ break;
+#endif // QT_NO_TABBAR
+#ifndef QT_NO_PROGRESSBAR
+ case CE_ProgressBarContents:
+ if (const QStyleOptionProgressBarV2 *optionProgressBar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
+ QRect progressRect = optionProgressBar->rect;
+
+ if (optionProgressBar->minimum == optionProgressBar->maximum && optionProgressBar->minimum == 0) {
+ // busy indicator
+ const QS60StylePrivate::SkinElementFlag orientationFlag = optionProgressBar->orientation == Qt::Horizontal ?
+ QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointWest;
+ QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnGrafBarWait, painter, progressRect, flags | orientationFlag);
+ } else {
+ const qreal progressFactor = (optionProgressBar->minimum == optionProgressBar->maximum) ? 1.0
+ : (qreal)optionProgressBar->progress / optionProgressBar->maximum;
+ if (optionProgressBar->orientation == Qt::Horizontal) {
+ progressRect.setWidth(int(progressRect.width() * progressFactor));
+ if(optionProgressBar->direction == Qt::RightToLeft)
+ progressRect.translate(optionProgressBar->rect.width()-progressRect.width(),0);
+ progressRect.adjust(1, 0, -1, 0);
+ } else {
+ progressRect.adjust(0, 1, 0, -1);
+ progressRect.setTop(progressRect.bottom() - int(progressRect.height() * progressFactor));
+ }
+
+ const QS60StylePrivate::SkinElements skinElement = optionProgressBar->orientation == Qt::Horizontal ?
+ QS60StylePrivate::SE_ProgressBarIndicatorHorizontal : QS60StylePrivate::SE_ProgressBarIndicatorVertical;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, progressRect, flags);
+ }
+ }
+ break;
+ case CE_ProgressBarGroove:
+ if (const QStyleOptionProgressBarV2 *optionProgressBar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
+ const QS60StylePrivate::SkinElements skinElement = optionProgressBar->orientation == Qt::Horizontal ?
+ QS60StylePrivate::SE_ProgressBarGrooveHorizontal : QS60StylePrivate::SE_ProgressBarGrooveVertical;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
+ }
+ break;
+ case CE_ProgressBarLabel:
+ if (const QStyleOptionProgressBarV2 *progressbar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
+ QStyleOptionProgressBarV2 optionProgressBar = *progressbar;
+ QCommonStyle::drawItemText(painter, progressbar->rect, flags | Qt::AlignCenter | Qt::TextSingleLine, optionProgressBar.palette,
+ progressbar->state & State_Enabled, progressbar->text, QPalette::WindowText);
+ }
+ break;
+#endif // QT_NO_PROGRESSBAR
+#ifndef QT_NO_MENU
+ case CE_MenuItem:
+ if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
+ QStyleOptionMenuItem optionMenuItem = *menuItem;
+
+ bool drawSubMenuIndicator = false;
+ switch(menuItem->menuItemType) {
+ case QStyleOptionMenuItem::Scroller:
+ case QStyleOptionMenuItem::Separator:
+ return; // no separators or scrollers in S60 menus
+ case QStyleOptionMenuItem::SubMenu:
+ drawSubMenuIndicator = true;
+ break;
+ default:
+ break;
+ }
+ const bool enabled = optionMenuItem.state & State_Enabled;
+ const bool checkable = optionMenuItem.checkType != QStyleOptionMenuItem::NotCheckable;
+
+ uint text_flags = Qt::AlignLeading | Qt::TextShowMnemonic | Qt::TextDontClip
+ | Qt::TextSingleLine | Qt::AlignVCenter;
+ if (!styleHint(SH_UnderlineShortcut, menuItem, widget))
+ text_flags |= Qt::TextHideMnemonic;
+
+ QRect iconRect =
+ subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget);
+ QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget);
+
+ if ((option->state & State_Selected) && (option->state & State_Enabled))
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags);
+
+ //todo: move the vertical spacing stuff into subElementRect
+ const int vSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing);
+ if (checkable){
+ QStyleOptionMenuItem optionCheckBox;
+ optionCheckBox.QStyleOption::operator=(*menuItem);
+ optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth));
+ optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight));
+ const int moveByX = optionCheckBox.rect.width()+vSpacing;
+ if (optionMenuItem.direction == Qt::LeftToRight) {
+ textRect.translate(moveByX,0);
+ iconRect.translate(moveByX, 0);
+ iconRect.setWidth(iconRect.width()+vSpacing);
+ textRect.setWidth(textRect.width()-moveByX-vSpacing);
+ } else {
+ textRect.setWidth(textRect.width()-moveByX);
+ iconRect.setWidth(iconRect.width()+vSpacing);
+ iconRect.translate(-optionCheckBox.rect.width()-vSpacing, 0);
+ optionCheckBox.rect.translate(textRect.width()+iconRect.width(),0);
+ }
+ drawPrimitive(PE_IndicatorMenuCheckMark, &optionCheckBox, painter, widget);
+ }
+ //draw icon and/or checkState
+ QPixmap pix = menuItem->icon.pixmap(pixelMetric(PM_SmallIconSize),
+ enabled ? QIcon::Normal : QIcon::Disabled);
+ const bool itemWithIcon = !pix.isNull();
+ if (itemWithIcon) {
+ drawItemPixmap(painter, iconRect, text_flags, pix);
+ if (optionMenuItem.direction == Qt::LeftToRight)
+ textRect.translate(vSpacing,0);
+ else
+ textRect.translate(-vSpacing,0);
+ textRect.setWidth(textRect.width()-vSpacing);
+ }
+
+ //draw indicators
+ if (drawSubMenuIndicator) {
+ QStyleOptionMenuItem arrowOptions;
+ arrowOptions.QStyleOption::operator=(*menuItem);
+ const int indicatorWidth = (pixelMetric(PM_ListViewIconSize, option, widget)>>1) +
+ pixelMetric(QStyle::PM_LayoutVerticalSpacing, option, widget);
+ if (optionMenuItem.direction == Qt::LeftToRight)
+ arrowOptions.rect.setLeft(textRect.right());
+ arrowOptions.rect.setWidth(indicatorWidth);
+ //by default sub menu indicator in S60 points to east,so here icon
+ // direction is set to north (and south when in RightToLeft)
+ const QS60StylePrivate::SkinElementFlag arrowDirection = (arrowOptions.direction == Qt::LeftToRight) ?
+ QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointSouth;
+ QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnIndiSubMenu, painter, arrowOptions.rect,
+ (flags | QS60StylePrivate::SF_ColorSkinned | arrowDirection));
+ }
+
+ //draw text
+ if (!enabled){
+ //In s60, if something becomes disabled, it is removed from menu, so no native look-alike available.
+ optionMenuItem.palette.setColor(QPalette::Disabled, QPalette::Text, QS60StylePrivate::lighterColor(
+ optionMenuItem.palette.color(QPalette::Disabled, QPalette::Text)));
+ painter->save();
+ painter->setOpacity(0.5);
+ }
+ QCommonStyle::drawItemText(painter, textRect, text_flags,
+ optionMenuItem.palette, enabled,
+ optionMenuItem.text, QPalette::Text);
+ if (!enabled)
+ painter->restore();
+ }
+ break;
+ case CE_MenuEmptyArea:
+ break;
+#endif //QT_NO_MENU
+
+#ifndef QT_NO_MENUBAR
+ case CE_MenuBarEmptyArea:
+ break;
+#endif //QT_NO_MENUBAR
+
+ case CE_HeaderSection:
+ if ( const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
+ painter->save();
+ QPen linePen = QPen(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 1, header));
+ const int penWidth = (header->orientation == Qt::Horizontal) ?
+ linePen.width()+QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth)
+ : linePen.width()+QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth);
+ linePen.setWidth(penWidth);
+ painter->setPen(linePen);
+ if (header->orientation == Qt::Horizontal){
+ painter->drawLine(header->rect.bottomLeft(), header->rect.bottomRight());
+ } else {
+ if ( header->direction == Qt::LeftToRight ) {
+ painter->drawLine(header->rect.topRight(), header->rect.bottomRight());
+ } else {
+ painter->drawLine(header->rect.topLeft(), header->rect.bottomLeft());
+ }
+ }
+ painter->restore();
+ }
+ break;
+ case CE_HeaderEmptyArea: // no need to draw this
+ break;
+ case CE_Header:
+ if ( const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
+ drawControl(CE_HeaderSection, header, painter, widget);
+ QStyleOptionHeader subopt = *header;
+ subopt.rect = subElementRect(SE_HeaderLabel, header, widget);
+ if (subopt.rect.isValid())
+ drawControl(CE_HeaderLabel, &subopt, painter, widget);
+ if (header->sortIndicator != QStyleOptionHeader::None) {
+ subopt.rect = subElementRect(SE_HeaderArrow, option, widget);
+ drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget);
+ }
+ }
+ break;
+#ifndef QT_NO_TOOLBAR
+ case CE_ToolBar:
+ if (const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
+ const QToolBar *tbWidget = qobject_cast<const QToolBar *>(widget);
+
+ //toolbar within a toolbar, skip
+ if (!tbWidget || (widget && qobject_cast<QToolBar *>(widget->parentWidget())))
+ break;
+
+ // Normally in S60 5.0+ there is no background for toolbar, but in some cases with versatile QToolBar,
+ // it looks a bit strange. So, lets fillRect with Button.
+ if (!QS60StylePrivate::isToolBarBackground()) {
+ QList<QAction *> actions = tbWidget->actions();
+ bool justToolButtonsInToolBar = true;
+ for (int i = 0; i < actions.size(); ++i) {
+ QWidget *childWidget = tbWidget->widgetForAction(actions.at(i));
+ const QToolButton *button = qobject_cast<const QToolButton *>(childWidget);
+ if (!button){
+ justToolButtonsInToolBar = false;
+ }
+ }
+
+ // Draw frame background
+ // for vertical toolbars with text only and
+ // for toolbars with extension buttons and
+ // for toolbars with widgets in them.
+ if (!justToolButtonsInToolBar ||
+ (tbWidget &&
+ (tbWidget->orientation() == Qt::Vertical) &&
+ (tbWidget->toolButtonStyle() == Qt::ToolButtonTextOnly))) {
+ painter->save();
+ if (widget)
+ painter->setBrush(widget->palette().button());
+ painter->setOpacity(0.3);
+ painter->fillRect(toolBar->rect, painter->brush());
+ painter->restore();
+ }
+ } else {
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBar, painter, toolBar->rect, flags);
+ }
+ }
+ break;
+#endif //QT_NO_TOOLBAR
+ case CE_ShapedFrame:
+ if (qobject_cast<const QTextEdit *>(widget)) {
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_Editor, painter, option->rect, flags);
+ } else if (qobject_cast<const QTableView *>(widget)) {
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableItem, painter, option->rect, flags);
+ } else if (const QHeaderView *header = qobject_cast<const QHeaderView *>(widget)) {
+ if (header->orientation() == Qt::Horizontal) {
+ QRect headerRect = option->rect;
+ const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
+ headerRect.adjust(0,frameWidth,-2*frameWidth,0);
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableHeaderItem, painter, headerRect, flags);
+ } else {
+ //todo: update to horizontal table graphic
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableHeaderItem, painter, option->rect, flags | QS60StylePrivate::SF_PointWest);
+ }
+ } else if (qobject_cast<const QFrame *>(widget)) {
+ QCommonStyle::drawControl(element, option, painter, widget);
+ }
+ break;
+ case CE_MenuScroller:
+ break;
+ case CE_FocusFrame:
+ {
+ // The pen width should nearly fill the layoutspacings around the widget
+ const int penWidth =
+ qMin(pixelMetric(QS60Style::PM_LayoutVerticalSpacing), pixelMetric(QS60Style::PM_LayoutHorizontalSpacing))
+ - 2; // But keep 1 pixel distance to the focus widget and 1 pixel to the adjacent widgets
+
+#ifdef QT_KEYPAD_NAVIGATION
+ bool editFocus = false;
+ if (const QFocusFrame *focusFrame = qobject_cast<const QFocusFrame*>(widget)) {
+ if (focusFrame->widget() && focusFrame->widget()->hasEditFocus())
+ editFocus = true;
+ }
+ const qreal opacity = editFocus ? 0.65 : 0.45; // Trial and error factors. Feel free to improve.
+#else
+ const qreal opacity = 0.5;
+#endif
+ // Because of Qts coordinate system, we need to tweak the rect by .5 pixels, otherwise it gets blurred.
+ const qreal rectAdjustment = (penWidth % 2) ? -.5 : 0;
+
+ // Make sure that the pen stroke is inside the rect
+ const QRectF adjustedRect =
+ QRectF(option->rect).adjusted(
+ rectAdjustment + penWidth,
+ rectAdjustment + penWidth,
+ -rectAdjustment - penWidth,
+ -rectAdjustment - penWidth
+ );
+
+ const qreal roundRectRadius = penWidth * goldenRatio;
+
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+ painter->setOpacity(opacity);
+ painter->setPen(QPen(option->palette.color(QPalette::Highlight), penWidth));
+ painter->drawRoundedRect(adjustedRect, roundRectRadius, roundRectRadius);
+ painter->restore();
+ }
+ break;
+ default:
+ QCommonStyle::drawControl(element, option, painter, widget);
+ }
+}
+
+/*!
+ \reimp
+*/
+void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
+{
+ const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled;
+ switch (element) {
+#ifndef QT_NO_LINEEDIT
+ case PE_PanelLineEdit:
+ if (const QStyleOptionFrame *lineEdit = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+#ifndef QT_NO_COMBOBOX
+ if (widget && qobject_cast<const QComboBox *>(widget->parentWidget()))
+ break;
+#endif
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_FrameLineEdit,
+ painter, option->rect, flags);
+ }
+ break;
+#endif // QT_NO_LINEEDIT
+ case PE_IndicatorCheckBox:
+ {
+ const QRect indicatorRect = option->rect;
+ // Draw checkbox indicator as color skinned graphics.
+ const QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ?
+ QS60StyleEnums::SP_QgnIndiCheckboxOn : QS60StyleEnums::SP_QgnIndiCheckboxOff;
+ QS60StylePrivate::drawSkinPart(skinPart, painter, indicatorRect,
+ (flags | QS60StylePrivate::SF_ColorSkinned));
+ }
+ break;
+ case PE_IndicatorViewItemCheck:
+#ifndef QT_NO_ITEMVIEWS
+ if (const QListView *listItem = (qobject_cast<const QListView *>(widget))) {
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
+ const bool checkBoxVisible = vopt->features & QStyleOptionViewItemV2::HasCheckIndicator;
+ const bool singleSelection = listItem->selectionMode() ==
+ QAbstractItemView::SingleSelection || listItem->selectionMode() == QAbstractItemView::NoSelection;
+ // draw either checkbox at the beginning
+ if (checkBoxVisible && singleSelection) {
+ drawPrimitive(PE_IndicatorCheckBox, option, painter, widget);
+ // ... or normal "tick" selection at the end.
+ } else if (option->state & QStyle::State_Selected) {
+ QRect tickRect = option->rect;
+ const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth);
+ // adjust tickmark rect to exclude frame border
+ tickRect.adjust(0,-frameBorderWidth,0,-frameBorderWidth);
+ QS60StyleEnums::SkinParts skinPart = QS60StyleEnums::SP_QgnIndiMarkedAdd;
+ QS60StylePrivate::drawSkinPart(skinPart, painter, tickRect,
+ (flags | QS60StylePrivate::SF_ColorSkinned));
+ }
+ }
+ }
+#endif //QT_NO_ITEMVIEWS
+ break;
+ case PE_IndicatorRadioButton: {
+ QRect buttonRect = option->rect;
+ //there is empty (a. 33%) space in svg graphics for radiobutton
+ const qreal reduceWidth = (qreal)buttonRect.width()/3.0;
+ const qreal rectWidth = (qreal)option->rect.width() != 0 ? option->rect.width() : 1.0;
+ // Try to occupy the full area
+ const qreal scaler = 1 + (reduceWidth/rectWidth);
+ buttonRect.setWidth((int)((buttonRect.width()-reduceWidth) * scaler));
+ buttonRect.setHeight((int)(buttonRect.height() * scaler));
+ // move the rect up for half of the new height-gain
+ const int newY = (buttonRect.bottomRight().y() - option->rect.bottomRight().y()) >> 1 ;
+ buttonRect.adjust(0,-newY,0,-newY);
+
+ // Draw radiobutton indicator as color skinned graphics.
+ QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ?
+ QS60StyleEnums::SP_QgnIndiRadiobuttOn : QS60StyleEnums::SP_QgnIndiRadiobuttOff;
+ QS60StylePrivate::drawSkinPart(skinPart, painter, buttonRect,
+ (flags | QS60StylePrivate::SF_ColorSkinned));
+ }
+ break;
+ case PE_PanelButtonCommand:
+ case PE_PanelButtonTool:
+ case PE_PanelButtonBevel:
+ case PE_FrameButtonBevel: {
+ const bool isPressed = option->state & QStyle::State_Sunken;
+ const QS60StylePrivate::SkinElements skinElement =
+ isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
+ }
+ break;
+#ifndef QT_NO_TOOLBUTTON
+ case PE_IndicatorArrowDown:
+ case PE_IndicatorArrowLeft:
+ case PE_IndicatorArrowRight:
+ case PE_IndicatorArrowUp: {
+ QS60StyleEnums::SkinParts skinPart;
+ if (element==PE_IndicatorArrowDown)
+ skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowDown;
+ else if (element==PE_IndicatorArrowLeft)
+ skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowLeft;
+ else if (element==PE_IndicatorArrowRight)
+ skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowRight;
+ else if (element==PE_IndicatorArrowUp)
+ skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowUp;
+
+ QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags);
+ }
+ break;
+#endif //QT_NO_TOOLBUTTON
+#ifndef QT_NO_SPINBOX
+ case PE_IndicatorSpinDown:
+ case PE_IndicatorSpinUp:
+ if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ QStyleOptionSpinBox optionSpinBox = *spinBox;
+ const QS60StyleEnums::SkinParts part = (element == PE_IndicatorSpinUp) ?
+ QS60StyleEnums::SP_QgnGrafScrollArrowUp :
+ QS60StyleEnums::SP_QgnGrafScrollArrowDown;
+ const int adjustment = qMin(optionSpinBox.rect.width(), optionSpinBox.rect.height())/6;
+ optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment );
+ QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect,flags);
+ }
+#ifndef QT_NO_COMBOBOX
+ else if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+ // We want to draw down arrow here for comboboxes as well.
+ const QS60StyleEnums::SkinParts part = QS60StyleEnums::SP_QgnGrafScrollArrowDown;
+ QStyleOptionFrame comboBox = *cmb;
+ const int adjustment = qMin(comboBox.rect.width(), comboBox.rect.height())/6;
+ comboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment );
+ QS60StylePrivate::drawSkinPart(part, painter, comboBox.rect,flags);
+ }
+#endif //QT_NO_COMBOBOX
+ break;
+ case PE_IndicatorSpinMinus:
+ case PE_IndicatorSpinPlus:
+ if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ QStyleOptionSpinBox optionSpinBox = *spinBox;
+ QCommonStyle::drawPrimitive(element, &optionSpinBox, painter, widget);
+ }
+#ifndef QT_NO_COMBOBOX
+ else if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+ // We want to draw down arrow here for comboboxes as well.
+ QStyleOptionFrame comboBox = *cmb;
+ const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
+ comboBox.rect.adjust(0,frameWidth,0,-frameWidth);
+ QCommonStyle::drawPrimitive(element, &comboBox, painter, widget);
+ }
+#endif //QT_NO_COMBOBOX
+ break;
+#endif //QT_NO_SPINBOX
+ case PE_Widget:
+ if (QS60StylePrivate::drawsOwnThemeBackground(widget)
+#ifndef QT_NO_COMBOBOX
+ || qobject_cast<const QComboBoxListView *>(widget)
+#endif //QT_NO_COMBOBOX
+#ifndef QT_NO_MENU
+ || qobject_cast<const QMenu *> (widget)
+#endif //QT_NO_MENU
+ ) {
+ QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_OptionsMenu;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
+ }
+ break;
+ case PE_FrameWindow:
+ case PE_FrameTabWidget:
+ if (const QStyleOptionTabWidgetFrame *tabFrame = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
+ QStyleOptionTabWidgetFrame optionTabFrame = *tabFrame;
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PanelBackground, painter, optionTabFrame.rect, flags);
+ }
+ break;
+ case PE_IndicatorHeaderArrow:
+ if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
+ if (header->sortIndicator & QStyleOptionHeader::SortUp)
+ drawPrimitive(PE_IndicatorArrowUp, header, painter, widget);
+ else if (header->sortIndicator & QStyleOptionHeader::SortDown)
+ drawPrimitive(PE_IndicatorArrowDown, header, painter, widget);
+ } // QStyleOptionHeader::None is not drawn => not needed
+ break;
+#ifndef QT_NO_GROUPBOX
+ case PE_FrameGroupBox:
+ if (const QStyleOptionFrameV2 *frame = qstyleoption_cast<const QStyleOptionFrameV2 *>(option))
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_SettingsList, painter, frame->rect, flags);
+ break;
+#endif //QT_NO_GROUPBOX
+
+ // Qt3 primitives are not supported
+ case PE_Q3CheckListController:
+ case PE_Q3CheckListExclusiveIndicator:
+ case PE_Q3CheckListIndicator:
+ case PE_Q3DockWindowSeparator:
+ case PE_Q3Separator:
+ Q_ASSERT(false);
+ break;
+ case PE_Frame:
+ break;
+#ifndef QT_NO_ITEMVIEWS
+ case PE_PanelItemViewItem:
+ case PE_PanelItemViewRow: // ### Qt 5: remove
+ break;
+#endif //QT_NO_ITEMVIEWS
+
+ case PE_IndicatorMenuCheckMark:
+ if (const QStyleOptionMenuItem *checkBox = qstyleoption_cast<const QStyleOptionMenuItem *>(option)){
+ QStyleOptionMenuItem optionCheckBox = *checkBox;
+ if (optionCheckBox.checked)
+ optionCheckBox.state = (optionCheckBox.state | State_On);
+ drawPrimitive(PE_IndicatorCheckBox, &optionCheckBox, painter, widget);
+ }
+ break;
+#ifndef QT_NO_TOOLBAR
+ case PE_IndicatorToolBarHandle:
+ // no toolbar handles in S60/AVKON UI
+ case PE_IndicatorToolBarSeparator:
+ // no separators in S60/AVKON UI
+ break;
+#endif //QT_NO_TOOLBAR
+
+ case PE_PanelMenuBar:
+ case PE_FrameMenu:
+ break; //disable frame in menu
+
+ case PE_IndicatorBranch:
+#if defined(Q_WS_S60)
+ // 3.1 AVKON UI does not have tree view component, use common style for drawing there
+ if (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1) {
+#else
+ if (true) {
+#endif
+ QCommonStyle::drawPrimitive(element, option, painter, widget);
+ } else {
+ const bool rightLine = option->state & State_Item;
+ const bool downLine = option->state & State_Sibling;
+ const bool upLine = option->state & (State_Open | State_Children | State_Item | State_Sibling);
+
+ QS60StyleEnums::SkinParts skinPart;
+ bool drawSkinPart = false;
+ if (rightLine && downLine && upLine) {
+ skinPart = QS60StyleEnums::SP_QgnIndiHlLineBranch;
+ drawSkinPart = true;
+ } else if (rightLine && upLine) {
+ skinPart = QS60StyleEnums::SP_QgnIndiHlLineEnd;
+ drawSkinPart = true;
+ } else if (upLine && downLine) {
+ skinPart = QS60StyleEnums::SP_QgnIndiHlLineStraight;
+ drawSkinPart = true;
+ }
+
+ if ( drawSkinPart )
+ QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags);
+
+ if (option->state & State_Children) {
+ QS60StyleEnums::SkinParts skinPart =
+ (option->state & State_Open) ? QS60StyleEnums::SP_QgnIndiHlColSuper : QS60StyleEnums::SP_QgnIndiHlExpSuper;
+ int minDimension = qMin(option->rect.width(), option->rect.height());
+ const int resizeValue = minDimension >> 1;
+ minDimension += resizeValue; // Adjust the icon bigger because of empty space in svg icon.
+ QRect iconRect(option->rect.topLeft(), QSize(minDimension, minDimension));
+ int verticalMagic(0);
+ // magic values for positioning svg icon.
+ if (option->rect.width() <= option->rect.height())
+ verticalMagic = 3;
+ iconRect.translate(3, verticalMagic - resizeValue);
+ QS60StylePrivate::drawSkinPart(skinPart, painter, iconRect, flags);
+ }
+ }
+ break;
+
+ // todo: items are below with #ifdefs "just in case". in final version, remove all non-required cases
+ case PE_FrameLineEdit:
+ case PE_IndicatorButtonDropDown:
+ case PE_IndicatorDockWidgetResizeHandle:
+ case PE_PanelTipLabel:
+ case PE_PanelScrollAreaCorner:
+
+#ifndef QT_NO_TABBAR
+ case PE_IndicatorTabTear: // No tab tear in S60
+#endif // QT_NO_TABBAR
+ case PE_FrameDefaultButton:
+#ifndef QT_NO_DOCKWIDGET
+ case PE_FrameDockWidget:
+#endif //QT_NO_DOCKWIDGET
+#ifndef QT_NO_PROGRESSBAR
+ case PE_IndicatorProgressChunk:
+#endif //QT_NO_PROGRESSBAR
+#ifndef QT_NO_TOOLBAR
+ case PE_PanelToolBar:
+#endif //QT_NO_TOOLBAR
+#ifndef QT_NO_COLUMNVIEW
+ case PE_IndicatorColumnViewArrow:
+ case PE_IndicatorItemViewItemDrop:
+#endif //QT_NO_COLUMNVIEW
+ case PE_FrameTabBarBase: // since tabs are in S60 always in navipane, let's use common style for tab base in Qt.
+ default:
+ QCommonStyle::drawPrimitive(element, option, painter, widget);
+ }
+}
+
+/*! \reimp */
+int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
+{
+ int metricValue = QS60StylePrivate::pixelMetric(metric);
+ if (metricValue == KNotFound)
+ metricValue = QCommonStyle::pixelMetric(metric, option, widget);
+
+ if (metric == PM_SubMenuOverlap && widget){
+ const QMenu *menu = qobject_cast<const QMenu *>(widget);
+ if (menu && menu->activeAction() && menu->activeAction()->menu()) {
+ const int menuWidth = menu->activeAction()->menu()->sizeHint().width();
+ metricValue = -menuWidth;
+ }
+ }
+ return metricValue;
+}
+
+/*! \reimp */
+QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt,
+ const QSize &csz, const QWidget *widget) const
+{
+ QSize sz(csz);
+ switch (ct) {
+ case CT_PushButton:
+ sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
+ if (const QAbstractButton *buttonWidget = (qobject_cast<const QAbstractButton *>(widget)))
+ if (buttonWidget->isCheckable())
+ sz += QSize(pixelMetric(PM_IndicatorWidth) + pixelMetric(PM_CheckBoxLabelSpacing), 0);
+ break;
+ case CT_LineEdit:
+ if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt))
+ sz += QSize(2*f->lineWidth, 4*f->lineWidth);
+ break;
+ default:
+ sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
+ break;
+ }
+ return sz;
+}
+
+/*! \reimp */
+int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget,
+ QStyleHintReturn *hret) const
+{
+ int retValue = -1;
+ switch (sh) {
+ case SH_Table_GridLineColor:
+ retValue = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors,2,0).rgb();
+ break;
+ case SH_GroupBox_TextLabelColor:
+ retValue = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors,6,0).rgb();
+ break;
+ case SH_ScrollBar_ScrollWhenPointerLeavesControl:
+ retValue = true;
+ break;
+ case SH_Slider_SnapToValue:
+ retValue = true;
+ break;
+ case SH_Slider_StopMouseOverSlider:
+ retValue = true;
+ break;
+ case SH_LineEdit_PasswordCharacter:
+ retValue = '*';
+ break;
+ case SH_ComboBox_PopupFrameStyle:
+ retValue = QFrame::NoFrame | QFrame::Plain;
+ break;
+ case SH_Dial_BackgroundRole:
+ retValue = QPalette::Base;
+ break;
+ case SH_ItemView_ActivateItemOnSingleClick:
+ retValue = true;
+ break;
+ case SH_ProgressDialog_TextLabelAlignment:
+ retValue = (QApplication::layoutDirection() == Qt::LeftToRight) ?
+ Qt::AlignLeft :
+ Qt::AlignRight;
+ break;
+ case SH_Menu_SubMenuPopupDelay:
+ retValue = 300;
+ break;
+ case SH_Menu_Scrollable:
+ retValue = true;
+ break;
+ case SH_Menu_SelectionWrap:
+ retValue = true;
+ break;
+ case SH_ItemView_ShowDecorationSelected:
+ retValue = true;
+ break;
+ case SH_ToolBar_Movable:
+ retValue = false;
+ break;
+ case SH_BlinkCursorWhenTextSelected:
+ retValue = true;
+ break;
+ case SH_UnderlineShortcut:
+ retValue = 0;
+ break;
+ case SH_RequestSoftwareInputPanel:
+ retValue = RSIP_OnMouseClickAndAlreadyFocused;
+ break;
+ default:
+ break;
+ }
+ if (retValue == -1)
+ retValue = QCommonStyle::styleHint(sh, opt, widget, hret);
+ return retValue;
+}
+
+/*! \reimp */
+QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl scontrol, const QWidget *widget) const
+{
+ QRect ret;
+ switch (control) {
+#ifndef QT_NO_SCROLLBAR
+ // This implementation of subControlRect(CC_ScrollBar..) basically just removes the SC_ScrollBarSubLine and SC_ScrollBarAddLine
+ case CC_ScrollBar:
+ if (const QStyleOptionSlider *scrollbarOption = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ const QRect scrollBarRect = scrollbarOption->rect;
+ const bool isHorizontal = scrollbarOption->orientation == Qt::Horizontal;
+ const int maxlen = isHorizontal ? scrollBarRect.width() : scrollBarRect.height();
+ int sliderlen;
+
+ // calculate slider length
+ if (scrollbarOption->maximum != scrollbarOption->minimum) {
+ const uint range = scrollbarOption->maximum - scrollbarOption->minimum;
+ sliderlen = (qint64(scrollbarOption->pageStep) * maxlen) / (range + scrollbarOption->pageStep);
+
+ const int slidermin = pixelMetric(PM_ScrollBarSliderMin, scrollbarOption, widget);
+ if (sliderlen < slidermin || range > (INT_MAX>>1))
+ sliderlen = slidermin;
+ if (sliderlen > maxlen)
+ sliderlen = maxlen;
+ } else {
+ sliderlen = maxlen;
+ }
+
+ const int sliderstart = sliderPositionFromValue(scrollbarOption->minimum,
+ scrollbarOption->maximum,
+ scrollbarOption->sliderPosition,
+ maxlen - sliderlen,
+ scrollbarOption->upsideDown);
+
+ switch (scontrol) {
+ case SC_ScrollBarSubPage: // between top/left button and slider
+ if (isHorizontal)
+ ret.setRect(0, 0, sliderstart, scrollBarRect.height());
+ else
+ ret.setRect(0, 0, scrollBarRect.width(), sliderstart);
+ break;
+ case SC_ScrollBarAddPage: { // between bottom/right button and slider
+ const int addPageLength = sliderstart + sliderlen;
+ if (isHorizontal)
+ ret = scrollBarRect.adjusted(addPageLength, 0, 0, 0);
+ else
+ ret = scrollBarRect.adjusted(0, addPageLength, 0, 0);
+ }
+ break;
+ case SC_ScrollBarGroove:
+ ret = scrollBarRect;
+ break;
+ case SC_ScrollBarSlider:
+ if (scrollbarOption->orientation == Qt::Horizontal)
+ ret.setRect(sliderstart, 0, sliderlen, scrollBarRect.height());
+ else
+ ret.setRect(0, sliderstart, scrollBarRect.width(), sliderlen);
+ break;
+ case SC_ScrollBarSubLine: // top/left button
+ case SC_ScrollBarAddLine: // bottom/right button
+ default:
+ break;
+ }
+ ret = visualRect(scrollbarOption->direction, scrollBarRect, ret);
+ }
+ break;
+#endif // QT_NO_SCROLLBAR
+ case CC_SpinBox:
+ if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ const int frameThickness = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ const int buttonMargin = spinbox->frame ? 2 : 0;
+ const int buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize) + 2*buttonMargin;
+ QSize buttonSize;
+ buttonSize.setHeight(qMax(8, spinbox->rect.height() - frameThickness));
+ buttonSize.setWidth(buttonWidth);
+ buttonSize = buttonSize.expandedTo(QApplication::globalStrut());
+
+ const int y = frameThickness + spinbox->rect.y();
+ const int x = spinbox->rect.x() + spinbox->rect.width() - frameThickness - 2*buttonSize.width();
+
+ switch (scontrol) {
+ case SC_SpinBoxUp:
+ if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
+ return QRect();
+ ret = QRect(x, y, buttonWidth, buttonSize.height());
+ break;
+ case SC_SpinBoxDown:
+ if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
+ return QRect();
+ ret = QRect(x+buttonSize.width(), y, buttonWidth, buttonSize.height());
+ break;
+ case SC_SpinBoxEditField:
+ if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
+ ret = QRect(
+ frameThickness,
+ frameThickness,
+ spinbox->rect.width() - 2*frameThickness,
+ spinbox->rect.height() - 2*frameThickness);
+ else
+ ret = QRect(
+ frameThickness,
+ frameThickness,
+ x - frameThickness,
+ spinbox->rect.height() - 2*frameThickness);
+ break;
+ case SC_SpinBoxFrame:
+ ret = spinbox->rect;
+ break;
+ default:
+ break;
+ }
+ ret = visualRect(spinbox->direction, spinbox->rect, ret);
+ }
+ break;
+ case CC_ComboBox:
+ if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
+ ret = cmb->rect;
+ const int width = cmb->rect.width();
+ const int height = cmb->rect.height();
+ const int buttonMargin = cmb->frame ? 2 : 0;
+ // lets use spinbox frame here as well, as no combobox specific value available.
+ const int frameThickness = cmb->frame ? pixelMetric(PM_SpinBoxFrameWidth, cmb, widget) : 0;
+ const int buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize);
+ const int xposMod = (cmb->rect.x()) + width - buttonMargin - buttonWidth;
+ const int ypos = cmb->rect.y();
+
+ QSize buttonSize;
+ buttonSize.setHeight(qMax(8, (cmb->rect.height()>>1) - frameThickness)); //minimum of 8 pixels
+ buttonSize.setWidth(buttonWidth+2*buttonMargin);
+ buttonSize = buttonSize.expandedTo(QApplication::globalStrut());
+ switch (scontrol) {
+ case SC_ComboBoxArrow:
+ ret.setRect(xposMod, ypos + buttonMargin, buttonWidth, height - 2*buttonMargin);
+ break;
+ case SC_ComboBoxEditField: {
+ const int withFrameX = cmb->rect.x() + cmb->rect.width() - frameThickness - buttonSize.width();
+ ret = QRect(
+ frameThickness,
+ frameThickness,
+ withFrameX - frameThickness,
+ cmb->rect.height() - 2*frameThickness);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case CC_GroupBox:
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
+ ret = QCommonStyle::subControlRect(control, option, scontrol, widget);
+ switch (scontrol) {
+ case SC_GroupBoxCheckBox: //fallthrough
+ case SC_GroupBoxLabel: {
+ //slightly indent text and boxes, so that dialog border does not mess with them.
+ const int horizontalSpacing =
+ QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
+ ret.adjust(2,horizontalSpacing-3,0,0);
+ }
+ break;
+ case SC_GroupBoxFrame: {
+ const QRect textBox = subControlRect(control, option, SC_GroupBoxLabel, widget);
+ const int tbHeight = textBox.height();
+ ret.translate(0, -ret.y());
+ // include title to within the groupBox frame
+ ret.setHeight(ret.height()+tbHeight);
+ if (widget && ret.bottom() > widget->rect().bottom())
+ ret.setBottom(widget->rect().bottom());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ ret = QCommonStyle::subControlRect(control, option, scontrol, widget);
+ }
+ return ret;
+}
+
+/*!
+ \reimp
+*/
+QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, const QWidget *widget) const
+{
+ QRect ret;
+ switch (element) {
+ case SE_LineEditContents: {
+ // in S60 the input text box doesn't start from line Edit's TL, but
+ // a bit indented.
+ QRect lineEditRect = opt->rect;
+ const int adjustment = opt->rect.height()>>2;
+ lineEditRect.adjust(adjustment,0,0,0);
+ ret = lineEditRect;
+ }
+ break;
+ case SE_TabBarTearIndicator:
+ ret = QRect(0,0,0,0);
+ break;
+ case SE_TabWidgetTabBar:
+ if (const QStyleOptionTabWidgetFrame *optionTab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+
+ if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
+ const int tabOverlapNoBorder =
+ QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap);
+ const int tabOverlap =
+ tabOverlapNoBorder-QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const QTabWidget *tab = qobject_cast<const QTabWidget *>(widget);
+ int gain = (tab) ? tabOverlap * tab->count() : 0;
+ switch (twf->shape) {
+ case QTabBar::RoundedNorth:
+ case QTabBar::TriangularNorth:
+ case QTabBar::RoundedSouth:
+ case QTabBar::TriangularSouth: {
+ if (widget) {
+ // make sure that gain does not set the rect outside of widget boundaries
+ if (twf->direction == Qt::RightToLeft) {
+ if ((ret.left() - gain) < widget->rect().left())
+ gain = widget->rect().left()-ret.left();
+ ret.adjust(-gain,0,0,0);
+ } else {
+ if ((ret.right() + gain) > widget->rect().right())
+ gain = widget->rect().right()-ret.right();
+ ret.adjust(0,0,gain,0);
+ }
+ }
+ break;
+ }
+ default: {
+ if (widget) {
+ if ((ret.bottom() + gain) > widget->rect().bottom())
+ gain = widget->rect().bottom()-ret.bottom();
+ ret.adjust(0,0,0,gain);
+ }
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case SE_ItemViewItemText:
+ case SE_ItemViewItemDecoration:
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
+ const QListWidget *listItem = qobject_cast<const QListWidget *>(widget);
+ const bool multiSelection = !listItem ? false :
+ listItem->selectionMode() == QAbstractItemView::MultiSelection ||
+ listItem->selectionMode() == QAbstractItemView::ExtendedSelection ||
+ listItem->selectionMode() == QAbstractItemView::ContiguousSelection;
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+ // If both multiselect & check-state, then remove checkbox and move
+ // text and decoration towards the beginning
+ if (listItem &&
+ multiSelection &&
+ (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator)) {
+ const int verticalSpacing =
+ QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing);
+ //const int horizontalSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
+ const int checkBoxRectWidth = subElementRect(SE_ItemViewItemCheckIndicator, opt, widget).width();
+ ret.adjust(-checkBoxRectWidth-verticalSpacing,0,-checkBoxRectWidth-verticalSpacing,0);
+ }
+ } else if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
+ const bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable;
+ const int indicatorWidth = checkable ?
+ pixelMetric(PM_ListViewIconSize, opt, widget) :
+ pixelMetric(PM_SmallIconSize, opt, widget);
+ ret = menuItem->rect;
+
+ if (element == SE_ItemViewItemDecoration) {
+ if (menuItem->direction == Qt::RightToLeft)
+ ret.translate(ret.width()-indicatorWidth, 0);
+ ret.setWidth(indicatorWidth);
+ } else {
+ ret = menuItem->rect;
+ if (!menuItem->icon.isNull())
+ if (menuItem->direction == Qt::LeftToRight)
+ ret.adjust(indicatorWidth, 0, 0, 0);
+ else
+ ret.adjust(0, 0, -indicatorWidth, 0);
+
+ // Make room for submenu indicator
+ if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu){
+ // submenu indicator is very small, so lets halve the rect
+ if (menuItem->direction == Qt::LeftToRight)
+ ret.adjust(0,0,-(indicatorWidth >> 1),0);
+ else
+ ret.adjust((indicatorWidth >> 1),0,0,0);
+ }
+ }
+ }
+ break;
+ case SE_ItemViewItemCheckIndicator:
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
+ const QListWidget *listItem = qobject_cast<const QListWidget *>(widget);
+
+ const bool singleSelection = listItem &&
+ (listItem->selectionMode() == QAbstractItemView::SingleSelection ||
+ listItem->selectionMode() == QAbstractItemView::NoSelection);
+ const bool checkBoxOnly = (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) &&
+ listItem &&
+ singleSelection;
+
+ // Selection check mark rect.
+ const int indicatorWidth = QS60StylePrivate::pixelMetric(QStyle::PM_IndicatorWidth);
+ const int indicatorHeight = QS60StylePrivate::pixelMetric(QStyle::PM_IndicatorHeight);
+ const int spacing = QS60StylePrivate::pixelMetric(QStyle::PM_CheckBoxLabelSpacing);
+
+ const int itemHeight = opt->rect.height();
+ int heightOffset = 0;
+ if (indicatorHeight < itemHeight)
+ heightOffset = ((itemHeight - indicatorHeight)>>1);
+ if (checkBoxOnly) {
+ // Move rect and make it slightly smaller, so that
+ // a) highlight border does not cross the rect
+ // b) in s60 list checkbox is smaller than normal checkbox
+ //todo; magic three
+ ret.setRect(opt->rect.left()+3, opt->rect.top() + heightOffset,
+ indicatorWidth-3, indicatorHeight-3);
+ } else {
+ ret.setRect(opt->rect.right() - indicatorWidth - spacing, opt->rect.top() + heightOffset,
+ indicatorWidth, indicatorHeight);
+ }
+ } else {
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+ }
+ break;
+ case SE_HeaderLabel:
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+ if (qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
+ // Subtract area needed for line
+ if (opt->state & State_Horizontal)
+ ret.setHeight(ret.height() - QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth));
+ else
+ ret.setWidth(ret.width() - QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth));
+ }
+ ret = visualRect(opt->direction, opt->rect, ret);
+ break;
+ default:
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+ }
+ return ret;
+}
+
+/*!
+ \reimp
+ */
+void QS60Style::polish(QWidget *widget)
+{
+ Q_D(const QS60Style);
+ QCommonStyle::polish(widget);
+
+ if (!widget)
+ return;
+
+ if (false
+#ifndef QT_NO_SCROLLBAR
+ || qobject_cast<QScrollBar *>(widget)
+#endif
+ ) {
+ widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
+ }
+
+ if (QS60StylePrivate::drawsOwnThemeBackground(widget)) {
+ widget->setAttribute(Qt::WA_StyledBackground);
+ } else if (false
+#ifndef QT_NO_MENU
+ || qobject_cast<const QMenu *> (widget)
+#endif // QT_NO_MENU
+ ) {
+ widget->setAttribute(Qt::WA_StyledBackground);
+ } else if (false
+#ifndef QT_NO_COMBOBOX
+ || qobject_cast<const QComboBoxListView *>(widget)
+#endif //QT_NO_COMBOBOX
+ ) {
+ widget->setAttribute(Qt::WA_StyledBackground);
+ }
+ d->setThemePalette(widget);
+ d->setFont(widget);
+}
+
+/*!
+ \reimp
+ */
+void QS60Style::unpolish(QWidget *widget)
+{
+ if (false
+ #ifndef QT_NO_SCROLLBAR
+ || qobject_cast<QScrollBar *>(widget)
+ #endif
+ )
+ widget->setAttribute(Qt::WA_OpaquePaintEvent);
+
+ if (QS60StylePrivate::drawsOwnThemeBackground(widget)) {
+ widget->setAttribute(Qt::WA_StyledBackground, false);
+ } else if (false
+#ifndef QT_NO_MENU
+ || qobject_cast<const QMenu *> (widget)
+#endif // QT_NO_MENU
+ ) {
+ widget->setAttribute(Qt::WA_StyledBackground, false);
+ } else if (false
+#ifndef QT_NO_COMBOBOX
+ || qobject_cast<const QComboBoxListView *>(widget)
+#endif //QT_NO_COMBOBOX
+ ) {
+ widget->setAttribute(Qt::WA_StyledBackground, false);
+ }
+
+ if (widget)
+ widget->setPalette(QPalette());
+
+ QCommonStyle::unpolish(widget);
+}
+
+/*!
+ \reimp
+ */
+void QS60Style::polish(QApplication *application)
+{
+ Q_D(QS60Style);
+ d->m_originalPalette = application->palette();
+ d->setThemePalette(application);
+}
+
+/*!
+ \reimp
+ */
+void QS60Style::unpolish(QApplication *application)
+{
+ Q_UNUSED(application)
+ Q_D(QS60Style);
+ const QPalette newPalette = QApplication::style()->standardPalette();
+ QApplication::setPalette(newPalette);
+ QApplicationPrivate::setSystemPalette(d->m_originalPalette);
+}
+
+/*!
+ Sets the style property \a name to the \a value.
+ */
+void QS60Style::setStyleProperty(const char *name, const QVariant &value)
+{
+ Q_D(QS60Style);
+ d->setStyleProperty_specific(name, value);
+}
+
+/*!
+ Returns the value of style property \a name.
+ */
+QVariant QS60Style::styleProperty(const char *name) const
+{
+ Q_D(const QS60Style);
+ return d->styleProperty_specific(name);
+}
+
+/*!
+ \reimp
+ */
+bool QS60Style::event(QEvent *e)
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QS60StylePrivate::isTouchSupported())
+ return false;
+ Q_D(QS60Style);
+ switch (e->type()) {
+ case QEvent::FocusIn:
+ if (QWidget *focusWidget = QApplication::focusWidget()) {
+ if (!d->m_focusFrame)
+ d->m_focusFrame = new QFocusFrame(focusWidget);
+ d->m_focusFrame->setWidget(focusWidget);
+ } else if (d->m_focusFrame) {
+ d->m_focusFrame->setWidget(0);
+ }
+ break;
+ case QEvent::FocusOut:
+ if (d->m_focusFrame)
+ d->m_focusFrame->setWidget(0);
+ break;
+ case QEvent::EnterEditFocus:
+ case QEvent::LeaveEditFocus:
+ if (d->m_focusFrame)
+ d->m_focusFrame->update();
+ break;
+ default:
+ break;
+ }
+#else
+ Q_UNUSED(e)
+#endif
+ return false;
+}
+
+/*!
+ \internal
+ */
+QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon,
+ const QStyleOption *option, const QWidget *widget) const
+{
+ const int iconDimension = QS60StylePrivate::pixelMetric(QStyle::PM_ToolBarIconSize);
+ const QRect iconSize = (!option) ? QRect(0,0,iconDimension,iconDimension) : option->rect;
+ QS60StyleEnums::SkinParts part;
+ QS60StylePrivate::SkinElementFlags adjustedFlags;
+ if (option)
+ adjustedFlags = (option->state & State_Enabled || option->state == 0) ?
+ QS60StylePrivate::SF_StateEnabled :
+ QS60StylePrivate::SF_StateDisabled;
+
+ switch(standardIcon) {
+ case QStyle::SP_MessageBoxWarning:
+ part = QS60StyleEnums::SP_QgnNoteWarning;
+ break;
+ case QStyle::SP_MessageBoxInformation:
+ part = QS60StyleEnums::SP_QgnNoteInfo;
+ break;
+ case QStyle::SP_MessageBoxCritical:
+ part = QS60StyleEnums::SP_QgnNoteError;
+ break;
+ case QStyle::SP_MessageBoxQuestion:
+ part = QS60StyleEnums::SP_QgnNoteQuery;
+ break;
+ case QStyle::SP_ArrowRight:
+ part = QS60StyleEnums::SP_QgnIndiNaviArrowRight;
+ break;
+ case QStyle::SP_ArrowLeft:
+ part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft;
+ break;
+ case QStyle::SP_ArrowUp:
+ part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft;
+ adjustedFlags |= QS60StylePrivate::SF_PointEast;
+ break;
+ case QStyle::SP_ArrowDown:
+ part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft;
+ adjustedFlags |= QS60StylePrivate::SF_PointWest;
+ break;
+ case QStyle::SP_ArrowBack:
+ if (QApplication::layoutDirection() == Qt::RightToLeft)
+ return QS60Style::standardIcon(SP_ArrowRight, option, widget);
+ return QS60Style::standardIcon(SP_ArrowLeft, option, widget);
+ case QStyle::SP_ArrowForward:
+ if (QApplication::layoutDirection() == Qt::RightToLeft)
+ return QS60Style::standardIcon(SP_ArrowLeft, option, widget);
+ return QS60Style::standardIcon(SP_ArrowRight, option, widget);
+ case QStyle::SP_ComputerIcon:
+ part = QS60StyleEnums::SP_QgnPropPhoneMemcLarge;
+ break;
+ case QStyle::SP_DirClosedIcon:
+ part = QS60StyleEnums::SP_QgnPropFolderSmall;
+ break;
+ case QStyle::SP_DirOpenIcon:
+ part = QS60StyleEnums::SP_QgnPropFolderCurrent;
+ break;
+ case QStyle::SP_DirIcon:
+ part = QS60StyleEnums::SP_QgnPropFolderSmall;
+ break;
+ case QStyle::SP_FileDialogNewFolder:
+ part = QS60StyleEnums::SP_QgnPropFolderSmallNew;
+ break;
+ case QStyle::SP_FileIcon:
+ part = QS60StyleEnums::SP_QgnPropFileSmall;
+ break;
+ case QStyle::SP_TrashIcon:
+ part = QS60StyleEnums::SP_QgnNoteErased;
+ break;
+ case QStyle::SP_ToolBarHorizontalExtensionButton:
+ part = QS60StyleEnums::SP_QgnIndiSubMenu;
+ if (QApplication::layoutDirection() == Qt::RightToLeft)
+ adjustedFlags |= QS60StylePrivate::SF_PointSouth;
+ break;
+ case QStyle::SP_ToolBarVerticalExtensionButton:
+ adjustedFlags |= QS60StylePrivate::SF_PointEast;
+ part = QS60StyleEnums::SP_QgnIndiSubMenu;
+ break;
+
+ default:
+ return QCommonStyle::standardIconImplementation(standardIcon, option, widget);
+ }
+ const QS60StylePrivate::SkinElementFlags flags = adjustedFlags;
+ const QPixmap cachedPixMap(QS60StylePrivate::cachedPart(part, iconSize.size(), flags));
+ return cachedPixMap.isNull() ?
+ QCommonStyle::standardIconImplementation(standardIcon, option, widget) : QIcon(cachedPixMap);
+}
+
+extern QPoint qt_s60_fill_background_offset(const QWidget *targetWidget);
+
+bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush)
+{
+ const QPixmap backgroundTexture(QS60StylePrivate::backgroundTexture());
+ if (backgroundTexture.cacheKey() != brush.texture().cacheKey())
+ return false;
+
+ const QPaintDevice *target = painter->device();
+ if (target->devType() == QInternal::Widget) {
+ const QWidget *widget = static_cast<const QWidget *>(target);
+ const QVector<QRect> &rects = rgn.rects();
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect rect(rects.at(i));
+ painter->drawPixmap(rect.topLeft(), backgroundTexture,
+ rect.translated(qt_s60_fill_background_offset(widget)));
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STYLE_S60 || QT_PLUGIN
diff --git a/src/gui/styles/qs60style.h b/src/gui/styles/qs60style.h
new file mode 100644
index 0000000..c01c40a
--- /dev/null
+++ b/src/gui/styles/qs60style.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QS60STYLE_H
+#define QS60STYLE_H
+
+#include <QtGui/qcommonstyle.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_STYLE_S60)
+
+class QS60StylePrivate;
+
+class Q_GUI_EXPORT QS60Style : public QCommonStyle
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QS60Style)
+
+public:
+ QS60Style();
+ ~QS60Style();
+
+ void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const;
+ int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const;
+ QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w = 0) const;
+ int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0,
+ QStyleHintReturn *shret = 0) const;
+ QRect subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl scontrol, const QWidget *widget = 0) const;
+ QRect subElementRect(SubElement element, const QStyleOption *opt, const QWidget *widget = 0) const;
+ void polish(QWidget *widget);
+ void unpolish(QWidget *widget);
+ void polish(QApplication *application);
+ void unpolish(QApplication *application);
+
+ void setStyleProperty(const char *name, const QVariant &value);
+ QVariant styleProperty(const char *name) const;
+
+ bool event(QEvent *e);
+
+#ifndef Q_WS_S60
+ static QStringList partKeys();
+ static QStringList colorListKeys();
+ void setS60Theme(const QHash<QString, QPicture> &parts,
+ const QHash<QPair<QString , int>, QColor> &colors);
+ bool loadS60ThemeFromBlob(const QString &blobFile);
+ bool saveS60ThemeToBlob(const QString &blobFile) const;
+#endif // !Q_WS_S60
+
+protected Q_SLOTS:
+ QIcon standardIconImplementation(
+ StandardPixmap standardIcon, const QStyleOption * option = 0, const QWidget * widget = 0 ) const;
+
+private:
+ Q_DISABLE_COPY(QS60Style)
+ friend class QStyleFactory;
+ friend class QApplication;
+};
+
+#endif // QT_NO_STYLE_S60
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QS60STYLE_H
diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h
new file mode 100644
index 0000000..ed0abfa
--- /dev/null
+++ b/src/gui/styles/qs60style_p.h
@@ -0,0 +1,508 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QS60STYLE_P_H
+#define QS60STYLE_P_H
+
+#include "qs60style.h"
+#include "qcommonstyle_p.h"
+#include <QtCore/qhash.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+const int MAX_NON_CUSTOM_PIXELMETRICS = 92;
+const int CUSTOMVALUESCOUNT = 4;
+enum {
+ PM_Custom_FrameCornerWidth = MAX_NON_CUSTOM_PIXELMETRICS,
+ PM_Custom_FrameCornerHeight,
+ PM_Custom_BoldLineWidth,
+ PM_Custom_ThinLineWidth
+ };
+const int MAX_PIXELMETRICS = MAX_NON_CUSTOM_PIXELMETRICS + CUSTOMVALUESCOUNT;
+
+typedef struct {
+ unsigned short height;
+ unsigned short width;
+ int major_version;
+ int minor_version;
+ bool mirroring; // TODO: (nice to have) Use Qt::LayoutDirection
+ const char* layoutName;
+} layoutHeader;
+
+#ifdef Q_OS_SYMBIAN
+NONSHARABLE_CLASS (QS60StyleEnums)
+#else
+class QS60StyleEnums
+#endif
+: public QObject
+{
+#ifndef Q_WS_S60
+ Q_OBJECT
+ Q_ENUMS(FontCategories)
+ Q_ENUMS(SkinParts)
+ Q_ENUMS(ColorLists)
+#endif // !Q_WS_S60
+
+public:
+ // S60 look-and-feel font categories
+ enum FontCategories {
+ FC_Undefined,
+ FC_Primary,
+ FC_Secondary,
+ FC_Title,
+ FC_PrimarySmall,
+ FC_Digital
+ };
+
+ enum SkinParts {
+ SP_QgnGrafBarWait,
+ SP_QgnGrafBarFrameCenter,
+ SP_QgnGrafBarFrameSideL,
+ SP_QgnGrafBarFrameSideR,
+ SP_QgnGrafBarProgress,
+ SP_QgnGrafScrollArrowDown,
+ SP_QgnGrafScrollArrowLeft,
+ SP_QgnGrafScrollArrowRight,
+ SP_QgnGrafScrollArrowUp,
+ SP_QgnGrafTabActiveL,
+ SP_QgnGrafTabActiveM,
+ SP_QgnGrafTabActiveR,
+ SP_QgnGrafTabPassiveL,
+ SP_QgnGrafTabPassiveM,
+ SP_QgnGrafTabPassiveR,
+ SP_QgnIndiCheckboxOff,
+ SP_QgnIndiCheckboxOn,
+ SP_QgnIndiHlColSuper, // Available in S60 release 3.2 and later.
+ SP_QgnIndiHlExpSuper, // Available in S60 release 3.2 and later.
+ SP_QgnIndiHlLineBranch, // Available in S60 release 3.2 and later.
+ SP_QgnIndiHlLineEnd, // Available in S60 release 3.2 and later.
+ SP_QgnIndiHlLineStraight, // Available in S60 release 3.2 and later.
+ SP_QgnIndiMarkedAdd,
+ SP_QgnIndiNaviArrowLeft,
+ SP_QgnIndiNaviArrowRight,
+ SP_QgnIndiRadiobuttOff,
+ SP_QgnIndiRadiobuttOn,
+ SP_QgnIndiSliderEdit,
+ SP_QgnIndiSubMenu,
+ SP_QgnNoteErased,
+ SP_QgnNoteError,
+ SP_QgnNoteInfo,
+ SP_QgnNoteOk,
+ SP_QgnNoteQuery,
+ SP_QgnNoteWarning,
+ SP_QgnPropFileSmall,
+ SP_QgnPropFolderCurrent,
+ SP_QgnPropFolderSmall,
+ SP_QgnPropFolderSmallNew,
+ SP_QgnPropPhoneMemcLarge,
+ SP_QsnCpScrollHandleBottomPressed, //ScrollBar handle, pressed state
+ SP_QsnCpScrollHandleMiddlePressed,
+ SP_QsnCpScrollHandleTopPressed,
+ SP_QsnBgScreen,
+ SP_QsnCpScrollBgBottom,
+ SP_QsnCpScrollBgMiddle,
+ SP_QsnCpScrollBgTop,
+ SP_QsnCpScrollHandleBottom,
+ SP_QsnCpScrollHandleMiddle,
+ SP_QsnCpScrollHandleTop,
+ SP_QsnFrButtonTbCornerTl, // Button, normal state
+ SP_QsnFrButtonTbCornerTr,
+ SP_QsnFrButtonTbCornerBl,
+ SP_QsnFrButtonTbCornerBr,
+ SP_QsnFrButtonTbSideT,
+ SP_QsnFrButtonTbSideB,
+ SP_QsnFrButtonTbSideL,
+ SP_QsnFrButtonTbSideR,
+ SP_QsnFrButtonTbCenter,
+ SP_QsnFrButtonTbCornerTlPressed, // Button, pressed state
+ SP_QsnFrButtonTbCornerTrPressed,
+ SP_QsnFrButtonTbCornerBlPressed,
+ SP_QsnFrButtonTbCornerBrPressed,
+ SP_QsnFrButtonTbSideTPressed,
+ SP_QsnFrButtonTbSideBPressed,
+ SP_QsnFrButtonTbSideLPressed,
+ SP_QsnFrButtonTbSideRPressed,
+ SP_QsnFrButtonTbCenterPressed,
+ SP_QsnFrCaleCornerTl, // calendar grid item
+ SP_QsnFrCaleCornerTr,
+ SP_QsnFrCaleCornerBl,
+ SP_QsnFrCaleCornerBr,
+ SP_QsnFrCaleGSideT,
+ SP_QsnFrCaleGSideB,
+ SP_QsnFrCaleGSideL,
+ SP_QsnFrCaleGSideR,
+ SP_QsnFrCaleCenter,
+ SP_QsnFrCaleHeadingCornerTl, // calendar grid header
+ SP_QsnFrCaleHeadingCornerTr,
+ SP_QsnFrCaleHeadingCornerBl,
+ SP_QsnFrCaleHeadingCornerBr,
+ SP_QsnFrCaleHeadingSideT,
+ SP_QsnFrCaleHeadingSideB,
+ SP_QsnFrCaleHeadingSideL,
+ SP_QsnFrCaleHeadingSideR,
+ SP_QsnFrCaleHeadingCenter,
+ SP_QsnFrInputCornerTl, // Text input field
+ SP_QsnFrInputCornerTr,
+ SP_QsnFrInputCornerBl,
+ SP_QsnFrInputCornerBr,
+ SP_QsnFrInputSideT,
+ SP_QsnFrInputSideB,
+ SP_QsnFrInputSideL,
+ SP_QsnFrInputSideR,
+ SP_QsnFrInputCenter,
+ SP_QsnFrListCornerTl, // List background
+ SP_QsnFrListCornerTr,
+ SP_QsnFrListCornerBl,
+ SP_QsnFrListCornerBr,
+ SP_QsnFrListSideT,
+ SP_QsnFrListSideB,
+ SP_QsnFrListSideL,
+ SP_QsnFrListSideR,
+ SP_QsnFrListCenter,
+ SP_QsnFrPopupCornerTl, // Option menu background
+ SP_QsnFrPopupCornerTr,
+ SP_QsnFrPopupCornerBl,
+ SP_QsnFrPopupCornerBr,
+ SP_QsnFrPopupSideT,
+ SP_QsnFrPopupSideB,
+ SP_QsnFrPopupSideL,
+ SP_QsnFrPopupSideR,
+ SP_QsnFrPopupCenter,
+ SP_QsnFrPopupPreviewCornerTl, // tool tip background
+ SP_QsnFrPopupPreviewCornerTr,
+ SP_QsnFrPopupPreviewCornerBl,
+ SP_QsnFrPopupPreviewCornerBr,
+ SP_QsnFrPopupPreviewSideT,
+ SP_QsnFrPopupPreviewSideB,
+ SP_QsnFrPopupPreviewSideL,
+ SP_QsnFrPopupPreviewSideR,
+ SP_QsnFrPopupPreviewCenter,
+ SP_QsnFrSetOptCornerTl, // Settings list
+ SP_QsnFrSetOptCornerTr,
+ SP_QsnFrSetOptCornerBl,
+ SP_QsnFrSetOptCornerBr,
+ SP_QsnFrSetOptSideT,
+ SP_QsnFrSetOptSideB,
+ SP_QsnFrSetOptSideL,
+ SP_QsnFrSetOptSideR,
+ SP_QsnFrSetOptCenter,
+ SP_QsnFrPopupSubCornerTl, // Toolbar background
+ SP_QsnFrPopupSubCornerTr,
+ SP_QsnFrPopupSubCornerBl,
+ SP_QsnFrPopupSubCornerBr,
+ SP_QsnFrPopupSubSideT,
+ SP_QsnFrPopupSubSideB,
+ SP_QsnFrPopupSubSideL,
+ SP_QsnFrPopupSubSideR,
+ SP_QsnFrPopupSubCenter,
+ SP_QsnFrSctrlButtonCornerTl, // Toolbar button
+ SP_QsnFrSctrlButtonCornerTr,
+ SP_QsnFrSctrlButtonCornerBl,
+ SP_QsnFrSctrlButtonCornerBr,
+ SP_QsnFrSctrlButtonSideT,
+ SP_QsnFrSctrlButtonSideB,
+ SP_QsnFrSctrlButtonSideL,
+ SP_QsnFrSctrlButtonSideR,
+ SP_QsnFrSctrlButtonCenter,
+ SP_QsnFrSctrlButtonCornerTlPressed, // Toolbar button, pressed
+ SP_QsnFrSctrlButtonCornerTrPressed,
+ SP_QsnFrSctrlButtonCornerBlPressed,
+ SP_QsnFrSctrlButtonCornerBrPressed,
+ SP_QsnFrSctrlButtonSideTPressed,
+ SP_QsnFrSctrlButtonSideBPressed,
+ SP_QsnFrSctrlButtonSideLPressed,
+ SP_QsnFrSctrlButtonSideRPressed,
+ SP_QsnFrSctrlButtonCenterPressed,
+ SP_QsnFrButtonCornerTlInactive, // Inactive button
+ SP_QsnFrButtonCornerTrInactive,
+ SP_QsnFrButtonCornerBlInactive,
+ SP_QsnFrButtonCornerBrInactive,
+ SP_QsnFrButtonSideTInactive,
+ SP_QsnFrButtonSideBInactive,
+ SP_QsnFrButtonSideLInactive,
+ SP_QsnFrButtonSideRInactive,
+ SP_QsnFrButtonCenterInactive,
+ SP_QsnFrNotepadCornerTl,
+ SP_QsnFrNotepadCornerTr,
+ SP_QsnFrNotepadCornerBl,
+ SP_QsnFrNotepadCornerBr,
+ SP_QsnFrNotepadSideT,
+ SP_QsnFrNotepadSideB,
+ SP_QsnFrNotepadSideL,
+ SP_QsnFrNotepadSideR,
+ SP_QsnFrNotepadCenter
+ };
+
+ enum ColorLists {
+ CL_QsnHighlightColors,
+ CL_QsnIconColors,
+ CL_QsnLineColors,
+ CL_QsnOtherColors,
+ CL_QsnParentColors,
+ CL_QsnTextColors
+ };
+};
+
+class QFocusFrame;
+
+// Private class
+#ifdef Q_OS_SYMBIAN
+NONSHARABLE_CLASS (QS60StylePrivate)
+#else
+class QS60StylePrivate
+#endif
+: public QCommonStylePrivate
+{
+ Q_DECLARE_PUBLIC(QS60Style)
+
+public:
+ QS60StylePrivate();
+ ~QS60StylePrivate();
+
+ enum SkinElements {
+ SE_ButtonNormal,
+ SE_ButtonPressed,
+ SE_FrameLineEdit,
+ SE_ProgressBarGrooveHorizontal,
+ SE_ProgressBarIndicatorHorizontal,
+ SE_ProgressBarGrooveVertical,
+ SE_ProgressBarIndicatorVertical,
+ SE_ScrollBarGrooveHorizontal,
+ SE_ScrollBarGrooveVertical,
+ SE_ScrollBarHandleHorizontal,
+ SE_ScrollBarHandleVertical,
+ SE_SliderHandleHorizontal,
+ SE_SliderHandleVertical,
+ SE_TabBarTabEastActive,
+ SE_TabBarTabEastInactive,
+ SE_TabBarTabNorthActive,
+ SE_TabBarTabNorthInactive,
+ SE_TabBarTabSouthActive,
+ SE_TabBarTabSouthInactive,
+ SE_TabBarTabWestActive,
+ SE_TabBarTabWestInactive,
+ SE_ListHighlight,
+ SE_OptionsMenu,
+ SE_SettingsList,
+ SE_TableItem,
+ SE_TableHeaderItem,
+ SE_ToolTip, //own graphic available on 3.2+ releases,
+ SE_ToolBar,
+ SE_ToolBarButton,
+ SE_ToolBarButtonPressed,
+ SE_PanelBackground,
+ SE_ScrollBarHandlePressedHorizontal, //only for 5.0+
+ SE_ScrollBarHandlePressedVertical,
+ SE_ButtonInactive,
+ SE_Editor,
+ };
+
+ enum SkinFrameElements {
+ SF_ButtonNormal,
+ SF_ButtonPressed,
+ SF_FrameLineEdit,
+ SF_ListHighlight,
+ SF_OptionsMenu,
+ SF_SettingsList,
+ SF_TableItem,
+ SF_TableHeaderItem,
+ SF_ToolTip,
+ SF_ToolBar,
+ SF_ToolBarButton,
+ SF_ToolBarButtonPressed,
+ SF_PanelBackground,
+ SF_ButtonInactive,
+ SF_Editor,
+ };
+
+ enum SkinElementFlag {
+ SF_PointNorth = 0x0001, // North = the default
+ SF_PointEast = 0x0002,
+ SF_PointSouth = 0x0004,
+ SF_PointWest = 0x0008,
+
+ SF_StateEnabled = 0x0010, // Enabled = the default
+ SF_StateDisabled = 0x0020,
+ SF_ColorSkinned = 0x0040,
+ };
+
+ enum CacheClearReason {
+ CC_UndefinedChange = 0,
+ CC_LayoutChange,
+ CC_ThemeChange
+ };
+
+ Q_DECLARE_FLAGS(SkinElementFlags, SkinElementFlag)
+
+ // draws skin element
+ static void drawSkinElement(SkinElements element, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+ // draws a specific skin part
+ static void drawSkinPart(QS60StyleEnums::SkinParts part, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+ // sets style property
+ void setStyleProperty(const char *name, const QVariant &value);
+ // sets specific style property
+ void setStyleProperty_specific(const char *name, const QVariant &value);
+ // gets style property
+ QVariant styleProperty(const char *name) const;
+ // gets specific style property
+ QVariant styleProperty_specific(const char *name) const;
+ // gets pixel metrics value
+ static short pixelMetric(int metric);
+ // gets color. 'index' is NOT 0-based.
+ // It corresponds to the enum key 1-based numbers of TAknsQsnXYZColorsIndex, not the values.
+ static QColor s60Color(QS60StyleEnums::ColorLists list,
+ int index, const QStyleOption *option);
+ // gets state specific color
+ static QColor stateColor(const QColor &color, const QStyleOption *option);
+ // gets lighter color than base color
+ static QColor lighterColor(const QColor &baseColor);
+ //deduces if the given widget should have separately themeable background
+ static bool drawsOwnThemeBackground(const QWidget *widget);
+
+ QFont s60Font(QS60StyleEnums::FontCategories fontCategory,
+ int pointSize = -1) const;
+ // clears all style caches (fonts, colors, pixmaps)
+ void clearCaches(CacheClearReason reason = CC_UndefinedChange);
+
+ // themed main background oprations
+ void setBackgroundTexture(QApplication *application) const;
+ static void deleteBackground();
+
+ static bool isTouchSupported();
+ static bool isToolBarBackground();
+
+ // calculates average color based on button skin graphics (minus borders).
+ QColor colorFromFrameGraphics(SkinFrameElements frame) const;
+
+ //set theme palette for application
+ void setThemePalette(QApplication *application) const;
+ //set theme palette for style option
+ void setThemePalette(QStyleOption *option) const;
+ //access to theme palette
+ static QPalette* themePalette();
+
+ static const layoutHeader m_layoutHeaders[];
+ static const short data[][MAX_PIXELMETRICS];
+
+ void setCurrentLayout(int layoutIndex);
+ void setActiveLayout();
+ // Pointer
+ static short const *m_pmPointer;
+ // number of layouts supported by the style
+ static const int m_numberOfLayouts;
+
+ mutable QHash<QPair<QS60StyleEnums::FontCategories , int>, QFont> m_mappedFontsCache;
+ mutable QHash<SkinFrameElements, QColor> m_colorCache;
+
+ // Has one entry per SkinFrameElements
+ static const struct frameElementCenter {
+ SkinElements element;
+ QS60StyleEnums::SkinParts center;
+ } m_frameElementsData[];
+
+ static QPixmap frame(SkinFrameElements frame, const QSize &size,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+ static QPixmap backgroundTexture();
+
+#ifdef Q_WS_S60
+ void handleDynamicLayoutVariantSwitch();
+ void handleSkinChange();
+#endif // Q_WS_S60
+
+private:
+ static void drawPart(QS60StyleEnums::SkinParts part, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+ static void drawRow(QS60StyleEnums::SkinParts start, QS60StyleEnums::SkinParts middle,
+ QS60StyleEnums::SkinParts end, Qt::Orientation orientation, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+ static void drawFrame(SkinFrameElements frame, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+
+ static QPixmap cachedPart(QS60StyleEnums::SkinParts part, const QSize &size,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+ static QPixmap cachedFrame(SkinFrameElements frame, const QSize &size,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+
+ static void refreshUI();
+
+ // set S60 font for widget
+ void setFont(QWidget *widget) const;
+ void setThemePalette(QWidget *widget) const;
+ void setThemePalette(QPalette *palette) const;
+ void setThemePaletteHash(QPalette *palette) const;
+ static void storeThemePalette(QPalette *palette);
+ static void deleteThemePalette();
+
+ static QSize partSize(QS60StyleEnums::SkinParts part,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+ static QPixmap part(QS60StyleEnums::SkinParts part, const QSize &size,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+
+ static QFont s60Font_specific(QS60StyleEnums::FontCategories fontCategory, int pointSize);
+
+ static QSize screenSize();
+
+ // Contains background texture.
+ static QPixmap *m_background;
+ const static SkinElementFlags KDefaultSkinElementFlags;
+ // defined theme palette
+ static QPalette *m_themePalette;
+ QPalette m_originalPalette;
+
+ QPointer<QFocusFrame> m_focusFrame;
+};
+
+QT_END_NAMESPACE
+
+#endif // QS60STYLE_P_H
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
new file mode 100644
index 0000000..1cf47cc
--- /dev/null
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -0,0 +1,1384 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qs60style.h"
+#include "qs60style_p.h"
+#include "qpainter.h"
+#include "qstyleoption.h"
+#include "qstyle.h"
+#include "private/qwindowsurface_s60_p.h"
+#include "private/qt_s60_p.h"
+#include "private/qcore_symbian_p.h"
+#include "qapplication.h"
+
+#include <w32std.h>
+#include <aknsconstants.h>
+#include <aknconsts.h>
+#include <aknsitemid.h>
+#include <aknsutils.h>
+#include <aknsdrawutils.h>
+#include <aknsskininstance.h>
+#include <aknsbasicbackgroundcontrolcontext.h>
+#include <avkon.mbg>
+#include <AknFontAccess.h>
+#include <AknLayoutFont.h>
+#include <aknutils.h>
+
+#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
+
+QT_BEGIN_NAMESPACE
+
+enum TDrawType {
+ EDrawIcon,
+ EDrawBackground,
+ ENoDraw
+};
+
+enum TSupportRelease {
+ ES60_None = 0x0000, //indicates that the commonstyle should draw the graphics
+ ES60_3_1 = 0x0001,
+ ES60_3_2 = 0x0002,
+ ES60_5_0 = 0x0004,
+ ES60_5_1 = 0x0008,
+ ES60_5_2 = 0x0010,
+ // Add all new releases here
+ ES60_AllReleases = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2
+};
+
+typedef struct {
+ const TAknsItemID &skinID;
+ TDrawType drawType;
+ int supportInfo;
+ int newMajorSkinId;
+ int newMinorSkinId;
+} partMapEntry;
+
+class QS60StyleModeSpecifics
+{
+public:
+ static QPixmap skinnedGraphics(QS60StyleEnums::SkinParts stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QPixmap skinnedGraphics(QS60StylePrivate::SkinFrameElements frameElement, const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QPixmap colorSkinnedGraphics(const QS60StyleEnums::SkinParts &stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QColor colorValue(const TAknsItemID &colorGroup, int colorIndex);
+ static QPixmap fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask, QS60StylePrivate::SkinElementFlags flags, QImage::Format format);
+ static bool disabledPartGraphic(QS60StyleEnums::SkinParts &part);
+ static bool disabledFrameGraphic(QS60StylePrivate::SkinFrameElements &frame);
+ static QPixmap generateMissingThemeGraphic(QS60StyleEnums::SkinParts &part, const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+
+private:
+ static QPixmap createSkinnedGraphicsLX(QS60StyleEnums::SkinParts part,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QPixmap createSkinnedGraphicsLX(QS60StylePrivate::SkinFrameElements frameElement, const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QPixmap colorSkinnedGraphicsLX(const QS60StyleEnums::SkinParts &stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static void frameIdAndCenterId(QS60StylePrivate::SkinFrameElements frameElement, TAknsItemID &frameId, TAknsItemID &centerId);
+ static TRect innerRectFromElement(QS60StylePrivate::SkinFrameElements frameElement, const TRect &outerRect);
+ static void checkAndUnCompressBitmapL(CFbsBitmap*& aOriginalBitmap);
+ static void checkAndUnCompressBitmap(CFbsBitmap*& aOriginalBitmap);
+ static void unCompressBitmapL(const TRect& aTrgRect, CFbsBitmap* aTrgBitmap, CFbsBitmap* aSrcBitmap);
+ static void colorGroupAndIndex(QS60StyleEnums::SkinParts skinID,
+ TAknsItemID &colorGroup, int colorIndex);
+ static void fallbackInfo(const QS60StyleEnums::SkinParts &stylepart, TDes& fallbackFileName, TInt& fallbackIndex);
+ static bool checkSupport(const int supportedRelease);
+ static TAknsItemID checkAndUpdateReleaseSpecificGraphics(int part);
+ // Array to match the skin ID, fallback graphics and Qt widget graphics.
+ static const partMapEntry m_partMap[];
+};
+
+const partMapEntry QS60StyleModeSpecifics::m_partMap[] = {
+ /* SP_QgnGrafBarWait */ {KAknsIIDQgnGrafBarWaitAnim, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafBarFrameCenter */ {KAknsIIDQgnGrafBarFrameCenter, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafBarFrameSideL */ {KAknsIIDQgnGrafBarFrameSideL, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafBarFrameSideR */ {KAknsIIDQgnGrafBarFrameSideR, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafBarProgress */ {KAknsIIDQgnGrafBarProgress, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafScrollArrowDown */ {KAknsIIDQgnGrafScrollArrowDown, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafScrollArrowLeft */ {KAknsIIDQgnGrafScrollArrowLeft, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafScrollArrowRight */ {KAknsIIDQgnGrafScrollArrowRight, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafScrollArrowUp */ {KAknsIIDQgnGrafScrollArrowUp, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabActiveL */ {KAknsIIDQgnGrafTabActiveL, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabActiveM */ {KAknsIIDQgnGrafTabActiveM, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabActiveR */ {KAknsIIDQgnGrafTabActiveR, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabPassiveL */ {KAknsIIDQgnGrafTabPassiveL, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabPassiveM */ {KAknsIIDQgnGrafTabPassiveM, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabPassiveR */ {KAknsIIDQgnGrafTabPassiveR, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiCheckboxOff */ {KAknsIIDQgnIndiCheckboxOff, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiCheckboxOn */ {KAknsIIDQgnIndiCheckboxOn, EDrawIcon, ES60_AllReleases, -1,-1},
+ // Following 5 items (SP_QgnIndiHlColSuper - SP_QgnIndiHlLineStraight) are available starting from S60 release 3.2.
+ // In 3.1 CommonStyle drawing is used for these QTreeView elements, since no similar icons in AVKON UI.
+ /* SP_QgnIndiHlColSuper */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d5 /* KAknsIIDQgnIndiHlColSuper */},
+ /* SP_QgnIndiHlExpSuper */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d6 /* KAknsIIDQgnIndiHlExpSuper */},
+ /* SP_QgnIndiHlLineBranch */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d7 /* KAknsIIDQgnIndiHlLineBranch */},
+ /* SP_QgnIndiHlLineEnd */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d8 /* KAknsIIDQgnIndiHlLineEnd */},
+ /* SP_QgnIndiHlLineStraight */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d9 /* KAknsIIDQgnIndiHlLineStraight */},
+ /* SP_QgnIndiMarkedAdd */ {KAknsIIDQgnIndiMarkedAdd, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiNaviArrowLeft */ {KAknsIIDQgnGrafScrollArrowLeft, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiNaviArrowRight */ {KAknsIIDQgnGrafScrollArrowRight, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiRadiobuttOff */ {KAknsIIDQgnIndiRadiobuttOff, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiRadiobuttOn */ {KAknsIIDQgnIndiRadiobuttOn, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiSliderEdit */ {KAknsIIDQgnIndiSliderEdit, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiSubMenu */ {KAknsIIDQgnIndiSubmenu, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteErased */ {KAknsIIDQgnNoteErased, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteError */ {KAknsIIDQgnNoteError, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteInfo */ {KAknsIIDQgnNoteInfo, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteOk */ {KAknsIIDQgnNoteOk, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteQuery */ {KAknsIIDQgnNoteQuery, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteWarning */ {KAknsIIDQgnNoteWarning, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropFileSmall */ {KAknsIIDQgnPropFileSmall, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropFolderCurrent */ {KAknsIIDQgnPropFolderCurrent, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropFolderSmall */ {KAknsIIDQgnPropFolderSmall, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropFolderSmallNew */ {KAknsIIDQgnPropFolderSmallNew, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropPhoneMemcLarge */ {KAknsIIDQgnPropPhoneMemcLarge, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ // 3.1 & 3.2 do not have pressed state for scrollbar, so use normal scrollbar graphics instead.
+ /* SP_QsnCpScrollHandleBottomPressed*/ {KAknsIIDQsnCpScrollHandleBottom, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorGeneric, 0x20f8}, /*KAknsIIDQsnCpScrollHandleBottomPressed*/
+ /* SP_QsnCpScrollHandleMiddlePressed*/ {KAknsIIDQsnCpScrollHandleMiddle, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorGeneric, 0x20f9}, /*KAknsIIDQsnCpScrollHandleMiddlePressed*/
+ /* SP_QsnCpScrollHandleTopPressed*/ {KAknsIIDQsnCpScrollHandleTop, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorGeneric, 0x20fa}, /*KAknsIIDQsnCpScrollHandleTopPressed*/
+
+ /* SP_QsnBgScreen */ {KAknsIIDQsnBgScreen, EDrawBackground, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnCpScrollBgBottom */ {KAknsIIDQsnCpScrollBgBottom, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QsnCpScrollBgMiddle */ {KAknsIIDQsnCpScrollBgMiddle, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QsnCpScrollBgTop */ {KAknsIIDQsnCpScrollBgTop, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnCpScrollHandleBottom */ {KAknsIIDQsnCpScrollHandleBottom, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QsnCpScrollHandleMiddle */ {KAknsIIDQsnCpScrollHandleMiddle, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QsnCpScrollHandleTop */ {KAknsIIDQsnCpScrollHandleTop, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrButtonTbCornerTl */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_AllReleases, -1,-1}, //todo: use "normal button" from 5.0 onwards
+ /* SP_QsnFrButtonTbCornerTr */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerBl */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerBr */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideT */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideB */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideL */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideR */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCenter */ {KAknsIIDQsnFrButtonTbCenter, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrButtonTbCornerTlPressed */{KAknsIIDQsnFrButtonTbCornerTlPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerTrPressed */{KAknsIIDQsnFrButtonTbCornerTrPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerBlPressed */{KAknsIIDQsnFrButtonTbCornerBlPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerBrPressed */{KAknsIIDQsnFrButtonTbCornerBrPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideTPressed */ {KAknsIIDQsnFrButtonTbSideTPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideBPressed */ {KAknsIIDQsnFrButtonTbSideBPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideLPressed */ {KAknsIIDQsnFrButtonTbSideLPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideRPressed */ {KAknsIIDQsnFrButtonTbSideRPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCenterPressed */ {KAknsIIDQsnFrButtonTbCenterPressed, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrCaleCornerTl */ {KAknsIIDQsnFrCaleCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleCornerTr */ {KAknsIIDQsnFrCaleCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleCornerBl */ {KAknsIIDQsnFrCaleCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleCornerBr */ {KAknsIIDQsnFrCaleCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleGSideT */ {KAknsIIDQsnFrCaleSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleGSideB */ {KAknsIIDQsnFrCaleSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleGSideL */ {KAknsIIDQsnFrCaleSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleGSideR */ {KAknsIIDQsnFrCaleSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleCenter */ {KAknsIIDQsnFrCaleCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrCaleHeadingCornerTl */ {KAknsIIDQsnFrCaleHeadingCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingCornerTr */ {KAknsIIDQsnFrCaleHeadingCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingCornerBl */ {KAknsIIDQsnFrCaleHeadingCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingCornerBr */ {KAknsIIDQsnFrCaleHeadingCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingSideT */ {KAknsIIDQsnFrCaleHeadingSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingSideB */ {KAknsIIDQsnFrCaleHeadingSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingSideL */ {KAknsIIDQsnFrCaleHeadingSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingSideR */ {KAknsIIDQsnFrCaleHeadingSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingCenter */ {KAknsIIDQsnFrCaleHeadingCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrInputCornerTl */ {KAknsIIDQsnFrInputCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputCornerTr */ {KAknsIIDQsnFrInputCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputCornerBl */ {KAknsIIDQsnFrInputCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputCornerBr */ {KAknsIIDQsnFrInputCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputSideT */ {KAknsIIDQsnFrInputSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputSideB */ {KAknsIIDQsnFrInputSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputSideL */ {KAknsIIDQsnFrInputSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputSideR */ {KAknsIIDQsnFrInputSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputCenter */ {KAknsIIDQsnFrInputCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrListCornerTl */ {KAknsIIDQsnFrListCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListCornerTr */ {KAknsIIDQsnFrListCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListCornerBl */ {KAknsIIDQsnFrListCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListCornerBr */ {KAknsIIDQsnFrListCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListSideT */ {KAknsIIDQsnFrListSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListSideB */ {KAknsIIDQsnFrListSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListSideL */ {KAknsIIDQsnFrListSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListSideR */ {KAknsIIDQsnFrListSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListCenter */ {KAknsIIDQsnFrListCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrPopupCornerTl */ {KAknsIIDQsnFrPopupCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupCornerTr */ {KAknsIIDQsnFrPopupCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupCornerBl */ {KAknsIIDQsnFrPopupCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupCornerBr */ {KAknsIIDQsnFrPopupCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupSideT */ {KAknsIIDQsnFrPopupSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupSideB */ {KAknsIIDQsnFrPopupSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupSideL */ {KAknsIIDQsnFrPopupSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupSideR */ {KAknsIIDQsnFrPopupSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupCenter */ {KAknsIIDQsnFrPopupCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ // ToolTip graphics different in 3.1 vs. 3.2+.
+ /* SP_QsnFrPopupPreviewCornerTl */ {KAknsIIDQsnFrPopupCornerTl, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c5}, /* KAknsIIDQsnFrPopupPreviewCornerTl */
+ /* SP_QsnFrPopupPreviewCornerTr */ {KAknsIIDQsnFrPopupCornerTr, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c6},
+ /* SP_QsnFrPopupPreviewCornerBl */ {KAknsIIDQsnFrPopupCornerBl, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c3},
+ /* SP_QsnFrPopupPreviewCornerBr */ {KAknsIIDQsnFrPopupCornerBr, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c4},
+ /* SP_QsnFrPopupPreviewSideT */ {KAknsIIDQsnFrPopupSideT, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19ca},
+ /* SP_QsnFrPopupPreviewSideB */ {KAknsIIDQsnFrPopupSideB, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c7},
+ /* SP_QsnFrPopupPreviewSideL */ {KAknsIIDQsnFrPopupSideL, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c8},
+ /* SP_QsnFrPopupPreviewSideR */ {KAknsIIDQsnFrPopupSideR, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c9},
+ /* SP_QsnFrPopupPreviewCenter */ {KAknsIIDQsnFrPopupCenter, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c2},
+
+ /* SP_QsnFrSetOptCornerTl */ {KAknsIIDQsnFrSetOptCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptCornerTr */ {KAknsIIDQsnFrSetOptCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptCornerBl */ {KAknsIIDQsnFrSetOptCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptCornerBr */ {KAknsIIDQsnFrSetOptCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptSideT */ {KAknsIIDQsnFrSetOptSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptSideB */ {KAknsIIDQsnFrSetOptSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptSideL */ {KAknsIIDQsnFrSetOptSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptSideR */ {KAknsIIDQsnFrSetOptSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptCenter */ {KAknsIIDQsnFrSetOptCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ // No toolbar frame for 5.0+ releases.
+ /* SP_QsnFrPopupSubCornerTl */ {KAknsIIDQsnFrPopupSubCornerTl, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubCornerTr */ {KAknsIIDQsnFrPopupSubCornerTr, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubCornerBl */ {KAknsIIDQsnFrPopupSubCornerBl, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubCornerBr */ {KAknsIIDQsnFrPopupSubCornerBr, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubSideT */ {KAknsIIDQsnFrPopupSubSideT, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubSideB */ {KAknsIIDQsnFrPopupSubSideB, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubSideL */ {KAknsIIDQsnFrPopupSubSideL, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubSideR */ {KAknsIIDQsnFrPopupSubSideR, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubCenter */ {KAknsIIDQsnFrPopupCenterSubmenu, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+
+ // Toolbar graphics is different in 3.1/3.2 vs. 5.0
+ /* SP_QsnFrSctrlButtonCornerTl */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2301}, /* KAknsIIDQgnFrSctrlButtonCornerTl*/
+ /* SP_QsnFrSctrlButtonCornerTr */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2302},
+ /* SP_QsnFrSctrlButtonCornerBl */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2303},
+ /* SP_QsnFrSctrlButtonCornerBr */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2304},
+ /* SP_QsnFrSctrlButtonSideT */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2305},
+ /* SP_QsnFrSctrlButtonSideB */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2306},
+ /* SP_QsnFrSctrlButtonSideL */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2307},
+ /* SP_QsnFrSctrlButtonSideR */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2308},
+ /* SP_QsnFrSctrlButtonCenter */ {KAknsIIDQsnFrButtonTbCenter, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2309}, /*KAknsIIDQgnFrSctrlButtonCenter*/
+
+ // No pressed state for toolbar button in 3.1/3.2.
+ /* SP_QsnFrSctrlButtonCornerTlPressed */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2621}, /*KAknsIIDQsnFrSctrlButtonCornerTlPressed*/
+ /* SP_QsnFrSctrlButtonCornerTrPressed */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2622},
+ /* SP_QsnFrSctrlButtonCornerBlPressed */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2623},
+ /* SP_QsnFrSctrlButtonCornerBrPressed */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2624},
+ /* SP_QsnFrSctrlButtonSideTPressed */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2625},
+ /* SP_QsnFrSctrlButtonSideBPressed */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2626},
+ /* SP_QsnFrSctrlButtonSideLPressed */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2627},
+ /* SP_QsnFrSctrlButtonSideRPressed */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2628},
+ /* SP_QsnFrSctrlButtonCenterPressed */ {KAknsIIDQsnFrButtonTbCenter, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2629},
+
+ // No inactive button graphics in 3.1/3.2
+ /* SP_QsnFrButtonCornerTlInactive */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b1}, /*KAknsIIDQsnFrButtonCornerTlInactive*/
+ /* SP_QsnFrButtonCornerTrInactive */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b2},
+ /* SP_QsnFrButtonCornerBlInactive */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b3},
+ /* SP_QsnFrButtonCornerTrInactive */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b4},
+ /* SP_QsnFrButtonSideTInactive */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b5},
+ /* SP_QsnFrButtonSideBInactive */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b6},
+ /* SP_QsnFrButtonSideLInactive */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b7},
+ /* SP_QsnFrButtonSideRInactive */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b8},
+ /* SP_QsnFrButtonCenterInactive */ {KAknsIIDQsnFrButtonTbCenter, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b9},
+
+ /* SP_QsnFrNotepadCornerTl */ {KAknsIIDQsnFrNotepadContCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadCornerTr */ {KAknsIIDQsnFrNotepadContCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadCornerBl */ {KAknsIIDQsnFrNotepadCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadCornerBr */ {KAknsIIDQsnFrNotepadCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadSideT */ {KAknsIIDQsnFrNotepadContSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadSideB */ {KAknsIIDQsnFrNotepadSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadSideL */ {KAknsIIDQsnFrNotepadSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadSideR */ {KAknsIIDQsnFrNotepadSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadCenter */ {KAknsIIDQsnFrNotepadCenter, EDrawIcon, ES60_AllReleases, -1,-1},
+
+};
+
+QPixmap QS60StyleModeSpecifics::skinnedGraphics(
+ QS60StyleEnums::SkinParts stylepart, const QSize &size,
+ QS60StylePrivate::SkinElementFlags flags)
+{
+ QPixmap themedImage;
+ TRAPD( error, QT_TRYCATCH_LEAVING({
+ const QPixmap skinnedImage = createSkinnedGraphicsLX(stylepart, size, flags);
+ themedImage = skinnedImage;
+ }));
+ if (error)
+ return themedImage = QPixmap();
+ return themedImage;
+}
+
+QPixmap QS60StyleModeSpecifics::skinnedGraphics(
+ QS60StylePrivate::SkinFrameElements frame, const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ QPixmap themedImage;
+ TRAPD( error, QT_TRYCATCH_LEAVING({
+ const QPixmap skinnedImage = createSkinnedGraphicsLX(frame, size, flags);
+ themedImage = skinnedImage;
+ }));
+ if (error)
+ return themedImage = QPixmap();
+ return themedImage;
+}
+
+QPixmap QS60StyleModeSpecifics::colorSkinnedGraphics(
+ const QS60StyleEnums::SkinParts &stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ QPixmap colorGraphics;
+ TRAPD(error, QT_TRYCATCH_LEAVING(colorGraphics = colorSkinnedGraphicsLX(stylepart, size, flags)));
+ return error ? QPixmap() : colorGraphics;
+}
+
+void QS60StyleModeSpecifics::fallbackInfo(const QS60StyleEnums::SkinParts &stylepart, TDes& fallbackFileName, TInt& fallbackIndex)
+{
+ switch(stylepart) {
+ case QS60StyleEnums::SP_QgnGrafBarWait:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_wait_1;
+ break;
+ case QS60StyleEnums::SP_QgnGrafBarFrameCenter:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_frame_center;
+ break;
+ case QS60StyleEnums::SP_QgnGrafBarFrameSideL:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_frame_side_l;
+ break;
+ case QS60StyleEnums::SP_QgnGrafBarFrameSideR:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_frame_side_r;
+ break;
+ case QS60StyleEnums::SP_QgnGrafBarProgress:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_progress;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabActiveL:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_active_l;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabActiveM:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_active_m;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabActiveR:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_active_r;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabPassiveL:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_passive_l;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabPassiveM:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_passive_m;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabPassiveR:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_passive_r;
+ break;
+ case QS60StyleEnums::SP_QgnIndiCheckboxOff:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_checkbox_off;
+ break;
+ case QS60StyleEnums::SP_QgnIndiCheckboxOn:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_checkbox_on;
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlColSuper:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x4456; /* EMbmAvkonQgn_indi_hl_col_super */
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlExpSuper:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x4458; /* EMbmAvkonQgn_indi_hl_exp_super */
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlLineBranch:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x445A; /* EMbmAvkonQgn_indi_hl_line_branch */
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlLineEnd:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x445C; /* EMbmAvkonQgn_indi_hl_line_end */
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlLineStraight:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x445E; /* EMbmAvkonQgn_indi_hl_line_straight */
+ break;
+ case QS60StyleEnums::SP_QgnIndiMarkedAdd:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_marked_add;
+ break;
+ case QS60StyleEnums::SP_QgnIndiNaviArrowLeft:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_navi_arrow_left;
+ break;
+ case QS60StyleEnums::SP_QgnIndiNaviArrowRight:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_navi_arrow_right;
+ break;
+ case QS60StyleEnums::SP_QgnIndiRadiobuttOff:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_radiobutt_off;
+ break;
+ case QS60StyleEnums::SP_QgnIndiRadiobuttOn:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_radiobutt_on;
+ break;
+ case QS60StyleEnums::SP_QgnIndiSliderEdit:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_slider_edit;
+ break;
+ case QS60StyleEnums::SP_QgnIndiSubMenu:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_submenu;
+ break;
+ case QS60StyleEnums::SP_QgnNoteErased:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_erased;
+ break;
+ case QS60StyleEnums::SP_QgnNoteError:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_error;
+ break;
+ case QS60StyleEnums::SP_QgnNoteInfo:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_info;
+ break;
+ case QS60StyleEnums::SP_QgnNoteOk:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_ok;
+ break;
+ case QS60StyleEnums::SP_QgnNoteQuery:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_query;
+ break;
+ case QS60StyleEnums::SP_QgnNoteWarning:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_warning;
+ break;
+ case QS60StyleEnums::SP_QgnPropFileSmall:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_file_small;
+ break;
+ case QS60StyleEnums::SP_QgnPropFolderCurrent:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_folder_current;
+ break;
+ case QS60StyleEnums::SP_QgnPropFolderSmall:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_folder_small;
+ break;
+ case QS60StyleEnums::SP_QgnPropFolderSmallNew:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_folder_small_new;
+ break;
+ case QS60StyleEnums::SP_QgnPropPhoneMemcLarge:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_phone_memc_large;
+ break;
+ default:
+ fallbackFileName = KNullDesC();
+ fallbackIndex = -1;
+ break;
+ }
+}
+
+QPixmap QS60StyleModeSpecifics::colorSkinnedGraphicsLX(
+ const QS60StyleEnums::SkinParts &stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ // this function can throw both exceptions and leaves. There are no cleanup dependencies between Qt and Symbian parts.
+ const int stylepartIndex = (int)stylepart;
+ const TAknsItemID skinId = m_partMap[stylepartIndex].skinID;
+
+ TInt fallbackGraphicID = -1;
+ HBufC* iconFile = HBufC::NewLC( KMaxFileName );
+ TPtr fileNamePtr = iconFile->Des();
+ fallbackInfo(stylepart, fileNamePtr, fallbackGraphicID);
+
+ TAknsItemID colorGroup = KAknsIIDQsnIconColors;
+ int colorIndex = 0;
+ colorGroupAndIndex(stylepart, colorGroup, colorIndex);
+
+ const bool rotatedBy90or270 =
+ (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest));
+ const TSize targetSize =
+ rotatedBy90or270?TSize(size.height(), size.width()):TSize(size.width(), size.height());
+ CFbsBitmap *icon = 0;
+ CFbsBitmap *iconMask = 0;
+ const TInt fallbackGraphicsMaskID =
+ fallbackGraphicID == KErrNotFound?KErrNotFound:fallbackGraphicID+1; //masks are auto-generated as next in mif files
+ MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+ AknsUtils::CreateColorIconLC(
+ skinInstance, skinId, colorGroup, colorIndex, icon, iconMask, fileNamePtr, fallbackGraphicID , fallbackGraphicsMaskID, KRgbBlack);
+ User::LeaveIfError(AknIconUtils::SetSize(icon, targetSize, EAspectRatioNotPreserved));
+ User::LeaveIfError(AknIconUtils::SetSize(iconMask, targetSize, EAspectRatioNotPreserved));
+ QPixmap result = fromFbsBitmap(icon, iconMask, flags, qt_TDisplayMode2Format(icon->DisplayMode()));
+ CleanupStack::PopAndDestroy(3); //icon, iconMask, iconFile
+ return result;
+}
+
+QColor QS60StyleModeSpecifics::colorValue(const TAknsItemID &colorGroup, int colorIndex)
+{
+ TRgb skinnedColor;
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ AknsUtils::GetCachedColor(skin, skinnedColor, colorGroup, colorIndex);
+ return QColor(skinnedColor.Red(),skinnedColor.Green(),skinnedColor.Blue());
+}
+
+struct QAutoFbsBitmapHeapLock
+{
+ QAutoFbsBitmapHeapLock(CFbsBitmap* aBmp) : mBmp(aBmp) { mBmp->LockHeap(); }
+ ~QAutoFbsBitmapHeapLock() { mBmp->UnlockHeap(); }
+ CFbsBitmap* mBmp;
+};
+
+QPixmap QS60StyleModeSpecifics::fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask, QS60StylePrivate::SkinElementFlags flags, QImage::Format format)
+{
+ Q_ASSERT(icon);
+ const TSize iconSize = icon->SizeInPixels();
+ const int iconBytesPerLine = CFbsBitmap::ScanLineLength(iconSize.iWidth, icon->DisplayMode());
+ const int iconBytesCount = iconBytesPerLine * iconSize.iHeight;
+
+ QImage iconImage(qt_TSize2QSize(iconSize), format);
+ if (iconImage.isNull())
+ return QPixmap();
+
+ checkAndUnCompressBitmap(icon);
+ if (!icon) //checkAndUnCompressBitmap might set icon to NULL
+ return QPixmap();
+
+ icon->LockHeap();
+ const uchar *const iconBytes = (uchar*)icon->DataAddress();
+ // The icon data needs to be copied, since the color format will be
+ // automatically converted to Format_ARGB32 when setAlphaChannel is called.
+ memcpy(iconImage.bits(), iconBytes, iconBytesCount);
+ icon->UnlockHeap();
+ if (mask) {
+ checkAndUnCompressBitmap(mask);
+ if (mask) { //checkAndUnCompressBitmap might set mask to NULL
+ const TSize maskSize = icon->SizeInPixels();
+ const int maskBytesPerLine = CFbsBitmap::ScanLineLength(maskSize.iWidth, mask->DisplayMode());
+ // heap lock object required because QImage ctor might throw
+ QAutoFbsBitmapHeapLock maskHeapLock(mask);
+ const uchar *const maskBytes = (uchar *)mask->DataAddress();
+ // Since no other bitmap should be locked, we can just "borrow" the mask data for setAlphaChannel
+ const QImage maskImage(maskBytes, maskSize.iWidth, maskSize.iHeight, maskBytesPerLine, QImage::Format_Indexed8);
+ if (!maskImage.isNull())
+ iconImage.setAlphaChannel(maskImage);
+ }
+ }
+
+ QTransform imageTransform;
+ if (flags & QS60StylePrivate::SF_PointEast) {
+ imageTransform.rotate(90);
+ } else if (flags & QS60StylePrivate::SF_PointSouth) {
+ imageTransform.rotate(180);
+ iconImage = iconImage.transformed(imageTransform);
+ } else if (flags & QS60StylePrivate::SF_PointWest) {
+ imageTransform.rotate(270);
+ }
+ if (imageTransform.isRotating())
+ iconImage = iconImage.transformed(imageTransform);
+
+ return QPixmap::fromImage(iconImage);
+}
+
+bool QS60StylePrivate::isTouchSupported()
+{
+ return bool(AknLayoutUtils::PenEnabled());
+}
+
+bool QS60StylePrivate::isToolBarBackground()
+{
+ return (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
+}
+
+QPoint qt_s60_fill_background_offset(const QWidget *targetWidget)
+{
+ CCoeControl *control = targetWidget->effectiveWinId();
+ TPoint globalPos = control ? control->PositionRelativeToScreen() : TPoint(0,0);
+ return QPoint(globalPos.iX, globalPos.iY);
+}
+
+QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(
+ QS60StyleEnums::SkinParts part,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ // this function can throw both exceptions and leaves. There are no cleanup dependencies between Qt and Symbian parts.
+ if (!size.isValid())
+ return QPixmap();
+
+ // Check release support and change part, if necessary.
+ const TAknsItemID skinId = checkAndUpdateReleaseSpecificGraphics((int)part);
+ const int stylepartIndex = (int)part;
+ const TDrawType drawType = m_partMap[stylepartIndex].drawType;
+ Q_ASSERT(drawType != ENoDraw);
+ const bool rotatedBy90or270 =
+ (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest));
+ const TSize targetSize =
+ rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size);
+
+ MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+
+ QPixmap result;
+
+ switch (drawType) {
+ case EDrawIcon: {
+ TInt fallbackGraphicID = -1;
+ HBufC* iconFile = HBufC::NewLC( KMaxFileName );
+ TPtr fileNamePtr = iconFile->Des();
+ fallbackInfo(part, fileNamePtr, fallbackGraphicID);
+ // todo: could we instead use AknIconUtils::AvkonIconFileName(); to avoid allocating each time?
+
+ CFbsBitmap *icon = 0;
+ CFbsBitmap *iconMask = 0;
+ const TInt fallbackGraphicsMaskID =
+ fallbackGraphicID == KErrNotFound?KErrNotFound:fallbackGraphicID+1; //masks are auto-generated as next in mif files
+ // QS60WindowSurface::unlockBitmapHeap();
+ AknsUtils::CreateIconLC(skinInstance, skinId, icon, iconMask, fileNamePtr, fallbackGraphicID , fallbackGraphicsMaskID);
+ User::LeaveIfError(AknIconUtils::SetSize(icon, targetSize, EAspectRatioNotPreserved));
+ User::LeaveIfError(AknIconUtils::SetSize(iconMask, targetSize, EAspectRatioNotPreserved));
+ result = fromFbsBitmap(icon, iconMask, flags, qt_TDisplayMode2Format(icon->DisplayMode()));
+ CleanupStack::PopAndDestroy(3); // iconMask, icon, iconFile
+ // QS60WindowSurface::lockBitmapHeap();
+ break;
+ }
+ case EDrawBackground: {
+ // QS60WindowSurface::unlockBitmapHeap();
+ CFbsBitmap *background = new (ELeave) CFbsBitmap(); //offscreen
+ CleanupStack::PushL(background);
+ User::LeaveIfError(background->Create(targetSize, EColor16MA));
+
+ CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(background);
+ CleanupStack::PushL(dev);
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError(dev->CreateContext(gc));
+ CleanupStack::PushL(gc);
+
+ CAknsBasicBackgroundControlContext* bgContext = CAknsBasicBackgroundControlContext::NewL(
+ skinId,
+ targetSize,
+ EFalse);
+ CleanupStack::PushL(bgContext);
+
+ const TBool drawn = AknsDrawUtils::DrawBackground(
+ skinInstance,
+ bgContext,
+ NULL,
+ *gc,
+ TPoint(),
+ targetSize,
+ KAknsDrawParamDefault | KAknsDrawParamRGBOnly);
+
+ if (drawn)
+ result = fromFbsBitmap(background, NULL, flags, QImage::Format_RGB32);
+
+ CleanupStack::PopAndDestroy(4, background); //background, dev, gc, bgContext
+ // QS60WindowSurface::lockBitmapHeap();
+ break;
+ }
+ }
+
+ return result;
+}
+
+QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(QS60StylePrivate::SkinFrameElements frameElement,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ // this function can throw both exceptions and leaves. There are no cleanup dependencies between Qt and Symbian parts.
+ if (!size.isValid())
+ return QPixmap();
+
+ const bool rotatedBy90or270 =
+ (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest));
+ const TSize targetSize =
+ rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size);
+
+ MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+ QPixmap result;
+
+// QS60WindowSurface::unlockBitmapHeap();
+ static const bool canDoEColor16MAP = !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
+ static const TDisplayMode displayMode = canDoEColor16MAP ? TDisplayMode(13) : EColor16MA; // 13 = EColor16MAP
+ static const TInt drawParam = canDoEColor16MAP ? KAknsDrawParamDefault : KAknsDrawParamNoClearUnderImage|KAknsDrawParamRGBOnly;
+
+ CFbsBitmap *frame = new (ELeave) CFbsBitmap(); //offscreen
+ CleanupStack::PushL(frame);
+ User::LeaveIfError(frame->Create(targetSize, displayMode));
+
+ CFbsBitmapDevice* bitmapDev = CFbsBitmapDevice::NewL(frame);
+ CleanupStack::PushL(bitmapDev);
+ CFbsBitGc* bitmapGc = NULL;
+ User::LeaveIfError(bitmapDev->CreateContext(bitmapGc));
+ CleanupStack::PushL(bitmapGc);
+
+ frame->LockHeap();
+ memset(frame->DataAddress(), 0, frame->SizeInPixels().iWidth * frame->SizeInPixels().iHeight * 4); // 4: argb bytes
+ frame->UnlockHeap();
+
+ const TRect outerRect(TPoint(0, 0), targetSize);
+ const TRect innerRect = innerRectFromElement(frameElement, outerRect);
+
+ TAknsItemID frameSkinID, centerSkinID;
+ frameSkinID = centerSkinID = checkAndUpdateReleaseSpecificGraphics(QS60StylePrivate::m_frameElementsData[frameElement].center);
+ frameIdAndCenterId(frameElement, frameSkinID, centerSkinID);
+ const TBool drawn = AknsDrawUtils::DrawFrame( skinInstance,
+ *bitmapGc, outerRect, innerRect,
+ frameSkinID, centerSkinID,
+ drawParam );
+
+ if (canDoEColor16MAP) {
+ if (drawn)
+ result = fromFbsBitmap(frame, NULL, flags, QImage::Format_ARGB32_Premultiplied);
+ } else {
+ TDisplayMode maskDepth = EGray2;
+ // Query the skin item for possible frame graphics mask details.
+ if (skinInstance) {
+ CAknsMaskedBitmapItemData* skinMaskedBmp = static_cast<CAknsMaskedBitmapItemData*>(
+ skinInstance->GetCachedItemData(frameSkinID,EAknsITMaskedBitmap));
+ if (skinMaskedBmp && skinMaskedBmp->Mask())
+ maskDepth = skinMaskedBmp->Mask()->DisplayMode();
+ }
+ if (maskDepth != ENone) {
+ CFbsBitmap *frameMask = new (ELeave) CFbsBitmap(); //offscreen
+ CleanupStack::PushL(frameMask);
+ User::LeaveIfError(frameMask->Create(targetSize, maskDepth));
+
+ CFbsBitmapDevice* maskBitmapDevice = CFbsBitmapDevice::NewL(frameMask);
+ CleanupStack::PushL(maskBitmapDevice);
+ CFbsBitGc* maskBitGc = NULL;
+ User::LeaveIfError(maskBitmapDevice->CreateContext(maskBitGc));
+ CleanupStack::PushL(maskBitGc);
+
+ if (drawn) {
+ //ensure that the mask is really transparent
+ maskBitGc->Activate( maskBitmapDevice );
+ maskBitGc->SetPenStyle(CGraphicsContext::ENullPen);
+ maskBitGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ maskBitGc->SetBrushColor(KRgbWhite);
+ maskBitGc->Clear();
+ maskBitGc->SetBrushStyle(CGraphicsContext::ENullBrush);
+
+ AknsDrawUtils::DrawFrame(skinInstance,
+ *maskBitGc, outerRect, innerRect,
+ frameSkinID, centerSkinID,
+ KAknsSDMAlphaOnly |KAknsDrawParamNoClearUnderImage);
+ result = fromFbsBitmap(frame, frameMask, flags, QImage::Format_ARGB32);
+ }
+ CleanupStack::PopAndDestroy(3, frameMask);
+ }
+ }
+ CleanupStack::PopAndDestroy(3, frame); //frame, bitmapDev, bitmapGc
+ return result;
+}
+
+void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameElements frameElement, TAknsItemID &frameId, TAknsItemID &centerId)
+{
+// There are some major mix-ups in skin declarations for some frames.
+// First, the frames are not declared in sequence.
+// Second, the parts use different major than the frame-master.
+
+ switch(frameElement) {
+ case QS60StylePrivate::SF_ToolTip:
+ if (QSysInfo::s60Version()!=QSysInfo::SV_S60_3_1) {
+ centerId.Set(EAknsMajorGeneric, 0x19c2);
+ frameId.Set(EAknsMajorSkin, 0x5300);
+ } else {
+ centerId.Set(KAknsIIDQsnFrPopupCenter);
+ frameId.iMinor = centerId.iMinor - 9;
+ }
+ break;
+ case QS60StylePrivate::SF_ToolBar:
+ if (QSysInfo::s60Version()==QSysInfo::SV_S60_3_1 || QSysInfo::s60Version()==QSysInfo::SV_S60_3_2) {
+ centerId.Set(KAknsIIDQsnFrPopupCenterSubmenu);
+ frameId.Set(KAknsIIDQsnFrPopupSub);
+ }
+ break;
+ case QS60StylePrivate::SF_PanelBackground:
+ // remove center piece for panel graphics, so that only border is drawn
+ centerId.Set(KAknsIIDNone);
+ frameId.Set(KAknsIIDQsnFrSetOpt);
+ break;
+ case QS60StylePrivate::SF_Editor:
+ centerId.Set(KAknsIIDQsnFrNotepadCenter);
+ frameId.Set(KAknsIIDQsnFrNotepadCont);
+ break;
+ default:
+ // center should be correct here
+ frameId.iMinor = centerId.iMinor - 9;
+ break;
+ }
+}
+
+TRect QS60StyleModeSpecifics::innerRectFromElement(QS60StylePrivate::SkinFrameElements frameElement, const TRect &outerRect)
+{
+ TInt widthShrink = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth);
+ TInt heightShrink = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerHeight);
+ switch(frameElement) {
+ case QS60StylePrivate::SF_PanelBackground:
+ // panel should have slightly slimmer border to enable thin line of background graphics between closest component
+ widthShrink = widthShrink-2;
+ heightShrink = heightShrink-2;
+ break;
+ case QS60StylePrivate::SF_ToolTip:
+ widthShrink = widthShrink>>1;
+ heightShrink = heightShrink>>1;
+ break;
+ case QS60StylePrivate::SF_ListHighlight:
+ widthShrink = widthShrink-2;
+ heightShrink = heightShrink-2;
+ break;
+ default:
+ break;
+ }
+ TRect innerRect(outerRect);
+ innerRect.Shrink(widthShrink, heightShrink);
+ return innerRect;
+}
+
+bool QS60StyleModeSpecifics::checkSupport(const int supportedRelease)
+{
+ const QSysInfo::S60Version currentRelease = QSysInfo::s60Version();
+ return ( (currentRelease == QSysInfo::SV_S60_3_1 && supportedRelease & ES60_3_1) ||
+ (currentRelease == QSysInfo::SV_S60_3_2 && supportedRelease & ES60_3_2) ||
+ (currentRelease == QSysInfo::SV_S60_5_0 && supportedRelease & ES60_5_0));
+}
+
+TAknsItemID QS60StyleModeSpecifics::checkAndUpdateReleaseSpecificGraphics(int part)
+{
+ TAknsItemID newSkinId;
+ if (!checkSupport(m_partMap[(int)part].supportInfo))
+ newSkinId.Set(m_partMap[(int)part].newMajorSkinId, m_partMap[(int)part].newMinorSkinId);
+ else
+ newSkinId.Set(m_partMap[(int)part].skinID);
+ return newSkinId;
+}
+
+void QS60StyleModeSpecifics::checkAndUnCompressBitmap(CFbsBitmap*& aOriginalBitmap)
+{
+ TRAPD(error, checkAndUnCompressBitmapL(aOriginalBitmap));
+ if (error)
+ aOriginalBitmap = NULL;
+}
+
+void QS60StyleModeSpecifics::checkAndUnCompressBitmapL(CFbsBitmap*& aOriginalBitmap)
+{
+ const TSize iconSize = aOriginalBitmap->SizeInPixels();
+ const int iconBytesPerLine = CFbsBitmap::ScanLineLength(iconSize.iWidth, aOriginalBitmap->DisplayMode());
+ const int iconBytesCount = iconBytesPerLine * iconSize.iHeight;
+ if (aOriginalBitmap->IsCompressedInRAM() || aOriginalBitmap->Header().iBitmapSize < iconBytesCount) {
+ const TSize iconSize(aOriginalBitmap->SizeInPixels().iWidth,
+ aOriginalBitmap->SizeInPixels().iHeight);
+ CFbsBitmap* uncompressedBitmap = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(uncompressedBitmap);
+ User::LeaveIfError(uncompressedBitmap->Create(iconSize,
+ aOriginalBitmap->DisplayMode()));
+ unCompressBitmapL(iconSize, uncompressedBitmap, aOriginalBitmap);
+ CleanupStack::Pop(uncompressedBitmap);
+ User::LeaveIfError(aOriginalBitmap->Duplicate(
+ uncompressedBitmap->Handle()));
+ delete uncompressedBitmap;
+ }
+}
+
+QFont QS60StylePrivate::s60Font_specific(
+ QS60StyleEnums::FontCategories fontCategory, int pointSize)
+{
+ TAknFontCategory aknFontCategory = EAknFontCategoryUndefined;
+ switch (fontCategory) {
+ case QS60StyleEnums::FC_Primary:
+ aknFontCategory = EAknFontCategoryPrimary;
+ break;
+ case QS60StyleEnums::FC_Secondary:
+ aknFontCategory = EAknFontCategorySecondary;
+ break;
+ case QS60StyleEnums::FC_Title:
+ aknFontCategory = EAknFontCategoryTitle;
+ break;
+ case QS60StyleEnums::FC_PrimarySmall:
+ aknFontCategory = EAknFontCategoryPrimarySmall;
+ break;
+ case QS60StyleEnums::FC_Digital:
+ aknFontCategory = EAknFontCategoryDigital;
+ break;
+ case QS60StyleEnums::FC_Undefined:
+ default:
+ break;
+ }
+
+ // Create AVKON font according the given parameters
+ CWsScreenDevice* dev = CCoeEnv::Static()->ScreenDevice();
+ TAknFontSpecification spec(aknFontCategory, TFontSpec(), NULL);
+ if (pointSize > 0) {
+ const TInt pixelSize = dev->VerticalTwipsToPixels(pointSize * KTwipsPerPoint);
+ spec.SetTextPaneHeight(pixelSize + 4); // TODO: Is 4 a reasonable top+bottom margin?
+ }
+
+ QFont result;
+ TRAPD( error, QT_TRYCATCH_LEAVING({
+ const CAknLayoutFont* aknFont =
+ AknFontAccess::CreateLayoutFontFromSpecificationL(*dev, spec);
+
+ result = qt_TFontSpec2QFontL(aknFont->DoFontSpecInTwips());
+ if (result.pointSize() != pointSize)
+ result.setPointSize(pointSize); // Correct the font size returned by CreateLayoutFontFromSpecificationL()
+
+ delete aknFont;
+ }));
+ if (error) result = QFont();
+ return result;
+}
+
+void QS60StylePrivate::setActiveLayout()
+{
+ const QSize activeScreenSize(screenSize());
+ int activeLayoutIndex = -1;
+ const bool mirrored = !QApplication::isLeftToRight();
+ const short screenHeight = (short)activeScreenSize.height();
+ const short screenWidth = (short)activeScreenSize.width();
+ for (int i=0; i<m_numberOfLayouts; i++) {
+ if (screenHeight==m_layoutHeaders[i].height &&
+ screenWidth==m_layoutHeaders[i].width &&
+ mirrored==m_layoutHeaders[i].mirroring) {
+ activeLayoutIndex = i;
+ break;
+ }
+ }
+
+ //not found, lets try without mirroring info
+ if (activeLayoutIndex==-1){
+ for (int i=0; i<m_numberOfLayouts; i++) {
+ if (screenHeight==m_layoutHeaders[i].height &&
+ screenWidth==m_layoutHeaders[i].width) {
+ activeLayoutIndex = i;
+ break;
+ }
+ }
+ }
+
+ //not found, lets try with either of dimensions
+ if (activeLayoutIndex==-1){
+ const QSysInfo::S60Version currentRelease = QSysInfo::s60Version();
+ const bool landscape = screenHeight < screenWidth;
+
+ activeLayoutIndex = (currentRelease == QSysInfo::SV_S60_3_1 || currentRelease == QSysInfo::SV_S60_3_2) ? 0 : 4;
+ activeLayoutIndex += (!landscape) ? 2 : 0;
+ activeLayoutIndex += (!mirrored) ? 1 : 0;
+ }
+
+ m_pmPointer = data[activeLayoutIndex];
+}
+
+QS60StylePrivate::QS60StylePrivate()
+{
+ // No need to set active layout, if dynamic metrics API is available
+ setActiveLayout();
+}
+
+void QS60StylePrivate::setStyleProperty_specific(const char *name, const QVariant &value)
+{
+ if (name == QLatin1String("foo")) {
+ // BaR
+ } else {
+ setStyleProperty(name, value);
+ }
+}
+
+QVariant QS60StylePrivate::styleProperty_specific(const char *name) const
+{
+ if (name == QLatin1String("foo"))
+ return QLatin1String("Bar");
+ else
+ return styleProperty(name);
+}
+
+QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list,
+ int index, const QStyleOption *option)
+{
+ static const TAknsItemID *idMap[] = {
+ &KAknsIIDQsnHighlightColors,
+ &KAknsIIDQsnIconColors,
+ &KAknsIIDQsnLineColors,
+ &KAknsIIDQsnOtherColors,
+ &KAknsIIDQsnParentColors,
+ &KAknsIIDQsnTextColors
+ };
+ Q_ASSERT((int)list <= (int)sizeof(idMap)/sizeof(idMap[0]));
+ const QColor color = QS60StyleModeSpecifics::colorValue(*idMap[(int) list], index - 1);
+ return option ? QS60StylePrivate::stateColor(color, option) : color;
+}
+
+// In some cases, the AVKON UI themegraphic is already in 'disabled state'.
+// If so, return true for these parts.
+bool QS60StyleModeSpecifics::disabledPartGraphic(QS60StyleEnums::SkinParts &part)
+{
+ bool disabledGraphic = false;
+ switch(part){
+ // inactive button graphics are available from 5.0 onwards
+ case QS60StyleEnums::SP_QsnFrButtonCornerTlInactive:
+ case QS60StyleEnums::SP_QsnFrButtonCornerTrInactive:
+ case QS60StyleEnums::SP_QsnFrButtonCornerBlInactive:
+ case QS60StyleEnums::SP_QsnFrButtonCornerBrInactive:
+ case QS60StyleEnums::SP_QsnFrButtonSideTInactive:
+ case QS60StyleEnums::SP_QsnFrButtonSideBInactive:
+ case QS60StyleEnums::SP_QsnFrButtonSideLInactive:
+ case QS60StyleEnums::SP_QsnFrButtonSideRInactive:
+ case QS60StyleEnums::SP_QsnFrButtonCenterInactive:
+ if (!(QSysInfo::s60Version()==QSysInfo::SV_S60_3_1 ||
+ QSysInfo::s60Version()==QSysInfo::SV_S60_3_2))
+ disabledGraphic = true;
+ break;
+ default:
+ break;
+ }
+ return disabledGraphic;
+}
+
+// In some cases, the AVKON UI themegraphic is already in 'disabled state'.
+// If so, return true for these frames.
+bool QS60StyleModeSpecifics::disabledFrameGraphic(QS60StylePrivate::SkinFrameElements &frame)
+{
+ bool disabledGraphic = false;
+ switch(frame){
+ // inactive button graphics are available from 5.0 onwards
+ case QS60StylePrivate::SF_ButtonInactive:
+ if (!(QSysInfo::s60Version()==QSysInfo::SV_S60_3_1 ||
+ QSysInfo::s60Version()==QSysInfo::SV_S60_3_2))
+ disabledGraphic = true;
+ break;
+ default:
+ break;
+ }
+ return disabledGraphic;
+}
+
+QPixmap QS60StyleModeSpecifics::generateMissingThemeGraphic(QS60StyleEnums::SkinParts &part,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ if (!QS60StylePrivate::isTouchSupported())
+ return QPixmap();
+
+ QS60StyleEnums::SkinParts updatedPart = part;
+ switch(part){
+ // AVKON UI has a abnormal handling for scrollbar graphics. It is possible that the root
+ // skin does not contain mandatory graphics for scrollbar pressed states. Therefore, AVKON UI
+ // creates dynamically these graphics by modifying the normal state scrollbar graphics slightly.
+ // S60Style needs to work similarly. Therefore if skingraphics call provides to be a miss
+ // (i.e. result is not valid), style needs to draw normal graphics instead and apply some
+ // modifications (similar to generatedIconPixmap()) to the result.
+ case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed:
+ updatedPart = QS60StyleEnums::SP_QsnCpScrollHandleBottom;
+ break;
+ case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed:
+ updatedPart = QS60StyleEnums::SP_QsnCpScrollHandleMiddle;
+ break;
+ case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed:
+ updatedPart = QS60StyleEnums::SP_QsnCpScrollHandleTop;
+ break;
+ default:
+ break;
+ }
+ if (part==updatedPart) {
+ return QPixmap();
+ } else {
+ QPixmap result = skinnedGraphics(updatedPart, size, flags);
+ QStyleOption opt;
+ QPalette *themePalette = QS60StylePrivate::themePalette();
+ if (themePalette)
+ opt.palette = *themePalette;
+
+ // For now, always generate new icon based on "selected". In the future possibly, expand
+ // this to consist other possibilities as well.
+ result = QApplication::style()->generatedIconPixmap(QIcon::Selected, result, &opt);
+ return result;
+ }
+}
+
+QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part,
+ const QSize &size, SkinElementFlags flags)
+{
+ QS60WindowSurface::unlockBitmapHeap();
+ QPixmap result = (flags & SF_ColorSkinned)?
+ QS60StyleModeSpecifics::colorSkinnedGraphics(part, size, flags)
+ : QS60StyleModeSpecifics::skinnedGraphics(part, size, flags);
+ QS60WindowSurface::lockBitmapHeap();
+
+ if (flags & SF_StateDisabled && !QS60StyleModeSpecifics::disabledPartGraphic(part)) {
+ QStyleOption opt;
+ QPalette *themePalette = QS60StylePrivate::themePalette();
+ if (themePalette)
+ opt.palette = *themePalette;
+ result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt);
+ }
+
+ if (!result)
+ result = QS60StyleModeSpecifics::generateMissingThemeGraphic(part, size, flags);
+
+ return result;
+}
+
+QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags)
+{
+ QS60WindowSurface::unlockBitmapHeap();
+ QPixmap result = QS60StyleModeSpecifics::skinnedGraphics(frame, size, flags);
+ QS60WindowSurface::lockBitmapHeap();
+
+ if (flags & SF_StateDisabled && !QS60StyleModeSpecifics::disabledFrameGraphic(frame)) {
+ QStyleOption opt;
+ QPalette *themePalette = QS60StylePrivate::themePalette();
+ if (themePalette)
+ opt.palette = *themePalette;
+ result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt);
+ }
+ return result;
+}
+
+QPixmap QS60StylePrivate::backgroundTexture()
+{
+ if (!m_background) {
+ QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen,
+ QSize(S60->screenWidthInPixels, S60->screenHeightInPixels), SkinElementFlags());
+ m_background = new QPixmap(background);
+ }
+ return *m_background;
+}
+
+// If the public SDK returns compressed images, please let us also uncompress those!
+void QS60StyleModeSpecifics::unCompressBitmapL(const TRect& aTrgRect, CFbsBitmap* aTrgBitmap, CFbsBitmap* aSrcBitmap)
+{
+ if (!aSrcBitmap)
+ User::Leave(KErrArgument);
+ if (!aTrgBitmap)
+ User::Leave(KErrArgument);
+
+ // Note! aSrcBitmap->IsCompressedInRAM() is always ETrue, since this method is called only if that applies!
+ // Extra note! this function is also being used when bitmaps appear to be compressed (because DataSize is too small)
+ // even when they pretend they are not. Assert removed.
+// ASSERT(aSrcBitmap->IsCompressedInRAM());
+
+ TDisplayMode displayMode = aSrcBitmap->DisplayMode();
+
+ if (displayMode != aTrgBitmap->DisplayMode())
+ User::Leave(KErrArgument);
+
+ const TSize trgSize = aTrgBitmap->SizeInPixels();
+ const TSize srcSize = aSrcBitmap->SizeInPixels();
+
+ // calculate the valid drawing area
+ TRect drawRect = aTrgRect;
+ drawRect.Intersection(TRect(TPoint(0, 0), trgSize));
+
+ if (drawRect.IsEmpty())
+ return;
+
+ CFbsBitmap* realSource = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(realSource);
+ User::LeaveIfError(realSource->Create(srcSize, displayMode));
+ CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(realSource);
+ CleanupStack::PushL(dev);
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError(dev->CreateContext(gc));
+ CleanupStack::PushL(gc);
+ gc->BitBlt(TPoint(0, 0), aSrcBitmap);
+ CleanupStack::PopAndDestroy(2); // dev, gc
+
+ // Heap lock for FBServ large chunk is only needed with large bitmaps.
+ if (realSource->IsLargeBitmap() || aTrgBitmap->IsLargeBitmap()) {
+ aTrgBitmap->LockHeapLC(ETrue); // fbsheaplock
+ } else {
+ CleanupStack::PushL((TAny*) NULL);
+ }
+
+ TUint32* srcAddress = realSource->DataAddress();
+ TUint32* trgAddress = aTrgBitmap->DataAddress();
+
+ const TInt xSkip = (srcSize.iWidth << 8) / aTrgRect.Width();
+ const TInt ySkip = (srcSize.iHeight << 8) / aTrgRect.Height();
+
+ const TInt drawWidth = drawRect.Width();
+ const TInt drawHeight = drawRect.Height();
+
+ const TRect offsetRect(aTrgRect.iTl, drawRect.iTl);
+ const TInt yPosOffset = ySkip * offsetRect.Height();
+ const TInt xPosOffset = xSkip * offsetRect.Width();
+
+ if ((displayMode == EGray256) || (displayMode == EColor256)) {
+ const TInt srcScanLen8 = CFbsBitmap::ScanLineLength(srcSize.iWidth,
+ displayMode);
+ const TInt trgScanLen8 = CFbsBitmap::ScanLineLength(trgSize.iWidth,
+ displayMode);
+
+ TUint8* trgAddress8 = reinterpret_cast<TUint8*> (trgAddress);
+
+ TInt yPos = yPosOffset;
+ // skip left and top margins in the beginning
+ trgAddress8 += trgScanLen8 * drawRect.iTl.iY + drawRect.iTl.iX;
+
+ for (TInt y = 0; y < drawHeight; y++) {
+ const TUint8* srcAddress8 = reinterpret_cast<const TUint8*> (srcAddress)
+ + (srcScanLen8 * (yPos >> 8));
+
+ TInt xPos = xPosOffset;
+ for (TInt x = 0; x < drawWidth; x++) {
+ *(trgAddress8++) = srcAddress8[xPos >> 8];
+ xPos += xSkip;
+ }
+
+ yPos += ySkip;
+
+ trgAddress8 += trgScanLen8 - drawWidth;
+ }
+ } else if (displayMode == EColor4K || displayMode == EColor64K) {
+ const TInt srcScanLen16 = CFbsBitmap::ScanLineLength(srcSize.iWidth,
+ displayMode) >>1;
+ const TInt trgScanLen16 = CFbsBitmap::ScanLineLength(trgSize.iWidth,
+ displayMode) >>1;
+
+ TUint16* trgAddress16 = reinterpret_cast<TUint16*> (trgAddress);
+
+ TInt yPos = yPosOffset;
+ // skip left and top margins in the beginning
+ trgAddress16 += trgScanLen16 * drawRect.iTl.iY + drawRect.iTl.iX;
+
+ for (TInt y = 0; y < drawHeight; y++) {
+ const TUint16* srcAddress16 = reinterpret_cast<const TUint16*> (srcAddress)
+ + (srcScanLen16 * (yPos >> 8));
+
+ TInt xPos = xPosOffset;
+ for (TInt x = 0; x < drawWidth; x++) {
+ *(trgAddress16++) = srcAddress16[xPos >> 8];
+ xPos += xSkip;
+ }
+
+ yPos += ySkip;
+
+ trgAddress16 += trgScanLen16 - drawWidth;
+ }
+ } else if (displayMode == EColor16MU || displayMode == EColor16MA) {
+ const TInt srcScanLen32 = CFbsBitmap::ScanLineLength(srcSize.iWidth,
+ displayMode) >>2;
+ const TInt trgScanLen32 = CFbsBitmap::ScanLineLength(trgSize.iWidth,
+ displayMode) >>2;
+
+ TUint32* trgAddress32 = reinterpret_cast<TUint32*> (trgAddress);
+
+ TInt yPos = yPosOffset;
+ // skip left and top margins in the beginning
+ trgAddress32 += trgScanLen32 * drawRect.iTl.iY + drawRect.iTl.iX;
+
+ for (TInt y = 0; y < drawHeight; y++) {
+ const TUint32* srcAddress32 = reinterpret_cast<const TUint32*> (srcAddress)
+ + (srcScanLen32 * (yPos >> 8));
+
+ TInt xPos = xPosOffset;
+ for (TInt x = 0; x < drawWidth; x++) {
+ *(trgAddress32++) = srcAddress32[xPos >> 8];
+ xPos += xSkip;
+ }
+
+ yPos += ySkip;
+
+ trgAddress32 += trgScanLen32 - drawWidth;
+ }
+ } else { User::Leave(KErrUnknown);}
+
+ CleanupStack::PopAndDestroy(2); // fbsheaplock, realSource
+}
+
+QSize QS60StylePrivate::screenSize()
+{
+ const TSize screenSize = QS60Data::screenDevice()->SizeInPixels();
+ return QSize(screenSize.iWidth, screenSize.iHeight);
+}
+
+void QS60StyleModeSpecifics::colorGroupAndIndex(
+ QS60StyleEnums::SkinParts skinID, TAknsItemID &colorGroup, int colorIndex)
+{
+ switch(skinID) {
+ case QS60StyleEnums::SP_QgnIndiSubMenu:
+ colorGroup = KAknsIIDQsnIconColors;
+ colorIndex = EAknsCIQsnIconColorsCG1;
+ break;
+ case QS60StyleEnums::SP_QgnIndiRadiobuttOff:
+ case QS60StyleEnums::SP_QgnIndiRadiobuttOn:
+ case QS60StyleEnums::SP_QgnIndiCheckboxOff:
+ case QS60StyleEnums::SP_QgnIndiCheckboxOn:
+ colorGroup = KAknsIIDQsnIconColors;
+ colorIndex = EAknsCIQsnIconColorsCG14;
+ break;
+ default:
+ break;
+ }
+}
+
+QS60Style::QS60Style()
+ : QCommonStyle(*new QS60StylePrivate)
+{
+}
+
+#ifdef Q_WS_S60
+void QS60StylePrivate::handleDynamicLayoutVariantSwitch()
+{
+ clearCaches(QS60StylePrivate::CC_LayoutChange);
+ setActiveLayout();
+ refreshUI();
+ setBackgroundTexture(qApp);
+ foreach (QWidget *widget, QApplication::allWidgets())
+ widget->ensurePolished();
+}
+
+void QS60StylePrivate::handleSkinChange()
+{
+ clearCaches(QS60StylePrivate::CC_ThemeChange);
+ setThemePalette(qApp);
+ foreach (QWidget *topLevelWidget, QApplication::allWidgets()){
+ QEvent e(QEvent::StyleChange);
+ QApplication::sendEvent(topLevelWidget, &e);
+ setThemePalette(topLevelWidget);
+ topLevelWidget->ensurePolished();
+ }
+}
+#endif // Q_WS_S60
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STYLE_S60 || QT_PLUGIN
diff --git a/src/gui/styles/qs60style_simulated.cpp b/src/gui/styles/qs60style_simulated.cpp
new file mode 100644
index 0000000..2d185bd
--- /dev/null
+++ b/src/gui/styles/qs60style_simulated.cpp
@@ -0,0 +1,448 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qs60style.h"
+#include "qs60style_p.h"
+#include "qfile.h"
+#include "qhash.h"
+#include "qapplication.h"
+#include "qpainter.h"
+#include "qpicture.h"
+#include "qstyleoption.h"
+#include "qtransform.h"
+#include "qlayout.h"
+#include "qpixmapcache.h"
+#include "qmetaobject.h"
+#include "qdebug.h"
+#include "qbuffer.h"
+#include "qdesktopwidget.h"
+
+#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
+
+QT_BEGIN_NAMESPACE
+
+static const quint32 blobVersion = 1;
+static const int pictureSize = 256;
+
+#if defined(Q_CC_GNU)
+#if __GNUC__ >= 2
+#define __FUNCTION__ __func__
+#endif
+#endif
+
+
+bool saveThemeToBlob(const QString &themeBlob,
+ const QHash<QString, QPicture> &partPictures,
+ const QHash<QPair<QString, int>, QColor> &colors)
+{
+ QFile blob(themeBlob);
+ if (!blob.open(QIODevice::WriteOnly)) {
+ qWarning() << __FUNCTION__ << ": Could not create blob: " << themeBlob;
+ return false;
+ }
+
+ QByteArray data;
+ QBuffer dataBuffer(&data);
+ dataBuffer.open(QIODevice::WriteOnly);
+ QDataStream dataOut(&dataBuffer);
+
+ const int colorsCount = colors.count();
+ dataOut << colorsCount;
+ const QList<QPair<QString, int> > colorKeys = colors.keys();
+ for (int i = 0; i < colorsCount; ++i) {
+ const QPair<QString, int> &key = colorKeys.at(i);
+ dataOut << key;
+ const QColor color = colors.value(key);
+ dataOut << color;
+ }
+
+ const int picturesCount = partPictures.count();
+ dataOut << picturesCount;
+ foreach (const QString &key, partPictures.keys()) {
+ const QPicture picture = partPictures.value(key);
+ dataOut << key;
+ dataOut << picture;
+ }
+
+ QDataStream blobOut(&blob);
+ blobOut << blobVersion;
+ blobOut << qCompress(data);
+ return blobOut.status() == QDataStream::Ok;
+}
+
+bool loadThemeFromBlob(const QString &themeBlob,
+ QHash<QString, QPicture> &partPictures,
+ QHash<QPair<QString, int>, QColor> &colors)
+{
+ QFile blob(themeBlob);
+ if (!blob.open(QIODevice::ReadOnly)) {
+ qWarning() << __FUNCTION__ << ": Could not read blob: " << themeBlob;
+ return false;
+ }
+ QDataStream blobIn(&blob);
+
+ quint32 version;
+ blobIn >> version;
+
+ if (version != blobVersion) {
+ qWarning() << __FUNCTION__ << ": Invalid blob version: " << version << " ...expected: " << blobVersion;
+ return false;
+ }
+
+ QByteArray data;
+ blobIn >> data;
+ data = qUncompress(data);
+ QBuffer dataBuffer(&data);
+ dataBuffer.open(QIODevice::ReadOnly);
+ QDataStream dataIn(&dataBuffer);
+
+ int colorsCount;
+ dataIn >> colorsCount;
+ for (int i = 0; i < colorsCount; ++i) {
+ QPair<QString, int> key;
+ dataIn >> key;
+ QColor value;
+ dataIn >> value;
+ colors.insert(key, value);
+ }
+
+ int picturesCount;
+ dataIn >> picturesCount;
+ for (int i = 0; i < picturesCount; ++i) {
+ QString key;
+ dataIn >> key;
+ QPicture value;
+ dataIn >> value;
+ value.setBoundingRect(QRect(0, 0, pictureSize, pictureSize)); // Bug? The forced bounding rect was not deserialized.
+ partPictures.insert(key, value);
+ }
+
+ if (dataIn.status() != QDataStream::Ok) {
+ qWarning() << __FUNCTION__ << ": Invalid data blob: " << themeBlob;
+ return false;
+ }
+ return true;
+}
+
+class QS60StyleModeSpecifics
+{
+public:
+ static QPixmap skinnedGraphics(QS60StyleEnums::SkinParts stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QHash<QString, QPicture> m_partPictures;
+ static QHash<QPair<QString , int>, QColor> m_colors;
+};
+QHash<QString, QPicture> QS60StyleModeSpecifics::m_partPictures;
+QHash<QPair<QString , int>, QColor> QS60StyleModeSpecifics::m_colors;
+
+QS60StylePrivate::QS60StylePrivate()
+{
+ setCurrentLayout(0);
+}
+
+QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list,
+ int index, const QStyleOption *option)
+{
+ const QString listKey = QS60Style::colorListKeys().at(list);
+ return QS60StylePrivate::stateColor(
+ QS60StyleModeSpecifics::m_colors.value(QPair<QString, int>(listKey, index)),
+ option
+ );
+}
+
+QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, const QSize &size,
+ QS60StylePrivate::SkinElementFlags flags)
+{
+ const QString partKey = QS60Style::partKeys().at(part);
+ const QPicture partPicture = QS60StyleModeSpecifics::m_partPictures.value(partKey);
+ QSize partSize(partPicture.boundingRect().size());
+ if (flags & (SF_PointEast | SF_PointWest)) {
+ const int temp = partSize.width();
+ partSize.setWidth(partSize.height());
+ partSize.setHeight(temp);
+ }
+ const qreal scaleX = size.width() / (qreal)partSize.width();
+ const qreal scaleY = size.height() / (qreal)partSize.height();
+
+ QImage partImage(size, QImage::Format_ARGB32);
+ partImage.fill(Qt::transparent);
+ QPainter resultPainter(&partImage);
+ QTransform t;
+
+ if (flags & SF_PointEast)
+ t.translate(size.width(), 0);
+ else if (flags & SF_PointSouth)
+ t.translate(size.width(), size.height());
+ else if (flags & SF_PointWest)
+ t.translate(0, size.height());
+
+ t.scale(scaleX, scaleY);
+
+ if (flags & SF_PointEast)
+ t.rotate(90);
+ else if (flags & SF_PointSouth)
+ t.rotate(180);
+ else if (flags & SF_PointWest)
+ t.rotate(270);
+
+ resultPainter.setTransform(t, true);
+ const_cast<QPicture *>(&partPicture)->play(&resultPainter);
+ resultPainter.end();
+
+ QPixmap result = QPixmap::fromImage(partImage);
+ if (flags & SF_StateDisabled) {
+ QStyleOption opt;
+ QPalette *themePalette = QS60StylePrivate::themePalette();
+ if (themePalette)
+ opt.palette = *themePalette;
+ result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt);
+ }
+
+ return result;
+}
+
+QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size,
+ SkinElementFlags flags)
+{
+ const QS60StyleEnums::SkinParts center = m_frameElementsData[frame].center;
+ const QS60StyleEnums::SkinParts topLeft = QS60StyleEnums::SkinParts(center - 8);
+ const QS60StyleEnums::SkinParts topRight = QS60StyleEnums::SkinParts(center - 7);
+ const QS60StyleEnums::SkinParts bottomLeft = QS60StyleEnums::SkinParts(center - 6);
+ const QS60StyleEnums::SkinParts bottomRight = QS60StyleEnums::SkinParts(center - 5);
+ const QS60StyleEnums::SkinParts top = QS60StyleEnums::SkinParts(center - 4);
+ const QS60StyleEnums::SkinParts bottom = QS60StyleEnums::SkinParts(center - 3);
+ const QS60StyleEnums::SkinParts left = QS60StyleEnums::SkinParts(center - 2);
+ const QS60StyleEnums::SkinParts right = QS60StyleEnums::SkinParts(center - 1);
+
+ // The size of topLeft defines all other sizes
+ const QSize cornerSize(partSize(topLeft));
+ // if frame is so small that corners would cover it completely, draw only center piece
+ const bool drawOnlyCenter =
+ 2 * cornerSize.width() + 1 >= size.width() || 2 * cornerSize.height() + 1 >= size.height();
+
+ const int cornerWidth = cornerSize.width();
+ const int cornerHeight = cornerSize.height();
+ const int rectWidth = size.width();
+ const int rectHeight = size.height();
+ const QRect rect(QPoint(), size);
+
+ const QRect topLeftRect = QRect(rect.topLeft(), cornerSize);
+ const QRect topRect = rect.adjusted(cornerWidth, 0, -cornerWidth, -(rectHeight - cornerHeight));
+ const QRect topRightRect = topLeftRect.translated(rectWidth - cornerWidth, 0);
+ const QRect rightRect = rect.adjusted(rectWidth - cornerWidth, cornerHeight, 0, -cornerHeight);
+ const QRect bottomRightRect = topRightRect.translated(0, rectHeight - cornerHeight);
+ const QRect bottomRect = topRect.translated(0, rectHeight - cornerHeight);
+ const QRect bottomLeftRect = topLeftRect.translated(0, rectHeight - cornerHeight);
+ const QRect leftRect = rightRect.translated(cornerWidth - rectWidth, 0);
+ const QRect centerRect = drawOnlyCenter ? rect : rect.adjusted(cornerWidth, cornerWidth, -cornerWidth, -cornerWidth);
+
+ QPixmap result(size);
+ result.fill(Qt::transparent);
+ QPainter painter(&result);
+
+#if 0
+ painter.save();
+ painter.setOpacity(.3);
+ painter.fillRect(topLeftRect, Qt::red);
+ painter.fillRect(topRect, Qt::green);
+ painter.fillRect(topRightRect, Qt::blue);
+ painter.fillRect(rightRect, Qt::green);
+ painter.fillRect(bottomRightRect, Qt::red);
+ painter.fillRect(bottomRect, Qt::blue);
+ painter.fillRect(bottomLeftRect, Qt::green);
+ painter.fillRect(leftRect, Qt::blue);
+ painter.fillRect(centerRect, Qt::red);
+ painter.restore();
+#else
+ drawPart(topLeft, &painter, topLeftRect, flags);
+ drawPart(top, &painter, topRect, flags);
+ drawPart(topRight, &painter, topRightRect, flags);
+ drawPart(right, &painter, rightRect, flags);
+ drawPart(bottomRight, &painter, bottomRightRect, flags);
+ drawPart(bottom, &painter, bottomRect, flags);
+ drawPart(bottomLeft, &painter, bottomLeftRect, flags);
+ drawPart(left, &painter, leftRect, flags);
+ drawPart(center, &painter, centerRect, flags);
+#endif
+
+ return result;
+}
+
+void QS60StylePrivate::setStyleProperty_specific(const char *name, const QVariant &value)
+{
+ setStyleProperty(name, value);
+}
+
+QVariant QS60StylePrivate::styleProperty_specific(const char *name) const
+{
+ return styleProperty(name);
+}
+
+QPixmap QS60StylePrivate::backgroundTexture()
+{
+ if (!m_background) {
+ const QSize size = QApplication::desktop()->screen()->size();
+ QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen, size);
+ m_background = new QPixmap(background);
+ }
+ return *m_background;
+}
+
+
+bool QS60StylePrivate::isTouchSupported()
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ return !QApplication::keypadNavigationEnabled();
+#else
+ return true;
+#endif
+}
+
+bool QS60StylePrivate::isToolBarBackground()
+{
+ return true;
+}
+
+QFont QS60StylePrivate::s60Font_specific(QS60StyleEnums::FontCategories fontCategory, int pointSize)
+{
+ QFont result;
+ result.setPointSize(pointSize);
+ switch (fontCategory) {
+ case QS60StyleEnums::FC_Primary:
+ result.setBold(true);
+ break;
+ case QS60StyleEnums::FC_Secondary:
+ case QS60StyleEnums::FC_Title:
+ case QS60StyleEnums::FC_PrimarySmall:
+ case QS60StyleEnums::FC_Digital:
+ case QS60StyleEnums::FC_Undefined:
+ default:
+ break;
+ }
+ return result;
+}
+
+/*!
+ Constructs a QS60Style object.
+*/
+QS60Style::QS60Style()
+ : QCommonStyle(*new QS60StylePrivate)
+{
+ const QString defaultBlob = QString::fromLatin1(":/trolltech/styles/s60style/images/defaults60theme.blob");
+ if (QFile::exists(defaultBlob))
+ loadS60ThemeFromBlob(defaultBlob);
+}
+
+Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, enumPartKeys, {
+ const int enumIndex = QS60StyleEnums::staticMetaObject.indexOfEnumerator("SkinParts");
+ Q_ASSERT(enumIndex >= 0);
+ const QMetaEnum metaEnum = QS60StyleEnums::staticMetaObject.enumerator(enumIndex);
+ for (int i = 0; i < metaEnum.keyCount(); ++i) {
+ const QString enumKey = QString::fromLatin1(metaEnum.key(i));
+ QString partKey;
+ // Following loop does following conversions: "SP_QgnNoteInfo" to "qgn_note_info"...
+ for (int charPosition = 3; charPosition < enumKey.length(); charPosition++) {
+ if (charPosition > 3 && enumKey[charPosition].isUpper())
+ partKey.append(QChar::fromLatin1('_'));
+ partKey.append(enumKey[charPosition].toLower());
+ }
+ x->append(partKey);
+ }
+})
+
+QStringList QS60Style::partKeys()
+{
+ return *enumPartKeys();
+}
+
+Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, enumColorListKeys, {
+ const int enumIndex = QS60StyleEnums::staticMetaObject.indexOfEnumerator("ColorLists");
+ Q_ASSERT(enumIndex >= 0);
+ const QMetaEnum metaEnum = QS60StyleEnums::staticMetaObject.enumerator(enumIndex);
+ for (int i = 0; i < metaEnum.keyCount(); i++) {
+ const QString enumKey = QString::fromLatin1(metaEnum.key(i));
+ // Following line does following conversions: CL_QsnTextColors to "text"...
+ x->append(enumKey.mid(6, enumKey.length() - 12).toLower());
+ }
+})
+
+QStringList QS60Style::colorListKeys()
+{
+ return *enumColorListKeys();
+}
+
+void QS60Style::setS60Theme(const QHash<QString, QPicture> &parts,
+ const QHash<QPair<QString , int>, QColor> &colors)
+{
+ Q_D(QS60Style);
+ QS60StyleModeSpecifics::m_partPictures = parts;
+ QS60StyleModeSpecifics::m_colors = colors;
+ d->clearCaches(QS60StylePrivate::CC_ThemeChange);
+ d->setBackgroundTexture(qApp);
+ d->setThemePalette(qApp);
+}
+
+bool QS60Style::loadS60ThemeFromBlob(const QString &blobFile)
+{
+ QHash<QString, QPicture> partPictures;
+ QHash<QPair<QString, int>, QColor> colors;
+
+ if (!loadThemeFromBlob(blobFile, partPictures, colors))
+ return false;
+ setS60Theme(partPictures, colors);
+ return true;
+}
+
+bool QS60Style::saveS60ThemeToBlob(const QString &blobFile) const
+{
+ return saveThemeToBlob(blobFile,
+ QS60StyleModeSpecifics::m_partPictures, QS60StyleModeSpecifics::m_colors);
+}
+
+QPoint qt_s60_fill_background_offset(const QWidget *targetWidget)
+{
+ Q_UNUSED(targetWidget)
+ return QPoint();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STYLE_S60 || QT_PLUGIN
diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp
index af3a834..d61d291 100644
--- a/src/gui/styles/qstyle.cpp
+++ b/src/gui/styles/qstyle.cpp
@@ -168,12 +168,21 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C
\section1 Creating a Custom Style
- If you want to design a custom look and feel for your application,
- the first step is to pick one of the styles provided with Qt to
- build your custom style from. The choice will depend on which
- existing style resembles your style the most. The most general
- class that you can use as base is QCommonStyle (and not QStyle).
- This is because Qt requires its styles to be \l{QCommonStyle}s.
+ You can create a custom look and feel for your application by
+ creating a custom style. There are two approaches to creating a
+ custom style. In the static approach, you either choose an
+ existing QStyle class, subclass it, and reimplement virtual
+ functions to provide the custom behavior, or you create an entire
+ QStyle class from scratch. In the dynamic approach, you modify the
+ behavior of your system style at runtime. The static approach is
+ described below. The dynamic approach is described in QProxyStyle.
+
+ The first step in the static approach is to pick one of the styles
+ provided by Qt from which you will build your custom style. Your
+ choice of QStyle class will depend on which style resembles your
+ desired style the most. The most general class that you can use as
+ a base is QCommonStyle (not QStyle). This is because Qt requires
+ its styles to be \l{QCommonStyle}s.
Depending on which parts of the base style you want to change,
you must reimplement the functions that are used to draw those
@@ -222,7 +231,7 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C
\section1 Using a Custom Style
There are several ways of using a custom style in a Qt
- application. The simplest way is call the
+ application. The simplest way is to pass the custom style to the
QApplication::setStyle() static function before creating the
QApplication object:
@@ -232,8 +241,8 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C
it before the constructor, you ensure that the user's preference,
set using the \c -style command-line option, is respected.
- You may want to make your style available for use in other
- applications, some of which may not be yours and are not available for
+ You may want to make your custom style available for use in other
+ applications, which may not be yours and hence not available for
you to recompile. The Qt Plugin system makes it possible to create
styles as plugins. Styles created as plugins are loaded as shared
objects at runtime by Qt itself. Please refer to the \link
@@ -325,9 +334,10 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C
QStyle::QStyle()
: QObject(*new QStylePrivate)
{
+ Q_D(QStyle);
+ d->proxyStyle = this;
}
-
/*!
\internal
@@ -336,6 +346,8 @@ QStyle::QStyle()
QStyle::QStyle(QStylePrivate &dd)
: QObject(dd)
{
+ Q_D(QStyle);
+ d->proxyStyle = this;
}
/*!
@@ -514,8 +526,9 @@ void QStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, c
}
if (!enabled) {
if (styleHint(SH_DitherDisabledText)) {
- painter->drawText(rect, alignment, text);
- painter->fillRect(painter->boundingRect(rect, alignment, text), QBrush(painter->background().color(), Qt::Dense5Pattern));
+ QRect br;
+ painter->drawText(rect, alignment, text, &br);
+ painter->fillRect(br, QBrush(painter->background().color(), Qt::Dense5Pattern));
return;
} else if (styleHint(SH_EtchDisabledText)) {
QPen pen = painter->pen();
@@ -551,7 +564,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
/*!
\enum QStyle::PrimitiveElement
- This enum describes that various primitive elements. A
+ This enum describes the various primitive elements. A
primitive element is a common GUI element, such as a checkbox
indicator or button bevel.
@@ -1048,6 +1061,8 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SE_TabBarTabRightButton Area for a widget on the right side of a tab in a tab bar.
\value SE_TabBarTabText Area for the text on a tab in a tab bar.
+ \value SE_ToolBarHandle Area for the handle of a tool bar.
+
\sa subElementRect()
*/
@@ -1093,7 +1108,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value CC_ScrollBar A scroll bar, like QScrollBar.
\value CC_Slider A slider, like QSlider.
\value CC_ToolButton A tool button, like QToolButton.
- \value CC_TitleBar A Title bar, like those used in QWorkspace.
+ \value CC_TitleBar A Title bar, like those used in QMdiSubWindow.
\value CC_Q3ListView Used for drawing the Q3ListView class.
\value CC_GroupBox A group box, like QGroupBox.
\value CC_Dial A dial, like QDial.
@@ -1177,6 +1192,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SC_All Special value that matches all sub-controls.
\omitvalue SC_Q3ListViewBranch
+ \omitvalue SC_CustomBase
\sa ComplexControl
*/
@@ -1330,7 +1346,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value PM_LayoutVerticalSpacing Default \l{QLayout::spacing}{vertical spacing} for a QLayout.
\value PM_MaximumDragDistance The maximum allowed distance between
- the mouse and a slider when dragging. Exceeding the specified
+ the mouse and a scrollbar when dragging. Exceeding the specified
distance will cause the slider to jump back to the original
position; a value of -1 disables this behavior.
@@ -1570,6 +1586,20 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
*/
/*!
+ \enum QStyle::RequestSoftwareInputPanel
+
+ This enum describes under what circumstances a software input panel will be
+ requested by input capable widgets.
+
+ \value RSIP_OnMouseClickAndAlreadyFocused Requests an input panel if the user
+ clicks on the widget, but only if it is already focused.
+ \value RSIP_OnMouseClick Requests an input panel if the user clicks on the
+ widget.
+
+ \sa QEvent::RequestSoftwareInputPanel, QInputContext
+*/
+
+/*!
\enum QStyle::StyleHint
This enum describes the available style hints. A style hint is a general look
@@ -1850,6 +1880,11 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SH_DockWidget_ButtonsHaveFrame Determines if dockwidget buttons should have frames. Default is true.
+ \value SH_ToolButtonStyle Determines the default system style for tool buttons that uses Qt::ToolButtonFollowStyle.
+
+ \value SH_RequestSoftwareInputPanel Determines when a software input panel should
+ be requested by input widgets. Returns an enum of type QStyle::RequestSoftwareInputPanel.
+
\omitvalue SH_UnderlineAccelerator
\sa styleHint()
@@ -1876,7 +1911,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
can follow some existing GUI style or guideline.
\value SP_TitleBarMinButton Minimize button on title bars (e.g.,
- in QWorkspace).
+ in QMdiSubWindow).
\value SP_TitleBarMenuButton Menu button on a title bar.
\value SP_TitleBarMaxButton Maximize button on title bars.
\value SP_TitleBarCloseButton Close button on title bars.
@@ -1948,22 +1983,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SP_CustomBase Base value for custom standard pixmaps;
custom values must be greater than this value.
- \sa standardPixmap() standardIcon()
-*/
-
-/*###
- \enum QStyle::IconMode
-
- This enum represents the effects performed on a pixmap to achieve a
- GUI style's perferred way of representing the image in different
- states.
-
- \value IM_Disabled A disabled pixmap (drawn on disabled widgets)
- \value IM_Active An active pixmap (drawn on active tool buttons and menu items)
- \value IM_CustomBase Base value for custom PixmapTypes; custom
- values must be greater than this value
-
- \sa generatedIconPixmap()
+ \sa standardIcon()
*/
/*!
@@ -2246,7 +2266,7 @@ QPalette QStyle::standardPalette() const
slot in your subclass instead. The standardIcon() function will
dynamically detect the slot and call it.
- \sa standardIconImplementation(), standardPixmap()
+ \sa standardIconImplementation()
*/
QIcon QStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option,
const QWidget *widget) const
@@ -2271,8 +2291,7 @@ QIcon QStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *opti
subclass; because of binary compatibility constraints, the
standardIcon() function (introduced in Qt 4.1) is not
virtual. Instead, standardIcon() will dynamically detect and call
- \e this slot. The default implementation simply calls the
- standardPixmap() function with the given parameters.
+ \e this slot.
The \a standardIcon is a standard pixmap which can follow some
existing GUI style or guideline. The \a option argument can be
@@ -2437,9 +2456,36 @@ QDebug operator<<(QDebug debug, QStyle::State state)
qSort(states);
debug << states.join(QLatin1String(" | "));
- debug << ")";
+ debug << ')';
return debug;
}
#endif
+/*!
+ \since 4.6
+
+ \fn const QStyle *QStyle::proxy() const
+
+ This function returns the current proxy for this style.
+ By default most styles will return themselves. However
+ when a proxy style is in use, it will allow the style to
+ call back into its proxy.
+*/
+const QStyle * QStyle::proxy() const
+{
+ Q_D(const QStyle);
+ return d->proxyStyle;
+}
+
+/* \internal
+
+ This function sets the base style that style calls will be
+ redirected to. Note that ownership is not transferred.
+*/
+void QStyle::setProxy(QStyle *style)
+{
+ Q_D(QStyle);
+ d->proxyStyle = style;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/styles/qstyle.h b/src/gui/styles/qstyle.h
index 41a993d..8664d79 100644
--- a/src/gui/styles/qstyle.h
+++ b/src/gui/styles/qstyle.h
@@ -373,6 +373,8 @@ public:
SE_ShapedFrameContents,
+ SE_ToolBarHandle,
+
// do not add any values below/greater than this
SE_CustomBase = 0xf0000000
};
@@ -453,6 +455,7 @@ public:
SC_MdiNormalButton = 0x00000002,
SC_MdiCloseButton = 0x00000004,
+ SC_CustomBase = 0xf0000000,
SC_All = 0xffffffff
};
Q_DECLARE_FLAGS(SubControls, SubControl)
@@ -629,6 +632,11 @@ public:
virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt,
const QSize &contentsSize, const QWidget *w = 0) const = 0;
+ enum RequestSoftwareInputPanel {
+ RSIP_OnMouseClickAndAlreadyFocused,
+ RSIP_OnMouseClick
+ };
+
enum StyleHint {
SH_EtchDisabledText,
SH_DitherDisabledText,
@@ -727,7 +735,8 @@ public:
SH_ItemView_DrawDelegateFrame,
SH_TabBar_CloseButtonPosition,
SH_DockWidget_ButtonsHaveFrame,
-
+ SH_ToolButtonStyle,
+ SH_RequestSoftwareInputPanel,
// Add new style hint values here
#ifdef QT3_SUPPORT
@@ -845,6 +854,8 @@ public:
QSizePolicy::ControlTypes controls2, Qt::Orientation orientation,
QStyleOption *option = 0, QWidget *widget = 0) const;
+ const QStyle * proxy() const;
+
protected Q_SLOTS:
QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0,
const QWidget *widget = 0) const;
@@ -859,6 +870,9 @@ private:
friend class QWidget;
friend class QWidgetPrivate;
friend class QApplication;
+ friend class QProxyStyle;
+ friend class QProxyStylePrivate;
+ void setProxy(QStyle *style);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::State)
diff --git a/src/gui/styles/qstyle_p.h b/src/gui/styles/qstyle_p.h
index f75fae9..0445537 100644
--- a/src/gui/styles/qstyle_p.h
+++ b/src/gui/styles/qstyle_p.h
@@ -43,6 +43,8 @@
#define QSTYLE_P_H
#include "private/qobject_p.h"
+#include "private/qstylehelper_p.h"
+#include <QtGui/qstyle.h>
QT_BEGIN_NAMESPACE
@@ -51,22 +53,24 @@ QT_BEGIN_NAMESPACE
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of qstyle_*.cpp. This header file may change from version to version
+// without notice, or even be removed.
//
// We mean it.
//
// Private class
+class QStyle;
+
class QStylePrivate: public QObjectPrivate
{
Q_DECLARE_PUBLIC(QStyle)
public:
inline QStylePrivate()
- : layoutSpacingIndex(-1)
- { }
+ : layoutSpacingIndex(-1), proxyStyle(0) {}
mutable int layoutSpacingIndex;
+ QStyle *proxyStyle;
};
@@ -75,9 +79,9 @@ public:
QPixmap internalPixmapCache; \
QImage imageCache; \
QPainter *p = painter; \
- QString unique = uniqueName((a), option, option->rect.size()); \
+ QString unique = QStyleHelper::uniqueName((a), option, option->rect.size()); \
int txType = painter->deviceTransform().type() | painter->worldTransform().type(); \
- bool doPixmapCache = UsePixmapCache && txType <= QTransform::TxTranslate; \
+ bool doPixmapCache = txType <= QTransform::TxTranslate; \
if (doPixmapCache && QPixmapCache::find(unique, internalPixmapCache)) { \
painter->drawPixmap(option->rect.topLeft(), internalPixmapCache); \
} else { \
@@ -89,6 +93,7 @@ public:
}
+
#define END_STYLE_PIXMAPCACHE \
if (doPixmapCache) { \
p->end(); \
diff --git a/src/gui/styles/qstyle_s60_simulated.qrc b/src/gui/styles/qstyle_s60_simulated.qrc
new file mode 100644
index 0000000..969732e
--- /dev/null
+++ b/src/gui/styles/qstyle_s60_simulated.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource prefix="/trolltech/styles/s60style">
+ <file>images/defaults60theme.blob</file>
+ </qresource>
+</RCC>
diff --git a/src/gui/styles/qstylefactory.cpp b/src/gui/styles/qstylefactory.cpp
index 9ce745a..e4a134d 100644
--- a/src/gui/styles/qstylefactory.cpp
+++ b/src/gui/styles/qstylefactory.cpp
@@ -69,6 +69,9 @@
#ifndef QT_NO_STYLE_WINDOWSMOBILE
#include "qwindowsmobilestyle.h"
#endif
+#ifndef QT_NO_STYLE_S60
+#include "qs60style.h"
+#endif
QT_BEGIN_NAMESPACE
@@ -154,6 +157,11 @@ QStyle *QStyleFactory::create(const QString& key)
ret = new QCDEStyle;
else
#endif
+#ifndef QT_NO_STYLE_S60
+ if (style == QLatin1String("s60"))
+ ret = new QS60Style;
+ else
+#endif
#ifndef QT_NO_STYLE_PLASTIQUE
if (style == QLatin1String("plastique"))
ret = new QPlastiqueStyle;
@@ -170,7 +178,7 @@ QStyle *QStyleFactory::create(const QString& key)
else
#endif
#ifndef QT_NO_STYLE_MAC
- if (style.left(9) == QLatin1String("macintosh")) {
+ if (style.startsWith(QLatin1String("macintosh"))) {
ret = new QMacStyle;
# ifdef Q_WS_MAC
if (style == QLatin1String("macintosh"))
@@ -233,6 +241,10 @@ QStringList QStyleFactory::keys()
if (!list.contains(QLatin1String("CDE")))
list << QLatin1String("CDE");
#endif
+#ifndef QT_NO_STYLE_S60
+ if (!list.contains(QLatin1String("S60")))
+ list << QLatin1String("S60");
+#endif
#ifndef QT_NO_STYLE_PLASTIQUE
if (!list.contains(QLatin1String("Plastique")))
list << QLatin1String("Plastique");
diff --git a/src/gui/styles/qstylehelper.cpp b/src/gui/styles/qstylehelper.cpp
new file mode 100644
index 0000000..b26b44b
--- /dev/null
+++ b/src/gui/styles/qstylehelper.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstylehelper_p.h"
+
+#include <qstyleoption.h>
+#include <qpainter.h>
+#include <qpixmapcache.h>
+#include <private/qmath_p.h>
+#include <private/qstyle_p.h>
+#include <qmath.h>
+
+#if defined(Q_WS_WIN)
+#include "qt_windows.h"
+#elif defined(Q_WS_MAC)
+#include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QStyleHelper {
+
+QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size)
+{
+ const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option);
+ QString tmp = QString::fromLatin1("%1-%2-%3-%4-%5-%6x%7").arg(key).arg(uint(option->state)).arg(option->direction)
+ .arg(complexOption ? uint(complexOption->activeSubControls) : uint(0))
+ .arg(option->palette.cacheKey()).arg(size.width()).arg(size.height());
+#ifndef QT_NO_SPINBOX
+ if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ tmp.append(QLatin1Char('-'));
+ tmp.append(QString::number(spinBox->buttonSymbols));
+ tmp.append(QLatin1Char('-'));
+ tmp.append(QString::number(spinBox->stepEnabled));
+ tmp.append(QLatin1Char('-'));
+ tmp.append(QLatin1Char(spinBox->frame ? '1' : '0'));
+ }
+#endif // QT_NO_SPINBOX
+ return tmp;
+}
+
+qreal dpiScaled(qreal value)
+{
+ static qreal scale = -1;
+ if (scale < 0) {
+ scale = 1.0;
+#if defined(Q_WS_WIN)
+ {
+ HDC hdcScreen = GetDC(0);
+ int dpi = GetDeviceCaps(hdcScreen, LOGPIXELSX);
+ ReleaseDC(0, hdcScreen);
+ scale = dpi/96.0;
+ }
+#elif defined(Q_WS_MAC)
+ scale = qt_mac_get_scalefactor();
+#endif
+ }
+ return value * scale;
+}
+
+
+#ifndef QT_NO_DIAL
+
+int calcBigLineSize(int radius)
+{
+ int bigLineSize = radius / 6;
+ if (bigLineSize < 4)
+ bigLineSize = 4;
+ if (bigLineSize > radius / 2)
+ bigLineSize = radius / 2;
+ return bigLineSize;
+}
+
+static QPointF calcRadialPos(const QStyleOptionSlider *dial, qreal offset)
+{
+ const int width = dial->rect.width();
+ const int height = dial->rect.height();
+ const int r = qMin(width, height) / 2;
+ const int currentSliderPosition = dial->upsideDown ? dial->sliderPosition : (dial->maximum - dial->sliderPosition);
+ qreal a = 0;
+ if (dial->maximum == dial->minimum)
+ a = Q_PI / 2;
+ else if (dial->dialWrapping)
+ a = Q_PI * 3 / 2 - (currentSliderPosition - dial->minimum) * 2 * Q_PI
+ / (dial->maximum - dial->minimum);
+ else
+ a = (Q_PI * 8 - (currentSliderPosition - dial->minimum) * 10 * Q_PI
+ / (dial->maximum - dial->minimum)) / 6;
+ qreal xc = width / 2.0;
+ qreal yc = height / 2.0;
+ qreal len = r - QStyleHelper::calcBigLineSize(r) - 3;
+ qreal back = offset * len;
+ QPointF pos(QPointF(xc + back * qCos(a), yc - back * qSin(a)));
+ return pos;
+}
+
+qreal angle(const QPointF &p1, const QPointF &p2)
+{
+ static const qreal rad_factor = 180 / Q_PI;
+ qreal _angle = 0;
+
+ if (p1.x() == p2.x()) {
+ if (p1.y() < p2.y())
+ _angle = 270;
+ else
+ _angle = 90;
+ } else {
+ qreal x1, x2, y1, y2;
+
+ if (p1.x() <= p2.x()) {
+ x1 = p1.x(); y1 = p1.y();
+ x2 = p2.x(); y2 = p2.y();
+ } else {
+ x2 = p1.x(); y2 = p1.y();
+ x1 = p2.x(); y1 = p2.y();
+ }
+
+ qreal m = -(y2 - y1) / (x2 - x1);
+ _angle = atan(m) * rad_factor;
+
+ if (p1.x() < p2.x())
+ _angle = 180 - _angle;
+ else
+ _angle = -_angle;
+ }
+ return _angle;
+}
+
+QPolygonF calcLines(const QStyleOptionSlider *dial)
+{
+ QPolygonF poly;
+ int width = dial->rect.width();
+ int height = dial->rect.height();
+ qreal r = qMin(width, height) / 2;
+ int bigLineSize = calcBigLineSize(int(r));
+
+ qreal xc = width / 2 + 0.5;
+ qreal yc = height / 2 + 0.5;
+ int ns = dial->tickInterval;
+ int notches = (dial->maximum + ns - 1 - dial->minimum) / ns;
+ if (notches <= 0)
+ return poly;
+ if (dial->maximum < dial->minimum || dial->maximum - dial->minimum > 1000) {
+ int maximum = dial->minimum + 1000;
+ notches = (maximum + ns - 1 - dial->minimum) / ns;
+ }
+
+ poly.resize(2 + 2 * notches);
+ int smallLineSize = bigLineSize / 2;
+ for (int i = 0; i <= notches; ++i) {
+ qreal angle = dial->dialWrapping ? Q_PI * 3 / 2 - i * 2 * Q_PI / notches
+ : (Q_PI * 8 - i * 10 * Q_PI / notches) / 6;
+ qreal s = qSin(angle);
+ qreal c = qCos(angle);
+ if (i == 0 || (((ns * i) % (dial->pageStep ? dial->pageStep : 1)) == 0)) {
+ poly[2 * i] = QPointF(xc + (r - bigLineSize) * c,
+ yc - (r - bigLineSize) * s);
+ poly[2 * i + 1] = QPointF(xc + r * c, yc - r * s);
+ } else {
+ poly[2 * i] = QPointF(xc + (r - 1 - smallLineSize) * c,
+ yc - (r - 1 - smallLineSize) * s);
+ poly[2 * i + 1] = QPointF(xc + (r - 1) * c, yc -(r - 1) * s);
+ }
+ }
+ return poly;
+}
+
+// This will draw a nice and shiny QDial for us. We don't want
+// all the shinyness in QWindowsStyle, hence we place it here
+
+void drawDial(const QStyleOptionSlider *option, QPainter *painter)
+{
+ QPalette pal = option->palette;
+ QColor buttonColor = pal.button().color();
+ const int width = option->rect.width();
+ const int height = option->rect.height();
+ const bool enabled = option->state & QStyle::State_Enabled;
+ qreal r = qMin(width, height) / 2;
+ r -= r/50;
+ const qreal penSize = r/20.0;
+
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+
+ // Draw notches
+ if (option->subControls & QStyle::SC_DialTickmarks) {
+ painter->setPen(option->palette.dark().color().darker(120));
+ painter->drawLines(QStyleHelper::calcLines(option));
+ }
+
+ // Cache dial background
+ BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("qdial"));
+ p->setRenderHint(QPainter::Antialiasing);
+
+ const qreal d_ = r / 6;
+ const qreal dx = option->rect.x() + d_ + (width - 2 * r) / 2 + 1;
+ const qreal dy = option->rect.y() + d_ + (height - 2 * r) / 2 + 1;
+
+ QRectF br = QRectF(dx + 0.5, dy + 0.5,
+ int(r * 2 - 2 * d_ - 2),
+ int(r * 2 - 2 * d_ - 2));
+ buttonColor.setHsv(buttonColor .hue(),
+ qMin(140, buttonColor .saturation()),
+ qMax(180, buttonColor.value()));
+ QColor shadowColor(0, 0, 0, 20);
+
+ if (enabled) {
+ // Drop shadow
+ qreal shadowSize = qMax(1.0, penSize/2.0);
+ QRectF shadowRect= br.adjusted(-2*shadowSize, -2*shadowSize,
+ 2*shadowSize, 2*shadowSize);
+ QRadialGradient shadowGradient(shadowRect.center().x(),
+ shadowRect.center().y(), shadowRect.width()/2.0,
+ shadowRect.center().x(), shadowRect.center().y());
+ shadowGradient.setColorAt(qreal(0.91), QColor(0, 0, 0, 40));
+ shadowGradient.setColorAt(qreal(1.0), Qt::transparent);
+ p->setBrush(shadowGradient);
+ p->setPen(Qt::NoPen);
+ p->translate(shadowSize, shadowSize);
+ p->drawEllipse(shadowRect);
+ p->translate(-shadowSize, -shadowSize);
+
+ // Main gradient
+ QRadialGradient gradient(br.center().x() - br.width()/3, dy,
+ br.width()*1.3, br.center().x(),
+ br.center().y() - br.height()/2);
+ gradient.setColorAt(0, buttonColor.lighter(110));
+ gradient.setColorAt(qreal(0.5), buttonColor);
+ gradient.setColorAt(qreal(0.501), buttonColor.darker(102));
+ gradient.setColorAt(1, buttonColor.darker(115));
+ p->setBrush(gradient);
+ } else {
+ p->setBrush(Qt::NoBrush);
+ }
+
+ p->setPen(QPen(buttonColor.darker(280)));
+ p->drawEllipse(br);
+ p->setBrush(Qt::NoBrush);
+ p->setPen(buttonColor.lighter(110));
+ p->drawEllipse(br.adjusted(1, 1, -1, -1));
+
+ if (option->state & QStyle::State_HasFocus) {
+ QColor highlight = pal.highlight().color();
+ highlight.setHsv(highlight.hue(),
+ qMin(160, highlight.saturation()),
+ qMax(230, highlight.value()));
+ highlight.setAlpha(127);
+ p->setPen(QPen(highlight, 2.0));
+ p->setBrush(Qt::NoBrush);
+ p->drawEllipse(br.adjusted(-1, -1, 1, 1));
+ }
+
+ END_STYLE_PIXMAPCACHE
+
+ QPointF dp = calcRadialPos(option, qreal(0.70));
+ buttonColor = buttonColor.lighter(104);
+ buttonColor.setAlphaF(qreal(0.8));
+ const qreal ds = r/qreal(7.0);
+ QRectF dialRect(dp.x() - ds, dp.y() - ds, 2*ds, 2*ds);
+ QRadialGradient dialGradient(dialRect.center().x() + dialRect.width()/2,
+ dialRect.center().y() + dialRect.width(),
+ dialRect.width()*2,
+ dialRect.center().x(), dialRect.center().y());
+ dialGradient.setColorAt(1, buttonColor.darker(140));
+ dialGradient.setColorAt(qreal(0.4), buttonColor.darker(120));
+ dialGradient.setColorAt(0, buttonColor.darker(110));
+ if (penSize > 3.0) {
+ painter->setPen(QPen(QColor(0, 0, 0, 25), penSize));
+ painter->drawLine(calcRadialPos(option, qreal(0.90)), calcRadialPos(option, qreal(0.96)));
+ }
+
+ painter->setBrush(dialGradient);
+ painter->setPen(QColor(255, 255, 255, 150));
+ painter->drawEllipse(dialRect.adjusted(-1, -1, 1, 1));
+ painter->setPen(QColor(0, 0, 0, 80));
+ painter->drawEllipse(dialRect);
+ painter->restore();
+}
+#endif //QT_NO_DIAL
+
+void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect,
+ int left, int top, int right,
+ int bottom)
+{
+ QSize size = pixmap.size();
+ //painter->setRenderHint(QPainter::SmoothPixmapTransform);
+
+ //top
+ if (top > 0) {
+ painter->drawPixmap(QRect(rect.left() + left, rect.top(), rect.width() -right - left, top), pixmap,
+ QRect(left, 0, size.width() -right - left, top));
+
+ //top-left
+ if(left > 0)
+ painter->drawPixmap(QRect(rect.left(), rect.top(), left, top), pixmap,
+ QRect(0, 0, left, top));
+
+ //top-right
+ if (right > 0)
+ painter->drawPixmap(QRect(rect.left() + rect.width() - right, rect.top(), right, top), pixmap,
+ QRect(size.width() - right, 0, right, top));
+ }
+
+ //left
+ if (left > 0)
+ painter->drawPixmap(QRect(rect.left(), rect.top()+top, left, rect.height() - top - bottom), pixmap,
+ QRect(0, top, left, size.height() - bottom - top));
+
+ //center
+ painter->drawPixmap(QRect(rect.left() + left, rect.top()+top, rect.width() -right - left,
+ rect.height() - bottom - top), pixmap,
+ QRect(left, top, size.width() -right -left,
+ size.height() - bottom - top));
+ //right
+ if (right > 0)
+ painter->drawPixmap(QRect(rect.left() +rect.width() - right, rect.top()+top, right, rect.height() - top - bottom), pixmap,
+ QRect(size.width() - right, top, right, size.height() - bottom - top));
+
+ //bottom
+ if (bottom > 0) {
+ painter->drawPixmap(QRect(rect.left() +left, rect.top() + rect.height() - bottom,
+ rect.width() - right - left, bottom), pixmap,
+ QRect(left, size.height() - bottom,
+ size.width() - right - left, bottom));
+ //bottom-left
+ if (left > 0)
+ painter->drawPixmap(QRect(rect.left(), rect.top() + rect.height() - bottom, left, bottom), pixmap,
+ QRect(0, size.height() - bottom, left, bottom));
+
+ //bottom-right
+ if (right > 0)
+ painter->drawPixmap(QRect(rect.left() + rect.width() - right, rect.top() + rect.height() - bottom, right, bottom), pixmap,
+ QRect(size.width() - right, size.height() - bottom, right, bottom));
+
+ }
+}
+}
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qwindowsurface_d3d_p.h b/src/gui/styles/qstylehelper_p.h
index d9231d2..1f73018 100644
--- a/src/gui/painting/qwindowsurface_d3d_p.h
+++ b/src/gui/styles/qstylehelper_p.h
@@ -39,46 +39,46 @@
**
****************************************************************************/
-#ifndef QWINDOWSURFACE_D3D_P_H
-#define QWINDOWSURFACE_D3D_P_H
+#include <QtCore/qglobal.h>
+#include <QtCore/qpoint.h>
+#include <QtGui/qpolygon.h>
+
+#ifndef QSTYLEHELPER_P_H
+#define QSTYLEHELPER_P_H
//
// W A R N I N G
// -------------
//
-// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
-// version to version without notice, or even be removed.
+// 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 <qglobal.h>
-#include "private/qwindowsurface_p.h"
-
QT_BEGIN_NAMESPACE
-class QPaintDevice;
-class QPoint;
-class QRegion;
-class QWidget;
-struct QD3DWindowSurfacePrivate;
+class QPainter;
+class QPixmap;
+class QStyleOptionSlider;
+class QStyleOption;
-class QD3DWindowSurface : public QWindowSurface
+namespace QStyleHelper
{
-public:
- QD3DWindowSurface(QWidget *widget);
- ~QD3DWindowSurface();
-
- QPaintDevice *paintDevice();
- void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
- void setGeometry(const QRect &rect);
- bool scroll(const QRegion &area, int dx, int dy);
-
-private:
- QD3DWindowSurfacePrivate *d_ptr;
-};
+ QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size);
+ qreal dpiScaled(qreal value);
+#ifndef QT_NO_DIAL
+ qreal angle(const QPointF &p1, const QPointF &p2);
+ QPolygonF calcLines(const QStyleOptionSlider *dial);
+ int calcBigLineSize(int radius);
+ void drawDial(const QStyleOptionSlider *dial, QPainter *painter);
+#endif //QT_NO_DIAL
+ void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect,
+ int left = 0, int top = 0, int right = 0,
+ int bottom = 0);
+}
QT_END_NAMESPACE
-#endif // QWINDOWSURFACE_D3D_P_H
+#endif // QSTYLEHELPER_P_H
diff --git a/src/gui/styles/qstyleoption.cpp b/src/gui/styles/qstyleoption.cpp
index 2eef0de..fc2a13c 100644
--- a/src/gui/styles/qstyleoption.cpp
+++ b/src/gui/styles/qstyleoption.cpp
@@ -48,6 +48,7 @@
#ifndef QT_NO_DEBUG
#include <qdebug.h>
#endif
+#include <QtCore/qmath.h>
QT_BEGIN_NAMESPACE
@@ -656,7 +657,7 @@ QStyleOptionFrameV2 &QStyleOptionFrameV2::operator=(const QStyleOptionFrame &oth
/*!
\enum QStyleOptionFrameV2::FrameFeature
- This enum describles the different types of features a frame can have.
+ This enum describes the different types of features a frame can have.
\value None Indicates a normal frame.
\value Flat Indicates a flat frame.
@@ -711,7 +712,7 @@ QStyleOptionFrameV2 &QStyleOptionFrameV2::operator=(const QStyleOptionFrame &oth
Constructs a QStyleOptionFrameV3 object.
*/
QStyleOptionFrameV3::QStyleOptionFrameV3()
- : QStyleOptionFrameV2(Version), frameShape(QFrame::NoFrame)
+ : QStyleOptionFrameV2(Version), frameShape(QFrame::NoFrame), unused(0)
{
}
@@ -725,7 +726,7 @@ QStyleOptionFrameV3::QStyleOptionFrameV3()
\internal
*/
QStyleOptionFrameV3::QStyleOptionFrameV3(int version)
- : QStyleOptionFrameV2(version), frameShape(QFrame::NoFrame)
+ : QStyleOptionFrameV2(version), frameShape(QFrame::NoFrame), unused(0)
{
}
@@ -898,7 +899,7 @@ QStyleOptionViewItemV2 &QStyleOptionViewItemV2::operator=(const QStyleOptionView
/*!
\enum QStyleOptionViewItemV2::ViewItemFeature
- This enum describles the different types of features an item can have.
+ This enum describes the different types of features an item can have.
\value None Indicates a normal item.
\value WrapText Indicates an item with wrapped text.
@@ -953,7 +954,7 @@ QStyleOptionViewItemV2 &QStyleOptionViewItemV2::operator=(const QStyleOptionView
Constructs a QStyleOptionViewItemV3 object.
*/
QStyleOptionViewItemV3::QStyleOptionViewItemV3()
- : QStyleOptionViewItemV2(Version)
+ : QStyleOptionViewItemV2(Version), widget(0)
{
}
@@ -961,7 +962,7 @@ QStyleOptionViewItemV3::QStyleOptionViewItemV3()
Constructs a copy of \a other.
*/
QStyleOptionViewItemV3::QStyleOptionViewItemV3(const QStyleOptionViewItem &other)
- : QStyleOptionViewItemV2(Version)
+ : QStyleOptionViewItemV2(Version), widget(0)
{
(void)QStyleOptionViewItemV3::operator=(other);
}
@@ -990,7 +991,7 @@ QStyleOptionViewItemV3 &QStyleOptionViewItemV3::operator = (const QStyleOptionVi
\internal
*/
QStyleOptionViewItemV3::QStyleOptionViewItemV3(int version)
- : QStyleOptionViewItemV2(version)
+ : QStyleOptionViewItemV2(version), widget(0)
{
}
@@ -3541,7 +3542,8 @@ QStyleOptionQ3DockWindow::QStyleOptionQ3DockWindow(int version)
*/
QStyleOptionDockWidget::QStyleOptionDockWidget()
- : QStyleOption(Version, SO_DockWidget), movable(false)
+ : QStyleOption(Version, SO_DockWidget), closable(false),
+ movable(false), floatable(false)
{
}
@@ -4256,8 +4258,7 @@ QStyleOptionRubberBand::QStyleOptionRubberBand(int version)
parameters for drawing a title bar.
QStyleOptionTitleBar contains all the information that QStyle
- functions need to draw the title bars of QWorkspace's MDI
- children.
+ functions need to draw the title bar of a QMdiSubWindow.
For performance reasons, the access to the member variables is
direct (i.e., using the \c . or \c -> operator). This low-level feel
@@ -4267,7 +4268,7 @@ QStyleOptionRubberBand::QStyleOptionRubberBand(int version)
For an example demonstrating how style options can be used, see
the \l {widgets/styles}{Styles} example.
- \sa QStyleOption, QStyleOptionComplex, QWorkspace
+ \sa QStyleOption, QStyleOptionComplex, QMdiSubWindow
*/
/*!
@@ -4844,7 +4845,7 @@ QStyleOptionTabBarBaseV2 &QStyleOptionTabBarBaseV2::operator = (const QStyleOpti
/*! \internal */
QStyleOptionTabBarBaseV2::QStyleOptionTabBarBaseV2(int version)
- : QStyleOptionTabBarBase(version)
+ : QStyleOptionTabBarBase(version), documentMode(false)
{
}
@@ -4936,7 +4937,7 @@ QStyleOptionSizeGrip::QStyleOptionSizeGrip(int version)
\brief The QStyleOptionGraphicsItem class is used to describe
the parameters needed to draw a QGraphicsItem.
\since 4.2
- \ingroup multimedia
+ \ingroup graphicsview-api
For performance reasons, the access to the member variables is
direct (i.e., using the \c . or \c -> operator). This low-level feel
@@ -4981,8 +4982,7 @@ QStyleOptionSizeGrip::QStyleOptionSizeGrip(int version)
*/
/*!
- Constructs a QStyleOptionGraphicsItem. The levelOfDetail parameter is
- initialized to 1.
+ Constructs a QStyleOptionGraphicsItem.
*/
QStyleOptionGraphicsItem::QStyleOptionGraphicsItem()
: QStyleOption(Version, Type), levelOfDetail(1)
@@ -4998,6 +4998,29 @@ QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version)
}
/*!
+ \since 4.6
+
+ Returns the level of detail from the \a worldTransform.
+
+ Its value represents the maximum value of the height and
+ width of a unity rectangle, mapped using the \a worldTransform
+ of the painter used to draw the item. By default, if no
+ transformations are applied, its value is 1. If zoomed out 1:2, the level
+ of detail will be 0.5, and if zoomed in 2:1, its value is 2.
+*/
+qreal QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &worldTransform)
+{
+ if (worldTransform.type() <= QTransform::TxTranslate)
+ return 1; // Translation only? The LOD is 1.
+
+ // Two unit vectors.
+ QLineF v1(0, 0, 1, 0);
+ QLineF v2(0, 0, 0, 1);
+ // LOD is the transformed area of a 1x1 rectangle.
+ return qSqrt(worldTransform.map(v1).length() * worldTransform.map(v2).length());
+}
+
+/*!
\fn QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(const QStyleOptionGraphicsItem &other)
Constructs a copy of \a other.
@@ -5010,38 +5033,41 @@ QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version)
Make use of this rectangle to speed up item drawing when only parts of the
item are exposed. If the whole item is exposed, this rectangle will be the
same as QGraphicsItem::boundingRect().
+
+ This member is only initialized for items that have the
+ QGraphicsItem::ItemUsesExtendedStyleOption flag set.
*/
/*!
\variable QStyleOptionGraphicsItem::matrix
\brief the complete transformation matrix for the item
+ \obsolete
+
+ The QMatrix provided through this member does include information about
+ any perspective transformations applied to the view or item. To get the
+ correct transformation matrix, use QPainter::transform() on the painter
+ passed into the QGraphicsItem::paint() implementation.
- This matrix is the sum of the item's scene matrix and the matrix of the
- painter used for drawing the item. It is provided for convenience,
+ This matrix is the combination of the item's scene matrix and the matrix
+ of the painter used for drawing the item. It is provided for convenience,
allowing anvanced level-of-detail metrics that can be used to speed up
item drawing.
- To find the dimentions of an item in screen coordinates (i.e., pixels),
+ To find the dimensions of an item in screen coordinates (i.e., pixels),
you can use the mapping functions of QMatrix, such as QMatrix::map().
- \sa QStyleOptionGraphicsItem::levelOfDetail
+ This member is only initialized for items that have the
+ QGraphicsItem::ItemUsesExtendedStyleOption flag set.
+
+ \sa QStyleOptionGraphicsItem::levelOfDetailFromTransform()
*/
/*!
\variable QStyleOptionGraphicsItem::levelOfDetail
- \brief a simple metric for determining an item's level of detail
-
- This simple metric provides an easy way to determine the level of detail
- for an item. Its value represents the maximum value of the height and
- width of a unity rectangle, mapped using the complete transformation
- matrix of the painter used to draw the item. By default, if no
- transformations are applied, its value is 1. If zoomed out 1:2, the level
- of detail will be 0.5, and if zoomed in 2:1, its value is 2.
-
- For more advanced level-of-detail metrics, use
- QStyleOptionGraphicsItem::matrix directly.
+ \obsolete
- \sa QStyleOptionGraphicsItem::matrix
+ Use QStyleOptionGraphicsItem::levelOfDetailFromTransform()
+ together with QPainter::worldTransform() instead.
*/
/*!
@@ -5342,10 +5368,10 @@ QDebug operator<<(QDebug debug, const QStyleOption &option)
{
debug << "QStyleOption(";
debug << QStyleOption::OptionType(option.type);
- debug << "," << (option.direction == Qt::RightToLeft ? "RightToLeft" : "LeftToRight");
- debug << "," << option.state;
- debug << "," << option.rect;
- debug << ")";
+ debug << ',' << (option.direction == Qt::RightToLeft ? "RightToLeft" : "LeftToRight");
+ debug << ',' << option.state;
+ debug << ',' << option.rect;
+ debug << ')';
return debug;
}
#endif
diff --git a/src/gui/styles/qstyleoption.h b/src/gui/styles/qstyleoption.h
index 3729e9f..c19f020 100644
--- a/src/gui/styles/qstyleoption.h
+++ b/src/gui/styles/qstyleoption.h
@@ -856,6 +856,7 @@ public:
QStyleOptionGraphicsItem();
QStyleOptionGraphicsItem(const QStyleOptionGraphicsItem &other) : QStyleOption(Version, Type) { *this = other; }
+ static qreal levelOfDetailFromTransform(const QTransform &worldTransform);
protected:
QStyleOptionGraphicsItem(int version);
};
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index 4be0d53..cead2ac 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -81,6 +81,7 @@
#include <private/qwidget_p.h>
#include <QAbstractSpinBox>
#include <QLabel>
+#include "qdrawutil.h"
#include <limits.h>
@@ -213,6 +214,7 @@ enum PseudoElement {
PseudoElement_ViewItemText,
PseudoElement_ViewItemIndicator,
PseudoElement_ScrollAreaCorner,
+ PseudoElement_TabBarTabCloseButton,
NumPseudoElements
};
@@ -222,7 +224,7 @@ struct PseudoElementInfo {
};
static const PseudoElementInfo knownPseudoElements[NumPseudoElements] = {
- { QStyle::SC_None, "", },
+ { QStyle::SC_None, "" },
{ QStyle::SC_None, "down-arrow" },
{ QStyle::SC_None, "up-arrow" },
{ QStyle::SC_None, "left-arrow" },
@@ -299,8 +301,9 @@ static const PseudoElementInfo knownPseudoElements[NumPseudoElements] = {
{ QStyle::SC_None, "item" },
{ QStyle::SC_None, "icon" },
{ QStyle::SC_None, "text" },
- { QStyle::SC_None, "indicator" } ,
- { QStyle::SC_None, "corner" }
+ { QStyle::SC_None, "indicator" },
+ { QStyle::SC_None, "corner" },
+ { QStyle::SC_None, "close-button" },
};
@@ -312,15 +315,10 @@ struct QStyleSheetBorderImageData : public QSharedData
for (int i = 0; i < 4; i++)
cuts[i] = -1;
}
- QPixmap topEdge, bottomEdge, leftEdge, rightEdge, middle;
- QRect topEdgeRect, bottomEdgeRect, leftEdgeRect, rightEdgeRect, middleRect;
- QRect topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner;
int cuts[4];
QPixmap pixmap;
QImage image;
QCss::TileMode horizStretch, vertStretch;
-
- void cutBorderImage();
};
struct QStyleSheetBackgroundData : public QSharedData
@@ -871,7 +869,7 @@ static QStyle::StandardPixmap subControlIcon(int pe)
QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QWidget *widget)
: features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), ou(0), geo(0), p(0), img(0), clipset(0)
{
- QPalette palette = qApp->palette(); // ###: ideally widget's palette
+ QPalette palette = QApplication::palette(); // ###: ideally widget's palette
ValueExtractor v(declarations, palette);
features = v.extractStyleFeatures();
@@ -1122,176 +1120,27 @@ void QRenderRule::fixupBorder(int nativeWidth)
for (int i = 0; i < 4; i++) // assume, cut = border
bi->cuts[i] = int(border()->borders[i]);
}
- bi->cutBorderImage();
}
-void QStyleSheetBorderImageData::cutBorderImage()
-{
- const int w = pixmap.width();
- const int h = pixmap.height();
- const int &l = cuts[LeftEdge], &r = cuts[RightEdge],
- &t = cuts[TopEdge], &b = cuts[BottomEdge];
-
- topEdgeRect = QRect(l, 0, w - r - l, t);
- bottomEdgeRect = QRect(l, h - b, w - l - r, b);
- if (horizStretch != TileMode_Stretch) {
- if (topEdgeRect.isValid())
- topEdge = pixmap.copy(topEdgeRect).scaledToHeight(t);
- if (bottomEdgeRect.isValid())
- bottomEdge = pixmap.copy(bottomEdgeRect).scaledToHeight(b);
- }
-
- leftEdgeRect = QRect(0, t, l, h - b - t);
- rightEdgeRect = QRect(w - r, t, r, h - t- b);
- if (vertStretch != TileMode_Stretch) {
- if (leftEdgeRect.isValid())
- leftEdge = pixmap.copy(leftEdgeRect).scaledToWidth(l);
- if (rightEdgeRect.isValid())
- rightEdge = pixmap.copy(rightEdgeRect).scaledToWidth(r);
- }
-
- middleRect = QRect(l, t, w - r -l, h - t - b);
- if (middleRect.isValid()
- && !(horizStretch == TileMode_Stretch && vertStretch == TileMode_Stretch)) {
- middle = pixmap.copy(middleRect);
- }
-}
-
-static void qDrawCenterTiledPixmap(QPainter *p, const QRectF& r, const QPixmap& pix)
-{
- p->drawTiledPixmap(r, pix, QPoint(pix.width() - int(r.width())%pix.width(),
- pix.height() - int(r.height())%pix.height()));
-}
-
-// Note: Round is not supported
void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect)
{
- setClip(p, rect);
- const QRectF br(rect);
- const int *borders = border()->borders;
- const int &l = borders[LeftEdge], &r = borders[RightEdge],
- &t = borders[TopEdge], &b = borders[BottomEdge];
- QRectF pr = br.adjusted(l, t, -r, -b);
+ static const Qt::TileRule tileMode2TileRule[] = {
+ Qt::Stretch, Qt::Round, Qt::Stretch, Qt::Repeat, Qt::Stretch };
+
+ const QStyleSheetBorderImageData *borderImageData = border()->borderImage();
+ const int *targetBorders = border()->borders;
+ const int *sourceBorders = borderImageData->cuts;
+ QMargins sourceMargins(sourceBorders[TopEdge], sourceBorders[LeftEdge],
+ sourceBorders[BottomEdge], sourceBorders[RightEdge]);
+ QMargins targetMargins(targetBorders[TopEdge], targetBorders[LeftEdge],
+ targetBorders[BottomEdge], targetBorders[RightEdge]);
bool wasSmoothPixmapTransform = p->renderHints() & QPainter::SmoothPixmapTransform;
p->setRenderHint(QPainter::SmoothPixmapTransform);
-
- const QStyleSheetBorderImageData *bi = border()->borderImage();
- const QPixmap& pix = bi->pixmap;
- const int *c = bi->cuts;
- QRectF tlc(0, 0, c[LeftEdge], c[TopEdge]);
- if (tlc.isValid())
- p->drawPixmap(QRectF(br.topLeft(), QSizeF(l, t)), pix, tlc);
- QRectF trc(pix.width() - c[RightEdge], 0, c[RightEdge], c[TopEdge]);
- if (trc.isValid())
- p->drawPixmap(QRectF(br.left() + br.width() - r, br.y(), r, t), pix, trc);
- QRectF blc(0, pix.height() - c[BottomEdge], c[LeftEdge], c[BottomEdge]);
- if (blc.isValid())
- p->drawPixmap(QRectF(br.x(), br.y() + br.height() - b, l, b), pix, blc);
- QRectF brc(pix.width() - c[RightEdge], pix.height() - c[BottomEdge],
- c[RightEdge], c[BottomEdge]);
- if (brc.isValid())
- p->drawPixmap(QRectF(br.x() + br.width() - r, br.y() + br.height() - b, r, b),
- pix, brc);
-
- QRectF topEdgeRect(br.x() + l, br.y(), pr.width(), t);
- QRectF bottomEdgeRect(br.x() + l, br.y() + br.height() - b, pr.width(), b);
-
- switch (bi->horizStretch) {
- case TileMode_Stretch:
- if (bi->topEdgeRect.isValid())
- p->drawPixmap(topEdgeRect, pix, bi->topEdgeRect);
- if (bi->bottomEdgeRect.isValid())
- p->drawPixmap(bottomEdgeRect, pix, bi->bottomEdgeRect);
- if (bi->middleRect.isValid()) {
- if (bi->vertStretch == TileMode_Stretch)
- p->drawPixmap(pr, pix, bi->middleRect);
- else if (bi->vertStretch == TileMode_Repeat) {
- QPixmap scaled = bi->middle.scaled(int(pr.width()), bi->middle.height());
- qDrawCenterTiledPixmap(p, pr, scaled);
- }
- }
- break;
- case TileMode_Repeat:
- if (!bi->topEdge.isNull() && !topEdgeRect.isEmpty()) {
- QPixmap scaled = bi->topEdge.scaled(bi->topEdge.width(), t);
- qDrawCenterTiledPixmap(p, topEdgeRect, scaled);
- }
- if (!bi->bottomEdge.isNull() && !bottomEdgeRect.isEmpty()) {
- QPixmap scaled = bi->bottomEdge.scaled(bi->bottomEdge.width(), b);
- qDrawCenterTiledPixmap(p, bottomEdgeRect, scaled);
- }
- if (bi->middleRect.isValid()) {
- if (bi->vertStretch == TileMode_Repeat) {
- qDrawCenterTiledPixmap(p, pr, bi->middle);
- } else if (bi->vertStretch == TileMode_Stretch) {
- QPixmap scaled = bi->middle.scaled(bi->middle.width(), int(pr.height()));
- qDrawCenterTiledPixmap(p, pr, scaled);
- }
- }
- break;
- case TileMode_Round:
- if (!bi->topEdge.isNull()) {
- int rwh = (int)pr.width()/ceil(pr.width()/bi->topEdge.width());
- QPixmap scaled = bi->topEdge.scaled(rwh, bi->topEdge.height());
- int blank = int(pr.width()) % rwh;
- p->drawTiledPixmap(QRectF(br.x() + l + blank/2, br.y(), pr.width() - blank, t),
- scaled);
- }
- if (!bi->bottomEdge.isNull()) {
- int rwh = (int) pr.width()/ceil(pr.width()/bi->bottomEdge.width());
- QPixmap scaled = bi->bottomEdge.scaled(rwh, bi->bottomEdge.height());
- int blank = int(pr.width()) % rwh;
- p->drawTiledPixmap(QRectF(br.x() + l+ blank/2, br.y()+br.height()-b,
- pr.width() - blank, b), scaled);
- }
- break;
- default:
- break;
- }
-
- QRectF leftEdgeRect(br.x(), br.y() + t, l, pr.height());
- QRectF rightEdgeRect(br.x() + br.width()- r, br.y() + t, r, pr.height());
-
- switch (bi->vertStretch) {
- case TileMode_Stretch:
- if (bi->leftEdgeRect.isValid())
- p->drawPixmap(leftEdgeRect, pix, bi->leftEdgeRect);
- if (bi->rightEdgeRect.isValid())
- p->drawPixmap(rightEdgeRect, pix, bi->rightEdgeRect);
- break;
- case TileMode_Repeat:
- if (!bi->leftEdge.isNull() && !leftEdgeRect.isEmpty()) {
- QPixmap scaled = bi->leftEdge.scaled(l, bi->leftEdge.height());
- qDrawCenterTiledPixmap(p, leftEdgeRect, scaled);
- }
- if (!bi->rightEdge.isNull() && !rightEdgeRect.isEmpty()) {
- QPixmap scaled = bi->rightEdge.scaled(r, bi->rightEdge.height());
- qDrawCenterTiledPixmap(p, rightEdgeRect, scaled);
- }
- break;
- case TileMode_Round:
- if (!bi->leftEdge.isNull()) {
- int rwh = (int) pr.height()/ceil(pr.height()/bi->leftEdge.height());
- QPixmap scaled = bi->leftEdge.scaled(bi->leftEdge.width(), rwh);
- int blank = int(pr.height()) % rwh;
- p->drawTiledPixmap(QRectF(br.x(), br.y() + t + blank/2, l, pr.height() - blank),
- scaled);
- }
- if (!bi->rightEdge.isNull()) {
- int rwh = (int) pr.height()/ceil(pr.height()/bi->rightEdge.height());
- QPixmap scaled = bi->rightEdge.scaled(bi->rightEdge.width(), rwh);
- int blank = int(pr.height()) % rwh;
- p->drawTiledPixmap(QRectF(br.x() + br.width() - r, br.y()+t+blank/2, r,
- pr.height() - blank), scaled);
- }
- break;
- default:
- break;
- }
-
+ qDrawBorderPixmap(p, rect, targetMargins, borderImageData->pixmap,
+ QRect(QPoint(), borderImageData->pixmap.size()), sourceMargins,
+ QTileRules(tileMode2TileRule[borderImageData->horizStretch], tileMode2TileRule[borderImageData->vertStretch]));
p->setRenderHint(QPainter::SmoothPixmapTransform, wasSmoothPixmapTransform);
- unsetClip(p);
}
QRect QRenderRule::originRect(const QRect &rect, Origin origin) const
@@ -1451,7 +1300,6 @@ void QRenderRule::unsetClip(QPainter *p)
void QRenderRule::drawBackground(QPainter *p, const QRect& rect, const QPoint& off)
{
- setClip(p, borderRect(rect));
QBrush brush = hasBackground() ? background()->brush : QBrush();
if (brush.style() == Qt::NoBrush)
brush = defaultBackground;
@@ -1459,11 +1307,19 @@ void QRenderRule::drawBackground(QPainter *p, const QRect& rect, const QPoint& o
if (brush.style() != Qt::NoBrush) {
Origin origin = hasBackground() ? background()->clip : Origin_Border;
// ### fix for gradients
- p->fillRect(originRect(rect, origin), brush);
+ const QPainterPath &borderPath = borderClip(originRect(rect, origin));
+ if (!borderPath.isEmpty()) {
+ // Drawn intead of being used as clipping path for better visual quality
+ bool wasAntialiased = p->renderHints() & QPainter::Antialiasing;
+ p->setRenderHint(QPainter::Antialiasing);
+ p->fillPath(borderPath, brush);
+ p->setRenderHint(QPainter::Antialiasing, wasAntialiased);
+ } else {
+ p->fillRect(originRect(rect, origin), brush);
+ }
}
drawBackgroundImage(p, rect, off);
- unsetClip(p);
}
void QRenderRule::drawFrame(QPainter *p, const QRect& rect)
@@ -1525,7 +1381,7 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const Q
/* For embedded widgets (ComboBox, SpinBox and ScrollArea) we want the embedded widget
* to be transparent when we have a transparent background or border image */
if ((hasBackground() && background()->isTransparent())
- || (hasBorder() && border()->hasBorderImage() && border()->borderImage()->middleRect.isValid()))
+ || (hasBorder() && border()->hasBorderImage() && !border()->borderImage()->pixmap.isNull()))
p->setBrush(cg, w->backgroundRole(), Qt::NoBrush);
}
@@ -1708,7 +1564,7 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
if (widCacheIt == styleSheetCache->constEnd()) {
parser.init(wid->styleSheet());
if (!parser.parse(&ss)) {
- parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1String("}"));
+ parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1Char('}'));
if (!parser.parse(&ss))
qWarning("Could not parse stylesheet of widget %p", wid);
}
@@ -2737,7 +2593,7 @@ static void updateWidgets(const QList<const QWidget *>& widgets)
continue;
widget->style()->polish(widget);
QEvent event(QEvent::StyleChange);
- qApp->sendEvent(widget, &event);
+ QApplication::sendEvent(widget, &event);
widget->update();
widget->updateGeometry();
}
@@ -2783,9 +2639,9 @@ QStyle *QStyleSheetStyle::baseStyle() const
{
if (base)
return base;
- if (QStyleSheetStyle *me = qobject_cast<QStyleSheetStyle *>(qApp->style()))
+ if (QStyleSheetStyle *me = qobject_cast<QStyleSheetStyle *>(QApplication::style()))
return me->base;
- return qApp->style();
+ return QApplication::style();
}
void QStyleSheetStyle::widgetDestroyed(QObject *o)
@@ -2855,14 +2711,10 @@ void QStyleSheetStyle::polish(QWidget *w)
QRenderRule rule = renderRule(sa, PseudoElement_None, PseudoClass_Enabled);
if ((rule.hasBorder() && rule.border()->hasBorderImage())
|| (rule.hasBackground() && !rule.background()->pixmap.isNull())) {
- QObject::disconnect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
- QObject::disconnect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
QObject::connect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
+ sa, SLOT(update()), Qt::UniqueConnection);
QObject::connect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
+ sa, SLOT(update()), Qt::UniqueConnection);
}
}
#endif
@@ -2876,12 +2728,6 @@ void QStyleSheetStyle::polish(QWidget *w)
QRenderRule rule = renderRule(w, PseudoElement_None, PseudoClass_Any);
if (rule.hasDrawable() || rule.hasBox()) {
if (w->metaObject() == &QWidget::staticMetaObject
-#ifndef QT_NO_MENUBAR
- || qobject_cast<QMenuBar *>(w)
-#endif
-#ifndef QT_NO_MENU
- || qobject_cast<QMenu *>(w)
-#endif
#ifndef QT_NO_ITEMVIEWS
|| qobject_cast<QHeaderView *>(w)
#endif
@@ -2897,6 +2743,9 @@ void QStyleSheetStyle::polish(QWidget *w)
#ifndef QT_NO_MDIAREA
|| qobject_cast<QMdiSubWindow *>(w)
#endif
+#ifndef QT_NO_MENUBAR
+ || qobject_cast<QMenuBar *>(w)
+#endif
|| qobject_cast<QDialog *>(w)) {
w->setAttribute(Qt::WA_StyledBackground, true);
}
@@ -3013,7 +2862,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
rule.drawBackgroundImage(p, cmbOpt.rect);
rule.configurePalette(&cmbOpt.palette, QPalette::ButtonText, QPalette::Button);
bool customDropDown = (opt->subControls & QStyle::SC_ComboBoxArrow)
- && hasStyleRule(w, PseudoElement_ComboBoxDropDown);
+ && (hasStyleRule(w, PseudoElement_ComboBoxDropDown) || hasStyleRule(w, PseudoElement_ComboBoxArrow));
if (customDropDown)
cmbOpt.subControls &= ~QStyle::SC_ComboBoxArrow;
if (rule.baseStyleCanDraw()) {
@@ -3054,16 +2903,16 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
bool customUp = true, customDown = true;
QRenderRule upRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton);
QRenderRule downRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton);
- bool upRuleMatch = upRule.hasGeometry();
- bool downRuleMatch = downRule.hasGeometry();
+ bool upRuleMatch = upRule.hasGeometry() || upRule.hasPosition();
+ bool downRuleMatch = downRule.hasGeometry() || downRule.hasPosition();
if (rule.hasNativeBorder() && !upRuleMatch && !downRuleMatch) {
rule.drawBackgroundImage(p, spinOpt.rect);
customUp = (opt->subControls & QStyle::SC_SpinBoxUp)
- && hasStyleRule(w, PseudoElement_SpinBoxUpButton);
+ && (hasStyleRule(w, PseudoElement_SpinBoxUpButton) || hasStyleRule(w, PseudoElement_UpArrow));
if (customUp)
spinOpt.subControls &= ~QStyle::SC_SpinBoxUp;
customDown = (opt->subControls & QStyle::SC_SpinBoxDown)
- && hasStyleRule(w, PseudoElement_SpinBoxDownButton);
+ && (hasStyleRule(w, PseudoElement_SpinBoxDownButton) || hasStyleRule(w, PseudoElement_DownArrow));
if (customDown)
spinOpt.subControls &= ~QStyle::SC_SpinBoxDown;
if (rule.baseStyleCanDraw()) {
@@ -3189,6 +3038,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
if (const QStyleOptionToolButton *tool = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QStyleOptionToolButton toolOpt(*tool);
rule.configurePalette(&toolOpt.palette, QPalette::ButtonText, QPalette::Button);
+ toolOpt.font = rule.font.resolve(toolOpt.font);
toolOpt.rect = rule.borderRect(opt->rect);
bool customArrow = (tool->features & (QStyleOptionToolButton::HasMenu | QStyleOptionToolButton::MenuButtonPopup));
bool customDropDown = tool->features & QStyleOptionToolButton::MenuButtonPopup;
@@ -3348,7 +3198,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
if (subRule.hasDrawable()) {
QRect rect = subRule.boxRect(subControlRect(CC_MdiControls, opt, control, w), Margin);
subRule.drawRule(p, rect);
- QIcon icon = standardIcon(subControlIcon(layoutButton));
+ QIcon icon = standardIcon(subControlIcon(layoutButton), opt);
icon.paint(p, subRule.contentsRect(rect), Qt::AlignCenter);
} else {
optCopy.subControls |= control;
@@ -3618,6 +3468,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
case CE_MenuEmptyArea:
case CE_MenuBarEmptyArea:
if (rule.hasDrawable()) {
+ // Drawn by PE_Widget
return;
}
break;
@@ -3735,7 +3586,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
mi.rect = positionRect(w, subRule, subRule2, PseudoElement_MenuRightArrow, opt->rect, mi.direction);
drawPrimitive(arrow, &mi, p, w);
}
- } else if (hasStyleRule(w, PseudoElement_MenuCheckMark)) {
+ } else if (hasStyleRule(w, PseudoElement_MenuCheckMark) || hasStyleRule(w, PseudoElement_MenuRightArrow)) {
QWindowsStyle::drawControl(ce, &mi, p, w);
} else {
if (rule.hasDrawable() && !subRule.hasDrawable() && !(opt->state & QStyle::State_Selected)) {
@@ -3768,6 +3619,11 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
subRule.drawRule(p, opt->rect);
QCommonStyle::drawControl(ce, &mi, p, w);
} else {
+ if (rule.hasDrawable() && !(opt->state & QStyle::State_Selected)) {
+ // So that the menu bar background is not hidden by the items
+ mi.palette.setColor(QPalette::Window, Qt::transparent);
+ mi.palette.setColor(QPalette::Button, Qt::transparent);
+ }
baseStyle()->drawControl(ce, &mi, p, w);
}
}
@@ -3789,9 +3645,9 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
QRect iconRect(editRect);
iconRect.setWidth(cb->iconSize.width());
- iconRect = alignedRect(QApplication::layoutDirection(),
- Qt::AlignLeft | Qt::AlignVCenter,
- iconRect.size(), editRect);
+ iconRect = alignedRect(cb->direction,
+ Qt::AlignLeft | Qt::AlignVCenter,
+ iconRect.size(), editRect);
drawItemPixmap(p, iconRect, Qt::AlignCenter, pixmap);
if (cb->direction == Qt::RightToLeft)
@@ -4164,9 +4020,8 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base);
frmOpt.rect = rule.borderRect(frmOpt.rect);
baseStyle()->drawControl(ce, &frmOpt, p, w);
- } else {
- rule.drawBorder(p, rule.borderRect(opt->rect));
}
+ // else, borders are already drawn in PE_Widget
}
return;
@@ -4220,12 +4075,6 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
QRect rect = opt->rect;
switch (pe) {
- case PE_PanelStatusBar:
- if (rule.hasDrawable()) {
- rule.drawRule(p, opt->rect);
- return;
- }
- break;
case PE_FrameStatusBar: {
QRenderRule subRule = renderRule(w->parentWidget(), opt, PseudoElement_Item);
@@ -4337,7 +4186,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
return;
case PE_Widget:
- if (!rule.hasBackground()) {
+ if (!rule.hasDrawable()) {
QWidget *container = containerWidget(w);
if (autoFillDisabledWidgets->contains(container)
&& (container == w || !renderRule(container, opt).hasBackground())) {
@@ -4347,26 +4196,30 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
}
break;
}
-
#ifndef QT_NO_SCROLLAREA
if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w)) {
const QAbstractScrollAreaPrivate *sap = sa->d_func();
rule.drawBackground(p, opt->rect, sap->contentsOffset());
- } else
+ if (rule.hasBorder())
+ rule.drawBorder(p, rule.borderRect(opt->rect));
+ break;
+ }
#endif
- {
- rule.drawBackground(p, opt->rect);
+ //fall tghought
+ case PE_PanelMenu:
+ case PE_PanelStatusBar:
+ if(rule.hasDrawable()) {
+ rule.drawRule(p, opt->rect);
+ return;
}
+ break;
- return;
-
- case PE_FrameMenu:
case PE_PanelMenuBar:
- if (!rule.hasNativeBorder()) {
- rule.drawBorder(p, rule.borderRect(opt->rect));
- return;
- }
- break;
+ if (rule.hasDrawable()) {
+ // Drawn by PE_Widget
+ return;
+ }
+ break;
case PE_IndicatorToolBarSeparator:
case PE_IndicatorToolBarHandle: {
@@ -4510,6 +4363,22 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
pseudoElement = PseudoElement_ScrollAreaCorner;
break;
+ case PE_IndicatorSpinDown:
+ case PE_IndicatorSpinMinus:
+ pseudoElement = PseudoElement_SpinBoxDownArrow;
+ break;
+
+ case PE_IndicatorSpinUp:
+ case PE_IndicatorSpinPlus:
+ pseudoElement = PseudoElement_SpinBoxUpArrow;
+ break;
+#ifndef QT_NO_TABBAR
+ case PE_IndicatorTabClose:
+ if (w)
+ w = w->parentWidget(); //match on the QTabBar instead of the CloseButton
+ pseudoElement = PseudoElement_TabBarTabCloseButton;
+#endif
+
default:
break;
}
@@ -4973,13 +4842,10 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
if ((pe == PseudoElement_MenuSeparator) && subRule.hasContentsSize()) {
return QSize(sz.width(), subRule.size().height());
} else if ((pe == PseudoElement_Item) && (subRule.hasBox() || subRule.hasBorder())) {
- int width = csz.width(), height = qMax(csz.height(), mi->fontMetrics.height());
- if (!mi->icon.isNull()) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
- height = qMax(height, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height());
- }
- width += mi->tabWidth;
- return subRule.boxSize(csz.expandedTo(subRule.minimumContentsSize()));
+ int width = csz.width();
+ if (mi->text.contains(QLatin1Char('\t')))
+ width += 12; //as in QCommonStyle
+ return subRule.boxSize(subRule.adjustSize(QSize(width, csz.height())));
}
}
break;
@@ -5246,6 +5112,18 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
#endif // QT_NO_TABWIDGET
s = QLatin1String("alignment");
break;
+#ifndef QT_NO_TABBAR
+ case SH_TabBar_CloseButtonPosition:
+ rule = renderRule(w, opt, PseudoElement_TabBarTabCloseButton);
+ if (rule.hasPosition()) {
+ Qt::Alignment align = rule.position()->position;
+ if (align & Qt::AlignLeft || align & Qt::AlignTop)
+ return QTabBar::LeftSide;
+ if (align & Qt::AlignRight || align & Qt::AlignBottom)
+ return QTabBar::RightSide;
+ }
+ break;
+#endif
case SH_TabBar_ElideMode: s = QLatin1String("tabbar-elide-mode"); break;
case SH_TabBar_PreferNoArrows: s = QLatin1String("tabbar-prefer-no-arrows"); break;
case SH_ComboBox_PopupFrameStyle:
@@ -5331,8 +5209,8 @@ QRect QStyleSheetStyle::subControlRect(ComplexControl cc, const QStyleOptionComp
QRenderRule upRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton);
QRenderRule downRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton);
bool ruleMatch = rule.hasBox() || !rule.hasNativeBorder();
- bool upRuleMatch = upRule.hasGeometry();
- bool downRuleMatch = downRule.hasGeometry();
+ bool upRuleMatch = upRule.hasGeometry() || upRule.hasPosition();
+ bool downRuleMatch = downRule.hasGeometry() || upRule.hasPosition();
if (ruleMatch || upRuleMatch || downRuleMatch) {
switch (sc) {
case SC_SpinBoxFrame:
@@ -5890,13 +5768,11 @@ void QStyleSheetStyle::clearWidgetFont(QWidget* w) const
w->setProperty("_q_styleSheetWidgetFont", QVariant(QVariant::Invalid));
}
-// Returns the palette that should be used when the particular widget is focused.
-// This needs to be called by some widgets that do drawing themselves instead
-// of through the style.
-// ### This should be removed ideally by Qt 4.5, and at least by Qt 5, and fixed
-// for good by letting the style draw everything.
+// Polish palette that should be used for a particular widget, with particular states
+// (eg. :focus, :hover, ...)
+// this is called by widgets that paint themself in their paint event
// Returns true if there is a new palette in pal.
-bool QStyleSheetStyle::focusPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal)
+bool QStyleSheetStyle::styleSheetPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal)
{
if (!w || !opt || !pal)
return false;
diff --git a/src/gui/styles/qstylesheetstyle_default.cpp b/src/gui/styles/qstylesheetstyle_default.cpp
index 53565fb..3d2dee4 100644
--- a/src/gui/styles/qstylesheetstyle_default.cpp
+++ b/src/gui/styles/qstylesheetstyle_default.cpp
@@ -154,11 +154,12 @@ StyleSheet QStyleSheetStyle::getDefaultStyleSheet() const
Value value;
Pseudo pseudo;
AttributeSelector attr;
-
+
// pixmap based style doesn't support any features
bool styleIsPixmapBased = baseStyle()->inherits("QMacStyle")
|| baseStyle()->inherits("QWindowsXPStyle")
- || baseStyle()->inherits("QGtkStyle");
+ || baseStyle()->inherits("QGtkStyle")
+ || baseStyle()->inherits("QS60Style");
/*QLineEdit {
@@ -212,7 +213,7 @@ StyleSheet QStyleSheetStyle::getDefaultStyleSheet() const
ADD_BASIC_SELECTOR;
ADD_SELECTOR;
-
+
SET_PROPERTY(QLatin1String("padding-top"), PaddingTop);
ADD_VALUE(Value::Identifier, QString::fromLatin1("2px"));
ADD_DECLARATION;
diff --git a/src/gui/styles/qstylesheetstyle_p.h b/src/gui/styles/qstylesheetstyle_p.h
index 1ba206f..824c107 100644
--- a/src/gui/styles/qstylesheetstyle_p.h
+++ b/src/gui/styles/qstylesheetstyle_p.h
@@ -131,7 +131,7 @@ public:
void saveWidgetFont(QWidget* w, const QFont& font) const;
void clearWidgetFont(QWidget* w) const;
- bool focusPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal);
+ bool styleSheetPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal);
protected Q_SLOTS:
QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0,
diff --git a/src/gui/styles/qwindowscestyle.cpp b/src/gui/styles/qwindowscestyle.cpp
index 542ee3f..46630bf 100644
--- a/src/gui/styles/qwindowscestyle.cpp
+++ b/src/gui/styles/qwindowscestyle.cpp
@@ -56,7 +56,6 @@
QT_BEGIN_NAMESPACE
static const int windowsItemFrame = 2; // menu item frame width
-static const int windowsSepHeight = 9; // separator item height
static const int windowsItemHMargin = 3; // menu item hor text margin
static const int windowsItemVMargin = 2; // menu item ver text margin
static const int windowsArrowHMargin = 6; // arrow horizontal margin
@@ -2295,6 +2294,9 @@ int QWindowsCEStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QW
break;
case SH_EtchDisabledText:
ret = false;
+ case SH_RequestSoftwareInputPanel:
+ ret = RSIP_OnMouseClick;
+ break;
default:
ret = QWindowsStyle::styleHint(hint, opt, widget, returnData);
break;
diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp
index ed44782..00e27ab 100644
--- a/src/gui/styles/qwindowsmobilestyle.cpp
+++ b/src/gui/styles/qwindowsmobilestyle.cpp
@@ -72,21 +72,17 @@
#include "qdebug.h"
#include "qtabwidget.h"
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qt_windows.h"
#include "qguifunctions_wince.h"
-extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
-extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.cpp
-#endif // Q_OS_WINCE
+extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
+extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.cpp
+extern bool qt_wince_is_windows_mobile_65(); //defined in qguifunctions_wince.cpp
+#endif // Q_WS_WINCE
QT_BEGIN_NAMESPACE
static const int windowsItemFrame = 1; // menu item frame width
-static const int windowsItemHMargin = 2; // menu item hor text margin
-static const int windowsItemVMargin = 2; // menu item ver text margin
-static const int windowsArrowHMargin = 6; // arrow horizontal margin
-static const int windowsRightBorder = 15; // right border on windows
-static const int windowsCheckMarkWidth = 14; // checkmarks width on windows
static const int windowsMobileitemViewCheckBoxSize = 13;
static const int windowsMobileFrameGroupBoxOffset = 9;
@@ -669,10 +665,3841 @@ static const char * const min_small_xpm[] = {
" ++++++++++++ ",
" "};
+#ifdef Q_WS_WINCE_WM
+
+static char * sbhandleup_xpm[] = {
+"26 41 45 1",
+" c None",
+". c #000000",
+"+ c #E7E7E7",
+"@ c #D6D7D6",
+"# c #949294",
+"$ c #737573",
+"% c #636563",
+"& c #636163",
+"* c #5A5D5A",
+"= c #5A595A",
+"- c #525552",
+"; c #525152",
+"> c #4A4D4A",
+", c #7B797B",
+"' c #CECFCE",
+") c #CED3CE",
+"! c #6B6D6B",
+"~ c #6B696B",
+"{ c #737173",
+"] c #7B7D7B",
+"^ c #848684",
+"/ c #848284",
+"( c #8C8A8C",
+"_ c #8C8E8C",
+": c #B5B2B5",
+"< c #FFFFFF",
+"[ c #949694",
+"} c #B5B6B5",
+"| c #9C9A9C",
+"1 c #ADAEAD",
+"2 c #9C9E9C",
+"3 c #BDBABD",
+"4 c #BDBEBD",
+"5 c #F7F3F7",
+"6 c #C6C3C6",
+"7 c #C6C7C6",
+"8 c #A5A2A5",
+"9 c #CECBCE",
+"0 c #FFFBFF",
+"a c #ADAAAD",
+"b c #A5A6A5",
+"c c #D6D3D6",
+"d c #B5BAB5",
+"e c #DEDFDE",
+"f c #DEDBDE",
+"..........................",
+"+@#$%%&&&**===---;;;;>=,'+",
+"+@#$%%&&&**===---;;;;>=$'+",
+")$!!~~%%&&&**===---;;;;>;'",
+"#{$]],,$${{{!!~~%%%&&&*-;]",
+"#{$]],,$${{{!!~~%%%&&&*-;]",
+",$^//]],,$${{{!!~~%%%&&*;*",
+",,(^^//]],$${!!!!!~~%%%&-*",
+",,(^^//]],$${!!!!!~~%%%&-*",
+"]]_((^^//]$!%%~!{{!!~~%%-*",
+"//#__((^^]{:<<:~!{{{!!~~=*",
+"//#__((^^]{:<<:~!{{{!!~~=&",
+"//###__(/$:<<<<:~{${{!!~*&",
+"^^[[##_^]:<<<<<<}!{$${{!*%",
+"^^[[##_^]:<<<<<<}!{$${{!*%",
+"((|[[#_/:<<<<<<<<}!$$${{&~",
+"((||[#^1<<<<1:<<<<}!$$$$&~",
+"((||[#^1<<<<1:<<<<}!$$$$&~",
+"__2|#(1<<<<}],}<<<<}{$,$%~",
+"##2|_1<<<<}^((]3<<<<}{$,~!",
+"##2|_1<<<<}^((]3<<<<}{$,~!",
+"##2#1<<<<3^###(/4<<<<}{,~{",
+"##2#1<<<<3^###(/4<<<<}{,~!",
+"[[2_5<<<4(#|[[#_/6<<<<,,!{",
+"[|2_5<<4_[||||[[_/7<<<,]{$",
+"[|2_5<<4_[||||[[_/7<<<,]{$",
+"||8_5<6#|2222|||[_/9<<,]{$",
+"228#06[28888222||[_/'<,/$,",
+"228#06[28888222||[_/'<,/$,",
+"22a|6[8bbbb88822||[(/c](,]",
+"881b8baaabbbb88222|[(^(_,]",
+"881b8baaabbbb88222|[(^(_,]",
+"88111111aaabbb88822|[###]/",
+"bb:::11111aaabbb8822||[[/^",
+"bb:::11111aaabbb8822||[[//",
+"bb:::::1111aaabbb8822||[/(",
+"3a1::::::1111aaabb8822|_^8",
+"da1::::::1111aaabb8822|_^8",
+"e1aaabbbb888822||[[##__((@",
+"+e4:aaabbbb88822||[[[#[b@+",
+"+e4:aaabbbb88822||[[[#[bf+"};
+
+static char * sbhandledown_xpm[] = {
+"26 40 46 1",
+" c None",
+". c #E7E7E7",
+"+ c #DEDFDE",
+"@ c #BDBEBD",
+"# c #B5B2B5",
+"$ c #ADAAAD",
+"% c #A5A6A5",
+"& c #A5A2A5",
+"* c #9C9E9C",
+"= c #9C9A9C",
+"- c #949694",
+"; c #949294",
+"> c #D6D7D6",
+", c #DEDBDE",
+"' c #D6DBD6",
+") c #ADAEAD",
+"! c #8C8E8C",
+"~ c #8C8A8C",
+"{ c #BDBABD",
+"] c #848684",
+"^ c #B5BAB5",
+"/ c #848284",
+"( c #848A84",
+"_ c #7B7D7B",
+": c #7B797B",
+"< c #C6C3C6",
+"[ c #D6D3D6",
+"} c #FFFBFF",
+"| c #CECFCE",
+"1 c #FFFFFF",
+"2 c #737573",
+"3 c #F7F3F7",
+"4 c #CECBCE",
+"5 c #737173",
+"6 c #C6C7C6",
+"7 c #6B6D6B",
+"8 c #B5B6B5",
+"9 c #6B696B",
+"0 c #636563",
+"a c #636163",
+"b c #5A5D5A",
+"c c #5A595A",
+"d c #525552",
+"e c #525152",
+"f c #4A4D4A",
+"g c #C6CBC6",
+".+@#$$$%%%%&&&**==---;-%>.",
+".+@#$$$%%%%&&&**==---;-%,.",
+"')$$$%%%%&&&&**==--;;!!~~>",
+"{$)######))))$$$%%&&**=!]&",
+"^$)######))))$$$%%&&**=!]&",
+"%%#####))))$$$%%%&&**==-/(",
+"%%###)))))$$$%%%&&**==--/]",
+"%%###)))))$$$%%%&&**==--//",
+"&&))))))$$$%%%&&&**=-;;;_/",
+"&&)%&%$$$%%%%&&***=-~]~!:_",
+"&&)%&%$$$%%%%&&***=-~]~!:_",
+"**$=<-&%%%%&&&**==-~/[_~:_",
+"**&;}<-*&&&&***==-!/|1:/2:",
+"**&;}<-*&&&&***==-!/|1:/2:",
+"==&!31<;=****===-!/411:_5:",
+"-=*!311@!-====--!/6111:_52",
+"-=*!311@!-====--!/6111:_52",
+"--*!3111@~;=--;!/<1111::75",
+";;*;)1111{];;;~/@111185:95",
+";;*;)1111{];;;~/@111185:97",
+";;*=!)11118]~~_{1111852:97",
+";;*=!)11118]~~_{1111852:97",
+"!!*=;~)11118_:81111852:207",
+"~~==-;])1111)#1111872222a9",
+"~~==-;])1111)#1111872222a9",
+"~~=--;!/#111111118722255a0",
+"]]--;;!]_#11111187522557b0",
+"]]--;;!]_#11111187522557b0",
+"//;;;!!~/2#1111#95255779ba",
+"//;!!~~]]_5#11#975557799cb",
+"//;!!~~]]_5#11#975557799ca",
+"__!~~]]//_27009755779900db",
+"::~]]//__:2257777799000adb",
+"::~]]//__:2257777799000adb",
+":2]//__::225557799000aabeb",
+";52__::225557799000aaabde_",
+";52__::225557799000aaabde_",
+"[2779900aaabbcccdddeeeefeg",
+".>;200aaabbcccdddeeeefc:|.",
+".>;200aaabbcccdddeeeefc2|."};
+
+static char * sbgripdown_xpm[] = {
+"26 34 39 1",
+" c None",
+". c #949294",
+"+ c #9C9E9C",
+"@ c #9C9A9C",
+"# c #949694",
+"$ c #8C8E8C",
+"% c #8C8A8C",
+"& c #848684",
+"* c #848284",
+"= c #7B7D7B",
+"- c #7B797B",
+"; c #6B696B",
+"> c #636563",
+", c #737573",
+"' c #636163",
+") c #737173",
+"! c #5A5D5A",
+"~ c #6B6D6B",
+"{ c #5A595A",
+"] c #B5B6B5",
+"^ c #BDBEBD",
+"/ c #ADAEAD",
+"( c #BDBABD",
+"_ c #525552",
+": c #313031",
+"< c #525152",
+"[ c #ADAAAD",
+"} c #BDBAB5",
+"| c #4A4D4A",
+"1 c #4A494A",
+"2 c #C6C3C6",
+"3 c #C6CBC6",
+"4 c #E7E7E7",
+"5 c #DEDFDE",
+"6 c #E7E3E7",
+"7 c #DEE3DE",
+"8 c #CECBCE",
+"9 c #8C928C",
+"0 c #CECFCE",
+"..+++@@@###...$$%&&**==-;>",
+"$.++@@@@##...$$%%&**==-->>",
+"$$+@@@@###..$$%%&&*==--,>>",
+"$$@@@@###..$$%%&&**==-,,>'",
+"%%@@@###..$$$%&&**==--,,''",
+"%%@@###..$$$%&&**==--,,)''",
+"%%@###...$$%%&&*==--,,))'!",
+"&&###...$$%%&&**==--,)))!!",
+"&&##...$$%%&&**==--,,))~!!",
+"&&#...$$%%&&**==--,,))~~!{",
+"**...$$%%&&**==--,,))~~;!{",
+"**..$$%%&&**===--,)))~~;{{",
+"**.$$%%&]^&===//,,))~~;;{{",
+"==$$%%&&]^*==-((,))~~;;>{_",
+"==$%%&&***::--,,::~~;;;>__",
+"==%%&&&**=::-,,)::~~;;>>__",
+"--%&&&**==--,,)))~~;;>>>__",
+"--&&&**==--,,)))~~;;>>>'_<",
+",-&&**==]^-,))[[~;;>>>''<<",
+",,&**==-]^-)))}};;>>>'''<<",
+",,**==--,,::)~~;::>>'''!<<",
+"))*==--,,)::~~;;::>'''!!<|",
+"))==--,,)))~~;;;>>'''!!!||",
+"))=--,,)))~~;;;>>'''!!!{||",
+"~~--,,)))~~;;;>>'''!!!{{||",
+"~~-,,)))~~;;>>>'''!!!{{{|1",
+";;,,)))~~;;>>>'''!!!{{{_1<",
+"~;,)))~~;;>>>'''!!!{{{__1'",
+"%>~))~~;;>>>'''!!!{{{__|1$",
+"2>>~~~;;>>>''!!!{{{{__<113",
+"4%'';;;>>>''!!!{{{{__<11%4",
+"45-!!'>>>''!!!{{{{_<|11)64",
+"447+!{{___<<<||||1111|+444",
+"444489~__<<<||||111>$04444"};
+
+static char * sbgripup_xpm[] = {
+"26 34 38 1",
+" c None",
+". c #E7E7E7",
+"+ c #D6DBD6",
+"@ c #C6C7C6",
+"# c #B5B6B5",
+"$ c #ADAEAD",
+"% c #ADAAAD",
+"& c #A5A6A5",
+"* c #A5A2A5",
+"= c #BDBEBD",
+"- c #DEDFDE",
+"; c #C6CBC6",
+"> c #9C9E9C",
+", c #E7E3E7",
+"' c #BDBABD",
+") c #B5B2B5",
+"! c #9C9A9C",
+"~ c #DEE3DE",
+"{ c #949694",
+"] c #D6D7D6",
+"^ c #949294",
+"/ c #DEDBDE",
+"( c #8C8E8C",
+"_ c #8C8A8C",
+": c #848684",
+"< c #D6D3CE",
+"[ c #CECBCE",
+"} c #D6D3D6",
+"| c #848284",
+"1 c #313031",
+"2 c #7B7D7B",
+"3 c #CECFCE",
+"4 c #CECBC6",
+"5 c #7B797B",
+"6 c #737573",
+"7 c #737173",
+"8 c #6B6D6B",
+"9 c #6B696B",
+"....+@#$$%%%%&&&***$=-....",
+"...;$$$$$%%%&&&&**>>>>@...",
+".,'$$)#'#####)))$$$%*!!$~.",
+".=$)#'''####))))$$$%%*!{'.",
+"]$$''''#####)))$$$%%%&*{^/",
+"=$#'''#####)))$$$$%%&&&!^#",
+"$$'''#####))))$$$%%%&&*>(!",
+"$$''#####))))$$$%%%&&&*>(^",
+"$$######))))$$$$%%&&&**>(_",
+"%$#####))))$$$$%%%&&***>__",
+"%$####))))$$$$%%%&&&**>>__",
+"%%###)))))$$$%%%&&&**>>>_:",
+"%%##))))<])$$%[[&&***>>!::",
+"%%#)))))<]$$%%}<&&**>>!!:|",
+"&%)))))$$$11%%&&11*>>>!!:|",
+"&&))))$$$$11%&&&11*>>!!{||",
+"&&)))$$$$$%%%&&&**>>!!!{|2",
+"&&))$$$$$%%%&&&**>>>!!{{|2",
+"*&)$$$$$3]%&&&4@*>>!!{{{22",
+"**$$$$$%3]%&&&<<>>!!!{{^25",
+"**$$$$%%%%11&**>11!!{{^^25",
+"**$$$%%%%&11***>11!!{{^^55",
+"**$$%%%%&&&***>>!!!{{^^(55",
+">>$%%%%&&&***>>>!!{{^^((56",
+">>%%%%&&&&***>>!!!{{^^((66",
+">>%%%&&&&***>>!!!{{^^((_67",
+"!>%%&&&&***>>>!!{{{^^(__67",
+"!!%&&&&***>>>!!!{{^^((_:77",
+"!!&&&&***>>>!!!{{^^((__:77",
+"!!&&&****>>!!!{{^^^(__::78",
+"{!&&****>>>!!{{{^^((_::|88",
+"{{&****>>>!!!{{^^((__:||88",
+"{{****>>>!!!{{^^^(__::|289",
+"{{***>>>!!!{{{^^((_::||289"};
+
+static char * sbgripmiddle_xpm[] = {
+"26 2 12 1",
+" c None",
+". c #949294",
+"+ c #A5A2A5",
+"@ c #9C9E9C",
+"# c #9C9A9C",
+"$ c #949694",
+"% c #8C8E8C",
+"& c #8C8A8C",
+"* c #848684",
+"= c #848284",
+"- c #7B7D7B",
+"; c #6B696B",
+"..++@@@###$$$..%%&&*==--;;",
+"..++@@@###$$$..%%&&*==--;;"};
+
+
+static char * listviewhighmiddle_xpm[] = {
+"8 46 197 2",
+" c None",
+". c #66759E",
+"+ c #6C789D",
+"@ c #6A789E",
+"# c #6B789E",
+"$ c #6A779D",
+"% c #6C789C",
+"& c #6F7D9B",
+"* c #6F7D9A",
+"= c #9DB6EE",
+"- c #9DB6ED",
+"; c #9CB6ED",
+"> c #A1B6EF",
+", c #A2B6F0",
+"' c #93AAE9",
+") c #95ABEA",
+"! c #94ABEA",
+"~ c #94A9E8",
+"{ c #8BA8EA",
+"] c #8BA7EA",
+"^ c #8AA7EA",
+"/ c #8EAAE8",
+"( c #8FAAE8",
+"_ c #88A2E7",
+": c #8CA3E8",
+"< c #8BA3E7",
+"[ c #8BA3E8",
+"} c #8BA2E7",
+"| c #8CA2E7",
+"1 c #8DA2E7",
+"2 c #87A1E8",
+"3 c #87A1E9",
+"4 c #86A0E8",
+"5 c #86A1E7",
+"6 c #87A2E7",
+"7 c #859EE9",
+"8 c #849DE9",
+"9 c #869EE9",
+"0 c #869FE9",
+"a c #7C9BEA",
+"b c #7C9CEA",
+"c c #7B9CEA",
+"d c #7C9BE9",
+"e c #7E9CE9",
+"f c #7B9AEA",
+"g c #7C99E9",
+"h c #7C9AEA",
+"i c #7B9AE8",
+"j c #7A9AEA",
+"k c #7996E1",
+"l c #7C96E4",
+"m c #7B96E3",
+"n c #7B95E3",
+"o c #7E95E5",
+"p c #7E95E6",
+"q c #7292E1",
+"r c #7490DF",
+"s c #7591E0",
+"t c #7590DF",
+"u c #7392E1",
+"v c #6D8CDE",
+"w c #6F8EDD",
+"x c #6E8DDD",
+"y c #6E8DDE",
+"z c #6F8EDE",
+"A c #6E8EDE",
+"B c #718EDD",
+"C c #728EDD",
+"D c #6B89E0",
+"E c #6C89DF",
+"F c #6D89E0",
+"G c #6D89DF",
+"H c #6C88DF",
+"I c #6D88DF",
+"J c #6D86DD",
+"K c #6086E0",
+"L c #6686E0",
+"M c #6586E0",
+"N c #6486E0",
+"O c #6485E0",
+"P c #6786DF",
+"Q c #5F85E0",
+"R c #6583DE",
+"S c #6683DE",
+"T c #6682DD",
+"U c #6086DF",
+"V c #5F86E0",
+"W c #567ED7",
+"X c #567ED8",
+"Y c #557DD7",
+"Z c #5A7FD8",
+"` c #6281DA",
+" . c #5379D9",
+".. c #5278D9",
+"+. c #547BD8",
+"@. c #4C73D7",
+"#. c #4B72D2",
+"$. c #4C73D4",
+"%. c #4C73D3",
+"&. c #4B72D4",
+"*. c #4F75D3",
+"=. c #5074D2",
+"-. c #4971D0",
+";. c #4871D0",
+">. c #335ECF",
+",. c #325ECB",
+"'. c #335ECD",
+"). c #335ECE",
+"!. c #325DCD",
+"~. c #2E59C9",
+"{. c #3059C9",
+"]. c #2F59C9",
+"^. c #2F59C8",
+"/. c #2B59CA",
+"(. c #3355C6",
+"_. c #3354C5",
+":. c #3156C7",
+"<. c #3056C7",
+"[. c #3355C7",
+"}. c #3355C5",
+"|. c #254EBF",
+"1. c #1F51C1",
+"2. c #234FC0",
+"3. c #234FBF",
+"4. c #2350C0",
+"5. c #1E50BE",
+"6. c #1D50C0",
+"7. c #264DBE",
+"8. c #264CBD",
+"9. c #254DBE",
+"0. c #244EBF",
+"a. c #254DBF",
+"b. c #234CBF",
+"c. c #244CC0",
+"d. c #244BC0",
+"e. c #234BC0",
+"f. c #234BBF",
+"g. c #234CBE",
+"h. c #2049B7",
+"i. c #2A49B5",
+"j. c #2749B5",
+"k. c #2749B6",
+"l. c #2D49B4",
+"m. c #2649B6",
+"n. c #2946B5",
+"o. c #2A48B6",
+"p. c #2947B5",
+"q. c #2946B6",
+"r. c #2848B6",
+"s. c #2549B5",
+"t. c #2648B6",
+"u. c #2744B5",
+"v. c #2744B4",
+"w. c #2744AF",
+"x. c #2543B4",
+"y. c #2543B2",
+"z. c #2442B2",
+"A. c #2442B3",
+"B. c #2442B5",
+"C. c #2543B3",
+"D. c #1F40B1",
+"E. c #1E40B1",
+"F. c #243EAE",
+"G. c #273BAC",
+"H. c #263DAC",
+"I. c #253CAB",
+"J. c #273CAB",
+"K. c #273CAC",
+"L. c #263BAA",
+"M. c #253CAE",
+"N. c #263BA6",
+"O. c #253BA5",
+"P. c #253AA5",
+"Q. c #253BA6",
+"R. c #253CA7",
+"S. c #263AA6",
+"T. c #243CA6",
+"U. c #253CA5",
+"V. c #273BA8",
+"W. c #2F4DA4",
+"X. c #2F4DA3",
+"Y. c #1B2F85",
+"Z. c #B5B5B6",
+"`. c #B5B5B5",
+" + c #B5B6B6",
+".+ c #B5B4B6",
+"++ c #C2C3C5",
+"@+ c #C0C3C3",
+"#+ c #C1C3C4",
+"$+ c #E3E3E3",
+"%+ c #E3E3E4",
+"&+ c #E4E3E4",
+"*+ c #E2E3E4",
+"=+ c #ECEEEB",
+"-+ c #EBEDEA",
+";+ c #EEF0ED",
+">+ c #EFF0EE",
+". + @ @ # # $ % ",
+"& & * & & & & & ",
+"= = - = = ; > , ",
+"' ) ! ! ! ) ' ~ ",
+"{ ] { { { ^ / ( ",
+"_ : < [ : } | 1 ",
+"2 2 2 3 2 4 5 6 ",
+"7 7 7 7 7 8 9 0 ",
+"a b a a a c d e ",
+"f g h h h h i j ",
+"k l m m m n o p ",
+"q q q q q q q q ",
+"r r s s s t q u ",
+"v w x y z A B C ",
+"D E F F G F H I ",
+"J K L M N O P Q ",
+"R R S S S T U V ",
+"W W X X X Y Z ` ",
+" . . . . ...+.W ",
+" . . . . ..... .",
+"@.#.$.$.%.&.*.=.",
+"-.-.;.-.-.-.-.-.",
+">.,.'.).).!.!.>.",
+"~.{.].^.].^././.",
+"(.(.(.(.(._.:.<.",
+"(.(.[.[.[.[.(.}.",
+"|.1.2.3.3.4.5.6.",
+"7.7.7.7.7.8.9.0.",
+"a.b.c.d.c.e.f.g.",
+"h.i.j.k.j.k.l.m.",
+"n.o.p.q.r.p.s.t.",
+"u.u.v.u.u.u.u.u.",
+"w.x.y.z.A.y.B.C.",
+"D.D.E.D.D.D.D.D.",
+"D.D.E.D.D.D.D.D.",
+"F.G.H.I.J.K.L.M.",
+"N.N.O.N.N.P.Q.R.",
+"N.N.S.N.N.N.N.N.",
+"T.N.T.T.T.U.N.V.",
+"W.W.X.W.W.W.W.W.",
+"W.W.W.W.W.W.W.W.",
+"Y.Y.Y.Y.Y.Y.Y.Y.",
+"Z.`. + +.+Z.`.`.",
+"++@+#+#+#+#+@+@+",
+"$+%+&+&+*+%+%+%+",
+"=+-+;+-+-+>+-+-+"};
+
+
+
+static char * listviewhighcornerleft_xpm[] = {
+"100 46 1475 2",
+" c None",
+". c #FBFBFC",
+"+ c #E8EAE7",
+"@ c #758DC3",
+"# c #42599E",
+"$ c #28418A",
+"% c #19418F",
+"& c #3F5695",
+"* c #415896",
+"= c #435A98",
+"- c #445C99",
+"; c #465E9B",
+"> c #48609B",
+", c #49629C",
+"' c #4A639D",
+") c #49639D",
+"! c #4A629D",
+"~ c #4B639D",
+"{ c #4B649D",
+"] c #4C659D",
+"^ c #4D669D",
+"/ c #4E689D",
+"( c #506A9D",
+"_ c #516A9D",
+": c #536B9C",
+"< c #546C9C",
+"[ c #566D9B",
+"} c #576D9B",
+"| c #586E9C",
+"1 c #5B6F9D",
+"2 c #61739D",
+"3 c #63749E",
+"4 c #64749E",
+"5 c #68769E",
+"6 c #6A779E",
+"7 c #6B789E",
+"8 c #66759E",
+"9 c #6C789D",
+"0 c #EEF0ED",
+"a c #D0D3DC",
+"b c #3E51A3",
+"c c #28428B",
+"d c #29428C",
+"e c #425996",
+"f c #455C99",
+"g c #485F9C",
+"h c #49619E",
+"i c #4A63A0",
+"j c #4B64A1",
+"k c #4B65A1",
+"l c #4C66A2",
+"m c #4D67A2",
+"n c #4F69A1",
+"o c #516AA1",
+"p c #536CA0",
+"q c #556DA1",
+"r c #576EA0",
+"s c #586F9F",
+"t c #586E9F",
+"u c #596F9E",
+"v c #5A6F9E",
+"w c #5C709E",
+"x c #5E719E",
+"y c #5F729F",
+"z c #62739F",
+"A c #63739E",
+"B c #64749D",
+"C c #65749E",
+"D c #69769D",
+"E c #6C799E",
+"F c #6D799F",
+"G c #707D9F",
+"H c #717F9E",
+"I c #6E7AA1",
+"J c #6C789E",
+"K c #6F7C9C",
+"L c #6F7D9B",
+"M c #2A4AA0",
+"N c #4971D0",
+"O c #4C72D8",
+"P c #5472C0",
+"Q c #5573BF",
+"R c #5774BF",
+"S c #5875BF",
+"T c #5976C1",
+"U c #5A76C1",
+"V c #5C78C2",
+"W c #5E7AC2",
+"X c #607CC3",
+"Y c #627EC3",
+"Z c #637FC4",
+"` c #6581C5",
+" . c #6682C6",
+".. c #6783C7",
+"+. c #6984C8",
+"@. c #6B85C9",
+"#. c #6D87CA",
+"$. c #6F89CB",
+"%. c #718CCD",
+"&. c #748ECF",
+"*. c #7690D0",
+"=. c #7992D2",
+"-. c #7A93D3",
+";. c #7C95D5",
+">. c #7F98D7",
+",. c #8099D8",
+"'. c #859CDB",
+"). c #8AA0DD",
+"!. c #8DA3DF",
+"~. c #8FA5E0",
+"{. c #90A5E0",
+"]. c #91A6E1",
+"^. c #91A5E1",
+"/. c #90A4E0",
+"(. c #8EA3DE",
+"_. c #92A6E2",
+":. c #8FA4DF",
+"<. c #90A5DE",
+"[. c #90A5DC",
+"}. c #90A6DB",
+"|. c #91A6E0",
+"1. c #93A7E2",
+"2. c #95AAE6",
+"3. c #99AEEA",
+"4. c #9AB2EA",
+"5. c #99B1E9",
+"6. c #99B1E7",
+"7. c #98AFE6",
+"8. c #93A8E2",
+"9. c #97ACE7",
+"0. c #9AB3EB",
+"a. c #9DB5ED",
+"b. c #9DB6EE",
+"c. c #375095",
+"d. c #4056AD",
+"e. c #506DCD",
+"f. c #4360CC",
+"g. c #345ED6",
+"h. c #335ECF",
+"i. c #355ED6",
+"j. c #355FD6",
+"k. c #365FD6",
+"l. c #355FD0",
+"m. c #3760D5",
+"n. c #3A63D4",
+"o. c #3C63D1",
+"p. c #3B63CD",
+"q. c #3B63C9",
+"r. c #3B62C9",
+"s. c #3D63C8",
+"t. c #4065C5",
+"u. c #4567C5",
+"v. c #496BC5",
+"w. c #4F70C7",
+"x. c #5273C8",
+"y. c #5475CA",
+"z. c #5777CB",
+"A. c #5879CD",
+"B. c #5A7BCE",
+"C. c #5D7DCF",
+"D. c #5F7ECF",
+"E. c #617FD0",
+"F. c #6381D1",
+"G. c #6583D2",
+"H. c #6785D2",
+"I. c #6886D3",
+"J. c #6A88D4",
+"K. c #6C89D5",
+"L. c #6E8BD6",
+"M. c #708CD7",
+"N. c #718DD8",
+"O. c #738EDA",
+"P. c #748FDB",
+"Q. c #7691DC",
+"R. c #7893DD",
+"S. c #7994DD",
+"T. c #7A96DE",
+"U. c #7B97DF",
+"V. c #7C98E0",
+"W. c #7E9AE2",
+"X. c #7F9BE3",
+"Y. c #829DE4",
+"Z. c #849FE5",
+"`. c #87A0E6",
+" + c #88A1E7",
+".+ c #89A2E6",
+"++ c #8CA3E7",
+"@+ c #8EA5E9",
+"#+ c #8EA6E9",
+"$+ c #8FA7E9",
+"%+ c #8FA8E8",
+"&+ c #8FA9E8",
+"*+ c #91A9E8",
+"=+ c #90A7E8",
+"-+ c #8FA8EA",
+";+ c #90AAEA",
+">+ c #93ABEA",
+",+ c #95ABEA",
+"'+ c #93ABE9",
+")+ c #94ABEA",
+"!+ c #90A9EA",
+"~+ c #93AAE9",
+"{+ c #273E7E",
+"]+ c #345ED5",
+"^+ c #3D60CE",
+"/+ c #3D60CF",
+"(+ c #345ECF",
+"_+ c #335ED0",
+":+ c #355FD3",
+"<+ c #3A60CE",
+"[+ c #3A5FCB",
+"}+ c #385FC9",
+"|+ c #3B60C8",
+"1+ c #3C63CB",
+"2+ c #3E64CB",
+"3+ c #4166CA",
+"4+ c #4568C9",
+"5+ c #4A6CC7",
+"6+ c #4F71C8",
+"7+ c #5172CA",
+"8+ c #5475CE",
+"9+ c #5678D3",
+"0+ c #597CD6",
+"a+ c #5C7ED7",
+"b+ c #5E7FD8",
+"c+ c #6181D9",
+"d+ c #6383DA",
+"e+ c #6585DA",
+"f+ c #6786DB",
+"g+ c #6988DC",
+"h+ c #6B8ADD",
+"i+ c #6D8BDE",
+"j+ c #6F8DDE",
+"k+ c #718EDF",
+"l+ c #728FE0",
+"m+ c #7390E1",
+"n+ c #7390E2",
+"o+ c #7491E3",
+"p+ c #7592E4",
+"q+ c #7693E4",
+"r+ c #7794E5",
+"s+ c #7894E5",
+"t+ c #7995E6",
+"u+ c #7B96E6",
+"v+ c #7C97E7",
+"w+ c #7D9AE8",
+"x+ c #7F9CE9",
+"y+ c #829DE9",
+"z+ c #849EE9",
+"A+ c #859EE9",
+"B+ c #87A0E7",
+"C+ c #8AA2E7",
+"D+ c #8BA3E8",
+"E+ c #89A2E7",
+"F+ c #8CA6EA",
+"G+ c #8BA6EA",
+"H+ c #8BA7EA",
+"I+ c #8CA3E8",
+"J+ c #8BA8EA",
+"K+ c #8CA7EA",
+"L+ c #8CA8EA",
+"M+ c #4659C7",
+"N+ c #355ECF",
+"O+ c #3660CF",
+"P+ c #3860CE",
+"Q+ c #3961CD",
+"R+ c #3B61CB",
+"S+ c #3B61CA",
+"T+ c #3D62CA",
+"U+ c #3D63CA",
+"V+ c #4165CB",
+"W+ c #456ACB",
+"X+ c #4B6FCD",
+"Y+ c #5174CE",
+"Z+ c #5275D1",
+"`+ c #5477D4",
+" @ c #5678D9",
+".@ c #587ADB",
+"+@ c #597BDB",
+"@@ c #5B7DDC",
+"#@ c #5E7FDC",
+"$@ c #6081DD",
+"%@ c #6283DE",
+"&@ c #6484DF",
+"*@ c #6787E0",
+"=@ c #6989E1",
+"-@ c #6B8BE1",
+";@ c #6D8DE2",
+">@ c #6F8EE3",
+",@ c #718FE4",
+"'@ c #7290E4",
+")@ c #7491E5",
+"!@ c #7692E6",
+"~@ c #7793E5",
+"{@ c #7894E6",
+"]@ c #7895E7",
+"^@ c #7996E8",
+"/@ c #7A97E8",
+"(@ c #7B98E9",
+"_@ c #7D99E8",
+":@ c #7F9AE8",
+"<@ c #7F9BE9",
+"[@ c #7F9CEA",
+"}@ c #859EE8",
+"|@ c #859FE8",
+"1@ c #85A0E9",
+"2@ c #869FE9",
+"3@ c #86A1E7",
+"4@ c #86A0E9",
+"5@ c #87A1E7",
+"6@ c #88A2E7",
+"7@ c #87A1E9",
+"8@ c #5A6FCA",
+"9@ c #365FCF",
+"0@ c #345ED0",
+"a@ c #385FCC",
+"b@ c #385FCE",
+"c@ c #3A61CC",
+"d@ c #3B62CD",
+"e@ c #3E64CD",
+"f@ c #4167CF",
+"g@ c #4469CF",
+"h@ c #486CD1",
+"i@ c #4D71D2",
+"j@ c #5175D4",
+"k@ c #5376D6",
+"l@ c #5578DA",
+"m@ c #5679DC",
+"n@ c #587BDD",
+"o@ c #5A7DDE",
+"p@ c #5D80DE",
+"q@ c #5F82DF",
+"r@ c #6284DF",
+"s@ c #6585E0",
+"t@ c #6787E1",
+"u@ c #6988E2",
+"v@ c #6B8AE2",
+"w@ c #6D8CE3",
+"x@ c #6E8DE3",
+"y@ c #708EE4",
+"z@ c #718FE3",
+"A@ c #7391E4",
+"B@ c #7592E5",
+"C@ c #7895E5",
+"D@ c #7996E6",
+"E@ c #7A97E6",
+"F@ c #7B98E7",
+"G@ c #7A98E8",
+"H@ c #7B99E9",
+"I@ c #7E9AE9",
+"J@ c #7D9AE9",
+"K@ c #7E9AEA",
+"L@ c #809CE9",
+"M@ c #819DE8",
+"N@ c #7F9BEA",
+"O@ c #819DE9",
+"P@ c #819CE9",
+"Q@ c #839EE9",
+"R@ c #839EE8",
+"S@ c #839DEA",
+"T@ c #859FE9",
+"U@ c #87A0E8",
+"V@ c #86A0E8",
+"W@ c #87A1E8",
+"X@ c #3760CF",
+"Y@ c #3A61CE",
+"Z@ c #3A62CD",
+"`@ c #3F66CE",
+" # c #4368D0",
+".# c #466CD2",
+"+# c #496DD5",
+"@# c #4E72D6",
+"## c #5175D8",
+"$# c #5276DA",
+"%# c #5578DC",
+"&# c #577ADC",
+"*# c #597CDD",
+"=# c #5B7DDD",
+"-# c #5D7FDE",
+";# c #5E81DE",
+"># c #6183DF",
+",# c #6386DF",
+"'# c #6687E0",
+")# c #6888E0",
+"!# c #6A89E1",
+"~# c #6C8AE1",
+"{# c #6E8CE2",
+"]# c #6F8DE2",
+"^# c #7390E4",
+"/# c #7390E3",
+"(# c #7491E4",
+"_# c #7693E5",
+":# c #7895E6",
+"<# c #7896E6",
+"[# c #7997E7",
+"}# c #7B97E7",
+"|# c #7B98E8",
+"1# c #7C98E8",
+"2# c #7E9BE9",
+"3# c #809CEA",
+"4# c #819CEA",
+"5# c #839DE9",
+"6# c #365FD0",
+"7# c #3660D0",
+"8# c #3961CF",
+"9# c #3B63CF",
+"0# c #3D64D0",
+"a# c #4067D0",
+"b# c #4469D2",
+"c# c #466BD3",
+"d# c #496ED5",
+"e# c #4C71D6",
+"f# c #4E72D8",
+"g# c #5074D9",
+"h# c #5376DB",
+"i# c #5578DB",
+"j# c #587ADC",
+"k# c #5B7CDC",
+"l# c #5D7EDD",
+"m# c #5F80DD",
+"n# c #6081DE",
+"o# c #6383DE",
+"p# c #6686DF",
+"q# c #6887E0",
+"r# c #6988E0",
+"s# c #6B89E1",
+"t# c #6C8AE0",
+"u# c #6E8CE1",
+"v# c #708EE2",
+"w# c #718FE2",
+"x# c #7290E3",
+"y# c #7391E2",
+"z# c #7492E1",
+"A# c #7592E2",
+"B# c #7691E3",
+"C# c #7591E3",
+"D# c #7692E3",
+"E# c #7693E3",
+"F# c #7793E4",
+"G# c #7893E4",
+"H# c #7994E5",
+"I# c #7D97E8",
+"J# c #7E98E8",
+"K# c #7D98E8",
+"L# c #7D99E9",
+"M# c #7D9BEA",
+"N# c #7D9CEA",
+"O# c #7E99E8",
+"P# c #7D9AEA",
+"Q# c #7C9BEA",
+"R# c #7C9CEA",
+"S# c #355FCF",
+"T# c #3860D0",
+"U# c #3A62D0",
+"V# c #3C64D1",
+"W# c #4167D1",
+"X# c #4369D3",
+"Y# c #466BD4",
+"Z# c #486DD5",
+"`# c #4A6ED7",
+" $ c #4C70D8",
+".$ c #5478D9",
+"+$ c #577BDA",
+"@$ c #597DDB",
+"#$ c #5B7EDB",
+"$$ c #5D7FDC",
+"%$ c #6182DE",
+"&$ c #6284DE",
+"*$ c #6485DF",
+"=$ c #6586DF",
+"-$ c #6787DF",
+";$ c #6888DF",
+">$ c #6A8ADF",
+",$ c #6C8BE0",
+"'$ c #6D8CE0",
+")$ c #6E8DE1",
+"!$ c #6F8DE1",
+"~$ c #708EE1",
+"{$ c #718FE0",
+"]$ c #728FE1",
+"^$ c #7390E0",
+"/$ c #738FE0",
+"($ c #7490E1",
+"_$ c #7590E1",
+":$ c #7591E1",
+"<$ c #7592E1",
+"[$ c #7692E2",
+"}$ c #7794E2",
+"|$ c #7894E3",
+"1$ c #7996E3",
+"2$ c #7A96E5",
+"3$ c #7B98E6",
+"4$ c #7B9AE8",
+"5$ c #7C99E8",
+"6$ c #7C96E5",
+"7$ c #7D97E7",
+"8$ c #7C99E9",
+"9$ c #7B9AE9",
+"0$ c #7B9AEA",
+"a$ c #5B6DCF",
+"b$ c #305EC8",
+"c$ c #335ECE",
+"d$ c #305ECA",
+"e$ c #345FCF",
+"f$ c #3761D0",
+"g$ c #3A62D1",
+"h$ c #3C64D2",
+"i$ c #4066D3",
+"j$ c #466BD5",
+"k$ c #486ED6",
+"l$ c #4A6ED6",
+"m$ c #4D71D8",
+"n$ c #4F72D9",
+"o$ c #5073D9",
+"p$ c #4F72D8",
+"q$ c #5074D8",
+"r$ c #5276D9",
+"s$ c #587ADA",
+"t$ c #5B7CDB",
+"u$ c #5D7EDC",
+"v$ c #5F7FDD",
+"w$ c #6081DC",
+"x$ c #6182DD",
+"y$ c #6283DD",
+"z$ c #6484DE",
+"A$ c #6585DD",
+"B$ c #6787DE",
+"C$ c #6988DF",
+"D$ c #6A89DE",
+"E$ c #6C8ADF",
+"F$ c #6D8BDF",
+"G$ c #6E8CE0",
+"H$ c #6F8DE0",
+"I$ c #718EE0",
+"J$ c #728FDF",
+"K$ c #728FDE",
+"L$ c #7290E0",
+"M$ c #7190E0",
+"N$ c #7291E0",
+"O$ c #7191E0",
+"P$ c #7392E1",
+"Q$ c #7493E1",
+"R$ c #7594E1",
+"S$ c #7594E2",
+"T$ c #7694E2",
+"U$ c #7695E2",
+"V$ c #7A96E4",
+"W$ c #7895E2",
+"X$ c #7A96E2",
+"Y$ c #7A96E3",
+"Z$ c #7B96E3",
+"`$ c #7996E1",
+" % c #7C96E4",
+".% c #305EC9",
+"+% c #315ECC",
+"@% c #325ECE",
+"#% c #3760D0",
+"$% c #3962D1",
+"%% c #3E66D3",
+"&% c #4268D4",
+"*% c #446BD5",
+"=% c #476CD6",
+"-% c #496ED7",
+";% c #4B6FD7",
+">% c #4C70D7",
+",% c #4E71D7",
+"'% c #5074D7",
+")% c #5276D8",
+"!% c #5376D8",
+"~% c #5779DA",
+"{% c #597ADA",
+"]% c #5A7BDB",
+"^% c #5B7CDA",
+"/% c #5D7EDB",
+"(% c #5E7FDB",
+"_% c #6182DB",
+":% c #6384DC",
+"<% c #6586DD",
+"[% c #6686DC",
+"}% c #6887DD",
+"|% c #6988DD",
+"1% c #6A8ADE",
+"2% c #6B8BDE",
+"3% c #6C8CDE",
+"4% c #6E8DDF",
+"5% c #6E8CDF",
+"6% c #6D8DDF",
+"7% c #6C8BDF",
+"8% c #6F8DDF",
+"9% c #718FDF",
+"0% c #7290DF",
+"a% c #7391E0",
+"b% c #7491E0",
+"c% c #7292E1",
+"d% c #3959C5",
+"e% c #345BC5",
+"f% c #315EC8",
+"g% c #355BC5",
+"h% c #325EC8",
+"i% c #315ECB",
+"j% c #345DCC",
+"k% c #335ECD",
+"l% c #345ECD",
+"m% c #355FCE",
+"n% c #3862D0",
+"o% c #3E66D2",
+"p% c #456BD5",
+"q% c #476CD5",
+"r% c #4B6ED7",
+"s% c #4B6FD6",
+"t% c #4B6FD5",
+"u% c #4D71D6",
+"v% c #5073D7",
+"w% c #5174D7",
+"x% c #5275D8",
+"y% c #5577D8",
+"z% c #5678D8",
+"A% c #5779D9",
+"B% c #587AD8",
+"C% c #597CD9",
+"D% c #5B7DD9",
+"E% c #5D7FDA",
+"F% c #5F80DB",
+"G% c #6182DC",
+"H% c #6484DC",
+"I% c #6585DC",
+"J% c #6787DD",
+"K% c #6988DE",
+"L% c #6B8ADE",
+"M% c #6B8ADF",
+"N% c #6989DE",
+"O% c #6B89DE",
+"P% c #6E8BDF",
+"Q% c #708CDE",
+"R% c #708DDF",
+"S% c #708FDF",
+"T% c #728EDF",
+"U% c #6F8EDD",
+"V% c #728EDD",
+"W% c #7390DF",
+"X% c #7490DF",
+"Y% c #335DC8",
+"Z% c #3759C5",
+"`% c #3859C5",
+" & c #335EC8",
+".& c #325DCA",
+"+& c #345CCB",
+"@& c #335DCC",
+"#& c #345DCD",
+"$& c #355FCD",
+"%& c #3861D0",
+"&& c #3B64D1",
+"*& c #3E65D2",
+"=& c #4168D3",
+"-& c #456AD5",
+";& c #4B6ED5",
+">& c #4C6FD4",
+",& c #4D70D5",
+"'& c #4F72D6",
+")& c #5173D6",
+"!& c #5375D7",
+"~& c #5476D8",
+"{& c #5577D7",
+"]& c #5477D8",
+"^& c #5677D8",
+"/& c #5879D9",
+"(& c #597AD9",
+"_& c #5C7DDA",
+":& c #6080DC",
+"<& c #6080DB",
+"[& c #6181DC",
+"}& c #6282DC",
+"|& c #6383DD",
+"1& c #6484DD",
+"2& c #6686DE",
+"3& c #6685DE",
+"4& c #6786DE",
+"5& c #6687DE",
+"6& c #6887DE",
+"7& c #6987DE",
+"8& c #6788DF",
+"9& c #6785DF",
+"0& c #6B89DF",
+"a& c #6C89DF",
+"b& c #6F8DDD",
+"c& c #6D8CDE",
+"d& c #445BBB",
+"e& c #3759BE",
+"f& c #375AC6",
+"g& c #355CC8",
+"h& c #345CCA",
+"i& c #355ECC",
+"j& c #365FCD",
+"k& c #3761CE",
+"l& c #3A63D0",
+"m& c #3D65D1",
+"n& c #466AD4",
+"o& c #476BD4",
+"p& c #486CD3",
+"q& c #4A6ED4",
+"r& c #4B6ED4",
+"s& c #4E71D6",
+"t& c #4F71D5",
+"u& c #5072D6",
+"v& c #5274D7",
+"w& c #5273D7",
+"x& c #5274D6",
+"y& c #5476D7",
+"z& c #5779D8",
+"A& c #587AD9",
+"B& c #5A7CDA",
+"C& c #5C7DDB",
+"D& c #5D7EDA",
+"E& c #6081DA",
+"F& c #6181DB",
+"G& c #6283DC",
+"H& c #6483DD",
+"I& c #6483DE",
+"J& c #6585DE",
+"K& c #6786DF",
+"L& c #6886DE",
+"M& c #6887DF",
+"N& c #6987DF",
+"O& c #6A88DF",
+"P& c #6786E0",
+"Q& c #6A86DE",
+"R& c #6B89E0",
+"S& c #365BC8",
+"T& c #365CC8",
+"U& c #375DCA",
+"V& c #375FCB",
+"W& c #3860CD",
+"X& c #3C63D0",
+"Y& c #4167D2",
+"Z& c #4268D2",
+"`& c #4368D2",
+" * c #4367D2",
+".* c #4568D2",
+"+* c #466AD2",
+"@* c #496CD3",
+"#* c #4A6DD3",
+"$* c #4A6DD4",
+"%* c #4D70D4",
+"&* c #4F72D5",
+"** c #4C70D4",
+"=* c #4E72D5",
+"-* c #5173D5",
+";* c #5375D6",
+">* c #597BDA",
+",* c #5B7DDA",
+"'* c #5C7EDB",
+")* c #5D7FDB",
+"!* c #5E80DB",
+"~* c #5E81DA",
+"{* c #5F81DB",
+"]* c #5F82DB",
+"^* c #6384DD",
+"/* c #6384DE",
+"(* c #6585DF",
+"_* c #6486E0",
+":* c #6583DD",
+"<* c #6386E0",
+"[* c #6686E0",
+"}* c #6B86DD",
+"|* c #6D86DD",
+"1* c #6086E0",
+"2* c #5573CD",
+"3* c #3959C3",
+"4* c #3959C4",
+"5* c #3759C0",
+"6* c #375BC7",
+"7* c #365CC7",
+"8* c #395FCC",
+"9* c #3B62CE",
+"0* c #3E64D0",
+"a* c #4066D1",
+"b* c #4166D1",
+"c* c #4064CF",
+"d* c #4065CF",
+"e* c #4266D0",
+"f* c #4468D1",
+"g* c #4569D1",
+"h* c #476BD2",
+"i* c #466AD1",
+"j* c #476AD2",
+"k* c #456AD1",
+"l* c #496DD2",
+"m* c #4A6FD3",
+"n* c #496ED2",
+"o* c #4B70D4",
+"p* c #4D71D4",
+"q* c #4E72D4",
+"r* c #5073D4",
+"s* c #5174D5",
+"t* c #5175D5",
+"u* c #5276D6",
+"v* c #5377D6",
+"w* c #5478D7",
+"x* c #5579D7",
+"y* c #567AD8",
+"z* c #577BD9",
+"A* c #597CD8",
+"B* c #5A7DD9",
+"C* c #5A7ED9",
+"D* c #5B7FDA",
+"E* c #5C80DA",
+"F* c #5D80DA",
+"G* c #5E81DB",
+"H* c #5D80DB",
+"I* c #6082DC",
+"J* c #6183DD",
+"K* c #6183DE",
+"L* c #6082DB",
+"M* c #6282DE",
+"N* c #6682DE",
+"O* c #6583DE",
+"P* c #3759BF",
+"Q* c #375AC2",
+"R* c #375AC1",
+"S* c #375AC4",
+"T* c #395DCA",
+"U* c #3A5ECA",
+"V* c #3C60CC",
+"W* c #3D61CD",
+"X* c #3D61CC",
+"Y* c #3C61CD",
+"Z* c #3E62CD",
+"`* c #3F64CE",
+" = c #4266CF",
+".= c #4468D0",
+"+= c #4267CF",
+"@= c #4166CE",
+"#= c #4065CE",
+"$= c #4166CD",
+"%= c #4267CE",
+"&= c #456AD0",
+"*= c #4368CE",
+"== c #4468CF",
+"-= c #4569D0",
+";= c #486BD1",
+">= c #4B6FD3",
+",= c #4C70D3",
+"'= c #4F73D4",
+")= c #5275D5",
+"!= c #5477D6",
+"~= c #577BD7",
+"{= c #587CD8",
+"]= c #577CD8",
+"^= c #597DD9",
+"/= c #5A7DDA",
+"(= c #597DDA",
+"_= c #587CDA",
+":= c #5A7EDA",
+"<= c #567BD8",
+"[= c #557AD9",
+"}= c #567BD9",
+"|= c #577CD9",
+"1= c #587DD9",
+"2= c #587ED9",
+"3= c #577ED8",
+"4= c #587DD8",
+"5= c #587ED8",
+"6= c #567ED7",
+"7= c #526ABD",
+"8= c #3759C1",
+"9= c #385BC7",
+"0= c #395CC8",
+"a= c #3B5DC9",
+"b= c #3B5ECA",
+"c= c #3A5FCA",
+"d= c #3B60CC",
+"e= c #3C61CC",
+"f= c #3D62CD",
+"g= c #3E63CD",
+"h= c #3C61CB",
+"i= c #3C61CA",
+"j= c #3D62CB",
+"k= c #3F64CC",
+"l= c #4065CD",
+"m= c #4669D0",
+"n= c #476AD0",
+"o= c #496BD1",
+"p= c #4A6DD2",
+"q= c #4B6ED2",
+"r= c #4D71D3",
+"s= c #4E73D4",
+"t= c #4F74D4",
+"u= c #5075D5",
+"v= c #5276D5",
+"w= c #5377D7",
+"x= c #5278D7",
+"y= c #5277D6",
+"z= c #5378D7",
+"A= c #5379D8",
+"B= c #5379D9",
+"C= c #5278D8",
+"D= c #5178D7",
+"E= c #3355C0",
+"F= c #3556C1",
+"G= c #395AC6",
+"H= c #385AC7",
+"I= c #395BC7",
+"J= c #395EC9",
+"K= c #395FCA",
+"L= c #3B60CA",
+"M= c #3B60CB",
+"N= c #375DC7",
+"O= c #385EC8",
+"P= c #395FC9",
+"Q= c #3A60CA",
+"R= c #3D63CC",
+"S= c #4367CF",
+"T= c #476BD1",
+"U= c #4A6ED2",
+"V= c #4B6FD2",
+"W= c #4C6FD2",
+"X= c #4D70D1",
+"Y= c #4E71D2",
+"Z= c #4E72D2",
+"`= c #4E74D4",
+" - c #4E75D5",
+".- c #4E75D4",
+"+- c #4F75D3",
+"@- c #5075D2",
+"#- c #5075D3",
+"$- c #5177D7",
+"%- c #5178D8",
+"&- c #4F75D5",
+"*- c #5076D5",
+"=- c #4F76D6",
+"-- c #5279D9",
+";- c #3C52B1",
+">- c #3656C3",
+",- c #3757C5",
+"'- c #3758C6",
+")- c #3759C6",
+"!- c #375BC6",
+"~- c #385CC7",
+"{- c #385DC8",
+"]- c #365CC6",
+"^- c #355BC6",
+"/- c #355CC6",
+"(- c #365DC7",
+"_- c #375EC8",
+":- c #375CC6",
+"<- c #385EC6",
+"[- c #3A5FC7",
+"}- c #3C60C8",
+"|- c #3D61C9",
+"1- c #3E62CA",
+"2- c #4063CC",
+"3- c #4165CE",
+"4- c #4268D0",
+"5- c #4269D1",
+"6- c #436AD2",
+"7- c #446AD2",
+"8- c #456BD2",
+"9- c #496CD1",
+"0- c #4C6CD0",
+"a- c #4D6CCF",
+"b- c #4E6DD0",
+"c- c #4F6ECF",
+"d- c #4E6FCF",
+"e- c #4C70CF",
+"f- c #4A71D0",
+"g- c #4F6FCF",
+"h- c #4B71D0",
+"i- c #4A72D1",
+"j- c #4B73D4",
+"k- c #4F70D0",
+"l- c #4C73D3",
+"m- c #4C73D6",
+"n- c #4B72D2",
+"o- c #4B71D1",
+"p- c #4C73D7",
+"q- c #3354C0",
+"r- c #3152BE",
+"s- c #3052BE",
+"t- c #3051BF",
+"u- c #2E4FBF",
+"v- c #2E4FBE",
+"w- c #2E50BF",
+"x- c #2F50BF",
+"y- c #3156C4",
+"z- c #2F56C5",
+"A- c #2E57C5",
+"B- c #2F57C5",
+"C- c #3057C6",
+"D- c #3258C6",
+"E- c #3459C7",
+"F- c #365AC7",
+"G- c #385BC8",
+"H- c #3B5DCA",
+"I- c #3B5DCB",
+"J- c #3C5ECC",
+"K- c #3C60CD",
+"L- c #3C62CE",
+"M- c #3D65D0",
+"N- c #3D66D1",
+"O- c #4166D2",
+"P- c #4667D2",
+"Q- c #4A67D1",
+"R- c #4C68D0",
+"S- c #4C69CF",
+"T- c #4D6BCE",
+"U- c #4E6DCD",
+"V- c #4E6ECE",
+"W- c #4E6DCE",
+"X- c #4970D0",
+"Y- c #4770D0",
+"Z- c #4B6BCE",
+"`- c #4A6CCE",
+" ; c #496DCF",
+".; c #476FD0",
+"+; c #4870D0",
+"@; c #486DCF",
+"#; c #242F79",
+"$; c #2F41AC",
+"%; c #2040B8",
+"&; c #2041B8",
+"*; c #2243B3",
+"=; c #2243B8",
+"-; c #2343B8",
+";; c #2444B8",
+">; c #2445B8",
+",; c #2445B6",
+"'; c #2445B7",
+"); c #2444B9",
+"!; c #2949BE",
+"~; c #2649BF",
+"{; c #234BBF",
+"]; c #224CBF",
+"^; c #224AC0",
+"/; c #244CC0",
+"(; c #254DC0",
+"_; c #254DC1",
+":; c #264DC2",
+"<; c #274EC3",
+"[; c #274CC3",
+"}; c #274DC4",
+"|; c #254DC5",
+"1; c #214EC5",
+"2; c #204FC6",
+"3; c #1F50C8",
+"4; c #2151C9",
+"5; c #2B53C8",
+"6; c #3154C7",
+"7; c #3255C6",
+"8; c #2F57C7",
+"9; c #2C58C9",
+"0; c #2D59CA",
+"a; c #2D58C9",
+"b; c #2E5BCC",
+"c; c #325ECC",
+"d; c #325ECB",
+"e; c #1F40B1",
+"f; c #1F40B2",
+"g; c #1F40B3",
+"h; c #2A44BD",
+"i; c #2845BE",
+"j; c #2745BE",
+"k; c #2646BF",
+"l; c #2546BE",
+"m; c #2347BF",
+"n; c #2147BF",
+"o; c #2048C0",
+"p; c #1D48C0",
+"q; c #1C48C0",
+"r; c #1B47C0",
+"s; c #1C48BF",
+"t; c #1E49BE",
+"u; c #214ABD",
+"v; c #244CBD",
+"w; c #264DBE",
+"x; c #254EC0",
+"y; c #214FC2",
+"z; c #1B51C5",
+"A; c #1C51C7",
+"B; c #2250C8",
+"C; c #2A52C8",
+"D; c #3254C6",
+"E; c #3355C5",
+"F; c #3154C8",
+"G; c #3355C6",
+"H; c #2F57C8",
+"I; c #2E58C9",
+"J; c #2E59C9",
+"K; c #3059C9",
+"L; c #2040B6",
+"M; c #2743BB",
+"N; c #2844BC",
+"O; c #2743BD",
+"P; c #2844BE",
+"Q; c #2844BD",
+"R; c #2346BE",
+"S; c #2047BF",
+"T; c #1E48C0",
+"U; c #1D47C0",
+"V; c #1D49BF",
+"W; c #1F49BF",
+"X; c #204ABE",
+"Y; c #254DBF",
+"Z; c #234EC0",
+"`; c #2050C1",
+" > c #1C51C3",
+".> c #1F51C6",
+"+> c #2651C8",
+"@> c #2D53C7",
+"#> c #3155C6",
+"$> c #3155C7",
+"%> c #3355C7",
+"&> c #3254C7",
+"*> c #1E40B1",
+"=> c #2141B8",
+"-> c #2442B9",
+";> c #2744BB",
+">> c #2945BB",
+",> c #2A45BB",
+"'> c #2944BA",
+")> c #2745BB",
+"!> c #2545BC",
+"~> c #2246BD",
+"{> c #2047BE",
+"]> c #1F47BD",
+"^> c #1D48BE",
+"/> c #1E49C0",
+"(> c #1F4AC0",
+"_> c #214BBF",
+":> c #244CBE",
+"<> c #254DBE",
+"[> c #244DBE",
+"}> c #224FBF",
+"|> c #2051C1",
+"1> c #2151C3",
+"2> c #2252C5",
+"3> c #2151C1",
+"4> c #2851C6",
+"5> c #2A50C6",
+"6> c #2E54C6",
+"7> c #1F51C2",
+"8> c #1D52C5",
+"9> c #2651C9",
+"0> c #2950C7",
+"a> c #2D40A5",
+"b> c #2040B0",
+"c> c #1F40B0",
+"d> c #223CAE",
+"e> c #233CAE",
+"f> c #253BAC",
+"g> c #253BAD",
+"h> c #233CB0",
+"i> c #213EB2",
+"j> c #1F3FB4",
+"k> c #1E40B6",
+"l> c #1F3FB7",
+"m> c #1E3EB8",
+"n> c #1F3FB8",
+"o> c #2040B7",
+"p> c #2141B6",
+"q> c #2140B7",
+"r> c #2241B6",
+"s> c #2342B5",
+"t> c #2442B6",
+"u> c #2543B5",
+"v> c #2643B4",
+"w> c #2544B6",
+"x> c #2346B8",
+"y> c #2247B9",
+"z> c #2048BC",
+"A> c #1F48BF",
+"B> c #2049C0",
+"C> c #214AC0",
+"D> c #224BBF",
+"E> c #234CBE",
+"F> c #244DBF",
+"G> c #234CBF",
+"H> c #264DC0",
+"I> c #274EBF",
+"J> c #264DBF",
+"K> c #254EBF",
+"L> c #2050C0",
+"M> c #1F51C1",
+"N> c #1E42A4",
+"O> c #263BA6",
+"P> c #253BA7",
+"Q> c #253CA7",
+"R> c #1E41A5",
+"S> c #1F40AF",
+"T> c #273AAC",
+"U> c #1E40B0",
+"V> c #1F40B5",
+"W> c #1F40B6",
+"X> c #1F40B8",
+"Y> c #1E40B8",
+"Z> c #1F3EB8",
+"`> c #203FB7",
+" , c #2240B6",
+"., c #2341B7",
+"+, c #2345B9",
+"@, c #2147BB",
+"#, c #2148BA",
+"$, c #2049BB",
+"%, c #2049BD",
+"&, c #2049BF",
+"*, c #224BBE",
+"=, c #244DBD",
+"-, c #244CBF",
+";, c #182969",
+">, c #273BAD",
+",, c #2739AB",
+"', c #263AAC",
+"), c #243CAE",
+"!, c #233DAE",
+"~, c #213EAF",
+"{, c #1F3FB0",
+"], c #2040B4",
+"^, c #1F3FB6",
+"/, c #1E3EB7",
+"(, c #2240B7",
+"_, c #2341B6",
+":, c #2543B4",
+"<, c #2644B3",
+"[, c #2544B5",
+"}, c #2545B5",
+"|, c #2547B6",
+"1, c #2548B7",
+"2, c #2349BA",
+"3, c #1F49BE",
+"4, c #2149BD",
+"5, c #2049BE",
+"6, c #214BBE",
+"7, c #2249BE",
+"8, c #234CBD",
+"9, c #2149BE",
+"0, c #1E49BF",
+"a, c #253BA9",
+"b, c #253BAB",
+"c, c #263AAB",
+"d, c #213DAF",
+"e, c #203EAF",
+"f, c #1D40AF",
+"g, c #1D40B0",
+"h, c #1E40B4",
+"i, c #2241B7",
+"j, c #2643B6",
+"k, c #2744B5",
+"l, c #2643B5",
+"m, c #2346B6",
+"n, c #2147B7",
+"o, c #2644B6",
+"p, c #2247B7",
+"q, c #2248B8",
+"r, c #2647B7",
+"s, c #2549B7",
+"t, c #2645B7",
+"u, c #2148B8",
+"v, c #2847B6",
+"w, c #2549B6",
+"x, c #2849B6",
+"y, c #2049B7",
+"z, c #2A49B5",
+"A, c #243BA4",
+"B, c #253BA5",
+"C, c #253BA6",
+"D, c #263AA7",
+"E, c #263AA8",
+"F, c #2739AA",
+"G, c #243CAD",
+"H, c #223DAE",
+"I, c #1F3EAF",
+"J, c #1E3FB0",
+"K, c #1D40B1",
+"L, c #1E3FB1",
+"M, c #1F3FB3",
+"N, c #1F3FB5",
+"O, c #2140B6",
+"P, c #2140B8",
+"Q, c #2744B4",
+"R, c #2746B6",
+"S, c #2947B6",
+"T, c #2946B5",
+"U, c #2A48B6",
+"V, c #3551A8",
+"W, c #1F399C",
+"X, c #143D9F",
+"Y, c #263BA5",
+"Z, c #273BA8",
+"`, c #273BAA",
+" ' c #263AAD",
+".' c #233CAD",
+"+' c #213DAE",
+"@' c #203FB2",
+"#' c #2342B6",
+"$' c #2443B6",
+"%' c #2543B6",
+"&' c #2644B5",
+"*' c #133D9E",
+"=' c #263BA7",
+"-' c #263BA9",
+";' c #273BA9",
+">' c #263AAA",
+",' c #2539AB",
+"'' c #2639AB",
+")' c #253AAC",
+"!' c #243BAD",
+"~' c #223DAF",
+"{' c #203FB0",
+"]' c #2040B1",
+"^' c #2140B3",
+"/' c #2543B1",
+"(' c #2744AF",
+"_' c #1A3CA0",
+":' c #1D3BA2",
+"<' c #233BA4",
+"[' c #263AA5",
+"}' c #253AA5",
+"|' c #263AA6",
+"1' c #263BA4",
+"2' c #243BA5",
+"3' c #263BA8",
+"4' c #223EAF",
+"5' c #3B4CA5",
+"6' c #1D379A",
+"7' c #1E389C",
+"8' c #1E399F",
+"9' c #1F3BA2",
+"0' c #1F3BA3",
+"a' c #213BA4",
+"b' c #233AA3",
+"c' c #243AA3",
+"d' c #2539A4",
+"e' c #253AA6",
+"f' c #243BA7",
+"g' c #253CAA",
+"h' c #253CAC",
+"i' c #253CAD",
+"j' c #253CAE",
+"k' c #243DAE",
+"l' c #213FAF",
+"m' c #223FAF",
+"n' c #2040AF",
+"o' c #253D93",
+"p' c #1D3894",
+"q' c #1F379A",
+"r' c #1E389B",
+"s' c #1D399C",
+"t' c #1C3A9D",
+"u' c #1B3A9D",
+"v' c #183B9E",
+"w' c #163C9E",
+"x' c #153C9E",
+"y' c #163B9D",
+"z' c #173B9D",
+"A' c #193A9D",
+"B' c #1C3A9E",
+"C' c #1F3AA1",
+"D' c #223AA4",
+"E' c #253BA8",
+"F' c #273BA7",
+"G' c #263CAB",
+"H' c #263CAC",
+"I' c #243EAE",
+"J' c #273BAC",
+"K' c #2A3795",
+"L' c #1F389B",
+"M' c #1D389B",
+"N' c #1C399C",
+"O' c #1B399C",
+"P' c #1A3A9D",
+"Q' c #1D399B",
+"R' c #1B399B",
+"S' c #1A3A9C",
+"T' c #1B3A9F",
+"U' c #1D3AA0",
+"V' c #203BA2",
+"W' c #203BA3",
+"X' c #2639A6",
+"Y' c #1B3692",
+"Z' c #1C3794",
+"`' c #1D3796",
+" ) c #1E3898",
+".) c #1E389A",
+"+) c #1F399B",
+"@) c #1A399C",
+"#) c #193A9E",
+"$) c #1A3BA0",
+"%) c #1C3BA2",
+"&) c #1D3CA3",
+"*) c #203CA4",
+"=) c #223BA5",
+"-) c #3C4699",
+";) c #2B4595",
+">) c #1C3793",
+",) c #1D3895",
+"') c #1E3897",
+")) c #1F3998",
+"!) c #1F3999",
+"~) c #1F399A",
+"{) c #1E399C",
+"]) c #1C3B9E",
+"^) c #1D3BA0",
+"/) c #1E3CA2",
+"() c #223CA5",
+"_) c #243CA6",
+":) c #596FA9",
+"<) c #3B4894",
+"[) c #314993",
+"}) c #29499F",
+"|) c #28489E",
+"1) c #2B4BA1",
+"2) c #2C4BA1",
+"3) c #2D4CA2",
+"4) c #2E4CA3",
+"5) c #2F4CA4",
+"6) c #2E4CA4",
+"7) c #2F4DA3",
+"8) c #2F4DA4",
+"9) c #D3D5D2",
+"0) c #3B4794",
+"a) c #314791",
+"b) c #304892",
+"c) c #304893",
+"d) c #2F4995",
+"e) c #2F4997",
+"f) c #2D4A9A",
+"g) c #2A4A9D",
+"h) c #294A9F",
+"i) c #284AA0",
+"j) c #294AA0",
+"k) c #2B4AA1",
+"l) c #2D4CA3",
+"m) c #C9CAC9",
+"n) c #455D9B",
+"o) c #242F78",
+"p) c #1B2F85",
+"q) c #C6C3C8",
+"r) c #B5B2B6",
+"s) c #B5B7B4",
+"t) c #B5B7B3",
+"u) c #B5B2B5",
+"v) c #B5B3B4",
+"w) c #B5B5B4",
+"x) c #B5B6B3",
+"y) c #B5B4B4",
+"z) c #B5B3B5",
+"A) c #B5B4B5",
+"B) c #B5B5B5",
+"C) c #B5B5B3",
+"D) c #B5B5B6",
+"E) c #BAC3BE",
+"F) c #B9C3BD",
+"G) c #C1C3C4",
+"H) c #BFC3C2",
+"I) c #B9C3BE",
+"J) c #BBC3BF",
+"K) c #BDC3C1",
+"L) c #C0C3C3",
+"M) c #BEC3C1",
+"N) c #C2C3C5",
+"O) c #E6E3E8",
+"P) c #E0E2DF",
+"Q) c #E1E1E1",
+"R) c #E2E1E3",
+"S) c #E4E1E6",
+"T) c #E4E2E7",
+"U) c #E4E2E6",
+"V) c #E3E3E4",
+"W) c #E2E3E3",
+"X) c #E1E3E2",
+"Y) c #E3E3E3",
+"Z) c #E3E3E2",
+"`) c #EBEDEA",
+" ! c #EAECE9",
+".! c #E9EBE8",
+"+! c #ECEEEB",
+". . + @ # $ $ $ $ $ $ $ % $ $ $ $ $ % $ $ $ $ $ $ % $ $ $ $ $ % $ $ $ $ $ $ $ $ $ % $ $ & * = - ; > , , ' ) ! ! ~ { ] ^ / ( _ : < [ } | | 1 2 3 3 4 4 4 4 4 4 4 5 6 4 4 4 5 6 7 8 9 4 5 6 7 8 9 6 7 8 9 ",
+"0 a b % $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ c d d d d $ $ $ $ $ c d e f g h i i i i j k l m n o p q r s t u v w x y z 4 A B C D 9 9 E 9 E F G H I F J K L L L L J K L L L L L L L L ",
+"@ % M N O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O P Q R S T U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.b.b.b.b.b.",
+"c.$ d.O e.f.g.g.g.h.g.g.g.g.g.h.h.g.g.g.g.g.h.h.g.g.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+++@+#+$+@+$+%+&+*+=+$+-+;+>+,+'+)+!+;+>+,+~+,+>+,+~+,+",
+"$ {+N N f.f.f.f.h.h.h.g.f.f.h.h.h.h.g.f.f.h.h.h.h.]+^+/+(+h._+:+<+[+}+|+1+2+3+4+5+6+7+8+9+0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+w+x+y+z+A+B+.+C+D+E+D+F+G+H+C+I+F+G+J+K+L+H+F+G+J+K+L+H+J+H+J+H+",
+"{+{+N N M+M+h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.N+N+h.h.(+O+P+P+Q+R+S+T+U+V+W+X+Y+Z+`+ @.@+@@@#@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@/@(@_@:@<@[@[@y+}@|@1@A+1@2@3@ +2@4@2@5@C+D+6@D+7@5@C+D+6@I+C+D+6@I+",
+"{+{+8@N M+M+h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.9@9@0@N+a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@z@A@B@q+r+C@D@E@F@G@H@_@I@J@K@<@L@M@N@O@P@Q@R@S@T@A+A+U@V@W@W@A+2@U@V@W@W@U@V@W@W@",
+"{+{+8@N f.M+h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.(+(+(+9@9@X@Y@Z@e@`@ #.#+#@###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]#z@^#/#(#p+_#r+:#s+t+<#[#}#|#|#1#_@|#_@_@2#L@3#4#y+y+5#z+z+z+5#z+z+z+z+A+A+A+A+A+",
+"{+{+8@8@f.f.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.(+6#7#8#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#&@p#q#r#s#t#u#v#w#x#x#y#y#z#A#B#C#D#E#E#F#G#H#F#H#H#u+v+I#J#K#L#J@J@M#N#O#P#M#M#M#N#M#Q#Q#R#",
+"$ {+8@e.f.f.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.S#l.7#T#U#V#W#X#Y#Z#`# $f#g###.$+$@$#$$$$@%$&$*$=$-$;$>$,$'$)$!$~$~${$]$^$/$($($_$_$:$<$_$<$[$}$|$|$1$2$2$3$}#4$5$6$7$8$8$9$8$8$8$0$8$",
+"$ {+a$e.f.f.h.h.h.h.h.h.h.h.h.b$h.c$c$c$c$c$d$c$c$c$c$c$c$c$c$c$c$e$e$7#f$g$h$i$X#j$k$l$m$n$o$p$q$r$l@s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$G$H$I$J$J$K$K$J$L$L$L$L$L$M$N$O$P$Q$R$S$T$U$1$V$T$W$X$Y$1$V$Y$Z$`$ %",
+"$ $ a$a$f.f.b$b$b$b$b$b$b$b$b$b$b$b$b$b$b$b$b$b$.%b$b$b$.%d$+%+%@%h.e$l.#%$%h$%%&%*%=%-%;%>%,%'%)%!% @ @~%{%]%^%/%(%w$_%:%<%[%}%|%D$1%2%3%4%5%4%4%6%5%5%4%4%4%5%7%5%8%9%L$0%a%a%a%P$b%P$P$z#z#z#P$c%c%c%",
+"$ $ 8@e.f.f.d%b$b$b$b$b$d%b$b$b$b$b$b$e%f%b$b$b$b$b$g%h%b$.%i%i%j%k%l%m%X@n%h$o%&%p%q%`#r%s%t%u%v%w%x%y% @z%A%B%C%D%E%F%G%:%H%I%[%J%}%K%|%D$K%D$D$L%M%M%M%M%M%D$N%O%i+P%j+Q%R%S%T%0%U%V%W%W%W%W%X%X%X%X%",
+"$ $ 8@8@f.f.d%d%b$b$b$b$d%d%b$b$b$h%Y%Z%Z%h%f%f%h%Y%`%`% &h%h%.&+&@&#&$&X@%&&&*&=&-&j$Z#+#;&>&,&'&)&)&!&~&{&]&^&/&(&^%_&(%:&<&[&}&|&1&A$A$2&3&4&4&5&B$6&7&B$7&8&9&6&7&0&a&a&i+i+i+b&a&a&j+U%c&U%j+U%c&U%",
+"$ $ 8@8@d&e&d%d%d%d%d%d%d%d%d%d%d%`%d%d%d%d%`%`%`%d%d%d%d%`%`%f&g&h&j%i&j&k&l&m&=&X#Y#n&o&p&q&r&>&s&t&t&u&v&w&x&y&{&z&A&B&C&D&(%(%F%F%E&F&}&}&|&G&|&H&1&I%I&A$1&}&z$z$J&K&L&M&N&O&0&P&Q&0&a&R&a&a&a&R&a&",
+"{+$ 8@8@e&e&d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%`%f&S&T&U&V&W&Y@X&Y&Z&`& *.*+*@*#*@*r&$*#*r&%*&***=*-*;*y&z%A%z&A&A&>*B&,*,*'*)*!*!*~*{*F&}&{*}&{*]*G%G%y$^*/*J&(*2&_*:*<*=$[*}*<*=$<*|*1*",
+"{+{+8@2*e&e&d%d%d%d%d%d%d%d%d%e&3*4*4*4*4*4*5*4*4*4*4*4*4*4*4*4*`%f&6*6*7*8*9*0*a*b*c*d*e*f*g*h*i*j*+*k*h*l*m*n*m*o*p*q*r*s*t*u*v*w*x*y*y*z*A*B*C*D*E*F*G*E*G*F*H*G*F*~*]*{*I*x$J*K*L*G%K*M*o#o#I&N*O*O*",
+"{+{+8@2*e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&P*e&e&e&e&e&e&P*P*e&e&e&P*P*5*Q*R*S*T*U*V*W*X*Y*Z*`*d* =.=+=@=#=$=%=g@&=*===-=i*;=l*>=,=q*'=s*)=k@!=x*~={=]=^=/=(=_=:=(=<=<=]=[=}=|=]=]=1=2=3=|=4=5=2=2=2=3=6=6=6=",
+"{+{+7=e.e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&e&P*P*8=9=0=a=b=U*c=d=e=f=e@#=g=h=i=i=j=k=k=l=%===m=n=o=p=q=,=r=s=t=u=v=v*w=x=x=y=z=z=A=z=A=B=C=B=D=C=B=x=B=B=B=B=B=B=B=B=B=B=B=B=B=B=",
+"{+{+7=7=e&e&e&e&E=E=e&e&e&e&E=E=E=e&e&e&e&E=E=E=e&e&e&e&E=E=e&e&e&e&E=E=E=F=d%G=G=H=I=J=K=L=M=R+}+N=O=P=Q=j=i=h=R=e@@=S=-=T=h@l*U=V=W=X=Y=Z=`= - - -.-+-@- -#-$-%-$-&-*-$-=-%-----C=$-%---------B=B=B=B=",
+"{+{+7=7=;-;-E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=>-,-'-)-!-6*~-{-{-]-^-/-/-(-_-:-N=<-[-}-|-1-2-3- =4-5-6-7-8-9-0-0-a-b-c-d-e-f-g-h-h-i-j-k-h-h-i-j-l-m-n-o-i-j-l-m-n-j-l-p-n-",
+"{+{+7=7=;-;-E=E=E=E=E=E=E=E=q-r-s-t-t-u-u-v-v-v-u-w-x-u-u-u-u-u-u-u-u-v-v-u-u-u-u-u-v-v-u-u-u-u-v-v-u-y-z-A-B-C-D-E-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-U-V-W-V-e-X-Y-Z-`- ;.;Y-N N +;@;.;Y-N N N N N N N ",
+"#;#;d&d&$;$;%;%;%;%;%;%;%;%;&;*;=;-;-;-;;;>;,;>;>;>;;;>;>;>;>;>;>;>;>;>;';);>;>;>;>;>;';>;>;>;>;>;';);!;~;{;];^;/;(;_;_;:;<;[;};};|;1;2;3;4;5;6;7;8;9;9;0;a;0;0;b;h.a;0;0;b;h.c;h.d;0;b;h.c;h.d;h.c;h.d;",
+"#;#;;-;-$;$;e;e;e;e;e;e;e;e;e;e;e;f;f;f;f;e;e;e;f;f;f;f;f;f;f;f;f;f;f;f;g;%;f;f;f;f;f;g;f;f;f;f;f;g;%;h;i;j;k;l;m;n;o;p;q;r;r;s;t;u;v;w;x;y;z;A;B;C;6;D;E;F;G;G;H;I;F;G;G;H;I;J;J;K;G;H;I;J;J;K;I;J;J;K;",
+"#;#;;-;-$;$;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;L;e;e;e;e;e;e;e;e;e;e;e;e;L;M;N;O;P;Q;i;i;k;R;S;T;U;q;q;V;W;X;{;Y;Z;`; >.>+>@>#>+>$>6;#>#>+>%>&>G;G;G;G;G;&>G;G;G;G;G;G;G;G;G;",
+"#;#;d.;-$;$;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;*>e;e;e;e;e;e;e;e;e;e;e;e;*>=>->;>>>,>'>'>)>!>~>{>]>^>^>V;V;/>(>_>:><>[>}>|>1>2>3>2>4>5>6>7>8>9>0>G;G;G;G;9>0>G;G;G;G;G;G;G;G;",
+"#;#;d.d.a>a>e;e;e;e;e;e;e;e;e;e;b>b>c>c>c>c>c>b>e;e;e;e;e;e;e;e;e;e;e;e;e;e;d>e>f>g>h>i>j>k>l>l>m>m>n>n>o>o>p>q>r>r>s>t>u>v>v>u>w>';x>y>z>t;A>B>C>D>E>E>F>G>F>H>H>I>F>Y;J>w;K>L>K>M>J>w;K>L>K>M>K>L>K>M>",
+"#;#;d.d.a>a>N>e;N>O>O>O>N>e;N>O>O>P>Q>R>S>R>Q>O>O>O>N>e;N>O>O>O>N>e;N>N>O>T>e;e;e;U>U>U>U>f;V>W>o>o>o>o>X>X>Y>Y>n>n>Z>Z>`> ,.,t>t>u>u>w>+,@,#,$,%,A>&,*,=,B>[>-,w;<>C>[>-,w;w;w;w;w;-,w;w;w;w;w;w;w;w;w;",
+"#;;,;-;-a>a>N>N>N>O>O>O>N>N>N>O>O>O>O>N>N>N>O>O>O>O>N>N>N>O>O>O>N>N>N>N>O>>,,,,,,,',g>),!,~,{,{,*>U>e;f;],o>%;o>^,^,/,/,l>q>(,_,t>u>:,<,v>[,},|,1,2,%,%,3,4,5,6,7,8,9,5,6,0,G>G>Y;G>6,0,G>G>Y;G>G>G>Y;G>",
+";,;,;-;-O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>P>a,b,',',c,c,f>),e>d,e,{,{,U>U>f,f,U>U>g,g,*>g;h,^,^,`>`>q>i,t>j,k,k,l,w>m,n,o,p,q,r,s,t,p,u,v,w,x,y,z,u,v,w,x,y,z,w,x,y,z,",
+";,;,b b O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>A,A,A,B,C,D,E,F,c,',g>G,!,H,~,e,{,I,J,J,K,K,U>f,f,J,L,M,N,L;O,i,P,.,l,Q,k,k,k,k,k,k,R,v,k,k,k,R,v,S,T,U,k,R,v,S,T,U,v,S,T,U,",
+";,;,b V,W,W,X,X,O>X,X,X,X,X,O>X,X,X,X,X,X,O>X,X,X,X,X,X,O>X,X,X,X,X,O>X,X,O>O>O>O>B,B,B,B,Y,O>O>Z,`,T>T> '',g>.'+'e,{,{,e,+'+'e,e,{,J,K,e;@'N,O,#'$'%'%'j,%'j,&'k,k,%'j,&'k,k,k,k,k,&'k,k,k,k,k,k,k,k,k,",
+";,;,b V,W,W,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,*'O>O>O>O>O>O>O>O>B,B,A,A,B,C,='-'`,;'>'>',''')'!'!'e>e>~'~'~,~,{'{,*>*>e;]']']']']']'^'/']']']'^'/':,(':,]'^'/':,(':,/':,(':,",
+";,;,V,V,W,W,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,_':'<'['}'|'|'O>O>O>O>O>O>O>Y,Y,1'1'B,B,2'2'C,3'-'>'c,)')'!'),4'{'e;]'e;*>*>e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;",
+";,;,5'5'W,W,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,W,6'6'6'7'8'9'0'a'b'c'd'd'}'}'O>O>O>O>O>O>O>O>Y,1'1'['['e'e'f'g'h'i'j'k'G,),!,l'j'm'n'b>b>),m'b>e;e;e;e;e;b>e;e;e;e;e;e;e;e;e;",
+";,;,b b o'o'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'W,q'q'q'r's't'u'v'w'x'y'z'A'B'C'D'2'2'B,B,O>O>O>O>O>O>O>O>O>O>O>Y,Y,C,C,='='='E'F'3'3'3'G'Z,='F'F'G'H'I'J'F'F'G'H'I'J'G'H'I'J'",
+";,;,b b K'K'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'W,W,W,W,W,L'L'q'r'M'N'O'P'u'N's'Q'R'S'A'T'U'C'V'9'0'W'D'}'X'|'O>O>B,B,O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>",
+";,;,b b K'K'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'Y'Y'Y'Z'`' ).)+)+)+)W,W,W,W,L'L'q'q'r'r's'M'N'P'@)A'#)$)%)&)*)=)B,|'|'O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>O>",
+"{+;,$ -);)K'p'p'o'p'p'p'p'p'o'p'p'p'p'p'p'o'p'p'p'p'p'p'o'p'p'p'p'p'o'o'p'p'p'p'p'p'p'p'p'p'>)>)Y'Y'>)Z',)')))!)~)+)W,W,W,W,W,W,W,W,W,W,W,L'L'{)s't'])^)/)])/)/)O>()])/)/)O>()O>_)O>/)O>()O>_)O>()O>_)O>",
+":);,;,;)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)[)M M M M M M M M M M M M M M M M M M })})|)|)})M M 1)2)3)4)5)6)6)6)7)7)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)",
+"9)#;;,;,$ -)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)<)0)a)a)a)b)c)d)e)f)g)h)i)i)j)j)M M M M M M M M M M M })})})})M k)k)M M k)l)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)8)",
+"+ 9)m)n)$ #;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;#;o)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)p)",
+"+ + 9)a m)q)r)s)r)s)r)s)r)s)r)r)s)r)s)r)s)r)r)s)r)s)r)s)r)s)r)s)r)s)r)s)r)t)u)v)w)x)x)w)y)z)A)A)B)B)B)B)w)w)C)C)w)w)B)B)B)B)B)w)w)w)w)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)B)D)B)B)B)B)B)D)B)B)B)D)B)",
+". + + 9)9)9)q)E)q)E)q)E)q)E)q)q)E)q)E)q)E)q)q)E)q)E)q)E)q)E)q)E)q)E)q)E)q)F)G)H)E)I)J)K)H)L)L)L)L)L)L)L)H)H)M)M)H)H)L)L)G)L)L)H)H)H)H)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)L)N)L)L)L)L)L)N)L)L)L)N)L)",
+". . 0 . + O)P)O)P)O)P)O)P)O)P)P)O)P)O)P)O)P)P)O)P)O)P)O)P)O)P)O)P)O)P)O)P)O)Q)R)S)T)U)V)W)X)W)W)V)V)V)V)V)V)V)V)Y)Y)Z)Z)Y)Z)Z)Y)Y)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)V)Y)V)V)V)V)V)Y)V)V)V)Y)V)",
+". . . 0 0 0 . 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 `) !+ + + .! !`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)`)+!`)`)`)`)`)+!`)`)`)+!`)"};
+
+
+static char * listviewhighcornerright_xpm[] = {
+"100 46 780 2",
+" c None",
+". c #6A779D",
+"+ c #6C789C",
+"@ c #6C789D",
+"# c #6B789D",
+"$ c #6A779E",
+"% c #66759E",
+"& c #64749E",
+"* c #63749E",
+"= c #61739D",
+"- c #576D9B",
+"; c #556C9C",
+"> c #4D679D",
+", c #4A649D",
+"' c #49629D",
+") c #465E9C",
+"! c #40579C",
+"~ c #3B5394",
+"{ c #2C4E97",
+"] c #314993",
+"^ c #2B4595",
+"/ c #1B4296",
+"( c #253D93",
+"_ c #19418F",
+": c #0F3C96",
+"< c #42599E",
+"[ c #758DC3",
+"} c #E8EAE7",
+"| c #EEF0ED",
+"1 c #FBFBFC",
+"2 c #6F7D9B",
+"3 c #6F7D9A",
+"4 c #6E7B9C",
+"5 c #67759E",
+"6 c #63739E",
+"7 c #62739D",
+"8 c #596F9C",
+"9 c #4A639D",
+"0 c #47609C",
+"a c #445B9F",
+"b c #3E5697",
+"c c #2E509A",
+"d c #2D509A",
+"e c #2D4F99",
+"f c #2D4F98",
+"g c #28418A",
+"h c #3E51A3",
+"i c #D0D3DC",
+"j c #A1B6EF",
+"k c #A2B6F0",
+"l c #A1B6F0",
+"m c #A3B6F0",
+"n c #A0B6EF",
+"o c #9DB6EE",
+"p c #9CB5EF",
+"q c #9CB2F0",
+"r c #9FB5EE",
+"s c #9CB4EB",
+"t c #9AB3EC",
+"u c #9AB0EC",
+"v c #9DB3EB",
+"w c #9BB4EC",
+"x c #9BB4EE",
+"y c #9BB1EF",
+"z c #9BB0F0",
+"A c #90ACF0",
+"B c #93ABEE",
+"C c #91A8EB",
+"D c #8BA3E8",
+"E c #88A1E7",
+"F c #809DE9",
+"G c #7A99E8",
+"H c #7491E5",
+"I c #698AE4",
+"J c #6184E3",
+"K c #507EDC",
+"L c #4E7CDB",
+"M c #4F7DDC",
+"N c #5479DA",
+"O c #567BDC",
+"P c #577CDD",
+"Q c #5074DA",
+"R c #5174DB",
+"S c #5175DC",
+"T c #5276DD",
+"U c #4D71DE",
+"V c #4C72D8",
+"W c #3A6CE0",
+"X c #2B49A6",
+"Y c #E0E2DF",
+"Z c #93AAE9",
+"` c #94A9E8",
+" . c #94AAE9",
+".. c #93A9E9",
+"+. c #92AAE9",
+"@. c #8DA9E8",
+"#. c #8CA7E9",
+"$. c #92ABE9",
+"%. c #8EAAE9",
+"&. c #8EA9E9",
+"*. c #8FAAE9",
+"=. c #8CA8E9",
+"-. c #8CA2E7",
+";. c #86A1E6",
+">. c #839EE9",
+",. c #7F9CE9",
+"'. c #7A97E8",
+"). c #7693E7",
+"!. c #6E8EE8",
+"~. c #678AE9",
+"{. c #5D84E3",
+"]. c #577CDF",
+"^. c #4E77DF",
+"/. c #4A70DB",
+"(. c #4870DB",
+"_. c #4870DC",
+":. c #4770E3",
+"<. c #496FDC",
+"[. c #486EDB",
+"}. c #466FE4",
+"|. c #466EE3",
+"1. c #4167D9",
+"2. c #4066D8",
+"3. c #3F66D8",
+"4. c #3D64D7",
+"5. c #3960DA",
+"6. c #476DD9",
+"7. c #446EE5",
+"8. c #305EC8",
+"9. c #8EAAE8",
+"0. c #8FAAE8",
+"a. c #91AAE9",
+"b. c #8FA9E8",
+"c. c #8BA8E8",
+"d. c #8AA7E9",
+"e. c #8BA5EA",
+"f. c #8AA7E8",
+"g. c #87A2E6",
+"h. c #859FE8",
+"i. c #7F9DE8",
+"j. c #7C9AE8",
+"k. c #7B95E7",
+"l. c #7090E8",
+"m. c #6B8BE9",
+"n. c #6386E6",
+"o. c #5881E1",
+"p. c #5479DE",
+"q. c #4D74DE",
+"r. c #476EDB",
+"s. c #446EE1",
+"t. c #446EE0",
+"u. c #446EDF",
+"v. c #446DE0",
+"w. c #426ADF",
+"x. c #3C64DA",
+"y. c #4360CC",
+"z. c #D3D5D2",
+"A. c #E6E3E8",
+"B. c #8DA2E7",
+"C. c #8CA6EA",
+"D. c #8DA3E9",
+"E. c #88A2E7",
+"F. c #87A1E7",
+"G. c #8AA1E7",
+"H. c #849EE9",
+"I. c #7D9AE9",
+"J. c #7B98E8",
+"K. c #7796E5",
+"L. c #7191E7",
+"M. c #688CE9",
+"N. c #6687E5",
+"O. c #5C83E1",
+"P. c #557BDE",
+"Q. c #4F76DE",
+"R. c #4C72DE",
+"S. c #456EDF",
+"T. c #426AD9",
+"U. c #4269D9",
+"V. c #4269D8",
+"W. c #3D64D9",
+"X. c #3A61DA",
+"Y. c #345ED6",
+"Z. c #335ECF",
+"`. c #C6C3C8",
+" + c #86A1E7",
+".+ c #87A2E7",
+"++ c #87A0E7",
+"@+ c #859EE8",
+"#+ c #849DE9",
+"$+ c #7E9BE9",
+"%+ c #7A99E9",
+"&+ c #7A95E5",
+"*+ c #7593E7",
+"=+ c #6F8EE9",
+"-+ c #668AE5",
+";+ c #6386E0",
+">+ c #5B82DF",
+",+ c #5379DE",
+"'+ c #5075DE",
+")+ c #4B6FDC",
+"!+ c #446AD7",
+"~+ c #4269D6",
+"{+ c #4269D5",
+"]+ c #3E65D7",
+"^+ c #C9CAC9",
+"/+ c #869EE9",
+"(+ c #859FE9",
+"_+ c #849FE9",
+":+ c #829DE8",
+"<+ c #819DE8",
+"[+ c #7B9AE9",
+"}+ c #7A96E6",
+"|+ c #7290E8",
+"1+ c #698CE6",
+"2+ c #6689E0",
+"3+ c #5D84E0",
+"4+ c #587FDF",
+"5+ c #5377DD",
+"6+ c #4B74DE",
+"7+ c #496BD8",
+"8+ c #7C9BE9",
+"9+ c #7E9CE9",
+"0+ c #7D9AEA",
+"a+ c #7D9BEA",
+"b+ c #7D98E8",
+"c+ c #7C98E8",
+"d+ c #7796E4",
+"e+ c #7592E6",
+"f+ c #7390E1",
+"g+ c #698DE0",
+"h+ c #6588DE",
+"i+ c #5E84E0",
+"j+ c #5880DF",
+"k+ c #5479DC",
+"l+ c #4F75DE",
+"m+ c #4A6FDB",
+"n+ c #436AD7",
+"o+ c #3F65D7",
+"p+ c #BAC3BE",
+"q+ c #7B9AE8",
+"r+ c #7B9AEA",
+"s+ c #7A9AEA",
+"t+ c #7B99E9",
+"u+ c #7D97E7",
+"v+ c #7D95E6",
+"w+ c #7D95E5",
+"x+ c #7C95E6",
+"y+ c #7493E3",
+"z+ c #7290DF",
+"A+ c #6C8DDE",
+"B+ c #6B89E1",
+"C+ c #6486DF",
+"D+ c #5D81DF",
+"E+ c #567DDE",
+"F+ c #4F73DE",
+"G+ c #496EDA",
+"H+ c #355ED6",
+"I+ c #345ED5",
+"J+ c #7E95E5",
+"K+ c #7C97E8",
+"L+ c #7C97E7",
+"M+ c #7B94E6",
+"N+ c #7A95E4",
+"O+ c #7695E5",
+"P+ c #7694E4",
+"Q+ c #7994E6",
+"R+ c #7995E4",
+"S+ c #7594E4",
+"T+ c #7391E2",
+"U+ c #6E8EDE",
+"V+ c #6B8ADE",
+"W+ c #6688DF",
+"X+ c #5F84E0",
+"Y+ c #5980E0",
+"Z+ c #4D72DD",
+"`+ c #456BD7",
+" @ c #4168D6",
+".@ c #3C64D7",
+"+@ c #335ED0",
+"@@ c #4659C7",
+"#@ c #7292E1",
+"$@ c #7392E1",
+"%@ c #7492E1",
+"&@ c #718FDF",
+"*@ c #6F8EDE",
+"=@ c #6D8BDE",
+"-@ c #6B88DF",
+";@ c #597FDF",
+">@ c #557ADD",
+",@ c #5176DC",
+"'@ c #4D74DD",
+")@ c #496DDA",
+"!@ c #3860D8",
+"~@ c #7391E0",
+"{@ c #7290DE",
+"]@ c #6D8EDD",
+"^@ c #6D8DDD",
+"/@ c #7190E0",
+"(@ c #6C8DDD",
+"_@ c #6B89DF",
+":@ c #6487E0",
+"<@ c #6085DF",
+"[@ c #5F81DE",
+"}@ c #567EDE",
+"|@ c #4F74D9",
+"1@ c #466BD7",
+"2@ c #4067D5",
+"3@ c #3C63D7",
+"4@ c #335ED3",
+"5@ c #335ED1",
+"6@ c #718EDD",
+"7@ c #728EDD",
+"8@ c #748EDD",
+"9@ c #708EDD",
+"0@ c #6F8DDD",
+"a@ c #6E8DDD",
+"b@ c #6C8ADE",
+"c@ c #6C89DF",
+"d@ c #6988DF",
+"e@ c #6387DF",
+"f@ c #6282DE",
+"g@ c #5681E0",
+"h@ c #577BDD",
+"i@ c #5277DB",
+"j@ c #4D73D8",
+"k@ c #4A70D8",
+"l@ c #436AD5",
+"m@ c #3F66D6",
+"n@ c #3C63D8",
+"o@ c #3960D8",
+"p@ c #3860D7",
+"q@ c #335ED2",
+"r@ c #345ED4",
+"s@ c #6C88DF",
+"t@ c #6D88DF",
+"u@ c #6B89DE",
+"v@ c #6888DF",
+"w@ c #6587E0",
+"x@ c #6989DF",
+"y@ c #6687E0",
+"z@ c #6287E0",
+"A@ c #6281DD",
+"B@ c #5881E0",
+"C@ c #557ADB",
+"D@ c #5176D9",
+"E@ c #4E75D7",
+"F@ c #4A6FD8",
+"G@ c #476BD6",
+"H@ c #4067D6",
+"I@ c #3C62D7",
+"J@ c #3C60D4",
+"K@ c #365ED1",
+"L@ c #345ED3",
+"M@ c #6786DF",
+"N@ c #5F85E0",
+"O@ c #5F86E0",
+"P@ c #6186DF",
+"Q@ c #6286E0",
+"R@ c #6284DF",
+"S@ c #6384DF",
+"T@ c #5B7FDE",
+"U@ c #577DDC",
+"V@ c #557BDA",
+"W@ c #5278D8",
+"X@ c #4E76D6",
+"Y@ c #4C72D7",
+"Z@ c #486DD8",
+"`@ c #4469D6",
+" # c #3F62D2",
+".# c #3C60CF",
+"+# c #345ECF",
+"@# c #6086DF",
+"## c #6085E0",
+"$# c #6285DF",
+"%# c #6383DD",
+"&# c #6481DC",
+"*# c #6380DD",
+"=# c #6183DE",
+"-# c #6083DD",
+";# c #6081DC",
+"># c #6080DD",
+",# c #6083DE",
+"'# c #6181DC",
+")# c #6280DD",
+"!# c #577EDB",
+"~# c #557CD7",
+"{# c #4F76D6",
+"]# c #4E74D7",
+"^# c #466CD7",
+"/# c #3B64D6",
+"(# c #4261CD",
+"_# c #375FCE",
+":# c #5A7FD8",
+"<# c #6281DA",
+"[# c #5F81D8",
+"}# c #5C80D8",
+"|# c #557DD7",
+"1# c #577ED8",
+"2# c #567ED7",
+"3# c #587DD8",
+"4# c #577DD8",
+"5# c #587ED8",
+"6# c #567DD8",
+"7# c #5379D9",
+"8# c #5177D7",
+"9# c #4D74D5",
+"0# c #486ED9",
+"a# c #4068D4",
+"b# c #3D65D2",
+"c# c #4361CC",
+"d# c #345ECE",
+"e# c #325DCF",
+"f# c #2C5AD1",
+"g# c #3959C5",
+"h# c #547BD8",
+"i# c #567DD7",
+"j# c #557BD8",
+"k# c #5279D9",
+"l# c #5278D9",
+"m# c #4D74D6",
+"n# c #4B71D8",
+"o# c #496CD8",
+"p# c #4669D7",
+"q# c #3D66D3",
+"r# c #3F62CF",
+"s# c #4260CC",
+"t# c #5379D8",
+"u# c #4E75D4",
+"v# c #4C73D7",
+"w# c #476CD7",
+"x# c #4869D0",
+"y# c #4067D2",
+"z# c #3D64D1",
+"A# c #4261CC",
+"B# c #395FCE",
+"C# c #4F75D3",
+"D# c #5074D2",
+"E# c #5174D1",
+"F# c #5175D1",
+"G# c #4F74D3",
+"H# c #4C73D5",
+"I# c #4C73D4",
+"J# c #4A72D1",
+"K# c #4B70CF",
+"L# c #506CCC",
+"M# c #4D6BCE",
+"N# c #4167D0",
+"O# c #3D65D1",
+"P# c #3F63CF",
+"Q# c #3B5FCD",
+"R# c #3159CD",
+"S# c #4971D0",
+"T# c #4870CF",
+"U# c #4C6FCF",
+"V# c #4E6CCE",
+"W# c #4E6BCE",
+"X# c #4769CF",
+"Y# c #3D66D0",
+"Z# c #3C65D1",
+"`# c #4062CE",
+" $ c #3D5FCD",
+".$ c #365FCF",
+"+$ c #325DCD",
+"@$ c #2D5AD0",
+"#$ c #3859C5",
+"$$ c #355FCF",
+"%$ c #355ECF",
+"&$ c #335ECE",
+"*$ c #305CCD",
+"=$ c #2B5ACE",
+"-$ c #3056C9",
+";$ c #2553C6",
+">$ c #2153C8",
+",$ c #1F4FC7",
+"'$ c #274CC5",
+")$ c #214AC7",
+"!$ c #1C48C8",
+"~$ c #1244C9",
+"{$ c #1043C9",
+"]$ c #1144C9",
+"^$ c #2A45BE",
+"/$ c #2744B5",
+"($ c #1D49C0",
+"_$ c #2B58DE",
+":$ c #002D94",
+"<$ c #2B59CA",
+"[$ c #2A59CA",
+"}$ c #2E57C8",
+"|$ c #3255C6",
+"1$ c #3355C5",
+"2$ c #1C52C8",
+"3$ c #1D50C7",
+"4$ c #234FC6",
+"5$ c #264CC5",
+"6$ c #1D48C7",
+"7$ c #1245C8",
+"8$ c #1F44C2",
+"9$ c #2945BE",
+"0$ c #2A45BD",
+"a$ c #2040BF",
+"b$ c #3156C7",
+"c$ c #3056C7",
+"d$ c #3354C5",
+"e$ c #3355C6",
+"f$ c #3255C5",
+"g$ c #3254C5",
+"h$ c #1952C7",
+"i$ c #1951C8",
+"j$ c #2050C7",
+"k$ c #274CC4",
+"l$ c #244CC6",
+"m$ c #1F49C7",
+"n$ c #1E47C5",
+"o$ c #2045C3",
+"p$ c #1C44BF",
+"q$ c #2045BE",
+"r$ c #2040B8",
+"s$ c #3254C6",
+"t$ c #3055C6",
+"u$ c #2A54C6",
+"v$ c #2353C7",
+"w$ c #3054C5",
+"x$ c #2F55C5",
+"y$ c #2A54C5",
+"z$ c #2553C5",
+"A$ c #2F54C5",
+"B$ c #3155C6",
+"C$ c #2A54C7",
+"D$ c #1A52C8",
+"E$ c #204FC2",
+"F$ c #264DC6",
+"G$ c #234BC5",
+"H$ c #1D48C1",
+"I$ c #1E48BF",
+"J$ c #2646BE",
+"K$ c #2B45BD",
+"L$ c #1E43BE",
+"M$ c #2643BF",
+"N$ c #2243BF",
+"O$ c #3049BC",
+"P$ c #1E50BE",
+"Q$ c #1D50C0",
+"R$ c #1D50BF",
+"S$ c #1852C1",
+"T$ c #1E51C0",
+"U$ c #214FBF",
+"V$ c #2050C0",
+"W$ c #244EBF",
+"X$ c #2151C0",
+"Y$ c #234FBF",
+"Z$ c #2350C0",
+"`$ c #2351C0",
+" % c #244FBF",
+".% c #2250C0",
+"+% c #2051C0",
+"@% c #1E50C0",
+"#% c #244DBE",
+"$% c #274DBF",
+"%% c #244CBF",
+"&% c #1C48C0",
+"*% c #2247BF",
+"=% c #2C44BD",
+"-% c #1C44BE",
+";% c #1444BF",
+">% c #1841BF",
+",% c #1F40BF",
+"'% c #254DBE",
+")% c #224FBE",
+"!% c #224FBF",
+"~% c #234EBF",
+"{% c #254CBD",
+"]% c #244DBD",
+"^% c #244CBD",
+"/% c #264DBE",
+"(% c #264DBD",
+"_% c #214BC0",
+":% c #1D48C0",
+"<% c #2347BF",
+"[% c #2B44BD",
+"}% c #2444BE",
+"|% c #0F42BF",
+"1% c #0641BF",
+"2% c #0F41BF",
+"3% c #1741BE",
+"4% c #1F40BD",
+"5% c #234BBF",
+"6% c #234CBE",
+"7% c #214BBE",
+"8% c #244CBE",
+"9% c #214ABE",
+"0% c #214ABF",
+"a% c #1F48C0",
+"b% c #2746BE",
+"c% c #1F43BE",
+"d% c #0941BE",
+"e% c #0342BA",
+"f% c #0242BC",
+"g% c #1241B8",
+"h% c #1F40B7",
+"i% c #2F41AC",
+"j% c #2644AE",
+"k% c #2D49B4",
+"l% c #2649B6",
+"m% c #2949B7",
+"n% c #2849B5",
+"o% c #2149B8",
+"p% c #1E49B9",
+"q% c #1F48B8",
+"r% c #1F49B9",
+"s% c #2545B6",
+"t% c #2744B7",
+"u% c #2844B7",
+"v% c #2043B8",
+"w% c #1241B7",
+"x% c #1340B8",
+"y% c #0D41B8",
+"z% c #1941B8",
+"A% c #1F40B8",
+"B% c #203FB8",
+"C% c #2549B5",
+"D% c #2648B6",
+"E% c #2547B7",
+"F% c #2248B7",
+"G% c #2048B7",
+"H% c #2346B6",
+"I% c #2146B6",
+"J% c #2247B7",
+"K% c #2148B7",
+"L% c #2743B4",
+"M% c #2643B5",
+"N% c #2542B6",
+"O% c #1D42B7",
+"P% c #0E42B8",
+"Q% c #0C41B8",
+"R% c #1341B8",
+"S% c #1740B8",
+"T% c #1C41B8",
+"U% c #1F40B1",
+"V% c #2644B5",
+"W% c #2544B5",
+"X% c #2544B4",
+"Y% c #2444B5",
+"Z% c #2444B4",
+"`% c #2744B4",
+" & c #2241B7",
+".& c #1D41B8",
+"+& c #0B42B8",
+"@& c #0942B8",
+"#& c #0C42B8",
+"$& c #0F41B8",
+"%& c #1641B8",
+"&& c #2442B5",
+"*& c #2543B3",
+"=& c #2342B2",
+"-& c #2341B4",
+";& c #2141B3",
+">& c #2141B5",
+",& c #2140B5",
+"'& c #2040B5",
+")& c #1C40B7",
+"!& c #1B41B3",
+"~& c #0142B6",
+"{& c #0E41B7",
+"]& c #1141B7",
+"^& c #1440B2",
+"/& c #113FB0",
+"(& c #1440B0",
+"_& c #213EAF",
+":& c #233DAE",
+"<& c #223EAF",
+"[& c #1E40B1",
+"}& c #173EAD",
+"|& c #1440AF",
+"1& c #0D40AF",
+"2& c #0941B0",
+"3& c #0D3FAE",
+"4& c #1B3CAC",
+"5& c #233CAD",
+"6& c #203FB0",
+"7& c #273BAD",
+"8& c #1D40B0",
+"9& c #2040B1",
+"0& c #1E40B0",
+"a& c #1C40B0",
+"b& c #1B3DAC",
+"c& c #143DAC",
+"d& c #193DAD",
+"e& c #1B3DAD",
+"f& c #173DAD",
+"g& c #153DAC",
+"h& c #1C3CAC",
+"i& c #243CAD",
+"j& c #213FB0",
+"k& c #263BAA",
+"l& c #253CAE",
+"m& c #273AAC",
+"n& c #273AAD",
+"o& c #253BAD",
+"p& c #1D3CAC",
+"q& c #243BAD",
+"r& c #1E3CAC",
+"s& c #263BAD",
+"t& c #1A3DAC",
+"u& c #143DAB",
+"v& c #163DAC",
+"w& c #1A3CAC",
+"x& c #1F3CAD",
+"y& c #263BAB",
+"z& c #263BA6",
+"A& c #1E42A4",
+"B& c #2D40A5",
+"C& c #253BA6",
+"D& c #253CA7",
+"E& c #263AA5",
+"F& c #253BA7",
+"G& c #1E3BA6",
+"H& c #193DA6",
+"I& c #173DA5",
+"J& c #143DA6",
+"K& c #1A3DA7",
+"L& c #133DA6",
+"M& c #123DA5",
+"N& c #1A3CA7",
+"O& c #243BA6",
+"P& c #263AA7",
+"Q& c #273BA7",
+"R& c #263AA6",
+"S& c #223BA6",
+"T& c #1D3BA6",
+"U& c #173CA6",
+"V& c #133DA5",
+"W& c #1B3DA6",
+"X& c #193DA5",
+"Y& c #123DA4",
+"Z& c #163CA5",
+"`& c #213CA6",
+" * c #273BA8",
+".* c #263BA7",
+"+* c #253BA5",
+"@* c #263BA5",
+"#* c #1C3BA6",
+"$* c #1B3BA9",
+"%* c #133BA8",
+"&* c #0A3BA7",
+"** c #083AA6",
+"=* c #123CA5",
+"-* c #0839A8",
+";* c #0239A6",
+">* c #123AA8",
+",* c #1F49C8",
+"'* c #2F4DA4",
+")* c #2E4DA3",
+"!* c #384CA4",
+"~* c #3C4DA7",
+"{* c #394EA7",
+"]* c #3B4CA5",
+"^* c #3C52B1",
+"/* c #3551A8",
+"(* c #3759BE",
+"_* c #4161C7",
+":* c #0033A8",
+"<* c #596FA9",
+"[* c #2F4DA3",
+"}* c #2D4BA5",
+"|* c #2E4CA4",
+"1* c #2C4AA5",
+"2* c #2D4BA4",
+"3* c #354DA4",
+"4* c #3A4BA4",
+"5* c #394DA6",
+"6* c #4056AD",
+"7* c #445BBB",
+"8* c #B5B7B4",
+"9* c #1B2F85",
+"0* c #242F79",
+"a* c #B5B5B5",
+"b* c #B5B2B6",
+"c* c #C0C3C3",
+"d* c #E3E3E4",
+"e* c #EBEDEA",
+". + @ + # $ % & # $ % & # $ % & # $ % & & * = - ; > , ' ) ! ~ { { { { { { { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / / / ( / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / _ _ / / : / < [ } | | | 1 1 ",
+"2 2 2 2 3 2 4 @ 3 2 4 @ 3 2 4 @ 3 2 4 @ # 5 6 7 8 ; > 9 0 a b c d e f { { { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ( ( ( ( ( ( ( ( ( / / / / / / / / / / / / / / / / / _ _ _ _ _ _ _ _ _ _ _ g g _ / / : : : h i } 1 | 1 ",
+"j k l m n o p q n o p q r s t u v w x y z A B C D E F G H I J K L M N O P O O Q R S T T T T T T T T T T T T T T T T T T U U U U U U U U U U U U U U U U U U U U U U U U U U U U V V V U U W X : [ Y | | ",
+"Z ` . ...+.@.#...+.@.#.Z $.%.&.Z $.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.6.7.8.: h Y } 1 ",
+"9.0.a.b.c.c.d.e.f.c.d.e.f.c.d.e.f.c.d.e.g.h.i.j.k.l.m.n.o.p.q.r.s.s.t.u.u.v.w.x.4.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.y.5.7.6.: / z.A.} ",
+"-.B.C.D.-.E.g.F.G.E.g.F.G.E.g.F.G.E.g.F.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.V.U.U.W.X.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Z.y.Y.7.7.: : `.z.} ",
+" +.+g.;.++F.@+#+++F.@+#+++F.@+#+++F.@+#+$+%+&+*+=+-+;+>+,+'+)+!+~+{+]+{+{+4.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.Y.Y.5.5.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Z.Z.Z.y.y.5.7.7.: : ^+z.Y ",
+"/+(+_+#+H.H.>.:+H.H.>.:+H.H.>.:+H.H.>.<+[+}+*+|+1+2+3+4+5+6+7+{+{+4.4.4.4.4.4.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.Y.Y.Y.Y.Y.Y.Y.5.Y.Y.Y.Y.Y.Y.Y.Y.5.Y.Y.5.5.5.5.Y.Y.Y.Y.Y.Y.Z.Z.Z.Z.y.y.y.y.y.y.7.7.: : ^+i } ",
+"8+9+0+0+a+0+0+b+a+0+0+b+a+0+0+b+a+0+0+c+d+e+f+g+h+i+j+k+l+m+n+o+4.4.4.4.5.5.5.5.5.5.Y.Y.5.5.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Y.Y.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.7.7.: : p+z.Y ",
+"q+r+r+s+t+u+v+w+t+u+v+w+t+u+v+w+t+u+x+&+y+z+A+B+C+D+E+5+F+G+~+4.4.4.4.5.5.5.5.5.H+Y.Y.Y.Y.Y.Y.Y.Y.I+Y.Z.Y.Y.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.7.7.: : `.z.A.",
+"J+v+K+L+M+N+O+P+Q+R+O+P+Q+R+O+P+Q+R+O+S+T+U+V+W+X+Y+P.T Z+`+ @4.4..@5.5.5.5.5.5.Y.Y.Y.I+I+I+I+I++@+@Z.Z.Y.Y.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.@@Z.7.7.: : p+z.Y ",
+"#@$@$@%@%@$@#@&@#@#@#@&@#@#@#@&@#@#@#@*@=@-@;+i+;@>@,@'@)@ @4.X.5.5.H+Y.Y.Y.!@Y.Y.I++@+@Z.Z.+@Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.y.Z.6.6.: : `.z.A.",
+"#@$@~@~@~@{@]@^@/@{@]@^@/@{@]@^@/@{@]@(@_@:@<@[@}@k+|@V 1@2@3@5.5.5.Y.Y.I+4@I+5@+@Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.y.Z.6.6.: : p+z.Y ",
+"6@7@8@9@0@a@b@c@a@a@b@c@a@a@b@c@a@a@b@d@e@<@f@g@h@i@j@k@l@m@n@o@o@p@Y.I+q@q@r@+@Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.y.Z.6.6.: : `.z.A.",
+"s@t@u@_@_@v@w@w@x@v@w@w@x@v@y@y@x@v@:@z@A@B@P C@D@E@F@G@H@I@J@K@5@+@+@+@r@I+L@Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.@@Z.W W : : p+z.Y ",
+"M@N@O@P@C+Q@Q@R@C+;+Q@R@C+;+;+S@C+Q@Q@R@T@U@V@W@X@Y@Z@`@4. #.#+#Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.8.Z.Z.Z.Z.8.8.Z.Z.y.@@@@W W : : `.z.A.",
+"@#O@O@##$#%#&#*#=#-#;#>#,#-#;#>#,#-#'#)#!#~#W@{#]#k@^#H@/#(#_#Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.8.8.Z.Z.Z.Z.Z.Z.Z.8.8.8.8.8.8.8.8.8.8.8.Z.Z.y.y.@@W W : : p+z.Y ",
+":#<#[#}#|#1#2#3#4#5#1#4#4#1#1#4#4#1#1#6#7#8#9#V 0#`+a#b#c#d#e#Z.Z.Z.f#Z.Z.Z.f#f#f#f#f#f#f#f#f#f#g#g#g#g#g#8.8.8.8.8.8.8.8.8.g#g#g#g#8.g#8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.y.y.@@W W : : `.z.A.",
+"h#2#i#6#|#j#7#k#|#j#7#7#|#j#7#7#|#j#7#l#8#m#n#n#o#p#q#r#s#d#e#Z.Z.Z.f#f#f#f#Z.f#f#g#g#g#g#g#g#g#g#g#g#g#g#8.8.8.g#g#8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.y.y.y.y.8.8.8.y.y.@@W W : : p+z.Y ",
+"l#7#7#l#7#7#7#W@7#7#7#W@7#7#k#W@t#7#7#W@u#v#n#w#x#y#z#A#B#Z.e#f#f#Z.f#f#f#Z.Z.g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#8.8.8.g#g#g#g#8.8.g#g#g#g#g#g#8.8.g#8.8.y.8.8.y.y.8.y.y.y.y.@@W W : : `.z.A.",
+"C#D#E#F#G#H#I#J#G#H#I#J#G#H#I#J#G#H#I#J#K#L#M#N#O#P#s#Q#+#f#R#f#f#f#f#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#@@@@y.y.@@@@y.y.W W : : p+z.Y ",
+"S#S#S#S#S#T#S#U#S#T#S#U#S#T#S#U#S#T#S#U#V#W#X#Y#Z#`# $.$+$@$#$g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#@@@@@@@@@@@@@@@@@@y.y.W W : : `.z.A.",
+"+$Z..$$$%$+$&$*$%$+$&$*$%$+$&$*$%$+$&$*$=$-$;$>$,$'$)$!$~${$]$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$/$/$/$/$($($_$_$:$:$p+z.Y ",
+"<$<$<$<$<$[$}$|$<$[$}$|$<$[$}$|$<$[$}$|$1$2$3$4$5$)$6$7$8$9$0$a$a$a$a$a$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$/$/$/$^$^$^$/$/$/$/$/$/$/$/$/$/$/$/$/$/$($($_$_$:$:$`.z.A.",
+"b$c$c$c$d$e$e$f$g$|$|$1$d$e$e$1$d$e$e$1$h$i$j$k$l$m$n$o$p$9$q$a$a$a$a$a$a$a$a$^$a$a$^$^$^$^$^$^$a$r$r$r$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$^$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$($($_$_$:$:$p+z.Y ",
+"e$1$s$s$1$t$u$v$w$x$y$z$A$x$u$v$g$B$C$>$D$E$F$G$H$I$J$K$L$M$N$a$a$a$a$a$a$a$a$^$r$r$a$^$^$^$a$r$r$r$r$r$/$^$r$^$^$^$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$O$($_$_$:$:$`.z.A.",
+"P$Q$R$S$T$U$V$W$X$Y$Z$W$`$ %.%W$+%U$@%#%$%%%&%($*%=%-%;%>%>%,%r$r$r$r$r$a$a$a$/$/$/$r$r$r$r$r$r$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$O$($_$_$:$:$p+z.Y ",
+"'%W$)%!%~%{%'%]%~%^%'%]%~%^%'%]%~%^%/%(%_%&%:%<%[%}%|%1%2%3%4%r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$/$r$/$/$r$r$r$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$/$r$/$/$/$/$/$O$($_$_$:$:$`.z.A.",
+"5%6%'%'%6%7%8%9%6%7%8%9%6%7%8%9%6%7%8%0%&%a%<%b%[%c%d%e%f%g%h%r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$/$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$/$/$/$/$/$/$/$/$/$/$/$/$/$/$r$r$/$/$r$r$/$r$i%j%O$($_$_$:$:$p+z.Y ",
+"k%l%m%n%o%o%p%q%o%o%r%q%o%o%r%q%o%o%p%q%s%t%/$u%v%w%x%y%z%A%B%r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$/$/$/$/$/$/$/$r$r$i%i%i%r$r$i%i%i%i%i%i%i%i%i%i%i%i%r$/$/$j%j%j%j%j%j%j%j%j%O$($_$_$:$:$`.z.A.",
+"C%D%E%F%G%H%I%J%K%H%I%J%K%H%I%J%K%H%I%J%L%M%N%O%P%Q%R%S%T%A%B%r$r$r$r$r$r$r$r$r$r$r$r$r$r$r$U%U%r$r$i%i%/$/$r$r$/$/$/$/$r$r$i%i%i%i%i%i%i%i%i%i%i%i%i%i%j%i%j%j%j%j%j%j%j%j%j%j%j%j%j%O$($_$_$:$:$p+z.Y ",
+"/$/$/$/$V%V%W%X%W%Y%Y%Z%W%W%Y%Z%W%W%W%`%`% &B%.&+&@&#&$&%&A%B%r$r$r$U%U%U%U%r$U%U%U%U%U%U%U%U%U%U%i%i%i%i%i%i%i%i%/$/$/$i%i%i%i%i%i%i%i%i%j%j%j%j%i%i%i%i%i%j%j%j%i%i%j%j%j%j%j%j%j%j%O$($_$_$:$:$`.z.A.",
+"&&*&=&-&=&;&>&,&=&;&>&,&=&;&>&,&=&;&>&'&)&!&~&{&]&^&/&(&_&:&<&U%U%U%U%U%U%U%U%U%U%U%U%U%i%i%U%U%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%O$($_$_$:$:$p+z.Y ",
+"U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%U%[&}&|&1&2&3&4&5&_&6&U%7&U%U%U%U%U%U%U%U%i%i%U%U%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%O$O$_$_$:$:$`.z.A.",
+"U%U%U%U%U%U%[&8&U%9&[&0&U%9&[&0&U%9&[&a&:&b&c&d&e&f&g&h&i&<&j&U%U%U%U%U%U%U%U%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%O$O$_$_$:$:$p+z.Y ",
+"k&l&m&7&7&n&o&p&7&n&q&r&s&s&q&r&s&n&o&p&t&u&u&g&v&w&x&q&n&m&y&7&7&U%U%7&z&7&z&U%A&B&i%i%B&B&i%i%B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&i%B&O$O$_$_$:$:$`.z.A.",
+"C&D&E&z&z&E&F&G&z&E&F&G&z&E&F&G&z&E&F&G&H&I&J&K&L&M&N&O&P&Q&z&z&z&z&z&z&z&z&z&z&z&z&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&O$O$_$_$:$:$p+z.Y ",
+"z&z&z&z&R&S&T&U&R&S&T&U&R&S&T&U&R&S&T&U&V&V&W&X&Y&Z&`&C&R&z&z&z&z&z&z&z&z&z&z&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&O$O$_$_$:$:$^+z.A.",
+"z& *.*+*@*#*$*%*@*#*$*%*@*#*$*%*@*#*$*%*&***=*-*;*>*k&P&+*z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&z&B&B&B&B&z&z&z&B&B&B&z&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&B&/$O$O$@@_$,*:$/ ^+z.Y ",
+"'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*)*'*!*~*{*]*^*^*^*/*/*/*/*/*/*/*^*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*^*/*/*/*/*/*h h ^*h h ^*^*h h ^*^*^*^*h ^*^*^*^*h ^*^*^*(*_*_*_*_*_$:*:$<*`.z.} ",
+"'*'*'*'*'*[*}*|*'*[*}*|*'*[*}*|*'*[*}*|*1*1*2*}*}*2*[*)*3*4*5*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*h h h h h h h h h h h h h h h h 6*7*_*_*_*_*^*:*:$: 8*z.Y } ",
+"9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*( <*8*^+z.Y } 1 ",
+"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*8*b*8*b*8*b*8*b*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*b*8*8*8*8*b*8*`.z.A.Y | | ",
+"c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*c*p+`.p+`.p+`.p+`.`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+`.p+^+`.^+^+z.z.Y Y | | 1 ",
+"d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*d*A.Y A.Y A.Y A.Y Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y A.Y } } | | | | 1 1 ",
+"e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*e*} | } | } | } | | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | } | | | | 1 | | | 1 1 1 "};
+
+
+static char * tabmiddle_xpm[] = {
+"33 42 32 1",
+" c None",
+". c #CECFEF",
+"+ c #CECBE7",
+"@ c #C6C7E7",
+"# c #C6CBE7",
+"$ c #BDBEDE",
+"% c #BDC3DE",
+"& c #CECBEF",
+"* c #B5B6D6",
+"= c #ADAECE",
+"- c #ADB2CE",
+"; c #BDBAD6",
+"> c #B5BAD6",
+", c #C6C3DE",
+"' c #ADAAC6",
+") c #B5B2CE",
+"! c #B5B6CE",
+"~ c #A5A2BD",
+"{ c #A5A6BD",
+"] c #9C9EB5",
+"^ c #9CA2BD",
+"/ c #ADAEC6",
+"( c #C6C3E7",
+"_ c #9C9AB5",
+": c #A5A6C6",
+"< c #949AAD",
+"[ c #A5AAC6",
+"} c #9496AD",
+"| c #BDBADE",
+"1 c #BDBED6",
+"2 c #9CA2B5",
+"3 c #A5AABD",
+"..........................+@.#.#.",
+"........................$@%&#.#..",
+"......................**$$@@&#.#.",
+".....................=-;>,%+@.#..",
+"....................'')!$$@@&#.#.",
+"...................~{=)$$@@&#.#..",
+"..................]^'/;;(%&#.#...",
+"................._]:/*>,%&@.#.#..",
+".................<{[)!$%+@.#.#...",
+"................}~{=!$%@@.#......",
+"................]^/-|$@@.#.......",
+"................]'/*;@@&#........",
+"...............<~[)>,%&#.#.......",
+"...............]~=)$%+#.#........",
+"...............]'/;1@@.#.........",
+"...............~{)*,%&#..........",
+"...............2/-$$@#...........",
+"...............~[*>(@&#..........",
+"...............^=)$%+#...........",
+"...............{'*>(@.#..........",
+"...............^=)$%+#...........",
+"...............{'*>(@.#..........",
+"...............^=)$%+#...........",
+"...............{'*>(@.#..........",
+"...............^=)$%+#...........",
+"...............{'*>(@.#..........",
+"...............^=)$%+#...........",
+"...............{'*>@@.#..........",
+"...............^=!$%&#...........",
+"...............{/*;@@.#..........",
+"...............{)!$%&#...........",
+"..............]'/;1@@.#..........",
+"..............23)>,%&#...........",
+"..............~=-$$@@.#..........",
+".............]{/*;@@.#...........",
+"............<^[)>,%&#............",
+"............]{/!$%@@.#...........",
+"..........]^[-!$%@@.#............",
+".........]^3/!>$@@.#.............",
+".......<]^3/!>$@@&#..............",
+".....<]2{[/!>$%@&#.#.............",
+"}<<_]2{3/-!>$%@&#.#.............."};
+
+
+static char * tabselectedbeginn_xpm[] = {
+"33 39 28 1",
+" c None",
+". c #CECFEF",
+"+ c #EFF3EF",
+"@ c #FFFBFF",
+"# c #F7FBF7",
+"$ c #FFFFFF",
+"% c #EFEFEF",
+"& c #F7F7F7",
+"* c #DEDFDE",
+"= c #E7E7E7",
+"- c #D6D3D6",
+"; c #DEE3DE",
+"> c #EFEBEF",
+", c #F7F3F7",
+"' c #CECBCE",
+") c #CECFCE",
+"! c #D6D7D6",
+"~ c #DEDBDE",
+"{ c #E7EBE7",
+"] c #C6C7C6",
+"^ c #E7E3E7",
+"/ c #BDC3BD",
+"( c #CED3CE",
+"_ c #BDBABD",
+": c #C6C3C6",
+"< c #C6CBC6",
+"[ c #D6DBD6",
+"} c #BDBEBD",
+"..........................+@#$#$$",
+"........................%%&&@#$#$",
+"......................*==%%&&@#$$",
+"....................--*;>%,&@#$#$",
+"...................')!~={,+@#$#$$",
+"...................]-!^=%%&&@#$#$",
+"................../'(~;>%&&@#$#$$",
+"................._])!*={,&@#$#$$$",
+"................_])~*>%&&$#$$$$$$",
+"................:<![={&&@#$$$$$$$",
+"................:)!^=,+@#$$$$$$$$",
+"...............}'(*^%+@#$#$$$$$$$",
+"...............:<!*>%&&$#$$$$$$$$",
+".............../)!^{,&@#$$$$$$$$$",
+"...............](*^%+@#$$$$$$$$$$",
+"...............]!~=%&&$$$$$$$$$$$",
+"...............'(*=,+@#$$$$$$$$$$",
+"...............<!*>%&&$$$$$$$$$$$",
+"...............'-^=,+@#$$$$$$$$$$",
+"...............<!*>%&#$$$$$$$$$$$",
+"...............'-^=,+@#$$$$$$$$$$",
+"...............<!*>%&#$$$$$$$$$$$",
+"...............'-^=,+@#$$$$$$$$$$",
+"...............<!*>%&#$$$$$$$$$$$",
+"...............'-^=,+@#$$$$$$$$$$",
+"...............<!*>%&#$$$$$$$$$$$",
+"...............'!^=,&@#$$$$$$$$$$",
+"...............<~*>%&#$$$$$$$$$$$",
+"...............)!^{,&@#$$$$$$$$$$",
+"..............])~;%+@#$$$$$$$$$$$",
+"..............]-[={&&$#$$$$$$$$$$",
+".............])!^=,&@#$$$$$$$$$$$",
+"............:'-*^%+@#$$$$$$$$$$$$",
+"............])~*>%&&$#$$$$$$$$$$$",
+"...........:'!*={,&@#$$$$$$$$$$$$",
+"..........:'-~^=,+@#$$$$$$$$$$$$$",
+".......}]'-~^=%,&@#$$$$$$$$$$$$$$",
+".....}:])-~^=%,+@#$#$$$$$$$$$$$$$",
+"}}}:]')-!*^=%,&@#$#$$$$$$$$$$$$$$"};
+
+
+static char * tabselectedend_xpm[] = {
+"33 42 33 1",
+" c None",
+". c #FFFFFF",
+"+ c #CECBE7",
+"@ c #C6C7E7",
+"# c #CECFEF",
+"$ c #C6CBE7",
+"% c #BDBEDE",
+"& c #BDC3DE",
+"* c #CECBEF",
+"= c #B5B6D6",
+"- c #ADAECE",
+"; c #ADB2CE",
+"> c #BDBAD6",
+", c #B5BAD6",
+"' c #C6C3DE",
+") c #ADAAC6",
+"! c #B5B2CE",
+"~ c #B5B6CE",
+"{ c #A5A2BD",
+"] c #A5A6BD",
+"^ c #9C9EB5",
+"/ c #9CA2BD",
+"( c #ADAEC6",
+"_ c #C6C3E7",
+": c #9C9AB5",
+"< c #A5A6C6",
+"[ c #949AAD",
+"} c #A5AAC6",
+"| c #9496AD",
+"1 c #BDBADE",
+"2 c #BDBED6",
+"3 c #9CA2B5",
+"4 c #A5AABD",
+"..........................+@#$#$#",
+"........................%@&*$#$##",
+"......................==%%@@*$#$#",
+".....................-;>,'&+@#$##",
+"....................))!~%%@@*$#$#",
+"...................{]-!%%@@*$#$##",
+"..................^/)(>>_&*$#$###",
+".................:^<(=,'&*@#$#$##",
+".................[]}!~%&+@#$#$###",
+"................|{]-~%&@@#$######",
+"................^/(;1%@@#$#######",
+"................^)(=>@@*$########",
+"...............[{}!,'&*$#$#######",
+"...............^{-!%&+$#$########",
+"...............^)(>2@@#$#########",
+"...............{]!='&*$##########",
+"...............3(;%%@$###########",
+"...............{}=,_@*$##########",
+".............../-!%&+$###########",
+"...............])=,_@#$##########",
+".............../-!%&+$###########",
+"...............])=,_@#$##########",
+".............../-!%&+$###########",
+"...............])=,_@#$##########",
+".............../-!%&+$###########",
+"...............])=,_@#$##########",
+".............../-!%&+$###########",
+"...............])=,@@#$##########",
+".............../-~%&*$###########",
+"...............](=>@@#$##########",
+"...............]!~%&*$###########",
+"..............^)(>2@@#$##########",
+"..............34!,'&*$###########",
+"..............{-;%%@@#$##########",
+".............^](=>@@#$###########",
+"............[/}!,'&*$############",
+"............^](~%&@@#$###########",
+"..........^/};~%&@@#$############",
+".........^/4(~,%@@#$#############",
+".......[^/4(~,%@@*$##############",
+".....[^3]}(~,%&@*$#$#############",
+"|[[:^3]4(;~,%&@*$#$##############"};
+
+
+static char * tabend_xpm[] = {
+"33 42 3 1",
+" c None",
+". c #CECFEF",
+"+ c #FFFFFF",
+"..........................+++++++",
+"........................+++++++++",
+"......................+++++++++++",
+".....................++++++++++++",
+"....................+++++++++++++",
+"...................++++++++++++++",
+"..................+++++++++++++++",
+".................++++++++++++++++",
+".................++++++++++++++++",
+"................+++++++++++++++++",
+"................+++++++++++++++++",
+"................+++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"...............++++++++++++++++++",
+"..............+++++++++++++++++++",
+"..............+++++++++++++++++++",
+"..............+++++++++++++++++++",
+".............++++++++++++++++++++",
+"............+++++++++++++++++++++",
+"............+++++++++++++++++++++",
+"..........+++++++++++++++++++++++",
+".........++++++++++++++++++++++++",
+".......++++++++++++++++++++++++++",
+".....++++++++++++++++++++++++++++",
+"+++++++++++++++++++++++++++++++++"};
+
+
+
+
+QColor fromHsl(QColor c)
+{
+ const qreal h = c.hueF();
+ const qreal s = c.saturationF();
+ const qreal l = c.valueF();
+
+ qreal ca[3] = {0, 0, 0};
+
+ if (s == 0 || h == 1) {
+ // achromatic case
+ ca[0] = ca[1] = ca[2] = l;
+ } else {
+ // chromatic case
+ qreal temp2;
+ if (l < qreal(0.5))
+ temp2 = l * (qreal(1.0) + s);
+ else
+ temp2 = l + s - (l * s);
+
+ const qreal temp1 = (qreal(2.0) * l) - temp2;
+ qreal temp3[3] = { h + (qreal(1.0) / qreal(3.0)),
+ h,
+ h - (qreal(1.0) / qreal(3.0)) };
+
+ for (int i = 0; i != 3; ++i) {
+ if (temp3[i] < qreal(0.0))
+ temp3[i] += qreal(1.0);
+ else if (temp3[i] > qreal(1.0))
+ temp3[i] -= qreal(1.0);
+
+ const qreal sixtemp3 = temp3[i] * qreal(6.0);
+
+ if (sixtemp3 < qreal(1.0))
+ ca[i] = ((temp1 + (temp2 - temp1) * sixtemp3));
+ else if ((temp3[i] * qreal(2.0)) < qreal(1.0))
+ ca[i] = (temp2);
+ else if ((temp3[i] * qreal(3.0)) < qreal(2.0))
+ ca[i] = temp1 + (temp2 -temp1) * (qreal(2.0) /qreal(3.0) - temp3[i]) * qreal(6.0);
+ else ca[i] = temp1;
+ }
+ }
+
+ return QColor::fromRgbF(ca[0], ca[1], ca[2]);
+}
+
+#define Q_MAX_3(a, b, c) ( ( a > b && a > c) ? a : (b > c ? b : c) )
+#define Q_MIN_3(a, b, c) ( ( a < b && a < c) ? a : (b < c ? b : c) )
+
+QColor toHsl(QColor c)
+{
+ QColor color;
+ qreal h;
+ qreal s;
+ qreal l;
+
+ const qreal r = c.redF();
+ const qreal g = c.greenF();
+ const qreal b = c.blueF();
+ const qreal max = Q_MAX_3(r, g, b);
+ const qreal min = Q_MIN_3(r, g, b);
+ const qreal delta = max - min;
+ const qreal delta2 = max + min;
+ const qreal lightness = qreal(0.5) * delta2;
+ l = (lightness);
+ if (qFuzzyIsNull(delta)) {
+ // achromatic case, hue is undefined
+ h = 0;
+ s = 0;
+ } else {
+ // chromatic case
+ qreal hue = 0;
+ if (lightness < qreal(0.5))
+ s = ((delta / delta2));
+ else
+ s = ((delta / (qreal(2.0) - delta2)));
+ if (qFuzzyCompare(r, max)) {
+ hue = ((g - b) /delta);
+ } else if (qFuzzyCompare(g, max)) {
+ hue = (2.0 + (b - r) / delta);
+ } else if (qFuzzyCompare(b, max)) {
+ hue = (4.0 + (r - g) / delta);
+ } else {
+ Q_ASSERT_X(false, "QColor::toHsv", "internal error");
+ }
+ hue *= 60.0;
+ if (hue < 0.0)
+ hue += 360.0;
+ h = (hue * 100);
+ }
+
+ h = h / 36000;
+
+ return QColor::fromHsvF(h, s, l);
+}
+
+void tintColor(QColor &color, QColor tintColor, qreal _saturation)
+{
+ tintColor = toHsl(tintColor);
+ color = toHsl(color);
+ qreal hue = tintColor.hueF();
+
+ qreal saturation = color.saturationF();
+ if (_saturation)
+ saturation = _saturation;
+ qreal lightness = color.valueF();
+ color.setHsvF(hue, saturation, lightness);
+
+ color = fromHsl(color);
+ color.toRgb();
+}
+
+void tintImagePal(QImage *image, QColor color, qreal saturation)
+{
+ QVector<QRgb> colorTable = image->colorTable();
+ for (int i=2;i< colorTable.size();i++) {
+ QColor c(toHsl(colorTable.at(i)));
+ tintColor(c, color, saturation);
+ colorTable[i] = c.rgb();
+ }
+ image->setColorTable(colorTable);
+}
+
+
+void tintImage(QImage *image, QColor color, qreal saturation)
+{
+ *image = image->convertToFormat(QImage::Format_RGB32);
+
+ for (int x = 0; x < image->width(); x++)
+ for (int y = 0; y < image->height(); y++) {
+ QColor c(image->pixel(x,y));
+ tintColor(c, color, saturation);
+ image->setPixel(x, y, c.rgb());
+ }
+}
+
+#endif //Q_WS_WINCE_WM
enum QSliderDirection { SliderUp, SliderDown, SliderLeft, SliderRight };
+#ifdef Q_WS_WINCE_WM
+
+void QWindowsMobileStylePrivate::tintImagesButton(QColor color)
+{
+ if (currentTintButton == color)
+ return;
+
+ imageTabEnd = QImage(tabend_xpm);
+ imageTabSelectedEnd = QImage(tabselectedend_xpm);
+ imageTabSelectedBegin = QImage(tabselectedbeginn_xpm);
+ imageTabMiddle = QImage(tabmiddle_xpm);
+ tintImage(&imageTabEnd, color, 0.0);
+ tintImage(&imageTabSelectedEnd, color, 0.0);
+ tintImage(&imageTabSelectedBegin, color, 0.0);
+ tintImage(&imageTabMiddle, color, 0.0);
+
+ if (!doubleControls) {
+ int height = imageTabMiddle.height() / 2 + 1;
+ imageTabEnd = imageTabEnd.scaledToHeight(height);
+ imageTabMiddle = imageTabMiddle.scaledToHeight(height);
+ imageTabSelectedEnd = imageTabSelectedEnd.scaledToHeight(height);
+ imageTabSelectedBegin = imageTabSelectedBegin.scaledToHeight(height);
+ }
+}
+
+void QWindowsMobileStylePrivate::tintImagesHigh(QColor color)
+{
+ if (currentTintHigh == color)
+ return;
+ currentTintHigh = color;
+ tintListViewHighlight(color);
+ imageScrollbarHandleUpHigh = imageScrollbarHandleUp;
+ imageScrollbarHandleDownHigh = imageScrollbarHandleDown;
+ tintImagePal(&imageScrollbarHandleDownHigh, color, qreal(0.8));
+ tintImagePal(&imageScrollbarHandleUpHigh, color, qreal(0.8));
+}
+
+void QWindowsMobileStylePrivate::tintListViewHighlight(QColor color)
+{
+ imageListViewHighlightCornerRight = QImage(listviewhighcornerright_xpm);
+ tintImage(&imageListViewHighlightCornerRight, color, qreal(0.0));
+
+ imageListViewHighlightCornerLeft = QImage(listviewhighcornerleft_xpm);
+ tintImage(&imageListViewHighlightCornerLeft, color, qreal(0.0));
+
+ imageListViewHighlightMiddle = QImage(listviewhighmiddle_xpm);
+ tintImage(&imageListViewHighlightMiddle, color, qreal(0.0));
+
+ int height = imageListViewHighlightMiddle.height();
+ if (!doubleControls) {
+ height = height / 2;
+ imageListViewHighlightCornerRight = imageListViewHighlightCornerRight.scaledToHeight(height);
+ imageListViewHighlightCornerLeft = imageListViewHighlightCornerLeft.scaledToHeight(height);
+ imageListViewHighlightMiddle = imageListViewHighlightMiddle.scaledToHeight(height);
+ }
+}
+
+#endif //Q_WS_WINCE_WM
+
+void QWindowsMobileStylePrivate::setupWindowsMobileStyle65()
+{
+#ifdef Q_WS_WINCE_WM
+ wm65 = qt_wince_is_windows_mobile_65();
+ if (wm65) {
+ imageScrollbarHandleUp = QImage(sbhandleup_xpm);
+ imageScrollbarHandleDown = QImage(sbhandledown_xpm);
+ imageScrollbarGripUp = QImage(sbgripup_xpm);
+ imageScrollbarGripDown = QImage(sbgripdown_xpm);
+ imageScrollbarGripMiddle = QImage(sbgripmiddle_xpm);
+
+ if (!doubleControls) {
+ imageScrollbarHandleUp = imageScrollbarHandleUp.scaledToHeight(imageScrollbarHandleUp.height() / 2);
+ imageScrollbarHandleDown = imageScrollbarHandleDown.scaledToHeight(imageScrollbarHandleDown.height() / 2);
+ imageScrollbarGripMiddle = imageScrollbarGripMiddle.scaledToHeight(imageScrollbarGripMiddle.height() / 2);
+ imageScrollbarGripUp = imageScrollbarGripUp.scaledToHeight(imageScrollbarGripUp.height() / 2);
+ imageScrollbarGripDown = imageScrollbarGripDown.scaledToHeight(imageScrollbarGripDown.height() / 2);
+ } else {
+ }
+ tintImagesHigh(Qt::blue);
+ }
+#endif //Q_WS_WINCE_WM
+}
+
+void QWindowsMobileStylePrivate::drawTabBarTab(QPainter *painter, const QStyleOptionTab *tab)
+{
+#ifdef Q_WS_WINCE_WM
+ if (wm65) {
+ tintImagesButton(tab->palette.button().color());
+ QRect r;
+ r.setTopLeft(tab->rect.topRight() - QPoint(imageTabMiddle.width(), 0));
+ r.setBottomRight(tab->rect.bottomRight());
+ if (tab->state & QStyle::State_Selected) {
+ painter->fillRect(tab->rect, tab->palette.window());
+ } else {
+ painter->fillRect(tab->rect, QColor(imageTabMiddle.pixel(0,0)));
+ }
+ if (tab->selectedPosition == QStyleOptionTab::NextIsSelected) {
+ painter->drawImage(r, imageTabSelectedBegin);
+ } else if (tab->position == QStyleOptionTab::End ||
+ tab->position == QStyleOptionTab::OnlyOneTab) {
+ if (!(tab->state & QStyle::State_Selected)) {
+ painter->drawImage(r, imageTabEnd);
+ }
+ } else if (tab->state & QStyle::State_Selected) {
+ painter->drawImage(r, imageTabSelectedEnd);
+ } else {
+ painter->drawImage(r, imageTabMiddle);
+ }
+ if (tab->position == QStyleOptionTab::Beginning && ! (tab->state & QStyle::State_Selected)) {
+ painter->drawImage(tab->rect.topLeft() - QPoint(imageTabMiddle.width() * 0.60, 0), imageTabSelectedEnd);
+ }
+ //imageTabBarBig
+ return;
+ }
+#endif //Q_WS_WINCE_WM
+ painter->save();
+ painter->setPen(tab->palette.shadow().color());
+ if (doubleControls) {
+ QPen pen = painter->pen();
+ pen.setWidth(2);
+ pen.setCapStyle(Qt::FlatCap);
+ painter->setPen(pen);
+ }
+ if(tab->shape == QTabBar::RoundedNorth) {
+ if (tab->state & QStyle::State_Selected) {
+ painter->fillRect(tab->rect, tab->palette.light());
+ painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
+ }
+ else {
+ painter->fillRect(tab->rect, tab->palette.button());
+ painter->drawLine(tab->rect.bottomLeft() , tab->rect.bottomRight());
+ painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
+ }
+ }
+ else if(tab->shape == QTabBar::RoundedSouth) {
+ if (tab->state & QStyle::State_Selected) {
+ painter->fillRect(tab->rect.adjusted(0,-2,0,0), tab->palette.light());
+ painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
+ }
+ else {
+ painter->fillRect(tab->rect, tab->palette.button());
+ if (doubleControls)
+ painter->drawLine(tab->rect.topLeft() + QPoint(0,1), tab->rect.topRight() + QPoint(0,1));
+ else
+ painter->drawLine(tab->rect.topLeft(), tab->rect.topRight());
+ painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
+ }
+ }
+ else if(tab->shape == QTabBar::RoundedEast) {
+ if (tab->state & QStyle::State_Selected) {
+ painter->fillRect(tab->rect, tab->palette.light());
+ painter->drawLine(tab->rect.topLeft(), tab->rect.topRight());
+ }
+ else {
+ painter->fillRect(tab->rect, tab->palette.button());
+ painter->drawLine(tab->rect.topLeft(), tab->rect.bottomLeft());
+ painter->drawLine(tab->rect.topLeft(), tab->rect.topRight());
+ }
+ }
+ else if(tab->shape == QTabBar::RoundedWest) {
+ if (tab->state & QStyle::State_Selected) {
+ painter->fillRect(tab->rect, tab->palette.light());
+ painter->drawLine(tab->rect.bottomLeft(), tab->rect.bottomRight());
+ }
+ else {
+ painter->fillRect(tab->rect, tab->palette.button());
+ painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
+ painter->drawLine(tab->rect.bottomLeft(), tab->rect.bottomRight());
+ }
+ }
+ painter->restore();
+}
+
+void QWindowsMobileStylePrivate::drawPanelItemViewSelected(QPainter *painter, const QStyleOptionViewItemV4 *option, QRect rect)
+{
+#ifdef Q_WS_WINCE_WM
+ if (wm65) {
+ QRect r;
+ if (rect.isValid())
+ r = rect;
+ else
+ r = option->rect;
+ tintImagesHigh(option->palette.highlight().color());
+
+ painter->setPen(QColor(Qt::lightGray));
+
+ if (option->viewItemPosition == QStyleOptionViewItemV4::Middle) {
+ painter->drawImage(r, imageListViewHighlightMiddle);
+ } else if (option->viewItemPosition == QStyleOptionViewItemV4::Beginning) {
+ painter->drawImage(r.adjusted(10, 0, 0, 0), imageListViewHighlightMiddle);
+ } else if (option->viewItemPosition == QStyleOptionViewItemV4::End) {
+ painter->drawImage(r.adjusted(0, 0, -10, 0), imageListViewHighlightMiddle);
+ } else {
+ painter->drawImage(r.adjusted(10, 0, -10, 0), imageListViewHighlightMiddle);
+ }
+
+ QImage cornerLeft = imageListViewHighlightCornerLeft;
+ QImage cornerRight = imageListViewHighlightCornerRight;
+
+ int width = r.width() > cornerRight.width() ? r.width() : cornerRight.width();
+
+ if ((width * 2) > r.width()) {
+ width = (r.width() - 5) / 2;
+ }
+
+ cornerLeft = cornerLeft.scaled(width, r.height());
+ cornerRight = cornerRight.scaled(width, r.height());
+
+ if ((option->viewItemPosition == QStyleOptionViewItemV4::Beginning) || (option->viewItemPosition == QStyleOptionViewItemV4::OnlyOne) || !option->viewItemPosition) {
+ painter->drawImage(r.topLeft(), cornerLeft);
+ }
+ if ((option->viewItemPosition == QStyleOptionViewItemV4::End) || (option->viewItemPosition == QStyleOptionViewItemV4::OnlyOne) || !option->viewItemPosition) {
+ painter->drawImage(r.topRight() - QPoint(cornerRight.width(),0), cornerRight);
+ }
+ return;
+ }
+#endif //Q_WS_WINCE_WM
+ QPalette::ColorGroup cg = option->state & QStyle::State_Enabled
+ ? QPalette::Normal : QPalette::Disabled;
+
+ if (rect.isValid())
+ painter->fillRect(rect, option->palette.brush(cg, QPalette::Highlight));
+ else
+ painter->fillRect(option->rect, option->palette.brush(cg, QPalette::Highlight));
+}
+
+void QWindowsMobileStylePrivate::drawScrollbarGrip(QPainter *p, QStyleOptionSlider *newScrollbar, const QStyleOptionComplex *option, bool drawCompleteFrame)
+{
+#ifdef Q_WS_WINCE_WM
+ if (wm65) {
+ if (newScrollbar->orientation == Qt::Horizontal) {
+ QTransform transform;
+ transform.rotate(-90);
+ QRect r = newScrollbar->rect;
+ p->drawImage(r.adjusted(10, 0, -10, 0), imageScrollbarGripMiddle.transformed(transform));
+ p->drawImage(r.topLeft(), imageScrollbarGripUp.transformed(transform));
+ p->drawImage(r.topRight() - QPoint(imageScrollbarGripDown.height() - 1, 0), imageScrollbarGripDown.transformed(transform));
+ } else {
+ QRect r = newScrollbar->rect;
+ p->drawImage(r.adjusted(0, 10, 0, -10), imageScrollbarGripMiddle);
+ p->drawImage(r.topLeft(), imageScrollbarGripUp);
+ p->drawImage(r.bottomLeft() - QPoint(0, imageScrollbarGripDown.height() - 1), imageScrollbarGripDown);
+ }
+ return ;
+ }
+#endif
+ if (newScrollbar->orientation == Qt::Horizontal) {
+ p->fillRect(newScrollbar->rect,option->palette.button());
+ QRect r = newScrollbar->rect;
+ p->drawLine(r.topLeft(), r.bottomLeft());
+ p->drawLine(r.topRight(), r.bottomRight());
+ if (smartphone) {
+ p->drawLine(r.topLeft(), r.topRight());
+ p->drawLine(r.bottomLeft(), r.bottomRight());
+ }
+ }
+ else {
+ p->fillRect(newScrollbar->rect,option->palette.button());
+ QRect r = newScrollbar->rect;
+ p->drawLine(r.topLeft(), r.topRight());
+ p->drawLine(r.bottomLeft(), r.bottomRight());
+ if (smartphone) {
+ p->drawLine(r.topLeft(), r.bottomLeft());
+ p->drawLine(r.topRight(), r.bottomRight());
+ }
+ }
+ if (newScrollbar->state & QStyle::State_HasFocus) {
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(*newScrollbar);
+ fropt.rect.setRect(newScrollbar->rect.x() + 2, newScrollbar->rect.y() + 2,
+ newScrollbar->rect.width() - 5,
+ newScrollbar->rect.height() - 5);
+ }
+ int gripMargin = doubleControls ? 4 : 2;
+ int doubleLines = doubleControls ? 2 : 1;
+ //If there is a frame around the scrollbar (abstractScrollArea),
+ //then the margin is different, because of the missing frame
+ int gripMarginFrame = doubleControls ? 3 : 1;
+ if (drawCompleteFrame)
+ gripMarginFrame = 0;
+ //draw grips
+ if (!smartphone)
+ if (newScrollbar->orientation == Qt::Horizontal) {
+ for (int i = -3; i < 3; i += 2) {
+ p->drawLine(
+ QPoint(newScrollbar->rect.center().x() + i * doubleLines + 1,
+ newScrollbar->rect.top() + gripMargin +gripMarginFrame),
+ QPoint(newScrollbar->rect.center().x() + i * doubleLines + 1,
+ newScrollbar->rect.bottom() - gripMargin));
+ }
+ } else {
+ for (int i = -2; i < 4 ; i += 2) {
+ p->drawLine(
+ QPoint(newScrollbar->rect.left() + gripMargin + gripMarginFrame ,
+ newScrollbar->rect.center().y() + 1 + i * doubleLines - 1),
+ QPoint(newScrollbar->rect.right() - gripMargin,
+ newScrollbar->rect.center().y() + 1 + i * doubleLines - 1));
+ }
+ }
+ if (!smartphone) {
+ QRect r;
+ if (doubleControls)
+ r = option->rect.adjusted(1, 1, -1, 0);
+ else
+ r = option->rect.adjusted(0, 0, -1, 0);
+ if (drawCompleteFrame && doubleControls)
+ r.adjust(0, 0, 0, -1);
+ //Check if the scrollbar is part of an abstractItemView and draw the frame according
+ if (drawCompleteFrame)
+ p->drawRect(r);
+ else
+ if (newScrollbar->orientation == Qt::Horizontal)
+ p->drawLine(r.topLeft(), r.topRight());
+ else
+ p->drawLine(r.topLeft(), r.bottomLeft());
+ }
+}
+
+void QWindowsMobileStylePrivate::drawScrollbarHandleUp(QPainter *p, QStyleOptionSlider *opt, bool completeFrame, bool )
+{
+#ifdef Q_WS_WINCE_WM
+ if (wm65) {
+ tintImagesHigh(opt->palette.highlight().color());
+ QRect r = opt->rect;
+ if (opt->orientation == Qt::Horizontal) {
+ QTransform transform;
+ transform.rotate(-90);
+ if (opt->state & QStyle::State_Sunken)
+ p->drawImage(r.topLeft(), imageScrollbarHandleUpHigh.transformed(transform));
+ else
+ p->drawImage(r.topLeft(), imageScrollbarHandleUp.transformed(transform));
+ } else {
+ if (opt->state & QStyle::State_Sunken)
+ p->drawImage(r.topLeft(), imageScrollbarHandleUpHigh);
+ else
+ p->drawImage(r.topLeft(), imageScrollbarHandleUp);
+ }
+ return ;
+ }
+#endif //Q_WS_WINCE_WM
+
+ QBrush fill = opt->palette.button();
+ if (opt->state & QStyle::State_Sunken)
+ fill = opt->palette.shadow();
+
+ QStyleOption arrowOpt = *opt;
+ if (doubleControls)
+ arrowOpt.rect = opt->rect.adjusted(4, 6, -5, -3);
+ else
+ arrowOpt.rect = opt->rect.adjusted(5, 6, -4, -3);
+
+ bool horizontal = (opt->orientation == Qt::Horizontal);
+
+ if (horizontal) {
+ p->fillRect(opt->rect,fill);
+ QRect r = opt->rect.adjusted(0,0,1,0);
+ p->drawLine(r.topRight(), r.bottomRight());
+ if (doubleControls)
+ arrowOpt.rect.adjust(0, -2 ,0, -2);
+ q_func()->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowLeft, &arrowOpt, p, 0);
+ } else {
+ p->fillRect(opt->rect,fill);
+ QRect r = opt->rect.adjusted(0, 0, 0, 1);
+ p->drawLine(r.bottomLeft(), r.bottomRight());
+ if (completeFrame)
+ arrowOpt.rect.adjust(-2, 0, -2, 0);
+ if (doubleControls)
+ arrowOpt.rect.adjust(0, -4 , 0, -4);
+ if (completeFrame && doubleControls)
+ arrowOpt.rect.adjust(2, 0, 2, 0);
+ q_func()->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowUp, &arrowOpt, p, 0);
+ }
+}
+
+void QWindowsMobileStylePrivate::drawScrollbarHandleDown(QPainter *p, QStyleOptionSlider *opt, bool completeFrame, bool secondScrollBar)
+{
+
+#ifdef Q_WS_WINCE_WM
+ if (wm65) {
+ tintImagesHigh(opt->palette.highlight().color());
+ QRect r = opt->rect;
+ if (opt->orientation == Qt::Horizontal) {
+ QTransform transform;
+ transform.rotate(-90);
+ if (opt->state & QStyle::State_Sunken)
+ p->drawImage(r.topLeft(), imageScrollbarHandleDownHigh.transformed(transform));
+ else
+ p->drawImage(r.topLeft(), imageScrollbarHandleDown.transformed(transform));
+ } else {
+ if (opt->state & QStyle::State_Sunken)
+ p->drawImage(r.topLeft(), imageScrollbarHandleDownHigh);
+ else
+ p->drawImage(r.topLeft(), imageScrollbarHandleDown);
+ }
+ return ;
+ }
+#endif //Q_WS_WINCE_WM
+
+ QBrush fill = opt->palette.button();
+ if (opt->state & QStyle::State_Sunken)
+ fill = opt->palette.shadow();
+
+ QStyleOption arrowOpt = *opt;
+ if (doubleControls)
+ arrowOpt.rect = opt->rect.adjusted(4, 0, -5, 3);
+ else
+ arrowOpt.rect = opt->rect.adjusted(5, 6, -4, -3);
+
+ bool horizontal = (opt->orientation == Qt::Horizontal);
+
+ if (horizontal) {
+ p->fillRect(opt->rect,fill);
+ QRect r = opt->rect.adjusted(0, 0, 0, 0);
+ p->drawLine(r.topLeft(), r.bottomLeft());
+ if (secondScrollBar)
+ p->drawLine(r.topRight(), r.bottomRight());
+ if (doubleControls)
+ arrowOpt.rect.adjust(0, 4, 0, 4 );
+ q_func()->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowRight, &arrowOpt, p, 0);
+ } else {
+ p->fillRect(opt->rect,fill);
+ QRect r = opt->rect.adjusted(0, -1, 0, -1);
+ p->drawLine(r.topLeft(), r.topRight());
+ if (secondScrollBar)
+ p->drawLine(r.bottomLeft() + QPoint(0,1), r.bottomRight() + QPoint(0, 1));
+ if (completeFrame)
+ arrowOpt.rect.adjust(-2, 0, -2, 0);
+ if (doubleControls)
+ arrowOpt.rect.adjust(1, 0, 1, 0 );
+ if (completeFrame && doubleControls)
+ arrowOpt.rect.adjust(1, 0, 1, 0);
+ q_func()->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &arrowOpt, p, 0);
+ }
+}
+
+void QWindowsMobileStylePrivate::drawScrollbarGroove(QPainter *p,const QStyleOptionSlider *opt)
+{
+#ifdef Q_OS_WINCE_WM
+ if (wm65) {
+ p->fillRect(opt->rect, QColor(231, 231, 231));
+ return ;
+ }
+#endif
+ QBrush fill;
+ if (smartphone) {
+ fill = opt->palette.light();
+ p->fillRect(opt->rect, fill);
+ fill = opt->palette.button();
+ QImage image;
+#ifndef QT_NO_IMAGEFORMAT_XPM
+ if (opt->orientation == Qt::Horizontal)
+ image = QImage(vertlines_xpm);
+ else
+ image = QImage(horlines_xpm);
+#endif
+ image.setColor(1, opt->palette.button().color().rgb());
+ fill.setTextureImage(image);
+ }
+ else {
+ fill = opt->palette.light();
+ }
+ p->fillRect(opt->rect, fill);
+}
+
QWindowsMobileStyle::QWindowsMobileStyle(QWindowsMobileStylePrivate &dd) : QWindowsStyle(dd) {
qApp->setEffectEnabled(Qt::UI_FadeMenu, false);
qApp->setEffectEnabled(Qt::UI_AnimateMenu, false);
@@ -685,13 +4512,13 @@ QWindowsMobileStyle::QWindowsMobileStyle() : QWindowsStyle(*new QWindowsMobileSt
QWindowsMobileStylePrivate::QWindowsMobileStylePrivate() :QWindowsStylePrivate() {
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
doubleControls = qt_wince_is_high_dpi();
smartphone = qt_wince_is_smartphone();
#else
doubleControls = false;
smartphone = false;
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
#ifndef QT_NO_IMAGEFORMAT_XPM
@@ -721,6 +4548,9 @@ QWindowsMobileStylePrivate::QWindowsMobileStylePrivate() :QWindowsStylePrivate()
imageNormalize = QImage(normal_small_xpm);
}
+ setupWindowsMobileStyle65();
+
+
imageArrowDownBig = QImage(arrowdown_big_xpm);
imageArrowUpBig = QImage(arrowdown_big_xpm).mirrored();
imageArrowLeftBig = QImage(arrowleft_big_xpm);
@@ -1156,7 +4986,7 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp
case PE_IndicatorSpinPlus:
case PE_IndicatorSpinMinus: {
QRect r = option->rect;
- int fw = pixelMetric(PM_DefaultFrameWidth, option, widget)+2;
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget)+2;
QRect br = r.adjusted(fw, fw, -fw, -fw);
int offset = (option->state & State_Sunken) ? 1 : 0;
int step = (br.width() + 4) / 5;
@@ -1193,8 +5023,8 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp
break;
}
if (option->state & State_Sunken)
- painter->translate(pixelMetric(PM_ButtonShiftHorizontal),
- pixelMetric(PM_ButtonShiftVertical));
+ painter->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal),
+ proxy()->pixelMetric(PM_ButtonShiftVertical));
if (option->state & State_Enabled) {
painter->translate(option->rect.x() + option->rect.width() / 2,
option->rect.y() + option->rect.height() / 2);
@@ -1373,21 +5203,37 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp
}
switch (tab->shape) {
case QTabBar::RoundedNorth:
+#ifdef Q_WS_WINCE_WM
+ if (!d->wm65)
+#endif
+ {
if (d->doubleControls)
- painter->drawLine(rect.topLeft() + QPoint(0, 1), rect.topRight() + QPoint(0, 1));
+ painter->drawLine(rect.topLeft() + QPoint(0, 1), rect.topRight() + QPoint(0, 1));
else
painter->drawLine(rect.topLeft(), rect.topRight());
+ }
break;
case QTabBar::RoundedSouth:
+#ifdef Q_WS_WINCE_WM
+ if (!d->wm65)
+#endif
+ {
if (d->doubleControls)
painter->drawLine(rect.bottomLeft(), rect.bottomRight());
else
painter->drawLine(rect.bottomLeft(), rect.bottomRight());
+ }
break;
case QTabBar::RoundedEast:
+#ifdef Q_WS_WINCE_WM
+ if (!d->wm65)
+#endif
painter->drawLine(rect.topRight(), rect.bottomRight());
break;
case QTabBar::RoundedWest:
+#ifdef Q_WS_WINCE_WM
+ if (!d->wm65)
+#endif
painter->drawLine(rect.topLeft(), rect.bottomLeft());
break;
case QTabBar::TriangularWest:
@@ -1406,6 +5252,47 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp
}
break;
#endif //QT_NO_TABBAR
+#ifndef QT_NO_ITEMVIEWS
+ case PE_PanelItemViewRow:
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
+ QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled
+ ? QPalette::Normal : QPalette::Disabled;
+ if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+
+ if ((vopt->state & QStyle::State_Selected) && proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, option, widget))
+ d->drawPanelItemViewSelected(painter, vopt);
+ else if (vopt->features & QStyleOptionViewItemV2::Alternate)
+ painter->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase));
+ else if (!(vopt->state & QStyle::State_Enabled))
+ painter->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Base));
+ }
+ break;
+ case PE_PanelItemViewItem:
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
+ QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled
+ ? QPalette::Normal : QPalette::Disabled;
+ if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+
+ if (vopt->showDecorationSelected && (vopt->state & QStyle::State_Selected)) {
+ d->drawPanelItemViewSelected(painter, vopt);
+ } else {
+ if (vopt->backgroundBrush.style() != Qt::NoBrush) {
+ QPointF oldBO = painter->brushOrigin();
+ painter->setBrushOrigin(vopt->rect.topLeft());
+ painter->fillRect(vopt->rect, vopt->backgroundBrush);
+ painter->setBrushOrigin(oldBO);
+ }
+
+ if (vopt->state & QStyle::State_Selected) {
+ QRect textRect = proxy()->subElementRect(QStyle::SE_ItemViewItemText, option, widget);
+ d->drawPanelItemViewSelected(painter, vopt, textRect);
+ }
+ }
+ }
+ break;
+#endif //QT_NO_ITEMVIEWS
case PE_FrameWindow: {
QPalette popupPal = option->palette;
@@ -1501,25 +5388,25 @@ void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption
case CE_PushButtonBevel:
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
QRect br = button->rect;
- int dbi = pixelMetric(PM_ButtonDefaultIndicator, button, widget);
+ int dbi = proxy()->pixelMetric(PM_ButtonDefaultIndicator, button, widget);
if (button->features & QStyleOptionButton::AutoDefaultButton)
br.setCoords(br.left() + dbi, br.top() + dbi, br.right() - dbi, br.bottom() - dbi);
QStyleOptionButton tmpBtn = *button;
tmpBtn.rect = br;
- drawPrimitive(PE_PanelButtonCommand, &tmpBtn, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &tmpBtn, painter, widget);
if (button->features & QStyleOptionButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, button, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget);
QRect ir = button->rect;
QStyleOptionButton newButton = *button;
if (d->doubleControls)
newButton.rect = QRect(ir.right() - mbi, ir.height() - 30, mbi, ir.height() - 4);
else
newButton.rect = QRect(ir.right() - mbi, ir.height() - 20, mbi, ir.height() - 4);
- drawPrimitive(PE_IndicatorArrowDown, &newButton, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newButton, painter, widget);
}
if (button->features & QStyleOptionButton::DefaultButton)
- drawPrimitive(PE_FrameDefaultButton, option, painter, widget);
+ proxy()->drawPrimitive(PE_FrameDefaultButton, option, painter, widget);
}
break;
case CE_RadioButton:
@@ -1527,19 +5414,19 @@ void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
bool isRadio = (element == CE_RadioButton);
QStyleOptionButton subopt = *button;
- subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
+ subopt.rect = proxy()->subElementRect(isRadio ? SE_RadioButtonIndicator
: SE_CheckBoxIndicator, button, widget);
- drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
+ proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
&subopt, painter, widget);
- subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
+ subopt.rect = proxy()->subElementRect(isRadio ? SE_RadioButtonContents
: SE_CheckBoxContents, button, widget);
- drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget);
+ proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget);
if (button->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*button);
- fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
+ fropt.rect = proxy()->subElementRect(isRadio ? SE_RadioButtonFocusRect
: SE_CheckBoxFocusRect, button, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
}
break;
@@ -1553,7 +5440,7 @@ void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption
QRect textRect = button->rect;
if (!button->icon.isNull()) {
pix = button->icon.pixmap(button->iconSize, button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled);
- drawItemPixmap(painter, button->rect, alignment, pix);
+ proxy()->drawItemPixmap(painter, button->rect, alignment, pix);
if (button->direction == Qt::RightToLeft)
textRect.setRight(textRect.right() - button->iconSize.width() - 4);
else
@@ -1561,10 +5448,10 @@ void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption
}
if (!button->text.isEmpty()){
if (button->state & State_Enabled)
- drawItemText(painter, textRect, alignment | Qt::TextShowMnemonic,
+ proxy()->drawItemText(painter, textRect, alignment | Qt::TextShowMnemonic,
button->palette, false, button->text, QPalette::WindowText);
else
- drawItemText(painter, textRect, alignment | Qt::TextShowMnemonic,
+ proxy()->drawItemText(painter, textRect, alignment | Qt::TextShowMnemonic,
button->palette, false, button->text, QPalette::Mid);
}
}
@@ -1580,73 +5467,16 @@ void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption
#ifndef QT_NO_TABBAR
case CE_TabBarTab:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
- drawControl(CE_TabBarTabShape, tab, painter, widget);
- drawControl(CE_TabBarTabLabel, tab, painter, widget);
+ proxy()->drawControl(CE_TabBarTabShape, tab, painter, widget);
+ proxy()->drawControl(CE_TabBarTabLabel, tab, painter, widget);
}
break;
case CE_TabBarTabShape:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
+
if (tab->shape == QTabBar::RoundedNorth || tab->shape == QTabBar::RoundedEast ||
tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::RoundedWest) {
-
- painter->save();
- painter->setPen(tab->palette.shadow().color());
- if (d->doubleControls) {
- QPen pen = painter->pen();
- pen.setWidth(2);
- pen.setCapStyle(Qt::FlatCap);
- painter->setPen(pen);
- }
- if(tab->shape == QTabBar::RoundedNorth) {
- if (tab->state & State_Selected) {
- painter->fillRect(tab->rect, tab->palette.light());
- painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
- }
- else {
- painter->fillRect(tab->rect, tab->palette.button());
- painter->drawLine(tab->rect.bottomLeft() , tab->rect.bottomRight());
- painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
- }
- }
- else if(tab->shape == QTabBar::RoundedSouth) {
-
- if (tab->state & State_Selected) {
- painter->fillRect(tab->rect.adjusted(0,-2,0,0), tab->palette.light());
- painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
- }
- else {
- painter->fillRect(tab->rect, tab->palette.button());
- if (d->doubleControls)
- painter->drawLine(tab->rect.topLeft() + QPoint(0,1), tab->rect.topRight() + QPoint(0,1));
- else
- painter->drawLine(tab->rect.topLeft(), tab->rect.topRight());
- painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
- }
- }
- else if(tab->shape == QTabBar::RoundedEast) {
- if (tab->state & State_Selected) {
- painter->fillRect(tab->rect, tab->palette.light());
- painter->drawLine(tab->rect.topLeft(), tab->rect.topRight());
- }
- else {
- painter->fillRect(tab->rect, tab->palette.button());
- painter->drawLine(tab->rect.topLeft(), tab->rect.bottomLeft());
- painter->drawLine(tab->rect.topLeft(), tab->rect.topRight());
- }
- }
- else if(tab->shape == QTabBar::RoundedWest) {
- if (tab->state & State_Selected) {
- painter->fillRect(tab->rect, tab->palette.light());
- painter->drawLine(tab->rect.bottomLeft(), tab->rect.bottomRight());
- }
- else {
- painter->fillRect(tab->rect, tab->palette.button());
- painter->drawLine(tab->rect.topRight(), tab->rect.bottomRight());
- painter->drawLine(tab->rect.bottomLeft(), tab->rect.bottomRight());
- }
- }
-
- painter->restore();
+ d->drawTabBarTab(painter, tab);
} else {
QCommonStyle::drawControl(element, option, painter, widget);
}
@@ -1677,17 +5507,17 @@ void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QRegion clipRegion = painter->clipRegion();
painter->setClipRect(option->rect);
- drawControl(CE_HeaderSection, header, painter, widget);
+ proxy()->drawControl(CE_HeaderSection, header, painter, widget);
QStyleOptionHeader subopt = *header;
- subopt.rect = subElementRect(SE_HeaderLabel, header, widget);
+ subopt.rect = proxy()->subElementRect(SE_HeaderLabel, header, widget);
if (header->state & State_Sunken)
subopt.palette.setColor(QPalette::ButtonText, header->palette.brightText().color());
subopt.state |= QStyle::State_On;
if (subopt.rect.isValid())
- drawControl(CE_HeaderLabel, &subopt, painter, widget);
+ proxy()->drawControl(CE_HeaderLabel, &subopt, painter, widget);
if (header->sortIndicator != QStyleOptionHeader::None) {
- subopt.rect = subElementRect(SE_HeaderArrow, option, widget);
- drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget);
+ subopt.rect = proxy()->subElementRect(SE_HeaderArrow, option, widget);
+ proxy()->drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget);
}
painter->setClipRegion(clipRegion);
}
@@ -1832,14 +5662,14 @@ void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption
painter->setFont(newFont);
QPalette palette = dwOpt->palette;
palette.setColor(QPalette::Window, inactiveCaptionTextColor);
- QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, option, widget);
+ QRect titleRect = proxy()->subElementRect(SE_DockWidgetTitleBarText, option, widget);
if (verticalTitleBar) {
titleRect = QRect(r.left() + rect.bottom()
- titleRect.bottom(),
r.top() + titleRect.left() - rect.left(),
titleRect.height(), titleRect.width());
}
- drawItemText(painter, titleRect,
+ proxy()->drawItemText(painter, titleRect,
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette,
dwOpt->state & State_Enabled, dwOpt->title,
floating ? (active ? QPalette::BrightText : QPalette::Window) : QPalette::WindowText);
@@ -1889,7 +5719,7 @@ void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption
point.rx() += pixw;
if ((button->state & (State_On | State_Sunken)) && button->direction == Qt::RightToLeft)
- point.rx() -= pixelMetric(PM_ButtonShiftHorizontal, option, widget) * 2;
+ point.rx() -= proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget) * 2;
painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap);
@@ -1905,9 +5735,9 @@ void QWindowsMobileStyle::drawControl(ControlElement element, const QStyleOption
tf |= Qt::AlignHCenter;
}
if (button->state & State_Enabled)
- drawItemText(painter, ir, tf, button->palette, true, button->text, colorRole);
+ proxy()->drawItemText(painter, ir, tf, button->palette, true, button->text, colorRole);
else
- drawItemText(painter, ir, tf, button->palette, true, button->text, QPalette::Mid);
+ proxy()->drawItemText(painter, ir, tf, button->palette, true, button->text, QPalette::Mid);
painter->restore();
}
break;
@@ -1927,11 +5757,11 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
int ticks = slider->tickPosition;
- QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget);
- QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget);
+ QRect groove = proxy()->subControlRect(CC_Slider, slider, SC_SliderGroove, widget);
+ QRect handle = proxy()->subControlRect(CC_Slider, slider, SC_SliderHandle, widget);
if ((slider->subControls & SC_SliderGroove) && groove.isValid()) {
int mid = thickness / 2;
@@ -1982,8 +5812,8 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
if (slider->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*slider);
- fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ fropt.rect = proxy()->subElementRect(SE_SliderFocusRect, slider, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
if ((tickAbove && tickBelow) || (!tickAbove && !tickBelow)) {
Qt::BGMode oldMode = painter->backgroundMode();
@@ -2118,26 +5948,8 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
painter->setPen(pen);
}
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ d->drawScrollbarGroove(painter, scrollbar);
// Make a copy here and reset it for each primitive.
- QBrush fill;
- if (d->smartphone) {
- fill = option->palette.light();
- painter->fillRect(option->rect,fill);
- fill = option->palette.button();
- QImage image;
-#ifndef QT_NO_IMAGEFORMAT_XPM
- if (scrollbar->orientation == Qt::Horizontal)
- image = QImage(vertlines_xpm);
- else
- image = QImage(horlines_xpm);
-#endif
- image.setColor(1, option->palette.button().color().rgb());
- fill.setTextureImage(image);
- }
- else {
- fill = option->palette.light();
- }
- painter->fillRect(option->rect,fill);
QStyleOptionSlider newScrollbar = *scrollbar;
State saveFlags = scrollbar->state;
//Check if the scrollbar is part of an abstractItemView and draw the frame according
@@ -2159,209 +5971,34 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
saveFlags |= State_Enabled;
if (scrollbar->subControls & SC_ScrollBarSubLine) {
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarSubLine, widget);
+ newScrollbar.rect = proxy()->subControlRect(control, &newScrollbar, SC_ScrollBarSubLine, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarSubLine))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- QStyleOption arrowOpt = newScrollbar;
- if (d->doubleControls)
- arrowOpt.rect = newScrollbar.rect.adjusted(4, 6, -5, -3);
- else
- arrowOpt.rect = newScrollbar.rect.adjusted(5, 6, -4, -3);
- QBrush fill = option->palette.button();
- if (newScrollbar.state & State_Sunken)
- fill = option->palette.shadow();
- if (scrollbar->orientation == Qt::Horizontal) {
- painter->fillRect(newScrollbar.rect,fill);
- QRect r = newScrollbar.rect.adjusted(0,0,1,0);
- painter->drawLine(r.topRight(), r.bottomRight());
- if (d->doubleControls)
- arrowOpt.rect.adjust(0, -2 ,0, -2);
- drawPrimitive(PE_IndicatorArrowLeft, &arrowOpt, painter, widget);
- }
- else {
- painter->fillRect(newScrollbar.rect,fill);
- QRect r = newScrollbar.rect.adjusted(0, 0, 0, 1);
- painter->drawLine(r.bottomLeft(), r.bottomRight());
- if (drawCompleteFrame)
- arrowOpt.rect.adjust(-2, 0, -2, 0);
- if (d->doubleControls)
- arrowOpt.rect.adjust(0, -4 , 0, -4);
- if (drawCompleteFrame && d->doubleControls)
- arrowOpt.rect.adjust(2, 0, 2, 0);
- drawPrimitive(PE_IndicatorArrowUp, &arrowOpt, painter, widget);
- }
+ d->drawScrollbarHandleUp(painter, &newScrollbar, drawCompleteFrame, secondScrollBar);
}
}
if (scrollbar->subControls & SC_ScrollBarAddLine) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarAddLine, widget);
+ newScrollbar.rect = proxy()->subControlRect(control, &newScrollbar, SC_ScrollBarAddLine, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarAddLine))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- QStyleOption arrowOpt = newScrollbar;
- if (d->doubleControls)
- arrowOpt.rect = newScrollbar.rect.adjusted(4, 0, -5, 3);
- else
- arrowOpt.rect = newScrollbar.rect.adjusted(5, 6, -4, -3);
- QBrush fill = option->palette.button();
- if (newScrollbar.state & State_Sunken)
- fill = option->palette.shadow();
- if (scrollbar->orientation == Qt::Horizontal) {
- painter->fillRect(newScrollbar.rect,fill);
- QRect r = newScrollbar.rect.adjusted(0, 0, 0, 0);
- painter->drawLine(r.topLeft(), r.bottomLeft());
- if (secondScrollBar)
- painter->drawLine(r.topRight(), r.bottomRight());
- if (d->doubleControls)
- arrowOpt.rect.adjust(0, 4, 0, 4 );
- drawPrimitive(PE_IndicatorArrowRight, &arrowOpt, painter, widget);
- }
- else {
- painter->fillRect(newScrollbar.rect,fill);
- QRect r = newScrollbar.rect.adjusted(0, -1, 0, -1);
- painter->drawLine(r.topLeft(), r.topRight());
- if (secondScrollBar)
- painter->drawLine(r.bottomLeft() + QPoint(0,1), r.bottomRight() + QPoint(0, 1));
- if (drawCompleteFrame)
- arrowOpt.rect.adjust(-2, 0, -2, 0);
- if (d->doubleControls)
- arrowOpt.rect.adjust(1, 0, 1, 0 );
- if (drawCompleteFrame && d->doubleControls)
- arrowOpt.rect.adjust(1, 0, 1, 0);
- drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget);
- }
- }
- }
- if (scrollbar->subControls & SC_ScrollBarSubPage) {
- newScrollbar.rect = scrollbar->rect;
- newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarSubPage, widget);
- if (newScrollbar.rect.isValid()) {
- if (!(scrollbar->activeSubControls & SC_ScrollBarSubPage))
- newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- if (scrollbar->orientation == Qt::Horizontal) {
- QRect r = newScrollbar.rect.adjusted(0, 0, 0, 0);
- }
- else{
- QRect r = newScrollbar.rect.adjusted(0, 0, 0, 0);
- }
- }
- }
- if (scrollbar->subControls & SC_ScrollBarAddPage) {
- newScrollbar.rect = scrollbar->rect;
- newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarAddPage, widget);
- if (newScrollbar.rect.isValid()) {
- if (!(scrollbar->activeSubControls & SC_ScrollBarAddPage))
- newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- if (scrollbar->orientation == Qt::Horizontal) {
- QRect r = newScrollbar.rect.adjusted(0, 0, 0, -1);
- }
- else {
- QRect r = newScrollbar.rect.adjusted(0, 0,- 1, 0);
- }
- }
- }
- if (scrollbar->subControls & SC_ScrollBarFirst) {
- newScrollbar.rect = scrollbar->rect;
- newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarFirst, widget);
- if (newScrollbar.rect.isValid()) {
- if (!(scrollbar->activeSubControls & SC_ScrollBarFirst))
- newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- QRect r = newScrollbar.rect;
- }
- }
- if (scrollbar->subControls & SC_ScrollBarLast) {
- newScrollbar.rect = scrollbar->rect;
- newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarLast, widget);
- if (newScrollbar.rect.isValid()) {
- if (!(scrollbar->activeSubControls & SC_ScrollBarLast))
- newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- QRect r = newScrollbar.rect;
+ d->drawScrollbarHandleDown(painter, &newScrollbar, drawCompleteFrame, secondScrollBar);
}
}
if (scrollbar->subControls & SC_ScrollBarSlider) {
- newScrollbar.rect = scrollbar->rect;
- newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(control, &newScrollbar, SC_ScrollBarSlider, widget);
- if (newScrollbar.rect.isValid()) {
- if (!(scrollbar->activeSubControls & SC_ScrollBarSlider))
- newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- if (scrollbar->orientation == Qt::Horizontal) {
- painter->fillRect(newScrollbar.rect,option->palette.button());
- QRect r = newScrollbar.rect;
- painter->drawLine(r.topLeft(), r.bottomLeft());
- painter->drawLine(r.topRight(), r.bottomRight());
- if (d->smartphone) {
- painter->drawLine(r.topLeft(), r.topRight());
- painter->drawLine(r.bottomLeft(), r.bottomRight());
- }
- }
- else {
- painter->fillRect(newScrollbar.rect,option->palette.button());
- QRect r = newScrollbar.rect;
- painter->drawLine(r.topLeft(), r.topRight());
- painter->drawLine(r.bottomLeft(), r.bottomRight());
- if (d->smartphone) {
- painter->drawLine(r.topLeft(), r.bottomLeft());
- painter->drawLine(r.topRight(), r.bottomRight());
- }
- }
- if (scrollbar->state & State_HasFocus) {
- QStyleOptionFocusRect fropt;
- fropt.QStyleOption::operator=(newScrollbar);
- fropt.rect.setRect(newScrollbar.rect.x() + 2, newScrollbar.rect.y() + 2,
- newScrollbar.rect.width() - 5,
- newScrollbar.rect.height() - 5);
- }
- }
- }
- int gripMargin = d->doubleControls ? 4 : 2;
- int doubleLines = d->doubleControls ? 2 : 1;
- //If there is a frame around the scrollbar (abstractScrollArea),
- //then the margin is different, because of the missing frame
- int gripMarginFrame = d->doubleControls ? 3 : 1;
- if (drawCompleteFrame)
- gripMarginFrame = 0;
- //draw grips
- if (!d->smartphone)
- if (scrollbar->orientation == Qt::Horizontal) {
- for (int i = -3; i < 3; i += 2) {
- painter->drawLine(
- QPoint(newScrollbar.rect.center().x() + i * doubleLines + 1,
- newScrollbar.rect.top() + gripMargin +gripMarginFrame),
- QPoint(newScrollbar.rect.center().x() + i * doubleLines + 1,
- newScrollbar.rect.bottom() - gripMargin));
- }
- } else {
- for (int i = -2; i < 4 ; i += 2) {
- painter->drawLine(
- QPoint(newScrollbar.rect.left() + gripMargin + gripMarginFrame ,
- newScrollbar.rect.center().y() + 1 + i * doubleLines - 1),
- QPoint(newScrollbar.rect.right() - gripMargin,
- newScrollbar.rect.center().y() + 1 + i * doubleLines - 1));
- }
- }
- if (!d->smartphone) {
- QRect r;
- if (d->doubleControls)
- r = option->rect.adjusted(1, 1, -1, 0);
- else
- r = option->rect.adjusted(0, 0, -1, 0);
- if (drawCompleteFrame && d->doubleControls)
- r.adjust(0, 0, 0, -1);
- //Check if the scrollbar is part of an abstractItemView and draw the frame according
- if (drawCompleteFrame)
- painter->drawRect(r);
- else
- if (scrollbar->orientation == Qt::Horizontal)
- painter->drawLine(r.topLeft(), r.topRight());
- else
- painter->drawLine(r.topLeft(), r.bottomLeft());
+
+ newScrollbar.rect = scrollbar->rect;
+ newScrollbar.state = saveFlags;
+ newScrollbar.rect = proxy()->subControlRect(control, &newScrollbar, SC_ScrollBarSlider, widget);
+
+ if (newScrollbar.rect.isValid()) {
+ if (!(scrollbar->activeSubControls & SC_ScrollBarSlider))
+ newScrollbar.state &= ~(State_Sunken | State_MouseOver);
+ d->drawScrollbarGrip(painter, &newScrollbar, option, drawCompleteFrame);
+ }
}
}
painter->restore();
@@ -2378,8 +6015,8 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
isTabWidget = (qobject_cast<QTabWidget *>(parent->parentWidget()));
#endif //QT_NO_TABWIDGET
- button = subControlRect(control, toolbutton, SC_ToolButton, widget);
- menuarea = subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(control, toolbutton, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
State buttonFlags = toolbutton->state;
if (buttonFlags & State_AutoRaise) {
if (!(buttonFlags & State_MouseOver)) {
@@ -2396,7 +6033,7 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
if (toolbutton->subControls & SC_ToolButton) {
tool.rect = button;
tool.state = buttonFlags;
- drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
}
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;
@@ -2405,7 +6042,7 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
toolMenu = *toolbutton;
toolMenu.state = menuFlags;
if (buttonFlags & State_Sunken)
- drawPrimitive(PE_PanelButtonTool, &toolMenu, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &toolMenu, painter, widget);
QStyleOption arrowOpt(0);
arrowOpt.rect = tool.rect;
arrowOpt.palette = tool.palette;
@@ -2417,25 +6054,25 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
painter->fillRect(menuarea, option->palette.shadow());
}
arrowOpt.state = flags;
- drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget);
}
if (toolbutton->state & State_HasFocus) {
QStyleOptionFocusRect focusRect;
focusRect.QStyleOption::operator=(*toolbutton);
focusRect.rect.adjust(3, 3, -3, -3);
if (toolbutton->features & QStyleOptionToolButton::Menu)
- focusRect.rect.adjust(0, 0, -pixelMetric(QStyle::PM_MenuButtonIndicator,
+ focusRect.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator,
toolbutton, widget), 0);
- drawPrimitive(PE_FrameFocusRect, &focusRect, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focusRect, painter, widget);
}
QStyleOptionToolButton label = *toolbutton;
if (isTabWidget)
label.state = toolbutton->state;
else
label.state = toolbutton->state & State_Enabled;
- int fw = pixelMetric(PM_DefaultFrameWidth, option, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
label.rect = button.adjusted(fw, fw, -fw, -fw);
- drawControl(CE_ToolButtonLabel, &label, painter, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, painter, widget);
}
break;
@@ -2449,15 +6086,15 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
painter->setFont(font);
QStyleOptionGroupBox groupBoxFont = *groupBox;
groupBoxFont.fontMetrics = QFontMetrics(font);
- QRect textRect = subControlRect(CC_GroupBox, &groupBoxFont, SC_GroupBoxLabel, widget);
- QRect checkBoxRect = subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget).adjusted(0,0,0,0);
+ QRect textRect = proxy()->subControlRect(CC_GroupBox, &groupBoxFont, SC_GroupBoxLabel, widget);
+ QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget).adjusted(0,0,0,0);
if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
QStyleOptionFrameV2 frame;
frame.QStyleOption::operator=(*groupBox);
frame.features = groupBox->features;
frame.lineWidth = groupBox->lineWidth;
frame.midLineWidth = groupBox->midLineWidth;
- frame.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
+ frame.rect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
painter->save();
QRegion region(groupBox->rect);
if (!groupBox->text.isEmpty()) {
@@ -2467,7 +6104,7 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0);
region -= finalRect;
}
- drawPrimitive(PE_FrameGroupBox, &frame, painter, widget);
+ proxy()->drawPrimitive(PE_FrameGroupBox, &frame, painter, widget);
painter->restore();
}
// Draw checkbox
@@ -2475,7 +6112,7 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
QStyleOptionButton box;
box.QStyleOption::operator=(*groupBox);
box.rect = checkBoxRect;
- drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
}
// Draw title
if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
@@ -2491,17 +6128,17 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
alignment |= Qt::TextHideMnemonic;
if (groupBox->state & State_Enabled)
- drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
+ proxy()->drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
groupBox->palette, true, groupBox->text,
textColor.isValid() ? QPalette::NoRole : QPalette::Link);
else
- drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
+ proxy()->drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
groupBox->palette, true, groupBox->text, QPalette::Mid);
if (groupBox->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*groupBox);
fropt.rect = textRect;
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
}
painter->restore();
@@ -2514,11 +6151,11 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
QBrush editBrush = cmb->palette.brush(QPalette::Base);
if ((cmb->subControls & SC_ComboBoxFrame) && cmb->frame)
- qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), pixelMetric(PM_ComboBoxFrameWidth, option, widget), &editBrush);
+ qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_ComboBoxFrameWidth, option, widget), &editBrush);
else
painter->fillRect(option->rect, editBrush);
State flags = State_None;
- QRect ar = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget);
+ QRect ar = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget);
if ((option->state & State_On)) {
painter->fillRect(ar.adjusted(0, 0, 1, 1),cmb->palette.brush(QPalette::Shadow));
}
@@ -2534,9 +6171,9 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
arrowOpt.rect = ar;
arrowOpt.palette = cmb->palette;
arrowOpt.state = flags;
- drawPrimitive(PrimitiveElement(PE_IndicatorArrowDownBig), &arrowOpt, painter, widget);
+ proxy()->drawPrimitive(PrimitiveElement(PE_IndicatorArrowDownBig), &arrowOpt, painter, widget);
if (cmb->subControls & SC_ComboBoxEditField) {
- QRect re = subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget);
+ QRect re = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget);
if (cmb->state & State_HasFocus && !cmb->editable)
painter->fillRect(re.x(), re.y(), re.width(), re.height(),
cmb->palette.brush(QPalette::Highlight));
@@ -2550,11 +6187,11 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
if (cmb->state & State_HasFocus && !cmb->editable) {
QStyleOptionFocusRect focus;
focus.QStyleOption::operator=(*cmb);
- focus.rect = subElementRect(SE_ComboBoxFocusRect, cmb, widget);
+ focus.rect = proxy()->subElementRect(SE_ComboBoxFocusRect, cmb, widget);
focus.state |= State_FocusAtBorder;
focus.backgroundColor = cmb->palette.highlight().color();
if ((option->state & State_On))
- drawPrimitive(PE_FrameFocusRect, &focus, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focus, painter, widget);
}
}
}
@@ -2570,8 +6207,8 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
int primitiveElement;
if (spinBox->frame && (spinBox->subControls & SC_SpinBoxFrame)) {
- QRect r = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxFrame, widget);
- qDrawPlainRect(painter, r, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget),0);
+ QRect r = proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxFrame, widget);
+ qDrawPlainRect(painter, r, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget),0);
}
QPalette shadePal(option->palette);
shadePal.setColor(QPalette::Button, option->palette.light().color());
@@ -2593,13 +6230,13 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
}
primitiveElement = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorArrowUpBig
: PE_IndicatorArrowUpBig);
- copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxUp, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxUp, widget);
if (copy.state & (State_Sunken | State_On))
- qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Shadow));
+ qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Shadow));
else
- qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Base));
- copy.rect.adjust(pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0, -pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0);
- drawPrimitive(PrimitiveElement(primitiveElement), &copy, painter, widget);
+ qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Base));
+ copy.rect.adjust(proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0, -pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0);
+ proxy()->drawPrimitive(PrimitiveElement(primitiveElement), &copy, painter, widget);
}
if (spinBox->subControls & SC_SpinBoxDown) {
copy.subControls = SC_SpinBoxDown;
@@ -2619,23 +6256,23 @@ void QWindowsMobileStyle::drawComplexControl(ComplexControl control, const QStyl
}
primitiveElement = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorArrowDownBig
: PE_IndicatorArrowDownBig);
- copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxDown, widget);
- qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Base));
+ copy.rect = proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxDown, widget);
+ qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Base));
if (copy.state & (State_Sunken | State_On))
- qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Shadow));
+ qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Shadow));
else
- qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(),pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Base));
+ qDrawPlainRect(painter, copy.rect, option->palette.shadow().color(), proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), &copy.palette.brush(QPalette::Base));
copy.rect.adjust(3, 0, -4, 0);
if (primitiveElement == PE_IndicatorArrowUp || primitiveElement == PE_IndicatorArrowDown) {
- int frameWidth = pixelMetric(PM_SpinBoxFrameWidth, option, widget);
+ int frameWidth = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget);
copy.rect = copy.rect.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth);
- drawPrimitive(PrimitiveElement(primitiveElement), &copy, painter, widget);
+ proxy()->drawPrimitive(PrimitiveElement(primitiveElement), &copy, painter, widget);
}
else {
- drawPrimitive(PrimitiveElement(primitiveElement), &copy, painter, widget);
+ proxy()->drawPrimitive(PrimitiveElement(primitiveElement), &copy, painter, widget);
}
if (spinBox->frame && (spinBox->subControls & SC_SpinBoxFrame)) {
- QRect r = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxEditField, widget);
+ QRect r = proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxEditField, widget);
}
}
}
@@ -2660,7 +6297,7 @@ QSize QWindowsMobileStyle::sizeFromContents(ContentsType type, const QStyleOptio
h = newSize.height();
int defwidth = 0;
if (button->features & QStyleOptionButton::AutoDefaultButton)
- defwidth = 2 * pixelMetric(PM_ButtonDefaultIndicator, button, widget);
+ defwidth = 2 * proxy()->pixelMetric(PM_ButtonDefaultIndicator, button, widget);
if (w < 75 + defwidth && button->icon.isNull())
w = 75 + defwidth;
if (h < 23 + defwidth)
@@ -2683,9 +6320,9 @@ QSize QWindowsMobileStyle::sizeFromContents(ContentsType type, const QStyleOptio
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
bool isRadio = (type == CT_RadioButton);
QRect irect = visualRect(button->direction, button->rect,
- subElementRect(isRadio ? SE_RadioButtonIndicator
+ proxy()->subElementRect(isRadio ? SE_RadioButtonIndicator
: SE_CheckBoxIndicator, button, widget));
- int h = pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight
+ int h = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight
: PM_IndicatorHeight, button, widget);
int margins = (!button->icon.isNull() && button->text.isEmpty()) ? 0 : 10;
if (d_func()->doubleControls)
@@ -2697,7 +6334,7 @@ QSize QWindowsMobileStyle::sizeFromContents(ContentsType type, const QStyleOptio
#ifndef QT_NO_COMBOBOX
case CT_ComboBox:
if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- int fw = comboBox->frame ? pixelMetric(PM_ComboBoxFrameWidth, option, widget) * 2 : 0;
+ int fw = comboBox->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, option, widget) * 2 : 0;
newSize = QSize(newSize.width() + fw + 9, newSize.height() + fw-4); //Nine is a magic Number - See CommonStyle for real magic (23)
}
break;
@@ -2705,7 +6342,7 @@ QSize QWindowsMobileStyle::sizeFromContents(ContentsType type, const QStyleOptio
#ifndef QT_NO_SPINBOX
case CT_SpinBox:
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- int fw = spinBox->frame ? pixelMetric(PM_SpinBoxFrameWidth, option, widget) * 2 : 0;
+ int fw = spinBox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget) * 2 : 0;
newSize = QSize(newSize.width() + fw-5, newSize.height() + fw-6);
}
break;
@@ -2719,11 +6356,25 @@ QSize QWindowsMobileStyle::sizeFromContents(ContentsType type, const QStyleOptio
newSize = QSize(newSize.width() + 1, newSize.height());
break;
case CT_TabBarTab:
- newSize += QSize(0,0);
+ if (d_func()->doubleControls)
+ newSize = QSize(newSize.width(), 42);
+ else
+ newSize = QSize(newSize.width(), 21);
break;
case CT_HeaderSection:
newSize += QSize(4, 2);
break;
+#ifndef QT_NO_ITEMVIEWS
+#ifdef Q_WS_WINCE_WM
+ case CT_ItemViewItem:
+ if (d_func()->wm65)
+ if (d_func()->doubleControls)
+ newSize.setHeight(46);
+ else
+ newSize.setHeight(23);
+ break;
+#endif //Q_WS_WINCE_WM
+#endif //QT_NO_ITEMVIEWS
default:
break;
}
@@ -2751,7 +6402,7 @@ QRect QWindowsMobileStyle::subElementRect(SubElement element, const QStyleOption
break;
default:
break;
- #ifndef QT_NO_SLIDER
+#ifndef QT_NO_SLIDER
case SE_SliderFocusRect:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
rect = slider->rect;
@@ -2762,6 +6413,14 @@ QRect QWindowsMobileStyle::subElementRect(SubElement element, const QStyleOption
rect.adjust(-1, -1, 0, 0);
break;
#endif // QT_NO_SLIDER
+#ifndef QT_NO_ITEMVIEWS
+ case SE_ItemViewItemFocusRect:
+#ifdef Q_WS_WINCE_WM
+ if (d->wm65)
+ rect = QRect();
+#endif
+ break;
+#endif //QT_NO_ITEMVIEWS
}
return rect;
}
@@ -2777,10 +6436,19 @@ QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOp
#ifndef QT_NO_SCROLLBAR
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int sliderButtonExtent = pixelMetric(PM_ScrollBarExtent, scrollbar, widget);
- int sliderlen;
+ int sliderButtonExtent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollbar, widget);
float stretchFactor = 1.4f;
int sliderButtonExtentDir = int (sliderButtonExtent * stretchFactor);
+
+#ifdef Q_WS_WINCE_WM
+ if (d->wm65)
+ {
+ sliderButtonExtent = d->imageScrollbarHandleUp.width();
+ sliderButtonExtentDir = d->imageScrollbarHandleUp.height();
+ }
+#endif //Q_WS_WINCE_WM
+
+ int sliderlen;
int maxlen = ((scrollbar->orientation == Qt::Horizontal) ?
scrollbar->rect.width() : scrollbar->rect.height()) - (sliderButtonExtentDir * 2);
// calculate slider length
@@ -2788,7 +6456,7 @@ QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOp
uint range = scrollbar->maximum - scrollbar->minimum;
sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep);
- int slidermin = pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget);
+ int slidermin = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget);
if (sliderlen < slidermin || range > INT_MAX / 2)
sliderlen = slidermin;
if (sliderlen > maxlen)
@@ -2883,7 +6551,7 @@ QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOp
#ifndef QT_NO_TOOLBUTTON
case CC_ToolButton:
if (const QStyleOptionToolButton *toolButton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, toolButton, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolButton, widget);
rect = toolButton->rect;
switch (subControl) {
case SC_ToolButton:
@@ -2909,12 +6577,12 @@ QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOp
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget);
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
switch (subControl) {
case SC_SliderHandle: {
int sliderPos = 0;
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum,
slider->sliderPosition,
@@ -2967,7 +6635,7 @@ QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOp
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
QSize bs;
- int fw = spinBox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinBox, widget) : 0;
+ int fw = spinBox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinBox, widget) : 0;
bs.setHeight(qMax(d->doubleControls ? 28 : 14, (spinBox->rect.height())));
// 1.6 -approximate golden mean
bs.setWidth(qMax(d->doubleControls ? 28 : 14, qMin((bs.height()*7/8), (spinBox->rect.width() / 8))));
@@ -2978,7 +6646,7 @@ QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOp
rx = x - fw;
switch (subControl) {
case SC_SpinBoxUp:
- rect = QRect(x+pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0 , bs.width(), bs.height());
+ rect = QRect(x + proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget), 0 , bs.width(), bs.height());
break;
case SC_SpinBoxDown:
rect = QRect(x + bs.width(), 0, bs.width(), bs.height());
@@ -3028,7 +6696,7 @@ QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOp
}
int frameWidth = 0;
if (groupBox->text.size()) {
- frameWidth = pixelMetric(PM_DefaultFrameWidth, groupBox, widget);
+ frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth, groupBox, widget);
rect = frameRect.adjusted(frameWidth, frameWidth + topHeight + labelMargin, -frameWidth, -frameWidth);
}
else {
@@ -3049,8 +6717,8 @@ QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOp
rect.setHeight(h);
else
rect.setHeight(0);
- int indicatorWidth = pixelMetric(PM_IndicatorWidth, option, widget);
- int indicatorSpace = pixelMetric(PM_CheckBoxLabelSpacing, option, widget) - 1;
+ int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
+ int indicatorSpace = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, option, widget) - 1;
bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox;
int checkBoxSize = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0;
@@ -3064,7 +6732,7 @@ QRect QWindowsMobileStyle::subControlRect(ComplexControl control, const QStyleOp
int left = 2;
// Adjust for check box
if (subControl == SC_GroupBoxCheckBox) {
- int indicatorHeight = pixelMetric(PM_IndicatorHeight, option, widget);
+ int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget);
left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth);
int top = totalRect.top() + (fontMetrics.height() - indicatorHeight) / 2;
totalRect.setRect(left, top, indicatorWidth, indicatorHeight);
@@ -3260,7 +6928,6 @@ int QWindowsMobileStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, co
case PM_RadioButtonLabelSpacing:
ret = d->doubleControls ? 6 * 2 : 6;
break;
- break;
// Returns the number of pixels to use for the business part of the
// slider (i.e., the non-tickmark portion). The remaining space is shared
// equally between the tickmark regions.
@@ -3279,7 +6946,7 @@ int QWindowsMobileStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, co
}
int thick = 8;
if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks)
- thick += pixelMetric(PM_SliderLength, sl, widget) / 4;
+ thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4;
space -= thick;
if (space > 0)
@@ -3301,7 +6968,7 @@ int QWindowsMobileStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, co
d->doubleControls ? ret = 64 : ret = 32;
break;
case PM_IconViewIconSize:
- ret = pixelMetric(PM_LargeIconSize, opt, widget);
+ ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget);
break;
case PM_ToolBarIconSize:
d->doubleControls ? ret = 2 * windowsMobileIconSize : ret = windowsMobileIconSize;
@@ -3322,15 +6989,36 @@ int QWindowsMobileStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, co
d->doubleControls ? ret = 42 : ret = 21;
break;
case PM_ScrollBarSliderMin:
- d->doubleControls ? ret = 36 : ret = 18;
+#ifdef Q_WS_WINCE_WM
+ if (d->wm65)
+#else
+ if (false)
+#endif
+ {
+ d->doubleControls ? ret = 68 : ret = 34;
+ } else {
+ d->doubleControls ? ret = 36 : ret = 18;
+ }
break;
case PM_ScrollBarExtent: {
- //Check if the scrollbar is part of an abstractItemView and set size according
+
if (d->smartphone)
ret = 9;
else
d->doubleControls ? ret = 25 : ret = 13;
+
+#ifdef Q_WS_WINCE_WM
+ if (d->wm65)
+#else
+ if (false)
+#endif
+ {
+ d->doubleControls ? ret = 26 : ret = 13;
+ break;
+ }
+
#ifndef QT_NO_SCROLLAREA
+ //Check if the scrollbar is part of an abstractItemView and set size according
if (widget)
if (QWidget *parent = widget->parentWidget())
if (qobject_cast<QAbstractScrollArea *>(parent->parentWidget()))
@@ -3408,6 +7096,9 @@ int QWindowsMobileStyle::styleHint(StyleHint hint, const QStyleOption *opt, cons
case SH_MenuBar_AltKeyNavigation:
ret = false;
break;
+ case SH_RequestSoftwareInputPanel:
+ ret = RSIP_OnMouseClick;
+ break;
default:
ret = QWindowsStyle::styleHint(hint, opt, widget, returnData);
break;
@@ -3470,6 +7161,10 @@ QPixmap QWindowsMobileStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPi
switch (iconMode) {
case QIcon::Selected: {
+#ifdef Q_WS_WINCE_WM
+ if (d_func()->wm65)
+ return pixmap;
+#endif //Q_WS_WINCE_WM
QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
int imgh = img.height();
int imgw = img.width();
diff --git a/src/gui/styles/qwindowsmobilestyle_p.h b/src/gui/styles/qwindowsmobilestyle_p.h
index 94e42a0..f643937 100644
--- a/src/gui/styles/qwindowsmobilestyle_p.h
+++ b/src/gui/styles/qwindowsmobilestyle_p.h
@@ -67,6 +67,9 @@ public:
QWindowsMobileStylePrivate();
bool doubleControls;
bool smartphone;
+#ifdef Q_WS_WINCE_WM
+ bool wm65;
+#endif
QImage imageRadioButton;
QImage imageRadioButtonChecked;
@@ -85,6 +88,42 @@ public:
QImage imageMaximize;
QImage imageNormalize;
QImage imageMinimize;
+
+ void setupWindowsMobileStyle65();
+
+#ifdef Q_WS_WINCE_WM
+ //Windows Mobile 6.5 images
+ QImage imageScrollbarHandleUp;
+ QImage imageScrollbarHandleDown;
+ QImage imageScrollbarHandleUpHigh;
+ QImage imageScrollbarHandleDownHigh;
+ QImage imageScrollbarGripUp;
+ QImage imageScrollbarGripDown;
+ QImage imageScrollbarGripMiddle;
+ QImage imageListViewHighlightCornerLeft;
+ QImage imageListViewHighlightCornerRight;
+ QImage imageListViewHighlightMiddle;
+ QImage imageTabEnd;
+ QImage imageTabSelectedEnd;
+ QImage imageTabSelectedBegin;
+ QImage imageTabMiddle;
+
+ QColor currentTintHigh;
+ QColor currentTintButton;
+
+ void tintImagesHigh(QColor color);
+ void tintImagesButton(QColor color);
+ void tintListViewHighlight(QColor color);
+
+#endif //Q_WS_WINCE_WM
+
+ void drawScrollbarHandleUp(QPainter *p, QStyleOptionSlider *opt, bool completeFrame = false, bool secondScrollBar = false);
+ void drawScrollbarHandleDown(QPainter *p, QStyleOptionSlider *opt, bool completeFrame = false, bool secondScrollBar = false);
+ void drawScrollbarGroove(QPainter *p, const QStyleOptionSlider *opt);
+ void drawScrollbarGrip(QPainter *p, QStyleOptionSlider *newScrollbar, const QStyleOptionComplex *option, bool drawCompleteFrame);
+ void drawTabBarTab(QPainter *p, const QStyleOptionTab *tab);
+ void drawPanelItemViewSelected(QPainter *painter, const QStyleOptionViewItemV4 *option, QRect rect = QRect());
+
};
QT_END_NAMESPACE
diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp
index 892fbff..31f96c3 100644
--- a/src/gui/styles/qwindowsstyle.cpp
+++ b/src/gui/styles/qwindowsstyle.cpp
@@ -42,6 +42,7 @@
#include "qwindowsstyle.h"
#include "qwindowsstyle_p.h"
#include <private/qpixmapdata_p.h>
+#include <private/qstylehelper_p.h>
#if !defined(QT_NO_STYLE_WINDOWS) || defined(QT_PLUGIN)
@@ -67,6 +68,9 @@
#include "qpixmapcache.h"
#include "qwizard.h"
#include "qlistview.h"
+#include <private/qmath_p.h>
+#include <qmath.h>
+
#ifdef Q_WS_X11
#include "qfileinfo.h"
@@ -117,13 +121,9 @@ static const int windowsSepHeight = 9; // separator item height
static const int windowsItemHMargin = 3; // menu item hor text margin
static const int windowsItemVMargin = 2; // menu item ver text margin
static const int windowsArrowHMargin = 6; // arrow horizontal margin
-static const int windowsTabSpacing = 12; // space between text and tab
-static const int windowsCheckMarkHMargin = 2; // horiz. margins of check mark
static const int windowsRightBorder = 15; // right border on windows
static const int windowsCheckMarkWidth = 12; // checkmarks width on windows
-static bool use2000style = true;
-
enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight };
/*
@@ -265,9 +265,6 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e)
*/
QWindowsStyle::QWindowsStyle() : QCommonStyle(*new QWindowsStylePrivate)
{
-#if defined(Q_OS_WIN32)
- use2000style = QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95;
-#endif
}
/*!
@@ -277,9 +274,6 @@ QWindowsStyle::QWindowsStyle() : QCommonStyle(*new QWindowsStylePrivate)
*/
QWindowsStyle::QWindowsStyle(QWindowsStylePrivate &dd) : QCommonStyle(dd)
{
-#if defined(Q_OS_WIN32)
- use2000style = QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95;
-#endif
}
@@ -301,7 +295,7 @@ void QWindowsStyle::polish(QApplication *app)
QCommonStyle::polish(app);
QWindowsStylePrivate *d = const_cast<QWindowsStylePrivate*>(d_func());
// We only need the overhead when shortcuts are sometimes hidden
- if (!styleHint(SH_UnderlineShortcut, 0) && app)
+ if (!proxy()->styleHint(SH_UnderlineShortcut, 0) && app)
app->installEventFilter(this);
d->activeCaptionColor = app->palette().highlight().color();
@@ -402,7 +396,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
#ifndef QT_NO_SLIDER
case PM_SliderLength:
- ret = 11;
+ ret = int(QStyleHelper::dpiScaled(11.));
break;
// Returns the number of pixels to use for the business part of the
@@ -424,7 +418,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
int thick = 6; // Magic constant to get 5 + 16 + 5
if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks)
- thick += pixelMetric(PM_SliderLength, sl, widget) / 4;
+ thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4;
space -= thick;
if (space > 0)
@@ -450,25 +444,25 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
break;
case PM_SmallIconSize:
- ret = 16;
+ ret = int(QStyleHelper::dpiScaled(16.));
break;
case PM_LargeIconSize:
- ret = 32;
+ ret = int(QStyleHelper::dpiScaled(32.));
break;
case PM_IconViewIconSize:
- ret = pixelMetric(PM_LargeIconSize, opt, widget);
+ ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget);
break;
case PM_ToolBarIconSize:
- ret = 24;
+ ret = int(QStyleHelper::dpiScaled(24.));
break;
case PM_DockWidgetTitleMargin:
- ret = 2;
+ ret = int(QStyleHelper::dpiScaled(2.));
break;
case PM_DockWidgetTitleBarButtonMargin:
- ret = 4;
+ ret = int(QStyleHelper::dpiScaled(4.));
break;
#if defined(Q_WS_WIN)
case PM_DockWidgetFrameWidth:
@@ -550,7 +544,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
ret = 0;
break;
case PM_ToolBarHandleExtent:
- ret = 10;
+ ret = int(QStyleHelper::dpiScaled(10.));
break;
default:
ret = QCommonStyle::pixelMetric(pm, opt, widget);
@@ -1065,6 +1059,8 @@ QPixmap QWindowsStyle::standardPixmap(StandardPixmap standardPixmap, const QStyl
}
}
break;
+ default:
+ break;
}
if (!desktopIcon.isNull()) {
return desktopIcon;
@@ -1133,12 +1129,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid
#endif
break;
case SH_ItemView_ChangeHighlightOnFocus:
-#if defined(Q_WS_WIN)
- if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT)
- ret = 1;
- else
-#endif
- ret = 0;
+ ret = 1;
break;
case SH_ToolBox_SelectedPageTitleBold:
ret = 0;
@@ -1146,36 +1137,34 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid
#if defined(Q_WS_WIN)
case SH_UnderlineShortcut:
+ {
ret = 1;
- if (QSysInfo::WindowsVersion != QSysInfo::WV_95
- && QSysInfo::WindowsVersion != QSysInfo::WV_98
- && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
- BOOL cues;
- SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &cues, 0);
- ret = int(cues);
- // Do nothing if we always paint underlines
- Q_D(const QWindowsStyle);
- if (!ret && widget && d) {
+ BOOL cues = false;
+ SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &cues, 0);
+ ret = int(cues);
+ // Do nothing if we always paint underlines
+ Q_D(const QWindowsStyle);
+ if (!ret && widget && d) {
#ifndef QT_NO_MENUBAR
- const QMenuBar *menuBar = qobject_cast<const QMenuBar *>(widget);
- if (!menuBar && qobject_cast<const QMenu *>(widget)) {
- QWidget *w = QApplication::activeWindow();
- if (w && w != widget)
- menuBar = qFindChild<QMenuBar *>(w);
- }
- // If we paint a menu bar draw underlines if is in the keyboardState
- if (menuBar) {
- if (menuBar->d_func()->keyboardState || d->altDown())
- ret = 1;
- // Otherwise draw underlines if the toplevel widget has seen an alt-press
- } else
-#endif // QT_NO_MENUBAR
- if (d->hasSeenAlt(widget)) {
+ const QMenuBar *menuBar = qobject_cast<const QMenuBar *>(widget);
+ if (!menuBar && qobject_cast<const QMenu *>(widget)) {
+ QWidget *w = QApplication::activeWindow();
+ if (w && w != widget)
+ menuBar = qFindChild<QMenuBar *>(w);
+ }
+ // If we paint a menu bar draw underlines if is in the keyboardState
+ if (menuBar) {
+ if (menuBar->d_func()->keyboardState || d->altDown())
ret = 1;
- }
+ // Otherwise draw underlines if the toplevel widget has seen an alt-press
+ } else
+#endif // QT_NO_MENUBAR
+ if (d->hasSeenAlt(widget)) {
+ ret = 1;
}
}
break;
+ }
#endif
#ifndef QT_NO_RUBBERBAND
case SH_RubberBand_Mask:
@@ -1272,7 +1261,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
p->translate(opt->rect.x(), opt->rect.y());
if (opt->state & State_Horizontal) {
int x = opt->rect.width() / 2 - 4;
- if (QApplication::layoutDirection() == Qt::RightToLeft)
+ if (opt->direction == Qt::RightToLeft)
x -= 2;
if (opt->rect.height() > 4) {
qDrawShadePanel(p, x, 2, 3, opt->rect.height() - 4,
@@ -1313,7 +1302,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
if ((!(opt->state & State_Sunken ))
&& (!(opt->state & State_Enabled)
|| !(opt->state & State_MouseOver && opt->state & State_AutoRaise))
- && (opt->state & State_On) && use2000style) {
+ && (opt->state & State_On)) {
fill = QBrush(opt->palette.light().color(), Qt::Dense4Pattern);
stippled = true;
} else {
@@ -1386,11 +1375,8 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
QRect r = opt->rect;
int size = qMin(r.height(), r.width());
QPixmap pixmap;
- QString pixmapName;
- pixmapName.sprintf("%s-%s-%d-%d-%d-%lld",
- "$qt_ia", metaObject()->className(),
- uint(opt->state), pe,
- size, opt->palette.cacheKey());
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("$qt_ia-") + QLatin1String(metaObject()->className()), opt, QSize(size, size))
+ + QLatin1Char('-') + QString::number(pe);
if (!QPixmapCache::find(pixmapName, pixmap)) {
int border = size/5;
int sqsize = 2*(size/2);
@@ -1420,8 +1406,8 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
int bsy = 0;
if (opt->state & State_Sunken) {
- bsx = pixelMetric(PM_ButtonShiftHorizontal, opt, w);
- bsy = pixelMetric(PM_ButtonShiftVertical, opt, w);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, w);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt, w);
}
QRect bounds = a.boundingRect();
@@ -1510,7 +1496,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
case PE_FrameFocusRect:
if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt)) {
//### check for d->alt_down
- if (!(fropt->state & State_KeyboardFocusChange) && !styleHint(SH_UnderlineShortcut, opt))
+ if (!(fropt->state & State_KeyboardFocusChange) && !proxy()->styleHint(SH_UnderlineShortcut, opt))
return;
QRect r = opt->rect;
p->save();
@@ -1577,8 +1563,8 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
//center when rect is larger than indicator size
int xOffset = 0;
int yOffset = 0;
- int indicatorWidth = pixelMetric(PM_ExclusiveIndicatorWidth);
- int indicatorHeight = pixelMetric(PM_ExclusiveIndicatorWidth);
+ int indicatorWidth = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth);
+ int indicatorHeight = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth);
if (ir.width() > indicatorWidth)
xOffset += (ir.width() - indicatorWidth)/2;
if (ir.height() > indicatorHeight)
@@ -1627,9 +1613,9 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
popupPal.setColor(QPalette::Light, frame->palette.background().color());
popupPal.setColor(QPalette::Midlight, frame->palette.light().color());
}
- if (use2000style && pe == PE_Frame && (frame->state & State_Raised))
+ if (pe == PE_Frame && (frame->state & State_Raised))
qDrawWinButton(p, frame->rect, popupPal, frame->state & State_Sunken);
- else if (use2000style && pe == PE_Frame && (frame->state & State_Sunken))
+ else if (pe == PE_Frame && (frame->state & State_Sunken))
{
popupPal.setColor(QPalette::Midlight, frame->palette.background().color());
qDrawWinPanel(p, frame->rect, popupPal, frame->state & State_Sunken);
@@ -1735,7 +1721,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
break; }
case PE_FrameDockWidget:
if (qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
- drawPrimitive(QStyle::PE_FrameWindow, opt, p, w);
+ proxy()->drawPrimitive(QStyle::PE_FrameWindow, opt, p, w);
}
break;
#endif // QT_NO_DOCKWIDGET
@@ -1754,7 +1740,7 @@ case PE_FrameDockWidget:
}
int space = 2;
- int chunksize = pixelMetric(PM_ProgressBarChunkWidth, opt, w) - space;
+ int chunksize = proxy()->pixelMetric(PM_ProgressBarChunkWidth, opt, w) - space;
if (!vertical) {
if (opt->rect.width() <= chunksize)
space = 0;
@@ -1780,13 +1766,12 @@ case PE_FrameDockWidget:
break;
#endif // QT_NO_PROGRESSBAR
- case PE_FrameTabWidget:
- if (use2000style) {
- QRect rect = opt->rect;
- QPalette pal = opt->palette;
- qDrawWinButton(p, opt->rect, opt->palette, false, 0);
- break;
- }
+ case PE_FrameTabWidget: {
+ QRect rect = opt->rect;
+ QPalette pal = opt->palette;
+ qDrawWinButton(p, opt->rect, opt->palette, false, 0);
+ break;
+ }
default:
QCommonStyle::drawPrimitive(pe, opt, p, w);
}
@@ -1813,7 +1798,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->save();
QRect r = opt->rect;
QStyleHintReturnMask mask;
- if (styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
+ if (proxy()->styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
p->setClipRegion(mask.region);
p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap);
p->restore();
@@ -1882,9 +1867,9 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
mode = QIcon::Active;
QPixmap pixmap;
if (checked)
- pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, opt, widget), mode, QIcon::On);
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, widget), mode, QIcon::On);
else
- pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, opt, widget), mode);
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, widget), mode);
int pixw = pixmap.width();
int pixh = pixmap.height();
if (act && !dis && !checked)
@@ -1903,7 +1888,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
newMi.state |= State_On;
newMi.rect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x() + windowsItemFrame, menuitem->rect.y() + windowsItemFrame,
checkcol - 2 * windowsItemFrame, menuitem->rect.height() - 2*windowsItemFrame));
- drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
}
p->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color());
@@ -1922,13 +1907,13 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->save();
int t = s.indexOf(QLatin1Char('\t'));
int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
text_flags |= Qt::TextHideMnemonic;
text_flags |= Qt::AlignLeft;
if (t >= 0) {
QRect vShortcutRect = visualRect(opt->direction, menuitem->rect,
QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
- if (dis && !act && styleHint(SH_EtchDisabledText, opt, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1));
p->setPen(discol);
@@ -1940,7 +1925,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
font.setBold(true);
p->setFont(font);
- if (dis && !act && styleHint(SH_EtchDisabledText, opt, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t));
p->setPen(discol);
@@ -1960,7 +1945,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
if (act)
newMI.palette.setColor(QPalette::ButtonText,
newMI.palette.highlightedText().color());
- drawPrimitive(arrow, &newMI, p, widget);
+ proxy()->drawPrimitive(arrow, &newMI, p, widget);
}
}
@@ -1982,8 +1967,8 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
qDrawShadeRect(p, mbi->rect.x(), mbi->rect.y(), mbi->rect.width(),
mbi->rect.height(), mbi->palette, active && down, 1, 0, &b);
if (active && down) {
- newMbi.rect.translate(pixelMetric(PM_ButtonShiftHorizontal, mbi, widget),
- pixelMetric(PM_ButtonShiftVertical, mbi, widget));
+ newMbi.rect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, mbi, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, mbi, widget));
p->setBrushOrigin(p->brushOrigin() - QPoint(1, 1));
}
}
@@ -2017,7 +2002,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
|| (rtlHorTabs
&& tab->selectedPosition
== QStyleOptionTab::PreviousIsSelected));
- int tabBarAlignment = styleHint(SH_TabBar_Alignment, tab, widget);
+ int tabBarAlignment = proxy()->styleHint(SH_TabBar_Alignment, tab, widget);
bool leftAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignLeft)
|| (rtlHorTabs
&& tabBarAlignment == Qt::AlignRight);
@@ -2031,7 +2016,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
QColor dark = tab->palette.dark().color();
QColor shadow = tab->palette.shadow().color();
QColor background = tab->palette.background().color();
- int borderThinkness = pixelMetric(PM_TabBarBaseOverlap, tab, widget);
+ int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
if (selected)
borderThinkness /= 2;
QRect r2(opt->rect);
@@ -2062,10 +2047,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->setPen(light);
p->drawLine(x1, y1 + 2, x1, y2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness));
p->drawPoint(x1 + 1, y1 + 1);
- if (!use2000style) {
- p->setPen(midlight);
- p->drawLine(x1 + 1, y1 + 2, x1 + 1, y2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness));
- }
}
// Top
{
@@ -2073,10 +2054,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
int end = x2 - (nextSelected ? 0 : 2);
p->setPen(light);
p->drawLine(beg, y1, end, y1);
- if (!use2000style) {
- p->setPen(midlight);
- p->drawLine(beg, y1 + 1, end, y1 + 1);
- }
}
// Right
if (lastTab || selected || onlyOne || !nextSelected) {
@@ -2106,10 +2083,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->setPen(light);
p->drawLine(x1, y2 - 2, x1, y1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness));
p->drawPoint(x1 + 1, y2 - 1);
- if (!use2000style) {
- p->setPen(midlight);
- p->drawLine(x1 + 1, y2 - 2, x1 + 1, y1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness));
- }
}
// Bottom
{
@@ -2148,10 +2121,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->setPen(light);
p->drawLine(x1 + 2, y1, x2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1);
p->drawPoint(x1 + 1, y1 + 1);
- if (!use2000style) {
- p->setPen(midlight);
- p->drawLine(x1 + 2, y1 + 1, x2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1 + 1);
- }
}
// Left
{
@@ -2159,10 +2128,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
int end = y2 - (nextSelected ? 0 : 2);
p->setPen(light);
p->drawLine(x1, beg, x1, end);
- if (!use2000style) {
- p->setPen(midlight);
- p->drawLine(x1 + 1, beg, x1 + 1, end);
- }
}
// Bottom
if (lastTab || selected || onlyOne || !nextSelected) {
@@ -2194,11 +2159,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->setPen(light);
p->drawLine(x2 - 2, y1, x1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1);
p->drawPoint(x2 - 1, y1 + 1);
- if (!use2000style) {
- p->setPen(midlight);
- p->drawLine(x2 - 3, y1 + 1, x1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1 + 1);
- p->drawPoint(x2 - 1, y1);
- }
}
// Right
{
@@ -2235,7 +2195,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
#ifndef QT_NO_SCROLLBAR
case CE_ScrollBarSubLine:
case CE_ScrollBarAddLine: {
- if (use2000style && (opt->state & State_Sunken)) {
+ if ((opt->state & State_Sunken)) {
p->setPen(opt->palette.dark().color());
p->setBrush(opt->palette.brush(QPalette::Button));
p->drawRect(opt->rect.adjusted(0, 0, -1, -1));
@@ -2263,7 +2223,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
}
QStyleOption arrowOpt = *opt;
arrowOpt.rect = opt->rect.adjusted(4, 4, -4, -4);
- drawPrimitive(arrow, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(arrow, &arrowOpt, p, widget);
break; }
case CE_ScrollBarAddPage:
case CE_ScrollBarSubPage: {
@@ -2352,7 +2312,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
default:
break;
}
- if(QApplication::layoutDirection() == Qt::RightToLeft){ //reverse layout changes the order of Beginning/end
+ if(opt->direction == Qt::RightToLeft){ //reverse layout changes the order of Beginning/end
bool tmp = paintLeftBorder;
paintRightBorder=paintLeftBorder;
paintLeftBorder=tmp;
@@ -2449,7 +2409,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
int w = rect.width();
if (pb->minimum == 0 && pb->maximum == 0) {
Q_D(const QWindowsStyle);
- const int unit_width = pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
+ const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
QStyleOptionProgressBarV2 pbBits = *pb;
Q_ASSERT(unit_width >0);
@@ -2473,7 +2433,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
for (int i = 0; i < chunksToDraw ; ++i) {
pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight);
pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
- drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
x += reverse ? -unit_width : unit_width;
}
//Draw wrap-around chunks
@@ -2484,7 +2444,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
for (int i = 0; i < chunksToDraw ; ++i) {
pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight);
pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
- drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
x += reverse ? -unit_width : unit_width;
}
}
@@ -2523,7 +2483,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
bool floating = false;
bool active = dwOpt->state & State_Active;
- int menuOffset = 0; //used to center text when floated
QColor inactiveCaptionTextColor = d->inactiveCaptionText;
if (dwOpt->movable) {
QColor left, right;
@@ -2538,7 +2497,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
left = d->inactiveCaptionColor;
right = d->inactiveGradientCaptionColor;
}
- menuOffset = 2;
QBrush fillBrush(left);
if (left != right) {
QPoint p1(r.x(), r.top() + r.height()/2);
@@ -2572,7 +2530,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
r.top() + titleRect.left() - rect.left(),
titleRect.height(), titleRect.width());
}
- drawItemText(p, titleRect,
+ proxy()->drawItemText(p, titleRect,
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette,
dwOpt->state & State_Enabled, dwOpt->title,
floating ? (active ? QPalette::BrightText : QPalette::Window) : QPalette::WindowText);
@@ -2602,11 +2560,11 @@ QRect QWindowsStyle::subElementRect(SubElement sr, const QStyleOption *opt, cons
const QStyleOptionDockWidgetV2 *v2
= qstyleoption_cast<const QStyleOptionDockWidgetV2*>(opt);
bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
- int m = pixelMetric(PM_DockWidgetTitleMargin, opt, w);
+ int m = proxy()->pixelMetric(PM_DockWidgetTitleMargin, opt, w);
if (verticalTitleBar) {
r.adjust(0, 0, 0, -m);
} else {
- if (QApplication::layoutDirection() == Qt::LeftToRight)
+ if (opt->direction == Qt::LeftToRight)
r.adjust(m, 0, 0, 0);
else
r.adjust(0, 0, -m, 0);
@@ -2636,11 +2594,11 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
int ticks = slider->tickPosition;
- QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget);
- QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget);
+ QRect groove = proxy()->subControlRect(CC_Slider, slider, SC_SliderGroove, widget);
+ QRect handle = proxy()->subControlRect(CC_Slider, slider, SC_SliderHandle, widget);
if ((slider->subControls & SC_SliderGroove) && groove.isValid()) {
int mid = thickness / 2;
@@ -2711,7 +2669,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*slider);
fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
if ((tickAbove && tickBelow) || (!tickAbove && !tickBelow)) {
@@ -3023,8 +2981,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
if ((cmb->subControls & SC_ComboBoxFrame)) {
if (cmb->frame) {
QPalette shadePal = opt->palette;
- if (use2000style)
- shadePal.setColor(QPalette::Midlight, shadePal.button().color());
+ shadePal.setColor(QPalette::Midlight, shadePal.button().color());
qDrawWinPanel(p, opt->rect, shadePal, true, &editBrush);
}
else {
@@ -3034,7 +2991,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
if (cmb->subControls & SC_ComboBoxArrow) {
State flags = State_None;
- QRect ar = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget);
+ QRect ar = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget);
bool sunkenArrow = cmb->activeSubControls == SC_ComboBoxArrow
&& cmb->state & State_Sunken;
if (sunkenArrow) {
@@ -3060,11 +3017,11 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
arrowOpt.rect = ar.adjusted(1, 1, -1, -1);
arrowOpt.palette = cmb->palette;
arrowOpt.state = flags;
- drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
}
if (cmb->subControls & SC_ComboBoxEditField) {
- QRect re = subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget);
+ QRect re = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget);
if (cmb->state & State_HasFocus && !cmb->editable)
p->fillRect(re.x(), re.y(), re.width(), re.height(),
cmb->palette.brush(QPalette::Highlight));
@@ -3084,7 +3041,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
focus.rect = subElementRect(SE_ComboBoxFocusRect, cmb, widget);
focus.state |= State_FocusAtBorder;
focus.backgroundColor = cmb->palette.highlight().color();
- drawPrimitive(PE_FrameFocusRect, &focus, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focus, p, widget);
}
}
}
@@ -3098,10 +3055,9 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
bool enabled = opt->state & State_Enabled;
if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) {
QBrush editBrush = sb->palette.brush(QPalette::Base);
- QRect r = subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget);
+ QRect r = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget);
QPalette shadePal = sb->palette;
- if (use2000style)
- shadePal.setColor(QPalette::Midlight, shadePal.button().color());
+ shadePal.setColor(QPalette::Midlight, shadePal.button().color());
qDrawWinPanel(p, r, shadePal, true, &editBrush);
}
@@ -3129,7 +3085,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus
: PE_IndicatorSpinUp);
- copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On),
&copy.palette.brush(QPalette::Button));
copy.rect.adjust(4, 1, -5, -1);
@@ -3137,9 +3093,9 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
QStyleOptionSpinBox lightCopy = copy;
lightCopy.rect.adjust(1, 1, 1, 1);
lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light());
- drawPrimitive(pe, &lightCopy, p, widget);
+ proxy()->drawPrimitive(pe, &lightCopy, p, widget);
}
- drawPrimitive(pe, &copy, p, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
if (sb->subControls & SC_SpinBoxDown) {
@@ -3162,7 +3118,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus
: PE_IndicatorSpinDown);
- copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On),
&copy.palette.brush(QPalette::Button));
copy.rect.adjust(4, 0, -5, -1);
@@ -3170,13 +3126,14 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
QStyleOptionSpinBox lightCopy = copy;
lightCopy.rect.adjust(1, 1, 1, 1);
lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light());
- drawPrimitive(pe, &lightCopy, p, widget);
+ proxy()->drawPrimitive(pe, &lightCopy, p, widget);
}
- drawPrimitive(pe, &copy, p, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
}
break;
#endif // QT_NO_SPINBOX
+
default:
QCommonStyle::drawComplexControl(cc, opt, p, widget);
}
@@ -3195,12 +3152,15 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
h = sz.height();
int defwidth = 0;
if (btn->features & QStyleOptionButton::AutoDefaultButton)
- defwidth = 2 * pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
+ defwidth = 2 * proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
+ int minwidth = int(QStyleHelper::dpiScaled(75.));
+ int minheight = int(QStyleHelper::dpiScaled(23.));
+
#ifndef QT_QWS_SMALL_PUSHBUTTON
- if (w < 75 + defwidth && !btn->text.isEmpty())
- w = 75 + defwidth;
- if (h < 23 + defwidth)
- h = 23 + defwidth;
+ if (w < minwidth + defwidth && !btn->text.isEmpty())
+ w = minwidth + defwidth;
+ if (h < minheight + defwidth)
+ h = minheight + defwidth;
#endif
sz = QSize(w, h);
}
@@ -3220,13 +3180,13 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
}
if (mi->menuItemType != QStyleOptionMenuItem::Separator && !mi->icon.isNull()) {
- int iconExtent = pixelMetric(PM_SmallIconSize, opt, widget);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
sz.setHeight(qMax(sz.height(),
mi->icon.actualSize(QSize(iconExtent, iconExtent)).height()
+ 2 * windowsItemFrame));
}
int maxpmw = mi->maxIconWidth;
- int tabSpacing = use2000style ? 20 :windowsTabSpacing;
+ int tabSpacing = 20;
if (mi->text.contains(QLatin1Char('\t')))
w += tabSpacing;
else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu)
@@ -3380,7 +3340,7 @@ QIcon QWindowsStyle::standardIconImplementation(StandardPixmap standardIcon, con
&& QSysInfo::WindowsVersion < QSysInfo::WV_NT_based
&& pSHGetStockIconInfo)
{
- icon.addPixmap(standardPixmap(SP_VistaShield, option, widget)); //fetches small icon
+ icon.addPixmap(proxy()->standardPixmap(SP_VistaShield, option, widget)); //fetches small icon
QSHSTOCKICONINFO iconInfo; //append large icon
memset(&iconInfo, 0, sizeof(iconInfo));
iconInfo.cbSize = sizeof(iconInfo);
diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp
index 483fb7c..a54c701 100644
--- a/src/gui/styles/qwindowsvistastyle.cpp
+++ b/src/gui/styles/qwindowsvistastyle.cpp
@@ -41,6 +41,7 @@
#include "qwindowsvistastyle.h"
#include "qwindowsvistastyle_p.h"
+#include <private/qstylehelper_p.h>
#if !defined(QT_NO_STYLE_WINDOWSVISTA) || defined(QT_PLUGIN)
@@ -195,17 +196,15 @@ void Animation::paint(QPainter *painter, const QStyleOption *option)
Q_UNUSED(painter);
}
-/*
-* ! \internal
-*
-* Helperfunction to paint the current transition state
-* between two animation frames.
-*
-* The result is a blended image consisting of
-* ((alpha)*_primaryImage) + ((1-alpha)*_secondaryImage)
-*
-*/
+/*! \internal
+
+ Helperfunction to paint the current transition state between two
+ animation frames.
+ The result is a blended image consisting of ((alpha)*_primaryImage)
+ + ((1-alpha)*_secondaryImage)
+
+*/
void Animation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) {
if (_secondaryImage.isNull() || _primaryImage.isNull())
return;
@@ -247,14 +246,11 @@ void Animation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) {
painter->drawImage(rect, _tempImage);
}
-/*
-* ! \internal
-*
-* Paints a transition state. The result will be a mix between the
-* initial and final state of the transition, depending on the
-* time difference between _startTime and current time.
+/*! \internal
+ Paints a transition state. The result will be a mix between the
+ initial and final state of the transition, depending on the time
+ difference between _startTime and current time.
*/
-
void Transition::paint(QPainter *painter, const QStyleOption *option)
{
float alpha = 1.0;
@@ -277,15 +273,11 @@ void Transition::paint(QPainter *painter, const QStyleOption *option)
drawBlendedImage(painter, option->rect, alpha);
}
-/*
-* ! \internal
-*
-* Paints a pulse. The result will be a mix between the
-* primary and secondary pulse images depending on the
-* time difference between _startTime and current time.
+/*! \internal
+ Paints a pulse. The result will be a mix between the primary and
+ secondary pulse images depending on the time difference between
+ _startTime and current time.
*/
-
-
void Pulse::paint(QPainter *painter, const QStyleOption *option)
{
float alpha = 1.0;
@@ -307,31 +299,37 @@ void Pulse::paint(QPainter *painter, const QStyleOption *option)
/*!
- \reimp
- *
- * Animations are used for some state transitions on specific widgets.
- *
- * Only one running animation can exist for a widget at any specific time.
- * Animations can be added through QWindowsVistaStylePrivate::startAnimation(Animation *)
- * and any existing animation on a widget can be retrieved with
- * QWindowsVistaStylePrivate::widgetAnimation(Widget *).
- *
- * Once an animation has been started, QWindowsVistaStylePrivate::timerEvent(QTimerEvent *)
- * will continuously call update() on the widget until it is stopped, meaning that drawPrimitive
- * will be called many times until the transition has completed. During this time, the result
- * will be retrieved by the Animation::paint(...) function and not by the style itself.
- *
- * To determine if a transition should occur, the style needs to know the previous state of the
- * widget as well as the current one. This is solved by updating dynamic properties on the widget
- * every time the function is called.
- *
- * Transitions interrupting existing transitions should always be smooth, so whenever a hover-transition
- * is started on a pulsating button, it uses the current frame of the pulse-animation as the
- * starting image for the hover transition.
- *
+ \internal
+
+ Animations are used for some state transitions on specific widgets.
+
+ Only one running animation can exist for a widget at any specific
+ time. Animations can be added through
+ QWindowsVistaStylePrivate::startAnimation(Animation *) and any
+ existing animation on a widget can be retrieved with
+ QWindowsVistaStylePrivate::widgetAnimation(Widget *).
+
+ Once an animation has been started,
+ QWindowsVistaStylePrivate::timerEvent(QTimerEvent *) will
+ continuously call update() on the widget until it is stopped,
+ meaning that drawPrimitive will be called many times until the
+ transition has completed. During this time, the result will be
+ retrieved by the Animation::paint(...) function and not by the style
+ itself.
+
+ To determine if a transition should occur, the style needs to know
+ the previous state of the widget as well as the current one. This is
+ solved by updating dynamic properties on the widget every time the
+ function is called.
+
+ Transitions interrupting existing transitions should always be
+ smooth, so whenever a hover-transition is started on a pulsating
+ button, it uses the current frame of the pulse-animation as the
+ starting image for the hover transition.
+
*/
void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
- QPainter *painter, const QWidget *widget) const
+ QPainter *painter, const QWidget *widget) const
{
QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
@@ -366,7 +364,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
w->setProperty("_q_stylestate", (int)option->state);
w->setProperty("_q_stylerect", w->rect());
- bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) ||
+ bool doTransition = oldState &&
+ ((state & State_Sunken) != (oldState & State_Sunken) ||
(state & State_On) != (oldState & State_On) ||
(state & State_MouseOver) != (oldState & State_MouseOver));
@@ -403,7 +402,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
// pulsating default button into the intended target state.
if (!anim)
- drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0
+ proxy()->drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0
else // this ensures that we do not recurse in the animation logic above
anim->paint(&startPainter, &opt);
@@ -417,7 +416,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
endImage.fill(0);
QStyleOption opt2 = opt;
opt2.state = option->state;
- drawPrimitive(element, &opt2, &endPainter, 0); // Note that the widget pointer is intentionally 0
+ proxy()->drawPrimitive(element, &opt2, &endPainter, 0); // Note that the widget pointer is intentionally 0
// this ensures that we do not recurse in the animation logic above
t->setEndImage(endImage);
@@ -487,7 +486,12 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
case PE_IndicatorBranch:
{
XPThemeData theme(d->treeViewHelper(), painter, QLatin1String("TREEVIEW"));
- static const int decoration_size = 16;
+ static int decoration_size = 0;
+ if (theme.isValid() && !decoration_size) {
+ SIZE size;
+ pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size);
+ decoration_size = qMax(size.cx, size.cy);
+ }
int mid_h = option->rect.x() + option->rect.width() / 2;
int mid_v = option->rect.y() + option->rect.height() / 2;
int bef_h = mid_h;
@@ -535,17 +539,6 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
}
break;
- case PE_IndicatorToolBarHandle:
- {
- XPThemeData theme;
- if (option->state & State_Horizontal)
- theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPER, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
- else
- theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPERVERT, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
- d->drawBackground(theme);
- }
- break;
-
case PE_FrameMenu:
{
int stateId = option->state & State_Active ? MB_ACTIVE : MB_INACTIVE;
@@ -645,7 +638,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
}
}
if (panel->lineWidth > 0)
- drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
+ proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
return;
}
break;
@@ -694,6 +687,24 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
}
break;
+ case PE_IndicatorToolBarHandle:
+ {
+ XPThemeData theme;
+ QRect rect;
+ if (option->state & State_Horizontal) {
+ theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPER, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
+ rect = option->rect.adjusted(0, 1, 0, -2);
+ rect.setWidth(4);
+ } else {
+ theme = XPThemeData(widget, painter, QLatin1String("REBAR"), RP_GRIPPERVERT, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2));
+ rect = option->rect.adjusted(1, 0, -1, 0);
+ rect.setHeight(4);
+ }
+ theme.rect = rect;
+ d->drawBackground(theme);
+ }
+ break;
+
case PE_IndicatorToolBarSeparator:
{
QPen pen = painter->pen();
@@ -725,7 +736,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
if (const QListView *listview = qobject_cast<const QListView *>(widget)) {
if (listview->viewMode() == QListView::IconMode)
newStyle = true;
- } else if (const QTreeView* treeview = qobject_cast<const QTreeView *>(widget)) {
+ } else if (qobject_cast<const QTreeView *>(widget)) {
newStyle = true;
}
if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) {
@@ -864,11 +875,9 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
/*!
-
- \reimp
+ \internal
see drawPrimitive for comments on the animation support
-
*/
void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const
@@ -934,7 +943,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QPainter startPainter(&startImage);
if (!anim) {
- drawControl(element, &opt, &startPainter, 0 /* Intentional */);
+ proxy()->drawControl(element, &opt, &startPainter, 0 /* Intentional */);
} else {
anim->paint(&startPainter, &opt);
d->stopAnimation(widget);
@@ -945,7 +954,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
endImage.fill(0);
QPainter endPainter(&endImage);
- drawControl(element, option, &endPainter, 0 /* Intentional */);
+ proxy()->drawControl(element, option, &endPainter, 0 /* Intentional */);
t->setEndImage(endImage);
int duration = 0;
HTHEME theme = pOpenThemeData(0, L"Button");
@@ -1047,9 +1056,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QRect ir = subElementRect(SE_PushButtonContents, option, 0);
QStyleOptionButton newBtn = *btn;
newBtn.rect = QStyle::visualRect(option->direction, option->rect,
- QRect(ir.right() - mbiw - 2, (option->rect.height()/2) - (mbih/2),
+ QRect(ir.right() - mbiw - 2,
+ option->rect.top() + (option->rect.height()/2) - (mbih/2),
mbiw + 1, mbih + 1));
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
}
return;
}
@@ -1084,7 +1094,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
XPThemeData theme(widget, painter, QLatin1String("PROGRESS"), vertical ? PP_FILLVERT : PP_FILL);
theme.rect = option->rect;
- bool reverse = bar->direction == Qt::LeftToRight && inverted || bar->direction == Qt::RightToLeft && !inverted;
+ bool reverse = bar->direction == (Qt::LeftToRight && inverted) || (bar->direction == Qt::RightToLeft && !inverted);
QTime current = QTime::currentTime();
if (isIndeterminate) {
@@ -1197,10 +1207,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
break;
QPalette::ColorRole textRole = disabled ? QPalette::Text : QPalette::ButtonText;
- QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
+ QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, mbi, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
//The rect adjustment is a workaround for the menu not really filling its background.
@@ -1229,7 +1239,15 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
case CE_MenuItem:
if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
// windows always has a check column, regardless whether we have an icon or not
- int checkcol = qMax(menuitem->maxIconWidth, 28);
+ int checkcol = 28;
+ {
+ SIZE size;
+ MARGINS margins;
+ XPThemeData theme(widget, 0, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND, MBI_HOT);
+ pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
+ pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins);
+ checkcol = qMax(menuitem->maxIconWidth, int(6 + size.cx + margins.cxLeftWidth + margins.cxRightWidth));
+ }
QColor darkLine = option->palette.background().color().darker(108);
QColor lightLine = option->palette.background().color().lighter(107);
QRect rect = option->rect;
@@ -1254,7 +1272,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
int yoff = y-2 + h / 2;
QPoint p1 = QPoint(x + checkcol, yoff);
QPoint p2 = QPoint(x + w + 6 , yoff);
- int stateId = stateId = MBI_HOT;
+ stateId = MBI_HOT;
QRect subRect(p1.x(), p1.y(), p2.x() - p1.x(), 6);
subRect = QStyle::visualRect(option->direction, option->rect, subRect );
XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPSEPARATOR, stateId, subRect);
@@ -1266,7 +1284,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
menuitem->rect.y(), checkcol - 6, menuitem->rect.height()));
if (act) {
- int stateId = stateId = MBI_HOT;
+ stateId = MBI_HOT;
XPThemeData theme2(widget, painter, QLatin1String("MENU"), MENU_POPUPITEM, stateId, option->rect);
d->drawBackground(theme2);
}
@@ -1274,8 +1292,23 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (checked) {
XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND,
menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect);
+ SIZE size;
+ MARGINS margins;
+ pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
+ pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0,
+ TMT_CONTENTMARGINS, NULL, &margins);
+ QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth ,
+ size.cy + margins.cyBottomHeight + margins.cyTopHeight);
+ checkRect.moveCenter(vCheckRect.center());
+ theme.rect = checkRect;
+
d->drawBackground(theme);
+
if (menuitem->icon.isNull()) {
+ checkRect = QRect(0, 0, size.cx, size.cy);
+ checkRect.moveCenter(theme.rect.center());
+ theme.rect = checkRect;
+
theme.partId = MENU_POPUPCHECK;
bool bullet = menuitem->checkType & QStyleOptionMenuItem::Exclusive;
if (dis)
@@ -1292,9 +1325,9 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
mode = QIcon::Active;
QPixmap pixmap;
if (checked)
- pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
else
- pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode);
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode);
int pixw = pixmap.width();
int pixh = pixmap.height();
QRect pmr(0, 0, pixw, pixh);
@@ -1320,7 +1353,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
painter->save();
int t = s.indexOf(QLatin1Char('\t'));
int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
text_flags |= Qt::TextHideMnemonic;
text_flags |= Qt::AlignLeft;
if (t >= 0) {
@@ -1346,7 +1379,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QStyleOptionMenuItem newMI = *menuitem;
newMI.rect = vSubMenuRect;
newMI.state = dis ? State_None : State_Enabled;
- drawPrimitive(arrow, &newMI, painter, widget);
+ proxy()->drawPrimitive(arrow, &newMI, painter, widget);
}
}
break;
@@ -1371,7 +1404,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
break;
case CE_MenuBarEmptyArea:
{
- int stateId = MBI_NORMAL;
+ stateId = MBI_NORMAL;
if (!(state & State_Enabled))
stateId = MBI_DISABLED;
XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_BARBACKGROUND, stateId, option->rect);
@@ -1416,8 +1449,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
painter->drawRect(rect.adjusted(0, 1, -1, -3));
int buttonMargin = 4;
- int mw = pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
- int fw = pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
+ int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
+ int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
const QDockWidget *dw = qobject_cast<const QDockWidget *>(widget);
bool isFloating = dw != 0 && dw->isFloating();
@@ -1436,7 +1469,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (isFloating) {
titleRect.adjust(0, -fw, 0, 0);
- if (widget != 0 && widget->windowIcon().cacheKey() != qApp->windowIcon().cacheKey())
+ if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey())
titleRect.adjust(titleRect.height() + mw, 0, 0, 0);
} else {
titleRect.adjust(mw, 0, 0, 0);
@@ -1468,7 +1501,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (const QListView *listview = qobject_cast<const QListView *>(widget)) {
if (listview->viewMode() == QListView::IconMode)
newStyle = true;
- } else if (const QTreeView* treeview = qobject_cast<const QTreeView *>(widget)) {
+ } else if (qobject_cast<const QTreeView *>(widget)) {
newStyle = true;
}
if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) {
@@ -1504,7 +1537,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
/*!
- \reimp
+ \internal
see drawPrimitive for comments on the animation support
@@ -1556,7 +1589,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
if (qstyleoption_cast<const QStyleOptionSlider *>(option)) {
QRect oldSliderPos = w->property("_q_stylesliderpos").toRect();
- QRect currentPos = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
w->setProperty("_q_stylesliderpos", currentPos);
if (oldSliderPos != currentPos) {
doTransition = false;
@@ -1587,7 +1620,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
QStyleOptionComboBox startCombo = *combo;
startCombo.state = (QStyle::State)oldState;
startCombo.activeSubControls = (QStyle::SubControl)oldActiveControls;
- drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */);
+ proxy()->drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */);
t->setStartImage(startImage);
} else if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
//This is a workaround for the direct3d engine as it currently has some issues with grabWindow
@@ -1596,7 +1629,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
QStyleOptionSlider startSlider = *slider;
startSlider.state = (QStyle::State)oldState;
startSlider.activeSubControls = (QStyle::SubControl)oldActiveControls;
- drawComplexControl(control, &startSlider, &startPainter, 0 /* Intentional */);
+ proxy()->drawComplexControl(control, &startSlider, &startPainter, 0 /* Intentional */);
t->setStartImage(startImage);
} else {
QPoint offset(0, 0);
@@ -1614,7 +1647,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->startAnimation(t);
endImage.fill(0);
QPainter endPainter(&endImage);
- drawComplexControl(control, option, &endPainter, 0 /* Intentional */);
+ proxy()->drawComplexControl(control, option, &endPainter, 0 /* Intentional */);
t->setEndImage(endImage);
t->setStartTime(QTime::currentTime());
@@ -1653,9 +1686,9 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_ComboBoxArrow) {
- QRect subRect = subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
+ QRect subRect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
XPThemeData theme(widget, painter, QLatin1String("COMBOBOX"));
- theme.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
+ theme.rect = subRect;
partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
if (!(cmb->state & State_Enabled))
@@ -1679,7 +1712,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
btn.rect = option->rect.adjusted(-1, -1, 1, 1);
if (sub & SC_ComboBoxArrow)
btn.features = QStyleOptionButton::HasMenu;
- drawControl(QStyle::CE_PushButton, &btn, painter, widget);
+ proxy()->drawControl(QStyle::CE_PushButton, &btn, painter, widget);
}
}
}
@@ -1696,7 +1729,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
bool isHorz = flags & State_Horizontal;
bool isRTL = option->direction == Qt::RightToLeft;
if (sub & SC_ScrollBarAddLine) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
partId = SBP_ARROWBTN;
if (!(flags & State_Enabled))
stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED);
@@ -1713,7 +1746,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_ScrollBarSubLine) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
partId = SBP_ARROWBTN;
if (!(flags & State_Enabled))
stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED);
@@ -1730,9 +1763,9 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (maxedOut) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
- theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
- theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
+ theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
stateId = SCRBS_DISABLED;
theme.partId = partId;
@@ -1740,7 +1773,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
} else {
if (sub & SC_ScrollBarSubPage) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
@@ -1755,7 +1788,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_ScrollBarAddPage) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
@@ -1770,7 +1803,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_ScrollBarSlider) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken))
@@ -1783,7 +1816,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
stateId = SCRBS_NORMAL;
// Draw handle
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
theme.stateId = stateId;
d->drawBackground(theme);
@@ -1851,7 +1884,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(ftheme);
}
if (sub & SC_SpinBoxUp) {
- theme.rect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
+ theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
partId = SPNP_UP;
if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled))
stateId = UPS_DISABLED;
@@ -1866,7 +1899,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_SpinBoxDown) {
- theme.rect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
+ theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
partId = SPNP_DOWN;
if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled))
stateId = DNS_DISABLED;
@@ -1890,7 +1923,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
}
/*!
- \reimp
+ \internal
*/
QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
const QSize &size, const QWidget *widget) const
@@ -1925,9 +1958,18 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption
return sz;
case CT_MenuItem:
sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget);
- sz.rwidth() += 28;
+ int minimumHeight;
+ {
+ SIZE size;
+ MARGINS margins;
+ XPThemeData theme(widget, 0, QLatin1String("MENU"), MENU_POPUPCHECKBACKGROUND, MBI_HOT);
+ pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size);
+ pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins);
+ minimumHeight = qMax<qint32>(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height());
+ sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth;
+ }
+
if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
- int minimumHeight = qMax<qint32>(22, sz.height());
if (menuitem->menuItemType != QStyleOptionMenuItem::Separator)
sz.setHeight(minimumHeight);
}
@@ -1947,7 +1989,7 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption
{
//Spinbox adds frame twice
sz = QWindowsStyle::sizeFromContents(type, option, size, widget);
- int border = pixelMetric(PM_SpinBoxFrameWidth, option, widget);
+ int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget);
sz -= QSize(2*border, 2*border);
}
return sz;
@@ -1958,7 +2000,7 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption
}
/*!
- \reimp
+ \internal
*/
QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
{
@@ -1973,7 +2015,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
MARGINS borderSize;
HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button");
if (theme) {
- int stateId;
+ int stateId = PBS_NORMAL;
if (!(option->state & State_Enabled))
stateId = PBS_DISABLED;
else if (option->state & State_Sunken)
@@ -1982,10 +2024,8 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
stateId = PBS_HOT;
else if (btn->features & QStyleOptionButton::DefaultButton)
stateId = PBS_DEFAULTED;
- else
- stateId = PBS_NORMAL;
- int border = pixelMetric(PM_DefaultFrameWidth, btn, widget);
+ int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
rect = option->rect.adjusted(border, border, -border, -border);
int result = pGetThemeMargins(theme,
@@ -2012,7 +2052,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
int w = option->rect.width();
int x = option->rect.x();
int y = option->rect.y();
- int margin = pixelMetric(QStyle::PM_HeaderMargin, option, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
XPThemeData theme(widget, 0, QLatin1String("HEADER"), HP_HEADERSORTARROW, HSAS_SORTEDDOWN, option->rect);
@@ -2038,7 +2078,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
case SE_HeaderLabel:
{
- int margin = pixelMetric(QStyle::PM_HeaderMargin, option, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
QRect r = option->rect;
r.setRect(option->rect.x() + margin, option->rect.y() + margin,
option->rect.width() - margin * 2, option->rect.height() - margin * 2);
@@ -2056,7 +2096,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget);
break;
case SE_ItemViewItemDecoration:
- if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))
+ if (qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))
rect.adjust(-2, 0, 2, 0);
break;
case SE_ItemViewItemFocusRect:
@@ -2129,7 +2169,7 @@ static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBa
}
-/*! \reimp */
+/*! \internal */
int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
QStyleHintReturn *returnData) const
{
@@ -2163,7 +2203,7 @@ int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, co
/*!
- \reimp
+ \internal
*/
QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
SubControl subControl, const QWidget *widget) const
@@ -2190,7 +2230,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
rect = cb->rect;
break;
case SC_ComboBoxArrow:
- rect.setRect(cb->editable ? xpos : 0, y , wi - xpos, he);
+ rect.setRect(xpos, y , wi - xpos, he);
break;
case SC_ComboBoxEditField:
rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin);
@@ -2214,7 +2254,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
const int width = tb->rect.width();
int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4;
- const int frameWidth = pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
+ const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0;
const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0;
@@ -2251,7 +2291,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
{
const int controlTop = 6;
const int controlHeight = height - controlTop - 3;
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
if (tb->icon.isNull())
iconSize = QSize(controlHeight, controlHeight);
@@ -2262,6 +2302,8 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
rect = visualRect(option->direction, option->rect, rect);
}
break;
+ default:
+ break;
}
}
break;
@@ -2272,7 +2314,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
}
/*!
- \reimp
+ \internal
*/
bool QWindowsVistaStyle::event(QEvent *e)
{
@@ -2295,7 +2337,7 @@ bool QWindowsVistaStyle::event(QEvent *e)
}
/*!
- \reimp
+ \internal
*/
QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
const QPoint &pos, const QWidget *widget) const
@@ -2307,7 +2349,7 @@ QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl cont
}
/*!
- \reimp
+ \internal
*/
int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{
@@ -2317,9 +2359,9 @@ int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *opti
switch (metric) {
case PM_DockWidgetTitleBarButtonMargin:
- return 5;
+ return int(QStyleHelper::dpiScaled(5.));
case PM_ScrollBarSliderMin:
- return 18;
+ return int(QStyleHelper::dpiScaled(18.));
case PM_MenuHMargin:
case PM_MenuVMargin:
return 0;
@@ -2332,7 +2374,7 @@ int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *opti
}
/*!
- \reimp
+ \internal
*/
QPalette QWindowsVistaStyle::standardPalette() const
{
@@ -2340,7 +2382,7 @@ QPalette QWindowsVistaStyle::standardPalette() const
}
/*!
- \reimp
+ \internal
*/
void QWindowsVistaStyle::polish(QApplication *app)
{
@@ -2348,7 +2390,7 @@ void QWindowsVistaStyle::polish(QApplication *app)
}
/*!
- \reimp
+ \internal
*/
void QWindowsVistaStyle::polish(QWidget *widget)
{
@@ -2402,7 +2444,7 @@ void QWindowsVistaStyle::polish(QWidget *widget)
}
/*!
- \reimp
+ \internal
*/
void QWindowsVistaStyle::unpolish(QWidget *widget)
{
@@ -2435,7 +2477,7 @@ void QWindowsVistaStyle::unpolish(QWidget *widget)
else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
tree->viewport()->setAttribute(Qt::WA_Hover, false);
} else if (qobject_cast<QCommandLinkButton*>(widget)) {
- QFont font = qApp->font("QCommandLinkButton");
+ QFont font = QApplication::font("QCommandLinkButton");
QFont widgetFont = widget->font();
widgetFont.setFamily(font.family()); //Only family set by polish
widget->setFont(widgetFont);
@@ -2444,7 +2486,7 @@ void QWindowsVistaStyle::unpolish(QWidget *widget)
/*!
- \reimp
+ \internal
*/
void QWindowsVistaStyle::unpolish(QApplication *app)
{
@@ -2452,7 +2494,7 @@ void QWindowsVistaStyle::unpolish(QApplication *app)
}
/*!
- \reimp
+ \internal
*/
void QWindowsVistaStyle::polish(QPalette &pal)
{
@@ -2461,7 +2503,7 @@ void QWindowsVistaStyle::polish(QPalette &pal)
}
/*!
- \reimp
+ \internal
*/
QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option,
const QWidget *widget) const
@@ -2530,9 +2572,7 @@ void QWindowsVistaStylePrivate::startAnimation(Animation *t)
bool QWindowsVistaStylePrivate::transitionsEnabled() const
{
BOOL animEnabled = false;
- if (QT_WA_INLINE(SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0),
- SystemParametersInfoA(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0)
- ))
+ if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0))
{
if (animEnabled)
return true;
diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp
index 850fc9f..de63274 100644
--- a/src/gui/styles/qwindowsxpstyle.cpp
+++ b/src/gui/styles/qwindowsxpstyle.cpp
@@ -46,6 +46,7 @@
#include <private/qobject_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qapplication_p.h>
+#include <private/qstylehelper_p.h>
#include <qlibrary.h>
#include <qpainter.h>
#include <qpaintengine.h>
@@ -124,15 +125,14 @@ static PtrIsThemeBackgroundPartiallyTransparent pIsThemeBackgroundPartiallyTrans
// General const values
static const int windowsItemFrame = 2; // menu item frame width
-static const int windowsSepHeight = 9; // separator item height
static const int windowsItemHMargin = 3; // menu item hor text margin
static const int windowsItemVMargin = 0; // menu item ver text margin
static const int windowsArrowHMargin = 6; // arrow horizontal margin
-static const int windowsCheckMarkHMargin = 0; // horiz. margins of check mark
static const int windowsRightBorder = 12; // right border on windows
// External function calls
extern Q_GUI_EXPORT HDC qt_win_display_dc();
+extern QRegion qt_region_from_HRGN(HRGN rgn);
@@ -160,8 +160,7 @@ HTHEME XPThemeData::handle()
htheme = QWindowsXPStylePrivate::handleMap->operator[](name);
if (!htheme) {
- htheme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget),
- (TCHAR*)name.utf16());
+ htheme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget), (wchar_t*)name.utf16());
if (htheme) {
if (!QWindowsXPStylePrivate::handleMap)
QWindowsXPStylePrivate::handleMap = new QMap<QString, HTHEME>;
@@ -260,7 +259,7 @@ void QWindowsXPStylePrivate::cleanup(bool force)
use_xp = false;
cleanupHandleMap();
if (limboWidget) {
- if (qApp->closingDown())
+ if (QApplication::closingDown())
delete limboWidget;
else
limboWidget->deleteLater();
@@ -445,6 +444,7 @@ bool QWindowsXPStylePrivate::isTransparent(XPThemeData &themeData)
themeData.stateId);
}
+
/*! \internal
Returns a QRegion of the region of the part
*/
@@ -456,12 +456,18 @@ QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData)
themeData.stateId, &rect, &hRgn)))
return QRegion();
- QRegion rgn = QRegion(0,0,1,1);
- const bool success = CombineRgn(rgn.handle(), hRgn, 0, RGN_COPY) != ERROR;
- DeleteObject(hRgn);
+ HRGN dest = CreateRectRgn(0, 0, 0, 0);
+ const bool success = CombineRgn(dest, hRgn, 0, RGN_COPY) != ERROR;
+
+ QRegion region;
+
if (success)
- return rgn;
- return QRegion();
+ region = qt_region_from_HRGN(dest);
+
+ DeleteObject(hRgn);
+ DeleteObject(dest);
+
+ return region;
}
/*! \internal
@@ -1025,7 +1031,7 @@ void QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
Most of the functions are documented in the base classes
QWindowsStyle, QCommonStyle, and QStyle, but the
QWindowsXPStyle overloads of drawComplexControl(), drawControl(),
- drawControlMask(), drawPrimitive(), subControlRect(), and
+ drawControlMask(), drawPrimitive(), proxy()->subControlRect(), and
sizeFromContents(), are documented here.
\img qwindowsxpstyle.png
@@ -1192,8 +1198,8 @@ QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option,
QStyleOptionTab otherOption;
otherOption.shape = (twfOption->shape == QTabBar::RoundedNorth
? QTabBar::RoundedEast : QTabBar::RoundedSouth);
- int overlap = pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget);
- int borderThickness = pixelMetric(PM_DefaultFrameWidth, option, widget);
+ int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget);
+ int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
rect.adjust(-overlap + borderThickness, 0, -overlap + borderThickness, 0);
}
break;}
@@ -1217,7 +1223,7 @@ QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option,
else
stateId = PBS_NORMAL;
- int border = pixelMetric(PM_DefaultFrameWidth, btn, widget);
+ int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
rect = option->rect.adjusted(border, border, -border, -border);
int result = pGetThemeMargins(theme,
@@ -1533,7 +1539,7 @@ case PE_Frame:
}
if (panel->lineWidth > 0)
- drawPrimitive(PE_FrameLineEdit, panel, p, widget);
+ proxy()->drawPrimitive(PE_FrameLineEdit, panel, p, widget);
return;
}
break;
@@ -1547,11 +1553,11 @@ case PE_Frame:
if (widget) {
bool useGradient = true;
const int maxlength = 256;
- WCHAR themeFileName[maxlength];
- WCHAR themeColor[maxlength];
+ wchar_t themeFileName[maxlength];
+ wchar_t themeColor[maxlength];
// Due to a a scaling issue with the XP Silver theme, tab gradients are not used with it
if (pGetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) {
- WCHAR* offset;
+ wchar_t *offset = 0;
if ((offset = wcsrchr(themeFileName, QChar(QLatin1Char('\\')).unicode())) != NULL) {
offset++;
if (!lstrcmp(offset, L"Luna.msstyles") && !lstrcmp(offset, L"Metallic")) {
@@ -1618,7 +1624,7 @@ case PE_Frame:
else
stateId = FS_INACTIVE;
- int fwidth = pixelMetric(PM_DockWidgetFrameWidth, frm, widget);
+ int fwidth = proxy()->pixelMetric(PM_DockWidgetFrameWidth, frm, widget);
XPThemeData theme(widget, p, name, 0, stateId);
if (!theme.isValid())
@@ -1792,7 +1798,12 @@ case PE_Frame:
return;
case PE_IndicatorToolBarSeparator:
-
+ if (option->rect.height() < 3) {
+ // XP style requires a few pixels for the separator
+ // to be visible.
+ QWindowsStyle::drawPrimitive(pe, option, p, widget);
+ return;
+ }
name = QLatin1String("TOOLBAR");
partId = TP_SEPARATOR;
@@ -1821,7 +1832,7 @@ case PE_Frame:
QStyleOptionButton button;
button.QStyleOption::operator=(*option);
button.state &= ~State_MouseOver;
- drawPrimitive(PE_IndicatorCheckBox, &button, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, p, widget);
return;
}
@@ -1914,8 +1925,8 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
{
name = QLatin1String("BUTTON");
partId = BP_PUSHBUTTON;
- bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken))
- || (btn->features & QStyleOptionButton::CommandLinkButton
+ bool justFlat = ((btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken)))
+ || ((btn->features & QStyleOptionButton::CommandLinkButton)
&& !(flags & State_MouseOver)
&& !(btn->features & QStyleOptionButton::DefaultButton));
if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat))
@@ -1949,7 +1960,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
QRect ir = btn->rect;
QStyleOptionButton newBtn = *btn;
newBtn.rect = QRect(ir.right() - mbiw - 1, 1 + (ir.height()/2) - (mbih/2), mbiw, mbih);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
return;
}
@@ -1972,10 +1983,10 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
bool lastTab = tab->position == QStyleOptionTab::End;
bool firstTab = tab->position == QStyleOptionTab::Beginning;
bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
- bool leftAligned = styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignLeft;
- bool centerAligned = styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignCenter;
- int borderThickness = pixelMetric(PM_DefaultFrameWidth, option, widget);
- int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget);
+ bool leftAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignLeft;
+ bool centerAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignCenter;
+ int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
+ int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, option, widget);
if (isDisabled)
stateId = TIS_DISABLED;
@@ -2120,8 +2131,8 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
if (act && !dis)
mode = QIcon::Active;
QPixmap pixmap = checked ?
- menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On) :
- menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode);
+ menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On) :
+ menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode);
int pixw = pixmap.width();
int pixh = pixmap.height();
QRect iconRect(0, 0, pixw, pixh);
@@ -2147,7 +2158,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
checkcol - 2 * windowsItemFrame,
menuitem->rect.height() - 2*windowsItemFrame);
newMi.rect = visualRect(option->direction, option->rect, checkMarkRect);
- drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
}
QColor textColor = dis ? menuitem->palette.text().color() :
@@ -2164,12 +2175,12 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
p->save();
int t = s.indexOf(QLatin1Char('\t'));
int text_flags = Qt::AlignVCenter|Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine | Qt::AlignLeft;
- if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
text_flags |= Qt::TextHideMnemonic;
// draw tab text ----------------
if (t >= 0) {
QRect vShortcutRect = visualRect(option->direction, option->rect, QRect(textRect.topRight(), menuitem->rect.bottomRight()));
- if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1));
p->setPen(textColor);
@@ -2181,7 +2192,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
font.setBold(true);
p->setFont(font);
- if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t));
p->setPen(textColor);
@@ -2202,7 +2213,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
newMI.state = dis ? State_None : State_Enabled;
if (act)
newMI.palette.setColor(QPalette::ButtonText, newMI.palette.highlightedText().color());
- drawPrimitive(arrow, &newMI, p, widget);
+ proxy()->drawPrimitive(arrow, &newMI, p, widget);
}
}
return;
@@ -2219,10 +2230,10 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
QBrush fill = mbi->palette.brush(act ? QPalette::Highlight : QPalette::Button);
QPalette::ColorRole textRole = dis ? QPalette::Text:
act ? QPalette::HighlightedText : QPalette::ButtonText;
- QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
+ QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, mbi, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
p->fillRect(rect, fill);
@@ -2237,8 +2248,8 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option))
{
int buttonMargin = 4;
- int mw = pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
- int fw = pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
+ int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
+ int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
bool isFloating = widget && widget->isWindow();
bool isActive = dwOpt->state & State_Active;
@@ -2259,18 +2270,18 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
QRect titleRect = r;
if (dwOpt->closable) {
- QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10));
+ QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10));
titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
}
if (dwOpt->floatable) {
- QSize sz = standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10));
+ QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10));
titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
}
if (isFloating) {
titleRect.adjust(0, -fw, 0, 0);
- if (widget != 0 && widget->windowIcon().cacheKey() != qApp->windowIcon().cacheKey())
+ if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey())
titleRect.adjust(titleRect.height() + mw, 0, 0, 0);
} else {
titleRect.adjust(mw, 0, 0, 0);
@@ -2317,10 +2328,10 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
// Figure out maximal button space on title bar
QIcon ico = widget->windowIcon();
- bool hasIcon = (ico.cacheKey() != qApp->windowIcon().cacheKey());
+ bool hasIcon = (ico.cacheKey() != QApplication::windowIcon().cacheKey());
if (hasIcon) {
QPixmap pxIco = ico.pixmap(titleHeight);
- if (!verticalTitleBar && QApplication::layoutDirection() == Qt::RightToLeft)
+ if (!verticalTitleBar && dwOpt->direction == Qt::RightToLeft)
p->drawPixmap(rect.width() - titleHeight - pxIco.width(), rect.bottom() - titleHeight - 2, pxIco);
else
p->drawPixmap(fw, rect.bottom() - titleHeight - 2, pxIco);
@@ -2450,7 +2461,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(ftheme);
}
if (sub & SC_SpinBoxUp) {
- theme.rect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
+ theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
partId = SPNP_UP;
if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled))
stateId = UPS_DISABLED;
@@ -2465,7 +2476,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_SpinBoxDown) {
- theme.rect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
+ theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
partId = SPNP_DOWN;
if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled))
stateId = DNS_DISABLED;
@@ -2502,7 +2513,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
p->fillRect(option->rect, editBrush);
}
if (!cmb->editable) {
- QRect re = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget);
+ QRect re = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget);
if (option->state & State_HasFocus) {
p->fillRect(re, option->palette.highlight());
p->setPen(option->palette.highlightedText().color());
@@ -2517,7 +2528,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
if (sub & SC_ComboBoxArrow) {
XPThemeData theme(widget, p, QLatin1String("COMBOBOX"));
- theme.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
+ theme.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
partId = CP_DROPDOWNBUTTON;
if (!(flags & State_Enabled))
stateId = CBXS_DISABLED;
@@ -2545,7 +2556,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
bool isHorz = flags & State_Horizontal;
bool isRTL = option->direction == Qt::RightToLeft;
if (sub & SC_ScrollBarAddLine) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
partId = SBP_ARROWBTN;
if (!(flags & State_Enabled))
stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED);
@@ -2560,7 +2571,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_ScrollBarSubLine) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
partId = SBP_ARROWBTN;
if (!(flags & State_Enabled))
stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED);
@@ -2575,9 +2586,9 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (maxedOut) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
- theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
- theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
+ theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
partId = scrollbar->orientation == Qt::Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
stateId = SCRBS_DISABLED;
theme.partId = partId;
@@ -2585,7 +2596,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
} else {
if (sub & SC_ScrollBarSubPage) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
@@ -2600,7 +2611,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_ScrollBarAddPage) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
@@ -2615,7 +2626,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_ScrollBarSlider) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken))
@@ -2626,7 +2637,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
stateId = SCRBS_NORMAL;
// Draw handle
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
theme.stateId = stateId;
d->drawBackground(theme);
@@ -2661,11 +2672,8 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
// Draw gripper if there is enough space
if (!gripperBounds.isEmpty()) {
p->save();
- XPThemeData grippBackground = theme;
- grippBackground.partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
theme.rect = gripperBounds;
p->setClipRegion(d->region(theme));// Only change inside the region of the gripper
- d->drawBackground(grippBackground);// The gutter is the grippers background
d->drawBackground(theme); // Transparent gripper ontop of background
p->restore();
}
@@ -2682,7 +2690,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
QRect slrect = slider->rect;
QRegion tickreg = slrect;
if (sub & SC_SliderGroove) {
- theme.rect = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
+ theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
if (slider->orientation == Qt::Horizontal) {
partId = TKP_TRACK;
stateId = TRS_NORMAL;
@@ -2698,11 +2706,11 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
tickreg -= theme.rect;
}
if (sub & SC_SliderTickmarks) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
int ticks = slider->tickPosition;
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
- int len = pixelMetric(PM_SliderLength, slider, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
interval = slider->singleStep;
@@ -2758,7 +2766,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
}
if (sub & SC_SliderHandle) {
- theme.rect = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
if (slider->orientation == Qt::Horizontal) {
if (slider->tickPosition == QSlider::TicksAbove)
partId = TKP_THUMBTOP;
@@ -2804,7 +2812,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*slider);
fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
@@ -2814,8 +2822,8 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
QRect button, menuarea;
- button = subControlRect(cc, toolbutton, SC_ToolButton, widget);
- menuarea = subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
State bflags = toolbutton->state & ~State_Sunken;
State mflags = bflags;
@@ -2863,9 +2871,9 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
tool.state = bflags;
if (widget && !qobject_cast<QToolBar*>(widget->parentWidget())
&& !(bflags & State_AutoRaise))
- drawPrimitive(PE_PanelButtonBevel, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, widget);
else
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
}
}
}
@@ -2875,26 +2883,26 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
fr.QStyleOption::operator=(*toolbutton);
fr.rect.adjust(3, 3, -3, -3);
if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup)
- fr.rect.adjust(0, 0, -pixelMetric(QStyle::PM_MenuButtonIndicator,
+ fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator,
toolbutton, widget), 0);
- drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
}
QStyleOptionToolButton label = *toolbutton;
label.state = bflags;
int fw = 2;
label.rect = button.adjusted(fw, fw, -fw, -fw);
- drawControl(CE_ToolButtonLabel, &label, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;
tool.state = mflags;
- drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
} else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
QRect ir = toolbutton->rect;
QStyleOptionToolButton newBtn = *toolbutton;
newBtn.rect = QRect(ir.right() + 4 - mbi, ir.height() - mbi + 4, mbi - 5, mbi - 5);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
break;
@@ -2926,7 +2934,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
theme.stateId = stateId;
d->drawBackground(theme);
- QRect ir = subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
+ QRect ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
int result = TST_NONE;
pGetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result);
@@ -2945,7 +2953,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text);
}
if (sub & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarSysMenu, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarSysMenu, widget);
partId = WP_SYSBUTTON;
if ((widget && !widget->isEnabled()) || !isActive)
stateId = SBS_DISABLED;
@@ -2963,8 +2971,8 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
SIZE sz;
pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz);
if (sz.cx == 0 || sz.cy == 0) {
- int iconSize = pixelMetric(PM_SmallIconSize, tb, widget);
- QPixmap pm = standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize);
+ int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget);
+ QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize);
p->save();
drawItemPixmap(p, theme.rect, Qt::AlignCenter, pm);
p->restore();
@@ -2976,7 +2984,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
if (sub & SC_TitleBarMinButton && tb->titleBarFlags & Qt::WindowMinimizeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarMinButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMinButton, widget);
partId = WP_MINBUTTON;
if (widget && !widget->isEnabled())
stateId = MINBS_DISABLED;
@@ -2994,7 +3002,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
if (sub & SC_TitleBarMaxButton && tb->titleBarFlags & Qt::WindowMaximizeButtonHint
&& !(tb->titleBarState & Qt::WindowMaximized)) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarMaxButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMaxButton, widget);
partId = WP_MAXBUTTON;
if (widget && !widget->isEnabled())
stateId = MAXBS_DISABLED;
@@ -3012,7 +3020,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
if (sub & SC_TitleBarContextHelpButton
&& tb->titleBarFlags & Qt::WindowContextHelpButtonHint) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarContextHelpButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarContextHelpButton, widget);
partId = WP_HELPBUTTON;
if (widget && !widget->isEnabled())
stateId = MINBS_DISABLED;
@@ -3034,7 +3042,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
|| ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
&& (tb->titleBarState & Qt::WindowMaximized)));
if (drawNormalButton) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarNormalButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarNormalButton, widget);
partId = WP_RESTOREBUTTON;
if (widget && !widget->isEnabled())
stateId = RBS_DISABLED;
@@ -3052,7 +3060,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
if (sub & SC_TitleBarShadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarShadeButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarShadeButton, widget);
partId = WP_MINBUTTON;
if (widget && !widget->isEnabled())
stateId = MINBS_DISABLED;
@@ -3070,7 +3078,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
if (sub & SC_TitleBarUnshadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
&& tb->titleBarState & Qt::WindowMinimized) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarUnshadeButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarUnshadeButton, widget);
partId = WP_RESTOREBUTTON;
if (widget && !widget->isEnabled())
stateId = RBS_DISABLED;
@@ -3087,7 +3095,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarCloseButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarCloseButton, widget);
//partId = titlebar->testWFlags(Qt::WA_WState_Tool) ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON;
partId = WP_CLOSEBUTTON;
if (widget && !widget->isEnabled())
@@ -3115,7 +3123,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
XPThemeData theme(widget, p, QLatin1String("WINDOW"), WP_MDICLOSEBUTTON, CBS_NORMAL);
if (option->subControls & SC_MdiCloseButton) {
- buttonRect = subControlRect(CC_MdiControls, option, SC_MdiCloseButton, widget);
+ buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiCloseButton, widget);
if (theme.isValid()) {
theme.partId = WP_MDICLOSEBUTTON;
theme.rect = buttonRect;
@@ -3131,7 +3139,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
}
if (option->subControls & SC_MdiNormalButton) {
- buttonRect = subControlRect(CC_MdiControls, option, SC_MdiNormalButton, widget);
+ buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiNormalButton, widget);
if (theme.isValid()) {
theme.partId = WP_MDIRESTOREBUTTON;
theme.rect = buttonRect;
@@ -3147,7 +3155,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
}
if (option->subControls & QStyle::SC_MdiMinButton) {
- buttonRect = subControlRect(CC_MdiControls, option, SC_MdiMinButton, widget);
+ buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiMinButton, widget);
if (theme.isValid()) {
theme.partId = WP_MDIMINBUTTON;
theme.rect = buttonRect;
@@ -3165,6 +3173,12 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
break;
#endif //QT_NO_WORKSPACE
+#ifndef QT_NO_DIAL
+ case CC_Dial:
+ if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
+ QStyleHelper::drawDial(dial, p);
+ break;
+#endif // QT_NO_DIAL
default:
QWindowsStyle::drawComplexControl(cc, option, p, widget);
break;
@@ -3224,7 +3238,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con
break;
case PM_SplitterWidth:
- res = qMax(5, QApplication::globalStrut().width());
+ res = qMax(int(QStyleHelper::dpiScaled(5.)), QApplication::globalStrut().width());
break;
case PM_IndicatorWidth:
@@ -3234,7 +3248,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con
if (theme.isValid()) {
SIZE size;
pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size);
- res = (pm == PM_IndicatorWidth ? size.cx+2 : res = size.cy+2);
+ res = (pm == PM_IndicatorWidth) ? size.cx : size.cy;
}
}
break;
@@ -3246,7 +3260,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con
if (theme.isValid()) {
SIZE size;
pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size);
- res = (pm == PM_ExclusiveIndicatorWidth ? size.cx+2 : res = size.cy+2);
+ res = (pm == PM_ExclusiveIndicatorWidth) ? size.cx : size.cy;
}
}
break;
@@ -3318,7 +3332,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con
#ifndef QT_NO_TOOLBAR
case PM_ToolBarHandleExtent:
- res = 8;
+ res = int(QStyleHelper::dpiScaled(8.));
break;
#endif // QT_NO_TOOLBAR
@@ -3333,10 +3347,10 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con
}
break;
case PM_DockWidgetSeparatorExtent:
- res = 4;
+ res = int(QStyleHelper::dpiScaled(4.));
break;
case PM_DockWidgetTitleMargin:
- res = 4;
+ res = int(QStyleHelper::dpiScaled(4.));
break;
case PM_ButtonShiftHorizontal:
@@ -3347,6 +3361,10 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con
res = 0;
break;
+ case PM_ButtonDefaultIndicator:
+ res = 0;
+ break;
+
default:
res = QWindowsStyle::pixelMetric(pm, option, widget);
}
@@ -3428,7 +3446,7 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4;
const int delta = buttonWidth + 2;
int controlTop = option->rect.bottom() - buttonHeight - 2;
- const int frameWidth = pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
+ const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0;
const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0;
@@ -3513,7 +3531,7 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
{
const int controlTop = 6;
const int controlHeight = height - controlTop - 3;
- const int iconExtent = pixelMetric(PM_SmallIconSize);
+ const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
if (tb->icon.isNull())
iconSize = QSize(controlHeight, controlHeight);
@@ -3522,6 +3540,8 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height());
}
break;
+ default:
+ break;
}
}
break;
@@ -3548,6 +3568,9 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
case SC_ComboBoxListBoxPopup:
rect = cmb->rect;
break;
+
+ default:
+ break;
}
}
break;
@@ -3635,7 +3658,7 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt
{
//Spinbox adds frame twice
sz = QWindowsStyle::sizeFromContents(ct, option, contentsSize, widget);
- int border = pixelMetric(PM_SpinBoxFrameWidth, option, widget);
+ int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget);
sz -= QSize(2*border, 2*border);
}
break;
@@ -3789,6 +3812,8 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt
}
}
break;
+ default:
+ break;
}
return QWindowsStyle::standardPixmap(standardPixmap, option, widget);
}
@@ -3910,6 +3935,8 @@ QIcon QWindowsXPStyle::standardIconImplementation(StandardPixmap standardIcon,
}
break;
+ default:
+ break;
}
return QWindowsStyle::standardIconImplementation(standardIcon, option, widget);
diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri
index 376f834..767ade0 100644
--- a/src/gui/styles/styles.pri
+++ b/src/gui/styles/styles.pri
@@ -7,13 +7,19 @@ HEADERS += \
styles/qstyleplugin.h \
styles/qcommonstylepixmaps_p.h \
styles/qcommonstyle.h \
+ styles/qstylehelper_p.h \
+ styles/qproxystyle.h \
+ styles/qproxystyle_p.h \
styles/qstylesheetstyle_p.h
+
SOURCES += \
styles/qstyle.cpp \
styles/qstylefactory.cpp \
styles/qstyleoption.cpp \
styles/qstyleplugin.cpp \
+ styles/qstylehelper.cpp \
styles/qcommonstyle.cpp \
+ styles/qproxystyle.cpp \
styles/qstylesheetstyle.cpp \
styles/qstylesheetstyle_default.cpp
@@ -31,7 +37,7 @@ x11|embedded|!macx-*:styles -= mac
x11{
QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTKSTYLE
- LIBS += $$QT_LIBS_QGTKSTYLE
+ LIBS_PRIVATE += $$QT_LIBS_QGTKSTYLE
styles += gtk
}
@@ -155,3 +161,18 @@ contains( styles, windowsmobile ) {
DEFINES += QT_NO_STYLE_WINDOWSMOBILE
}
+contains( styles, s60 ):contains(QT_CONFIG, s60) {
+ HEADERS += \
+ styles/qs60style.h \
+ styles/qs60style_p.h
+ SOURCES += styles/qs60style.cpp
+ symbian {
+ SOURCES += styles/qs60style_s60.cpp
+ LIBS += -laknicon -laknskins -laknskinsrv -lfontutils
+ } else {
+ SOURCES += styles/qs60style_simulated.cpp
+ RESOURCES += styles/qstyle_s60_simulated.qrc
+ }
+} else {
+ DEFINES += QT_NO_STYLE_S60
+}
diff --git a/src/gui/text/qabstractfontengine_p.h b/src/gui/text/qabstractfontengine_p.h
index 45a6da6..b912230 100644
--- a/src/gui/text/qabstractfontengine_p.h
+++ b/src/gui/text/qabstractfontengine_p.h
@@ -91,7 +91,7 @@ public:
virtual Type type() const { return Proxy; }
virtual const char *name() const { return "proxy engine"; }
-#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
virtual void draw(QPaintEngine *, qreal, qreal, const QTextItemInt &);
#endif
diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp
index 54bad36..1ea5feb 100644
--- a/src/gui/text/qabstracttextdocumentlayout.cpp
+++ b/src/gui/text/qabstracttextdocumentlayout.cpp
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
\brief The QAbstractTextDocumentLayout class is an abstract base
class used to implement custom layouts for QTextDocuments.
- \ingroup text
+ \ingroup richtext-processing
The standard layout provided by Qt can handle simple word processing
including inline images, lists and tables.
@@ -79,6 +79,7 @@ QT_BEGIN_NAMESPACE
\class QTextObjectInterface
\brief The QTextObjectInterface class allows drawing of
custom text objects in \l{QTextDocument}s.
+ \since 4.5
A text object describes the structure of one or more elements in a
text document; for instance, images imported from HTML are
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 9d1910d..6978b45 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -48,6 +48,7 @@
#include <qfontmetrics.h>
#include <qbrush.h>
#include <qimagereader.h>
+#include "private/qfunctions_p.h"
#ifndef QT_NO_CSSPARSER
@@ -57,46 +58,6 @@ QT_BEGIN_NAMESPACE
using namespace QCss;
-const char *Scanner::tokenName(QCss::TokenType t)
-{
- switch (t) {
- case NONE: return "NONE";
- case S: return "S";
- case CDO: return "CDO";
- case CDC: return "CDC";
- case INCLUDES: return "INCLUDES";
- case DASHMATCH: return "DASHMATCH";
- case LBRACE: return "LBRACE";
- case PLUS: return "PLUS";
- case GREATER: return "GREATER";
- case COMMA: return "COMMA";
- case STRING: return "STRING";
- case INVALID: return "INVALID";
- case IDENT: return "IDENT";
- case HASH: return "HASH";
- case ATKEYWORD_SYM: return "ATKEYWORD_SYM";
- case EXCLAMATION_SYM: return "EXCLAMATION_SYM";
- case LENGTH: return "LENGTH";
- case PERCENTAGE: return "PERCENTAGE";
- case NUMBER: return "NUMBER";
- case FUNCTION: return "FUNCTION";
- case COLON: return "COLON";
- case SEMICOLON: return "SEMICOLON";
- case RBRACE: return "RBRACE";
- case SLASH: return "SLASH";
- case MINUS: return "MINUS";
- case DOT: return "DOT";
- case STAR: return "STAR";
- case LBRACKET: return "LBRACKET";
- case RBRACKET: return "RBRACKET";
- case EQUAL: return "EQUAL";
- case LPAREN: return "LPAREN";
- case RPAREN: return "RPAREN";
- case OR: return "OR";
- }
- return "";
-}
-
struct QCssKnownValue
{
const char *name;
@@ -239,6 +200,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "link", Value_Link },
{ "link-visited", Value_LinkVisited },
{ "lower-alpha", Value_LowerAlpha },
+ { "lower-roman", Value_LowerRoman },
{ "lowercase", Value_Lowercase },
{ "medium", Value_Medium },
{ "mid", Value_Mid },
@@ -270,6 +232,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "transparent", Value_Transparent },
{ "underline", Value_Underline },
{ "upper-alpha", Value_UpperAlpha },
+ { "upper-roman", Value_UpperRoman },
{ "uppercase", Value_Uppercase },
{ "wave", Value_Wave },
{ "window", Value_Window },
@@ -279,10 +242,10 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
};
//Map id to strings as they appears in the 'values' array above
-static const int indexOfId[NumKnownValues] = { 0, 40, 47, 41, 48, 53, 34, 26, 68, 69, 25, 42, 5, 62, 46,
- 29, 57, 58, 27, 50, 60, 6, 10, 38, 55, 19, 13, 17, 18, 20, 21, 49, 24, 45, 65, 36, 3, 2, 39, 61, 16,
- 11, 56, 14, 32, 63, 54, 64, 33, 67, 8, 28, 37, 12, 35, 59, 7, 9, 4, 66, 52, 22, 23, 30, 31, 1, 15, 0,
- 51, 44, 43 };
+static const short indexOfId[NumKnownValues] = { 0, 41, 48, 42, 49, 54, 35, 26, 70, 71, 25, 43, 5, 63, 47,
+ 29, 58, 59, 27, 51, 61, 6, 10, 39, 56, 19, 13, 17, 18, 20, 21, 50, 24, 46, 67, 37, 3, 2, 40, 62, 16,
+ 11, 57, 14, 32, 64, 33, 65, 55, 66, 34, 69, 8, 28, 38, 12, 36, 60, 7, 9, 4, 68, 53, 22, 23, 30, 31,
+ 1, 15, 0, 52, 45, 44 };
QString Value::toString() const
{
@@ -378,12 +341,12 @@ static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1] = {
{ "none", StyleFeature_None }
};
-static bool operator<(const QString &name, const QCssKnownValue &prop)
+Q_STATIC_GLOBAL_OPERATOR bool operator<(const QString &name, const QCssKnownValue &prop)
{
return QString::compare(name, QLatin1String(prop.name), Qt::CaseInsensitive) < 0;
}
-static bool operator<(const QCssKnownValue &prop, const QString &name)
+Q_STATIC_GLOBAL_OPERATOR bool operator<(const QCssKnownValue &prop, const QString &name)
{
return QString::compare(QLatin1String(prop.name), name, Qt::CaseInsensitive) < 0;
}
@@ -420,10 +383,7 @@ LengthData ValueExtractor::lengthValue(const Value& v)
if (data.unit != LengthData::None)
s.chop(2);
- bool ok;
- data.number = s.toDouble(&ok);
- if (!ok)
- data.number = 0;
+ data.number = s.toDouble();
return data;
}
@@ -749,7 +709,7 @@ static ColorData parseColorValue(Value v)
for (int i = 0; i < qMin(colorDigits.count(), 7); i += 2) {
if (colorDigits.at(i).type == Value::Percentage) {
- colorDigits[i].variant = colorDigits.at(i).variant.toDouble() * 255. / 100.;
+ colorDigits[i].variant = colorDigits.at(i).variant.toReal() * (255. / 100.);
colorDigits[i].type = Value::Number;
} else if (colorDigits.at(i).type != Value::Number) {
return ColorData();
@@ -826,19 +786,19 @@ static BrushData parseBrushValue(const Value &v, const QPalette &pal)
ColorData cd = parseColorValue(color);
if(cd.type == ColorData::Role)
dependsOnThePalette = true;
- stops.append(QGradientStop(stop.variant.toDouble(), colorFromData(cd, pal)));
+ stops.append(QGradientStop(stop.variant.toReal(), colorFromData(cd, pal)));
} else {
parser.next();
Value value;
- parser.parseTerm(&value);
+ (void)parser.parseTerm(&value);
if (attr.compare(QLatin1String("spread"), Qt::CaseInsensitive) == 0) {
spread = spreads.indexOf(value.variant.toString());
} else {
- vars[attr] = value.variant.toString().toDouble();
+ vars[attr] = value.variant.toReal();
}
}
parser.skipSpace();
- parser.test(COMMA);
+ (void)parser.test(COMMA);
}
if (gradType == 0) {
@@ -1117,8 +1077,8 @@ static bool setFontSizeFromValue(Value value, QFont *font, int *fontSizeAdjustme
if (s.endsWith(QLatin1String("pt"), Qt::CaseInsensitive)) {
s.chop(2);
value.variant = s;
- if (value.variant.convert(QVariant::Double)) {
- font->setPointSizeF(value.variant.toDouble());
+ if (value.variant.convert((QVariant::Type)qMetaTypeId<qreal>())) {
+ font->setPointSizeF(value.variant.toReal());
valid = true;
}
} else if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {
@@ -1508,7 +1468,7 @@ QRect Declaration::rectValue() const
QStringList func = v.variant.toStringList();
if (func.count() != 2 || func.at(0).compare(QLatin1String("rect")) != 0)
return QRect();
- QStringList args = func[1].split(QLatin1String(" "), QString::SkipEmptyParts);
+ QStringList args = func[1].split(QLatin1Char(' '), QString::SkipEmptyParts);
if (args.count() != 4)
return QRect();
QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt());
@@ -2153,7 +2113,7 @@ void Parser::init(const QString &css, bool isFile)
if (isFile) {
QFile file(css);
if (file.open(QFile::ReadOnly)) {
- sourcePath = QFileInfo(styleSheet).absolutePath() + QLatin1String("/");
+ sourcePath = QFileInfo(styleSheet).absolutePath() + QLatin1Char('/');
QTextStream stream(&file);
styleSheet = stream.readAll();
} else {
@@ -2499,7 +2459,7 @@ bool Parser::parseAttrib(AttributeSelector *attr)
bool Parser::parsePseudo(Pseudo *pseudo)
{
- test(COLON);
+ (void)test(COLON);
pseudo->negated = test(EXCLAMATION_SYM);
if (test(IDENT)) {
pseudo->name = lexem();
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index a6f2ea2..8f30013 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -67,6 +67,11 @@
#ifndef QT_NO_CSSPARSER
+// VxWorks defines NONE as (-1) "for times when NULL won't do"
+#if defined(Q_OS_VXWORKS) && defined(NONE)
+# undef NONE
+#endif
+
QT_BEGIN_NAMESPACE
namespace QCss
@@ -223,6 +228,8 @@ enum KnownValue {
Value_Decimal,
Value_LowerAlpha,
Value_UpperAlpha,
+ Value_LowerRoman,
+ Value_UpperRoman,
Value_SmallCaps,
Value_Uppercase,
Value_Lowercase,
@@ -361,18 +368,18 @@ struct Q_GUI_EXPORT Value
};
struct ColorData {
- ColorData() : type(Invalid) {}
- ColorData(const QColor &col) : color(col) , type(Color) {}
- ColorData(QPalette::ColorRole r) : role(r) , type(Role) {}
+ ColorData() : role(QPalette::NoRole), type(Invalid) {}
+ ColorData(const QColor &col) : color(col), role(QPalette::NoRole), type(Color) {}
+ ColorData(QPalette::ColorRole r) : role(r), type(Role) {}
QColor color;
QPalette::ColorRole role;
enum { Invalid, Color, Role} type;
};
struct BrushData {
- BrushData() : type(Invalid) {}
- BrushData(const QBrush &br) : brush(br) , type(Brush) {}
- BrushData(QPalette::ColorRole r) : role(r) , type(Role) {}
+ BrushData() : role(QPalette::NoRole), type(Invalid) {}
+ BrushData(const QBrush &br) : brush(br), role(QPalette::NoRole), type(Brush) {}
+ BrushData(QPalette::ColorRole r) : role(r), type(Role) {}
QBrush brush;
QPalette::ColorRole role;
enum { Invalid, Brush, Role, DependsOnThePalette } type;
@@ -403,7 +410,7 @@ struct BorderData {
// 4. QVector<Declaration> - { prop1: value1; prop2: value2; }
// 5. Declaration - prop1: value1;
-struct Q_GUI_EXPORT Declaration
+struct Q_AUTOTEST_EXPORT Declaration
{
struct DeclarationData : public QSharedData
{
@@ -495,16 +502,16 @@ const quint64 PseudoClass_Alternate = Q_UINT64_C(0x0000100000000000);
const quint64 PseudoClass_Any = Q_UINT64_C(0x0000ffffffffffff);
const int NumPseudos = 46;
-struct Q_GUI_EXPORT Pseudo
+struct Pseudo
{
- Pseudo() : negated(false) { }
+ Pseudo() : type(0), negated(false) { }
quint64 type;
QString name;
QString function;
bool negated;
};
-struct Q_GUI_EXPORT AttributeSelector
+struct AttributeSelector
{
enum ValueMatchType {
NoMatch,
@@ -519,7 +526,7 @@ struct Q_GUI_EXPORT AttributeSelector
ValueMatchType valueMatchCriterium;
};
-struct Q_GUI_EXPORT BasicSelector
+struct BasicSelector
{
inline BasicSelector() : relationToNext(NoRelation) {}
@@ -539,7 +546,7 @@ struct Q_GUI_EXPORT BasicSelector
Relation relationToNext;
};
-struct Q_GUI_EXPORT Selector
+struct Q_AUTOTEST_EXPORT Selector
{
QVector<BasicSelector> basicSelectors;
int specificity() const;
@@ -552,7 +559,7 @@ struct MediaRule;
struct PageRule;
struct ImportRule;
-struct Q_GUI_EXPORT ValueExtractor
+struct Q_AUTOTEST_EXPORT ValueExtractor
{
ValueExtractor(const QVector<Declaration> &declarations, const QPalette & = QPalette());
@@ -586,7 +593,7 @@ private:
QPalette pal;
};
-struct Q_GUI_EXPORT StyleRule
+struct StyleRule
{
StyleRule() : order(0) { }
QVector<Selector> selectors;
@@ -594,19 +601,19 @@ struct Q_GUI_EXPORT StyleRule
int order;
};
-struct Q_GUI_EXPORT MediaRule
+struct MediaRule
{
QStringList media;
QVector<StyleRule> styleRules;
};
-struct Q_GUI_EXPORT PageRule
+struct PageRule
{
QString selector;
QVector<Declaration> declarations;
};
-struct Q_GUI_EXPORT ImportRule
+struct ImportRule
{
QString href;
QStringList media;
@@ -620,7 +627,7 @@ enum StyleSheetOrigin {
StyleSheetOrigin_Inline
};
-struct Q_GUI_EXPORT StyleSheet
+struct StyleSheet
{
StyleSheet() : origin(StyleSheetOrigin_Unspecified), depth(0) { }
QVector<StyleRule> styleRules; //only contains rules that are not indexed
@@ -719,7 +726,7 @@ enum TokenType {
struct Q_GUI_EXPORT Symbol
{
- inline Symbol() : start(0), len(-1) {}
+ inline Symbol() : token(NONE), start(0), len(-1) {}
TokenType token;
QString text;
int start, len;
@@ -731,7 +738,6 @@ class Q_AUTOTEST_EXPORT Scanner
public:
static QString preprocess(const QString &input, bool *hasEscapeSequences = 0);
static void scan(const QString &preprocessedInput, QVector<Symbol> *symbols);
- static const char *tokenName(TokenType t);
};
class Q_GUI_EXPORT Parser
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 4f24546..03f69db 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -72,6 +72,9 @@
#include "qfontengine_qpf_p.h"
#endif
#endif
+#ifdef Q_OS_SYMBIAN
+#include "qt_s60_p.h"
+#endif
#include <QMutexLocker>
@@ -169,6 +172,8 @@ Q_GUI_EXPORT int qt_defaultDpiX()
if (!subScreens.isEmpty())
screen = subScreens.at(0);
dpi = qRound(screen->width() / (screen->physicalWidth() / qreal(25.4)));
+#elif defined(Q_OS_SYMBIAN)
+ dpi = S60->defaultDpiX;
#endif // Q_WS_X11
return dpi;
@@ -195,6 +200,8 @@ Q_GUI_EXPORT int qt_defaultDpiY()
if (!subScreens.isEmpty())
screen = subScreens.at(0);
dpi = qRound(screen->height() / (screen->physicalHeight() / qreal(25.4)));
+#elif defined(Q_OS_SYMBIAN)
+ dpi = S60->defaultDpiY;
#endif // Q_WS_X11
return dpi;
@@ -210,7 +217,6 @@ QFontPrivate::QFontPrivate()
rawMode(false), underline(false), overline(false), strikeOut(false), kerning(true),
capital(0), letterSpacingIsAbsolute(false), scFont(0)
{
- ref = 1;
#ifdef Q_WS_X11
if (QX11Info::display())
screen = QX11Info::appScreen();
@@ -230,7 +236,6 @@ QFontPrivate::QFontPrivate(const QFontPrivate &other)
letterSpacing(other.letterSpacing), wordSpacing(other.wordSpacing),
scFont(other.scFont)
{
- ref = 1;
#ifdef Q_WS_WIN
hdc = other.hdc;
#endif
@@ -307,7 +312,7 @@ QFontPrivate *QFontPrivate::smallCapsFontPrivate() const
font.setPointSizeF(pointSize * .7);
else
font.setPixelSize((font.pixelSize() * 7 + 5) / 10);
- scFont = font.d;
+ scFont = font.d.data();
if (scFont != this)
scFont->ref.ref();
return scFont;
@@ -408,11 +413,11 @@ QFontEngineData::~QFontEngineData()
\brief The QFont class specifies a font used for drawing text.
- \ingroup multimedia
+ \ingroup painting
\ingroup appearance
\ingroup shared
- \ingroup text
- \mainclass
+ \ingroup richtext-processing
+
When you create a QFont object you specify various attributes that
you want the font to have. Qt will use the font with the specified
@@ -718,8 +723,7 @@ QFont::QFont(const QFont &font, QPaintDevice *pd)
d->dpi = dpi;
d->screen = screen;
} else {
- d = font.d;
- d->ref.ref();
+ d = font.d.data();
}
#ifdef Q_WS_WIN
if (pd->devType() == QInternal::Printer && pd->getDC())
@@ -731,10 +735,8 @@ QFont::QFont(const QFont &font, QPaintDevice *pd)
\internal
*/
QFont::QFont(QFontPrivate *data)
- : resolve_mask(QFont::AllPropertiesResolved)
+ : d(data), resolve_mask(QFont::AllPropertiesResolved)
{
- d = data;
- d->ref.ref();
}
/*! \internal
@@ -746,13 +748,13 @@ void QFont::detach()
if (d->engineData)
d->engineData->ref.deref();
d->engineData = 0;
- if (d->scFont && d->scFont != d)
+ if (d->scFont && d->scFont != d.data())
d->scFont->ref.deref();
d->scFont = 0;
return;
}
- qAtomicDetach(d);
+ d.detach();
}
/*!
@@ -761,16 +763,17 @@ void QFont::detach()
\sa QApplication::setFont(), QApplication::font()
*/
QFont::QFont()
- :d(QApplication::font().d), resolve_mask(0)
+ : d(QApplication::font().d.data()), resolve_mask(0)
{
- d->ref.ref();
}
/*!
Constructs a font object with the specified \a family, \a
pointSize, \a weight and \a italic settings.
- If \a pointSize is <= 0, it is set to 12.
+ If \a pointSize is zero or negative, the point size of the font
+ is set to a system-dependent default value. Generally, this is
+ 12 points, except on Symbian where it is 7 points.
The \a family name may optionally also include a foundry name,
e.g. "Helvetica [Cronyx]". If the \a family is
@@ -783,12 +786,14 @@ QFont::QFont()
setStyleHint() QApplication::font()
*/
QFont::QFont(const QString &family, int pointSize, int weight, bool italic)
- :d(new QFontPrivate)
+ : d(new QFontPrivate()), resolve_mask(QFont::FamilyResolved)
{
- resolve_mask = QFont::FamilyResolved;
-
if (pointSize <= 0) {
+#ifdef Q_OS_SYMBIAN
+ pointSize = 7;
+#else
pointSize = 12;
+#endif
} else {
resolve_mask |= QFont::SizeResolved;
}
@@ -810,10 +815,8 @@ QFont::QFont(const QString &family, int pointSize, int weight, bool italic)
Constructs a font that is a copy of \a font.
*/
QFont::QFont(const QFont &font)
+ : d(font.d.data()), resolve_mask(font.resolve_mask)
{
- d = font.d;
- d->ref.ref();
- resolve_mask = font.resolve_mask;
}
/*!
@@ -821,8 +824,6 @@ QFont::QFont(const QFont &font)
*/
QFont::~QFont()
{
- if (!d->ref.deref())
- delete d;
}
/*!
@@ -830,7 +831,7 @@ QFont::~QFont()
*/
QFont &QFont::operator=(const QFont &font)
{
- qAtomicAssign(d, font.d);
+ d = font.d.data();
resolve_mask = font.resolve_mask;
return *this;
}
@@ -1713,7 +1714,7 @@ QFont QFont::resolve(const QFont &other) const
QFont font(*this);
font.detach();
- font.d->resolve(resolve_mask, other.d);
+ font.d->resolve(resolve_mask, other.d.data());
return font;
}
@@ -2166,11 +2167,11 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << (quint8) font.d->request.styleStrategy;
s << (quint8) 0
<< (quint8) font.d->request.weight
- << get_font_bits(s.version(), font.d);
+ << get_font_bits(s.version(), font.d.data());
if (s.version() >= QDataStream::Qt_4_3)
s << (quint16)font.d->request.stretch;
if (s.version() >= QDataStream::Qt_4_4)
- s << get_extended_font_bits(font.d);
+ s << get_extended_font_bits(font.d.data());
if (s.version() >= QDataStream::Qt_4_5) {
s << font.d->letterSpacing.value();
s << font.d->wordSpacing.value();
@@ -2189,9 +2190,6 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
*/
QDataStream &operator>>(QDataStream &s, QFont &font)
{
- if (!font.d->ref.deref())
- delete font.d;
-
font.d = new QFontPrivate;
font.resolve_mask = QFont::AllPropertiesResolved;
@@ -2233,7 +2231,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d->request.styleStrategy = styleStrategy;
font.d->request.weight = weight;
- set_font_bits(s.version(), bits, font.d);
+ set_font_bits(s.version(), bits, font.d.data());
if (s.version() >= QDataStream::Qt_4_3) {
quint16 stretch;
@@ -2244,7 +2242,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
if (s.version() >= QDataStream::Qt_4_4) {
quint8 extendedBits;
s >> extendedBits;
- set_extended_font_bits(extendedBits, font.d);
+ set_extended_font_bits(extendedBits, font.d.data());
}
if (s.version() >= QDataStream::Qt_4_5) {
int value;
@@ -2270,9 +2268,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
\brief The QFontInfo class provides general information about fonts.
- \ingroup multimedia
+ \ingroup appearance
\ingroup shared
- \ingroup text
The QFontInfo class provides the same access functions as QFont,
e.g. family(), pointSize(), italic(), weight(), fixedPitch(),
@@ -2326,7 +2323,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
that is not screen-compatible.
*/
QFontInfo::QFontInfo(const QFont &font)
- : d(font.d)
+ : d(font.d.data())
{ d->ref.ref(); }
/*!
@@ -2599,7 +2596,14 @@ QFontCache *QFontCache::instance()
void QFontCache::cleanup()
{
- theFontCache()->setLocalData(0);
+ QThreadStorage<QFontCache *> *cache = 0;
+ QT_TRY {
+ cache = theFontCache();
+ } QT_CATCH (const std::bad_alloc &) {
+ // no cache - just ignore
+ }
+ if (cache && cache->hasLocalData())
+ cache->setLocalData(0);
}
#endif // QT_NO_THREAD
@@ -2612,8 +2616,8 @@ QFontCache::QFontCache()
QFontCache::~QFontCache()
{
{
- EngineDataCache::Iterator it = engineDataCache.begin(),
- end = engineDataCache.end();
+ EngineDataCache::ConstIterator it = engineDataCache.constBegin(),
+ end = engineDataCache.constEnd();
while (it != end) {
if (it.value()->ref == 0)
delete it.value();
@@ -2623,8 +2627,8 @@ QFontCache::~QFontCache()
++it;
}
}
- EngineCache::Iterator it = engineCache.begin(),
- end = engineCache.end();
+ EngineCache::ConstIterator it = engineCache.constBegin(),
+ end = engineCache.constEnd();
while (it != end) {
if (--it.value().data->cache_count == 0) {
if (it.value().data->ref == 0) {
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index d6be453..323a171 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -44,6 +44,7 @@
#include <QtGui/qwindowdefs.h>
#include <QtCore/qstring.h>
+#include <QtCore/qsharedpointer.h>
#if defined(Q_WS_X11) || defined(Q_WS_QWS)
typedef struct FT_FaceRec_* FT_Face;
@@ -312,7 +313,7 @@ private:
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QFont &);
#endif
- QFontPrivate *d;
+ QExplicitlySharedDataPointer<QFontPrivate> d;
uint resolve_mask;
};
diff --git a/src/gui/text/qfont_s60.cpp b/src/gui/text/qfont_s60.cpp
new file mode 100644
index 0000000..9541fe8
--- /dev/null
+++ b/src/gui/text/qfont_s60.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfont.h"
+#include "qt_s60_p.h"
+#include <private/qwindowsurface_s60_p.h>
+#include "qmutex.h"
+
+QT_BEGIN_NAMESPACE
+
+#if 1
+#ifdef QT_NO_FREETYPE
+Q_GLOBAL_STATIC(QMutex, lastResortFamilyMutex);
+#endif // QT_NO_FREETYPE
+
+QString QFont::lastResortFamily() const
+{
+#ifdef QT_NO_FREETYPE
+ QMutexLocker locker(lastResortFamilyMutex());
+ static QString family;
+ if (family.isEmpty()) {
+ QS60WindowSurface::unlockBitmapHeap();
+ CFont *font;
+ const TInt err = S60->screenDevice()->GetNearestFontInTwips(font, TFontSpec());
+ Q_ASSERT(err == KErrNone);
+ const TFontSpec spec = font->FontSpecInTwips();
+ family = QString((const QChar *)spec.iTypeface.iName.Ptr(), spec.iTypeface.iName.Length());
+ S60->screenDevice()->ReleaseFont(font);
+ QS60WindowSurface::lockBitmapHeap();
+ }
+ return family;
+#else
+ // For the FreeType case we just hard code the face name, since otherwise on
+ // East Asian systems we may get a name for a stroke based (non-ttf) font.
+
+ // TODO: Get the type face name in a proper way
+
+ const bool isJapaneseOrChineseSystem =
+ User::Language() == ELangJapanese || User::Language() == ELangPrcChinese;
+
+ return QLatin1String(isJapaneseOrChineseSystem?"Heisei Kaku Gothic S60":"Series 60 Sans");
+#endif // QT_NO_FREETYPE
+}
+#else // 0
+QString QFont::lastResortFamily() const
+{
+ return QLatin1String("Series 60 Sans");
+}
+#endif // 0
+
+QString QFont::defaultFamily() const
+{
+ return lastResortFamily();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qfont_win.cpp b/src/gui/text/qfont_win.cpp
index 0d23e49..4ddea10 100644
--- a/src/gui/text/qfont_win.cpp
+++ b/src/gui/text/qfont_win.cpp
@@ -39,11 +39,6 @@
**
****************************************************************************/
-// the miscrosoft platform SDK says that the Unicode versions of
-// TextOut and GetTextExtentsPoint32 are supported on all platforms, so we use them
-// exclusively to simplify code, save a lot of conversions into the local encoding
-// and have generally better unicode support :)
-
#include "qfont.h"
#include "qfont_p.h"
#include "qfontengine_p.h"
@@ -67,8 +62,7 @@ extern HDC shared_dc(); // common dc for all fonts
// ### maybe move to qapplication_win
QFont qt_LOGFONTtoQFont(LOGFONT& lf, bool /*scale*/)
{
- QString family = QT_WA_INLINE(QString::fromUtf16((ushort*)lf.lfFaceName),
- QString::fromLocal8Bit((char*)lf.lfFaceName));
+ QString family = QString::fromWCharArray(lf.lfFaceName);
QFont qf(family);
qf.setItalic(lf.lfItalic);
if (lf.lfWeight != FW_DONTCARE) {
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 9956496..0e2dc31 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -56,6 +56,11 @@
#include <stdlib.h>
#include <limits.h>
+#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
+# include <ft2build.h>
+# include FT_TRUETYPE_TABLES_H
+#endif
+
// #define QFONTDATABASE_DEBUG
#ifdef QFONTDATABASE_DEBUG
# define FD_DEBUG qDebug
@@ -76,9 +81,16 @@
QT_BEGIN_NAMESPACE
+#define SMOOTH_SCALABLE 0xffff
+
extern int qt_defaultDpiY(); // in qfont.cpp
-Q_GUI_EXPORT bool qt_enable_test_font = false;
+bool qt_enable_test_font = false;
+
+Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value)
+{
+ qt_enable_test_font = value;
+}
static int getFontWeight(const QString &weightString)
{
@@ -87,34 +99,34 @@ static int getFontWeight(const QString &weightString)
// Test in decreasing order of commonness
if (s == QLatin1String("medium") ||
s == QLatin1String("normal")
- || s.compare(qApp->translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0)
return QFont::Normal;
if (s == QLatin1String("bold")
- || s.compare(qApp->translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0)
return QFont::Bold;
if (s == QLatin1String("demibold") || s == QLatin1String("demi bold")
- || s.compare(qApp->translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0)
return QFont::DemiBold;
if (s == QLatin1String("black")
- || s.compare(qApp->translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
return QFont::Black;
if (s == QLatin1String("light"))
return QFont::Light;
if (s.contains(QLatin1String("bold"))
- || s.contains(qApp->translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) {
+ || s.contains(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) {
if (s.contains(QLatin1String("demi"))
- || s.compare(qApp->translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0)
return (int) QFont::DemiBold;
return (int) QFont::Bold;
}
if (s.contains(QLatin1String("light"))
- || s.compare(qApp->translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0)
return (int) QFont::Light;
if (s.contains(QLatin1String("black"))
- || s.compare(qApp->translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
return (int) QFont::Black;
return (int) QFont::Normal;
@@ -141,10 +153,10 @@ struct QtFontSize
QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0,
uint yres = 0, uint avgwidth = 0, bool add = false);
#endif // Q_WS_X11
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
QByteArray fileName;
int fileIndex;
-#endif
+#endif // defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
};
@@ -160,10 +172,13 @@ QtFontEncoding *QtFontSize::encodingID(int id, uint xpoint, uint xres,
if (!add) return 0;
- if (!(count % 4))
- encodings = (QtFontEncoding *)
+ if (!(count % 4)) {
+ QtFontEncoding *newEncodings = (QtFontEncoding *)
realloc(encodings,
(((count+4) >> 2) << 2) * sizeof(QtFontEncoding));
+ Q_CHECK_PTR(newEncodings);
+ encodings = newEncodings;
+ }
encodings[count].encoding = id;
encodings[count].xpoint = xpoint;
encodings[count].xres = xres;
@@ -215,12 +230,14 @@ struct QtFontStyle
delete [] weightName;
delete [] setwidthName;
#endif
-#if defined(Q_WS_X11) || defined(Q_WS_QWS)
- while (count--) {
+#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
+ while (count) {
+ // bitfield count-- in while condition does not work correctly in mwccsym2
+ count--;
#ifdef Q_WS_X11
free(pixelSizes[count].encodings);
#endif
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
pixelSizes[count].fileName.~QByteArray();
#endif
}
@@ -238,7 +255,7 @@ struct QtFontStyle
const char *weightName;
const char *setwidthName;
#endif // Q_WS_X11
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
bool antialiased;
#endif
@@ -251,10 +268,10 @@ QtFontStyle::Key::Key(const QString &styleString)
weight = getFontWeight(styleString);
if (styleString.contains(QLatin1String("Italic"))
- || styleString.contains(qApp->translate("QFontDatabase", "Italic")))
+ || styleString.contains(QApplication::translate("QFontDatabase", "Italic")))
style = QFont::StyleItalic;
else if (styleString.contains(QLatin1String("Oblique"))
- || styleString.contains(qApp->translate("QFontDatabase", "Oblique")))
+ || styleString.contains(QApplication::translate("QFontDatabase", "Oblique")))
style = QFont::StyleOblique;
}
@@ -267,16 +284,19 @@ QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add)
if (!add)
return 0;
- if (!(count % 8))
- pixelSizes = (QtFontSize *)
+ if (!(count % 8)) {
+ QtFontSize *newPixelSizes = (QtFontSize *)
realloc(pixelSizes,
(((count+8) >> 3) << 3) * sizeof(QtFontSize));
+ Q_CHECK_PTR(newPixelSizes);
+ pixelSizes = newPixelSizes;
+ }
pixelSizes[count].pixelSize = size;
#ifdef Q_WS_X11
pixelSizes[count].count = 0;
pixelSizes[count].encodings = 0;
#endif
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
new (&pixelSizes[count].fileName) QByteArray;
pixelSizes[count].fileIndex = 0;
#endif
@@ -321,12 +341,16 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create)
return 0;
// qDebug("adding key (weight=%d, style=%d, oblique=%d stretch=%d) at %d", key.weight, key.style, key.oblique, key.stretch, pos);
- if (!(count % 8))
- styles = (QtFontStyle **)
+ if (!(count % 8)) {
+ QtFontStyle **newStyles = (QtFontStyle **)
realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *));
+ Q_CHECK_PTR(newStyles);
+ styles = newStyles;
+ }
+ QtFontStyle *style = new QtFontStyle(key);
memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *));
- styles[pos] = new QtFontStyle(key);
+ styles[pos] = style;
count++;
return styles[pos];
}
@@ -358,7 +382,7 @@ struct QtFontFamily
fixedPitchComputed(false),
#endif
name(n), count(0), foundries(0)
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
, bogusWritingSystems(false)
#endif
{
@@ -388,7 +412,7 @@ struct QtFontFamily
#endif
QString name;
-#ifdef Q_WS_X11
+#if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
QByteArray fontFilename;
int fontFileIndex;
#endif
@@ -398,7 +422,7 @@ struct QtFontFamily
int count;
QtFontFoundry **foundries;
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
bool bogusWritingSystems;
QStringList fallbackFamilies;
#endif
@@ -431,10 +455,13 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
if (!create)
return 0;
- if (!(count % 8))
- foundries = (QtFontFoundry **)
+ if (!(count % 8)) {
+ QtFontFoundry **newFoundries = (QtFontFoundry **)
realloc(foundries,
(((count+8) >> 3) << 3) * sizeof(QtFontFoundry *));
+ Q_CHECK_PTR(newFoundries);
+ foundries = newFoundries;
+ }
foundries[count] = new QtFontFoundry(f);
return foundries[count++];
@@ -442,7 +469,7 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
// ### copied to tools/makeqpf/qpf2.cpp
-#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA))
+#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA))
// see the Unicode subset bitfields in the MSDN docs
static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
// Any,
@@ -563,6 +590,15 @@ static QList<QFontDatabase::WritingSystem> determineWritingSystemsFromTrueTypeBi
}
#endif
+#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+// class with virtual destructor, derived in qfontdatabase_s60.cpp
+class QFontDatabaseS60Store
+{
+public:
+ virtual ~QFontDatabaseS60Store() {};
+};
+#endif
+
class QFontDatabasePrivate
{
public:
@@ -571,6 +607,9 @@ public:
#if defined(Q_WS_QWS)
, stream(0)
#endif
+#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+ , s60Store(0)
+#endif
{ }
~QFontDatabasePrivate() {
free();
@@ -582,6 +621,12 @@ public:
::free(families);
families = 0;
count = 0;
+#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+ if (s60Store) {
+ delete s60Store;
+ s60Store = 0;
+ }
+#endif
// don't clear the memory fonts!
}
@@ -609,17 +654,22 @@ public:
#if defined(Q_WS_QWS)
bool loadFromCache(const QString &fontPath);
+ void addQPF2File(const QByteArray &file);
+#endif // Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
void addFont(const QString &familyname, const char *foundryname, int weight,
bool italic, int pixelSize, const QByteArray &file, int fileIndex,
bool antialiased,
const QList<QFontDatabase::WritingSystem> &writingSystems = QList<QFontDatabase::WritingSystem>());
- void addQPF2File(const QByteArray &file);
#ifndef QT_NO_FREETYPE
QStringList addTTFile(const QByteArray &file, const QByteArray &fontData = QByteArray());
+#endif // QT_NO_FREETYPE
#endif
-
+#if defined(Q_WS_QWS)
QDataStream *stream;
QStringList fallbackFamilies;
+#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+ const QFontDatabaseS60Store *s60Store;
#endif
};
@@ -654,17 +704,133 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create)
pos++;
// qDebug("adding family %s at %d total=%d", f.latin1(), pos, count);
- if (!(count % 8))
- families = (QtFontFamily **)
+ if (!(count % 8)) {
+ QtFontFamily **newFamilies = (QtFontFamily **)
realloc(families,
(((count+8) >> 3) << 3) * sizeof(QtFontFamily *));
+ Q_CHECK_PTR(newFamilies);
+ families = newFamilies;
+ }
+ QtFontFamily *family = new QtFontFamily(f);
memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *));
- families[pos] = new QtFontFamily(f);
+ families[pos] = family;
count++;
return families[pos];
}
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize,
+ const QByteArray &file, int fileIndex, bool antialiased,
+ const QList<QFontDatabase::WritingSystem> &writingSystems)
+{
+// qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased;
+ QtFontStyle::Key styleKey;
+ styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
+ styleKey.weight = weight;
+ styleKey.stretch = 100;
+ QtFontFamily *f = family(familyname, true);
+
+ if (writingSystems.isEmpty()) {
+ for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
+ f->writingSystems[ws] = QtFontFamily::Supported;
+ }
+ f->bogusWritingSystems = true;
+ } else {
+ for (int i = 0; i < writingSystems.count(); ++i) {
+ f->writingSystems[writingSystems.at(i)] = QtFontFamily::Supported;
+ }
+ }
+
+ QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true);
+ QtFontStyle *style = foundry->style(styleKey, true);
+ style->smoothScalable = (pixelSize == 0);
+ style->antialiased = antialiased;
+ QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
+ size->fileName = file;
+ size->fileIndex = fileIndex;
+
+#if defined(Q_WS_QWS)
+ if (stream) {
+ *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize
+ << file << fileIndex << quint8(antialiased);
+ *stream << quint8(writingSystems.count());
+ for (int i = 0; i < writingSystems.count(); ++i)
+ *stream << quint8(writingSystems.at(i));
+ }
+#else // ..in case of defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+ f->fontFilename = file;
+ f->fontFileIndex = fileIndex;
+#endif
+}
+#endif
+
+#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
+QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData)
+{
+ QStringList families;
+ extern FT_Library qt_getFreetype();
+ FT_Library library = qt_getFreetype();
+
+ int index = 0;
+ int numFaces = 0;
+ do {
+ FT_Face face;
+ FT_Error error;
+ if (!fontData.isEmpty()) {
+ error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
+ } else {
+ error = FT_New_Face(library, file, index, &face);
+ }
+ if (error != FT_Err_Ok) {
+ qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error;
+ break;
+ }
+ numFaces = face->num_faces;
+
+ int weight = QFont::Normal;
+ bool italic = face->style_flags & FT_STYLE_FLAG_ITALIC;
+
+ if (face->style_flags & FT_STYLE_FLAG_BOLD)
+ weight = QFont::Bold;
+
+ QList<QFontDatabase::WritingSystem> writingSystems;
+ // detect symbol fonts
+ for (int i = 0; i < face->num_charmaps; ++i) {
+ FT_CharMap cm = face->charmaps[i];
+ if (cm->encoding == ft_encoding_adobe_custom
+ || cm->encoding == ft_encoding_symbol) {
+ writingSystems.append(QFontDatabase::Symbol);
+ break;
+ }
+ }
+ if (writingSystems.isEmpty()) {
+ TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
+ if (os2) {
+ quint32 unicodeRange[4] = {
+ os2->ulUnicodeRange1, os2->ulUnicodeRange2, os2->ulUnicodeRange3, os2->ulUnicodeRange4
+ };
+ quint32 codePageRange[2] = {
+ os2->ulCodePageRange1, os2->ulCodePageRange2
+ };
+
+ writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+ //for (int i = 0; i < writingSystems.count(); ++i)
+ // qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i));
+ }
+ }
+
+ QString family = QString::fromAscii(face->family_name);
+ families.append(family);
+ addFont(family, /*foundry*/ "", weight, italic,
+ /*pixelsize*/ 0, file, index, /*antialias*/ true, writingSystems);
+
+ FT_Done_Face(face);
+ ++index;
+ } while (index < numFaces);
+ return families;
+}
+#endif
static const int scriptForWritingSystem[] = {
QUnicodeTables::Common, // Any
@@ -792,7 +958,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe
if (! desc.foundry->name.isEmpty() && desc.family->count > 1) {
fontDef->family += QString::fromLatin1(" [");
fontDef->family += desc.foundry->name;
- fontDef->family += QString::fromLatin1("]");
+ fontDef->family += QLatin1Char(']');
}
if (desc.style->smoothScalable)
@@ -814,7 +980,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe
#endif
#endif
-#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key)
{
// look for the requested font in the engine data cache
@@ -866,8 +1032,6 @@ QMutex *qt_fontdatabase_mutex()
return fontDatabaseMutex();
}
-#define SMOOTH_SCALABLE 0xffff
-
QT_BEGIN_INCLUDE_NAMESPACE
#if defined(Q_WS_X11)
# include "qfontdatabase_x11.cpp"
@@ -877,6 +1041,8 @@ QT_BEGIN_INCLUDE_NAMESPACE
# include "qfontdatabase_win.cpp"
#elif defined(Q_WS_QWS)
# include "qfontdatabase_qws.cpp"
+#elif defined(Q_OS_SYMBIAN)
+# include "qfontdatabase_s60.cpp"
#endif
QT_END_INCLUDE_NAMESPACE
@@ -1249,21 +1415,21 @@ static QString styleStringHelper(int weight, QFont::Style style)
{
QString result;
if (weight >= QFont::Black)
- result = qApp->translate("QFontDatabase", "Black");
+ result = QApplication::translate("QFontDatabase", "Black");
else if (weight >= QFont::Bold)
- result = qApp->translate("QFontDatabase", "Bold");
+ result = QApplication::translate("QFontDatabase", "Bold");
else if (weight >= QFont::DemiBold)
- result = qApp->translate("QFontDatabase", "Demi Bold");
+ result = QApplication::translate("QFontDatabase", "Demi Bold");
else if (weight < QFont::Normal)
- result = qApp->translate("QFontDatabase", "Light");
+ result = QApplication::translate("QFontDatabase", "Light");
if (style == QFont::StyleItalic)
- result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Italic");
+ result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Italic");
else if (style == QFont::StyleOblique)
- result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Oblique");
+ result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Oblique");
if (result.isEmpty())
- result = qApp->translate("QFontDatabase", "Normal");
+ result = QApplication::translate("QFontDatabase", "Normal");
return result.simplified();
}
@@ -1295,9 +1461,7 @@ QString QFontDatabase::styleString(const QFontInfo &fontInfo)
\brief The QFontDatabase class provides information about the fonts available in the underlying window system.
- \ingroup environment
- \ingroup multimedia
- \ingroup text
+ \ingroup appearance
The most common uses of this class are to query the database for
the list of font families() and for the pointSizes() and styles()
@@ -1495,7 +1659,7 @@ QStringList QFontDatabase::families(WritingSystem writingSystem) const
if (!foundry.isEmpty()) {
str += QLatin1String(" [");
str += foundry;
- str += QLatin1String("]");
+ str += QLatin1Char(']');
}
flist.append(str);
}
@@ -2067,7 +2231,7 @@ QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
break;
}
- return qApp ? qApp->translate("QFontDatabase", name) : QString::fromLatin1(name);
+ return QApplication::translate("QFontDatabase", name);
}
@@ -2254,7 +2418,16 @@ QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
sample += QChar(0xac2f);
break;
case Vietnamese:
+ {
+ static const char vietnameseUtf8[] = {
+ char(0xef), char(0xbb), char(0xbf), char(0xe1), char(0xbb), char(0x97),
+ char(0xe1), char(0xbb), char(0x99),
+ char(0xe1), char(0xbb), char(0x91),
+ char(0xe1), char(0xbb), char(0x93),
+ };
+ sample += QString::fromUtf8(vietnameseUtf8, sizeof(vietnameseUtf8));
break;
+ }
case Ogham:
sample += QChar(0x1681);
sample += QChar(0x1682);
@@ -2418,7 +2591,7 @@ QStringList QFontDatabase::applicationFontFamilies(int id)
\sa removeApplicationFont(), addApplicationFont(), addApplicationFontFromData()
*/
-/*!
+/*!
\fn bool QFontDatabase::supportsThreadedFontRendering()
\since 4.4
@@ -2427,7 +2600,7 @@ QStringList QFontDatabase::applicationFontFamilies(int id)
means that all QPainter::drawText() calls outside the GUI thread
will not produce readable output.
- \sa threads.html#painting-in-threads
+ \sa {Thread-Support in Qt Modules#Painting In Threads}{Painting In Threads}
*/
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index ebba2bb..e62bb31 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -151,7 +151,7 @@ public:
private:
static void createDatabase();
static void parseFontName(const QString &name, QString &foundry, QString &family);
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request);
#endif
static void load(const QFontPrivate *d, int script);
@@ -165,6 +165,7 @@ private:
friend class QFontDialogPrivate;
friend class QFontEngineMultiXLFD;
friend class QFontEngineMultiQWS;
+ friend class QFontEngineMultiS60;
QFontDatabasePrivate *d;
};
diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp
index 11e82d8..0a9630f 100644
--- a/src/gui/text/qfontdatabase_qws.cpp
+++ b/src/gui/text/qfontdatabase_qws.cpp
@@ -50,14 +50,15 @@
#include <ft2build.h>
#include FT_FREETYPE_H
-#include FT_TRUETYPE_TABLES_H
#endif
#include "qfontengine_qpf_p.h"
#include "private/qfactoryloader_p.h"
+#include "private/qcore_unix_p.h" // overrides QT_OPEN
#include "qabstractfontengine_qws.h"
#include "qabstractfontengine_p.h"
#include <qdatetime.h>
+#include "qplatformdefs.h"
// for mmap
#include <stdlib.h>
@@ -81,44 +82,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
const quint8 DatabaseVersion = 4;
-void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize,
- const QByteArray &file, int fileIndex, bool antialiased,
- const QList<QFontDatabase::WritingSystem> &writingSystems)
-{
-// qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased;
- QtFontStyle::Key styleKey;
- styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
- styleKey.weight = weight;
- styleKey.stretch = 100;
- QtFontFamily *f = family(familyname, true);
-
- if (writingSystems.isEmpty()) {
- for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
- f->writingSystems[ws] = QtFontFamily::Supported;
- }
- f->bogusWritingSystems = true;
- } else {
- for (int i = 0; i < writingSystems.count(); ++i) {
- f->writingSystems[writingSystems.at(i)] = QtFontFamily::Supported;
- }
- }
-
- QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true);
- QtFontStyle *style = foundry->style(styleKey, true);
- style->smoothScalable = (pixelSize == 0);
- style->antialiased = antialiased;
- QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
- size->fileName = file;
- size->fileIndex = fileIndex;
-
- if (stream) {
- *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize
- << file << fileIndex << quint8(antialiased);
- *stream << quint8(writingSystems.count());
- for (int i = 0; i < writingSystems.count(); ++i)
- *stream << quint8(writingSystems.at(i));
- }
-}
+// QFontDatabasePrivate::addFont() went into qfontdatabase.cpp
#ifndef QT_NO_QWS_QPF2
void QFontDatabasePrivate::addQPF2File(const QByteArray &file)
@@ -127,7 +91,7 @@ void QFontDatabasePrivate::addQPF2File(const QByteArray &file)
struct stat st;
if (stat(file.constData(), &st))
return;
- int f = ::open(file, O_RDONLY);
+ int f = QT_OPEN(file, O_RDONLY, 0);
if (f < 0)
return;
const uchar *data = (const uchar *)mmap(0, st.st_size, PROT_READ, MAP_SHARED, f, 0);
@@ -175,77 +139,12 @@ void QFontDatabasePrivate::addQPF2File(const QByteArray &file)
#endif
}
#ifndef QT_FONTS_ARE_RESOURCES
- ::close(f);
+ QT_CLOSE(f);
#endif
}
-#endif
-
-#ifndef QT_NO_FREETYPE
-QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData)
-{
- QStringList families;
- extern FT_Library qt_getFreetype();
- FT_Library library = qt_getFreetype();
-
- int index = 0;
- int numFaces = 0;
- do {
- FT_Face face;
- FT_Error error;
- if (!fontData.isEmpty()) {
- error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
- } else {
- error = FT_New_Face(library, file, index, &face);
- }
- if (error != FT_Err_Ok) {
- qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error;
- break;
- }
- numFaces = face->num_faces;
+#endif // QT_NO_QWS_QPF2
- int weight = QFont::Normal;
- bool italic = face->style_flags & FT_STYLE_FLAG_ITALIC;
-
- if (face->style_flags & FT_STYLE_FLAG_BOLD)
- weight = QFont::Bold;
-
- QList<QFontDatabase::WritingSystem> writingSystems;
- // detect symbol fonts
- for (int i = 0; i < face->num_charmaps; ++i) {
- FT_CharMap cm = face->charmaps[i];
- if (cm->encoding == ft_encoding_adobe_custom
- || cm->encoding == ft_encoding_symbol) {
- writingSystems.append(QFontDatabase::Symbol);
- break;
- }
- }
- if (writingSystems.isEmpty()) {
- TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
- if (os2) {
- quint32 unicodeRange[4] = {
- os2->ulUnicodeRange1, os2->ulUnicodeRange2, os2->ulUnicodeRange3, os2->ulUnicodeRange4
- };
- quint32 codePageRange[2] = {
- os2->ulCodePageRange1, os2->ulCodePageRange2
- };
-
- writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
- //for (int i = 0; i < writingSystems.count(); ++i)
- // qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i));
- }
- }
-
- QString family = QString::fromAscii(face->family_name);
- families.append(family);
- addFont(family, /*foundry*/ "", weight, italic,
- /*pixelsize*/ 0, file, index, /*antialias*/ true, writingSystems);
-
- FT_Done_Face(face);
- ++index;
- } while (index < numFaces);
- return families;
-}
-#endif
+// QFontDatabasePrivate::addTTFile() went into qfontdatabase.cpp
static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt);
@@ -358,7 +257,7 @@ static QString qwsFontPath()
return fontpath;
}
-#ifdef QFONTDATABASE_DEBUG
+#if defined(QFONTDATABASE_DEBUG) && defined(QT_FONTS_ARE_RESOURCES)
class FriendlyResource : public QResource
{
public:
@@ -669,19 +568,19 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
QFontEngineQPF *fe = new QFontEngineQPF(request, res.data(), res.size());
if (fe->isValid())
return fe;
- qDebug() << "fontengine is not valid! " << size->fileName;
delete fe;
+ qDebug() << "fontengine is not valid! " << size->fileName;
} else {
qDebug() << "Resource not valid" << size->fileName;
}
#else
- int f = ::open(size->fileName, O_RDONLY);
+ int f = ::open(size->fileName, O_RDONLY, 0);
if (f >= 0) {
QFontEngineQPF *fe = new QFontEngineQPF(request, f);
if (fe->isValid())
return fe;
- qDebug() << "fontengine is not valid!";
delete fe; // will close f
+ qDebug() << "fontengine is not valid!";
}
#endif
} else
@@ -692,73 +591,74 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
QFontDef def = request;
def.pixelSize = pixelSize;
+#ifdef QT_NO_QWS_SHARE_FONTS
+ bool shareFonts = false;
+#else
static bool dontShareFonts = !qgetenv("QWS_NO_SHARE_FONTS").isEmpty();
bool shareFonts = !dontShareFonts;
+#endif
- QFontEngine *engine = 0;
+ QScopedPointer<QFontEngine> engine;
#ifndef QT_NO_LIBRARY
QFontEngineFactoryInterface *factory = qobject_cast<QFontEngineFactoryInterface *>(loader()->instance(foundry->name));
- if (factory) {
- QFontEngineInfo info;
- info.setFamily(request.family);
- info.setPixelSize(request.pixelSize);
- info.setStyle(QFont::Style(request.style));
- info.setWeight(request.weight);
- // #### antialiased
-
- QAbstractFontEngine *customEngine = factory->create(info);
- if (customEngine) {
- engine = new QProxyFontEngine(customEngine, def);
-
- if (shareFonts) {
- QVariant hint = customEngine->fontProperty(QAbstractFontEngine::CacheGlyphsHint);
- if (hint.isValid())
- shareFonts = hint.toBool();
- else
- shareFonts = (pixelSize < 64);
- }
+ if (factory) {
+ QFontEngineInfo info;
+ info.setFamily(request.family);
+ info.setPixelSize(request.pixelSize);
+ info.setStyle(QFont::Style(request.style));
+ info.setWeight(request.weight);
+ // #### antialiased
+
+ QAbstractFontEngine *customEngine = factory->create(info);
+ if (customEngine) {
+ engine.reset(new QProxyFontEngine(customEngine, def));
+
+ if (shareFonts) {
+ QVariant hint = customEngine->fontProperty(QAbstractFontEngine::CacheGlyphsHint);
+ if (hint.isValid())
+ shareFonts = hint.toBool();
+ else
+ shareFonts = (pixelSize < 64);
}
+ }
}
#endif // QT_NO_LIBRARY
- if (!engine && !file.isEmpty() && QFile::exists(file) || privateDb()->isApplicationFont(file)) {
+ if ((engine.isNull() && !file.isEmpty() && QFile::exists(file)) || privateDb()->isApplicationFont(file)) {
QFontEngine::FaceId faceId;
faceId.filename = file.toLocal8Bit();
faceId.index = size->fileIndex;
#ifndef QT_NO_FREETYPE
- QFontEngineFT *fte = new QFontEngineFT(def);
+ QScopedPointer<QFontEngineFT> fte(new QFontEngineFT(def));
if (fte->init(faceId, style->antialiased,
style->antialiased ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) {
#ifdef QT_NO_QWS_QPF2
- return fte;
+ return fte.take();
#else
- engine = fte;
// try to distinguish between bdf and ttf fonts we can pre-render
// and don't try to share outline fonts
shareFonts = shareFonts
&& !fte->defaultGlyphs()->outline_drawing
&& !fte->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')).isEmpty();
+ engine.reset(fte.take());
#endif
- } else {
- delete fte;
}
#endif // QT_NO_FREETYPE
}
- if (engine) {
+ if (!engine.isNull()) {
#if !defined(QT_NO_QWS_QPF2) && !defined(QT_FONTS_ARE_RESOURCES)
if (shareFonts) {
- QFontEngineQPF *fe = new QFontEngineQPF(def, -1, engine);
- engine = 0;
+ QScopedPointer<QFontEngineQPF> fe(new QFontEngineQPF(def, -1, engine.data()));
+ engine.take();
if (fe->isValid())
- return fe;
+ return fe.take();
qWarning("Initializing QFontEngineQPF failed for %s", qPrintable(file));
- engine = fe->takeRenderingEngine();
- delete fe;
+ engine.reset(fe->takeRenderingEngine());
}
#endif
- return engine;
+ return engine.take();
}
} else
{
@@ -766,8 +666,8 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
QString fn = qwsFontPath();
fn += QLatin1Char('/');
fn += family->name.toLower()
- + QLatin1String("_") + QString::number(pixelSize*10)
- + QLatin1String("_") + QString::number(style->key.weight)
+ + QLatin1Char('_') + QString::number(pixelSize*10)
+ + QLatin1Char('_') + QString::number(style->key.weight)
+ (style->key.style == QFont::StyleItalic ?
QLatin1String("i.qpf") : QLatin1String(".qpf"));
//###rotation ###
@@ -785,20 +685,22 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp,
QtFontFamily *family, QtFontFoundry *foundry,
QtFontStyle *style, QtFontSize *size)
{
- QFontEngine *fe = loadSingleEngine(script, fp, request, family, foundry,
- style, size);
- if (fe
+ QScopedPointer<QFontEngine> engine(loadSingleEngine(script, fp, request, family, foundry,
+ style, size));
+ if (!engine.isNull()
&& script == QUnicodeTables::Common
- && !(request.styleStrategy & QFont::NoFontMerging) && !fe->symbol) {
+ && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) {
QStringList fallbacks = privateDb()->fallbackFamilies;
if (family && !family->fallbackFamilies.isEmpty())
fallbacks = family->fallbackFamilies;
- fe = new QFontEngineMultiQWS(fe, script, fallbacks);
+ QFontEngine *fe = new QFontEngineMultiQWS(engine.data(), script, fallbacks);
+ engine.take();
+ engine.reset(fe);
}
- return fe;
+ return engine.take();
}
static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
@@ -860,21 +762,21 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
if (!privateDb()->count)
initializeDb();
- QFontEngine *fe = 0;
+ QScopedPointer<QFontEngine> fe;
if (fp) {
if (fp->rawMode) {
- fe = loadEngine(script, fp, request, 0, 0, 0, 0
- );
+ fe.reset(loadEngine(script, fp, request, 0, 0, 0, 0));
// if we fail to load the rawmode font, use a 12pixel box engine instead
- if (! fe) fe = new QFontEngineBox(12);
- return fe;
+ if (fe.isNull())
+ fe.reset(new QFontEngineBox(12));
+ return fe.take();
}
QFontCache::Key key(request, script);
- fe = QFontCache::instance()->findEngine(key);
- if (fe)
- return fe;
+ fe.reset(QFontCache::instance()->findEngine(key));
+ if (! fe.isNull())
+ return fe.take();
}
QString family_name, foundry_name;
@@ -898,11 +800,11 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
- fe = new QTestFontEngine(request.pixelSize);
+ fe.reset(new QTestFontEngine(request.pixelSize));
fe->fontDef = request;
}
- if (!fe)
+ if (fe.isNull())
{
QtFontDesc desc;
match(script, request, family_name, foundry_name, force_encoding_id, &desc);
@@ -923,16 +825,28 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
'p', 0
);
- fe = loadEngine(script, fp, request, desc.family, desc.foundry, desc.style, desc.size
- );
+ fe.reset(loadEngine(script, fp, request, desc.family, desc.foundry, desc.style, desc.size
+ ));
} else {
FM_DEBUG(" NO MATCH FOUND\n");
}
- if (fe)
+ if (! fe.isNull())
initFontDef(desc, request, &fe->fontDef);
}
- if (fe) {
+#ifndef QT_NO_FREETYPE
+ if (! fe.isNull()) {
+ if (scriptRequiresOpenType(script) && fe->type() == QFontEngine::Freetype) {
+ HB_Face hbFace = static_cast<QFontEngineFT *>(fe.data())->harfbuzzFace();
+ if (!hbFace || !hbFace->supported_scripts[script]) {
+ FM_DEBUG(" OpenType support missing for script\n");
+ fe.reset(0);
+ }
+ }
+ }
+#endif
+
+ if (! fe.isNull()) {
if (fp) {
QFontDef def = request;
if (def.family.isEmpty()) {
@@ -940,32 +854,21 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
def.family = def.family.left(def.family.indexOf(QLatin1Char(',')));
}
QFontCache::Key key(def, script);
- QFontCache::instance()->insertEngine(key, fe);
- }
-
-#ifndef QT_NO_FREETYPE
- if (scriptRequiresOpenType(script) && fe->type() == QFontEngine::Freetype) {
- HB_Face hbFace = static_cast<QFontEngineFT *>(fe)->harfbuzzFace();
- if (!hbFace || !hbFace->supported_scripts[script]) {
- FM_DEBUG(" OpenType support missing for script\n");
- delete fe;
- fe = 0;
- }
+ QFontCache::instance()->insertEngine(key, fe.data());
}
-#endif
}
- if (!fe) {
+ if (fe.isNull()) {
if (!request.family.isEmpty())
return 0;
FM_DEBUG("returning box engine");
- fe = new QFontEngineBox(request.pixelSize);
+ fe.reset(new QFontEngineBox(request.pixelSize));
if (fp) {
QFontCache::Key key(request, script);
- QFontCache::instance()->insertEngine(key, fe);
+ QFontCache::instance()->insertEngine(key, fe.data());
}
}
@@ -975,7 +878,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
fe->fontDef.pointSize = request.pointSize;
}
- return fe;
+ return fe.take();
}
void QFontDatabase::load(const QFontPrivate *d, int script)
@@ -996,7 +899,13 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
if (!d->engineData) {
// create a new one
d->engineData = new QFontEngineData;
- QFontCache::instance()->insertEngineData(key, d->engineData);
+ QT_TRY {
+ QFontCache::instance()->insertEngineData(key, d->engineData);
+ } QT_CATCH(...) {
+ delete d->engineData;
+ d->engineData = 0;
+ QT_RETHROW;
+ }
} else {
d->engineData->ref.ref();
}
@@ -1005,8 +914,6 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
// the cached engineData could have already loaded the engine we want
if (d->engineData->engines[script]) return;
- // load the font
- QFontEngine *engine = 0;
// double scale = 1.0; // ### TODO: fix the scale calculations
// list of families to try
@@ -1038,20 +945,15 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
// null family means find the first font matching the specified script
family_list << QString();
+ // load the font
+ QFontEngine *engine = 0;
QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
- for (; ! engine && it != end; ++it) {
+ for (; !engine && it != end; ++it) {
req.family = *it;
engine = QFontDatabase::findFont(script, d, req);
- if (engine) {
- if (engine->type() != QFontEngine::Box)
- break;
-
- if (! req.family.isEmpty())
- engine = 0;
-
- continue;
- }
+ if (engine && (engine->type()==QFontEngine::Box) && !req.family.isEmpty())
+ engine = 0;
}
engine->ref.ref();
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
new file mode 100644
index 0000000..fe90010
--- /dev/null
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -0,0 +1,428 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qapplication_p.h>
+#include "qdir.h"
+#include "qfont_p.h"
+#include "qfontengine_s60_p.h"
+#include "qabstractfileengine.h"
+#include "qdesktopservices.h"
+#include "qt_s60_p.h"
+#include "qendian.h"
+#include <private/qwindowsurface_s60_p.h>
+#include <private/qcore_symbian_p.h>
+#if defined(QT_NO_FREETYPE)
+#include <OPENFONT.H>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QFileInfoList alternativeFilePaths(const QString &path, const QStringList &nameFilters,
+ QDir::Filters filters = QDir::NoFilter, QDir::SortFlags sort = QDir::NoSort,
+ bool uniqueFileNames = true)
+{
+ QFileInfoList result;
+
+ // Prepare a 'soft to hard' drive list: W:, X: ... A:, Z:
+ QStringList driveStrings;
+ foreach (const QFileInfo &drive, QDir::drives())
+ driveStrings.append(drive.absolutePath());
+ driveStrings.sort();
+ const QString zDriveString("Z:/");
+ driveStrings.removeAll(zDriveString);
+ driveStrings.prepend(zDriveString);
+
+ QStringList uniqueFileNameList;
+ for (int i = driveStrings.count() - 1; i >= 0; --i) {
+ const QDir dirOnDrive(driveStrings.at(i) + path);
+ const QFileInfoList entriesOnDrive = dirOnDrive.entryInfoList(nameFilters, filters, sort);
+ if (uniqueFileNames) {
+ foreach(const QFileInfo &entry, entriesOnDrive) {
+ if (!uniqueFileNameList.contains(entry.fileName())) {
+ uniqueFileNameList.append(entry.fileName());
+ result.append(entry);
+ }
+ }
+ } else {
+ result.append(entriesOnDrive);
+ }
+ }
+ return result;
+}
+
+#if defined(QT_NO_FREETYPE)
+class QFontDatabaseS60StoreImplementation : public QFontDatabaseS60Store
+{
+public:
+ QFontDatabaseS60StoreImplementation();
+ ~QFontDatabaseS60StoreImplementation();
+
+ const QFontEngineS60Extensions *extension(const QString &typeface) const;
+
+private:
+ RHeap* m_heap;
+ CFontStore *m_store;
+ COpenFontRasterizer *m_rasterizer;
+ mutable QHash<QString, const QFontEngineS60Extensions *> m_extensions;
+};
+
+QFontDatabaseS60StoreImplementation::QFontDatabaseS60StoreImplementation()
+{
+ m_heap = User::ChunkHeap(NULL, 0x1000, 0x100000);
+ QT_TRAP_THROWING(
+ m_store = CFontStore::NewL(m_heap);
+ m_rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E));
+ CleanupStack::PushL(m_rasterizer);
+ m_store->InstallRasterizerL(m_rasterizer);
+ CleanupStack::Pop(m_rasterizer););
+
+ QStringList filters;
+ filters.append(QString::fromLatin1("*.ttf"));
+ filters.append(QString::fromLatin1("*.ccc"));
+ const QFileInfoList fontFiles = alternativeFilePaths(QString::fromLatin1("resource\\Fonts"), filters);
+ foreach (const QFileInfo &fontFileInfo, fontFiles) {
+ const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath());
+ TPtrC fontFilePtr(qt_QString2TPtrC(fontFile));
+ QT_TRAP_THROWING(m_store->AddFileL(fontFilePtr));
+ }
+}
+QFontDatabaseS60StoreImplementation::~QFontDatabaseS60StoreImplementation()
+{
+ typedef QHash<QString, const QFontEngineS60Extensions *>::iterator iterator;
+ for (iterator p = m_extensions.begin(); p != m_extensions.end(); ++p) {
+ m_store->ReleaseFont((*p)->fontOwner());
+ delete *p;
+ }
+
+ delete m_store;
+ m_heap->Close();
+}
+
+const QFontEngineS60Extensions *QFontDatabaseS60StoreImplementation::extension(const QString &typeface) const
+{
+ if (!m_extensions.contains(typeface)) {
+ CFont* font = NULL;
+ TFontSpec spec(qt_QString2TPtrC(typeface), 1);
+ spec.iHeight = 1;
+ const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, spec);
+ Q_ASSERT(err == KErrNone && font);
+ CBitmapFont *bitmapFont = static_cast<CBitmapFont*>(font);
+ m_extensions.insert(typeface, new QFontEngineS60Extensions(font, bitmapFont->OpenFont()));
+ }
+ return m_extensions.value(typeface);
+}
+#else
+class QFontEngineFTS60 : public QFontEngineFT
+{
+public:
+ QFontEngineFTS60(const QFontDef &fd);
+};
+
+QFontEngineFTS60::QFontEngineFTS60(const QFontDef &fd)
+ : QFontEngineFT(fd)
+{
+ default_hint_style = HintFull;
+}
+#endif // defined(QT_NO_FREETYPE)
+
+/*
+ QFontEngineS60::pixelsToPoints, QFontEngineS60::pointsToPixels, QFontEngineMultiS60::QFontEngineMultiS60
+ and QFontEngineMultiS60::QFontEngineMultiS60 should be in qfontengine_s60.cpp. But since also the
+ Freetype based font rendering need them, they are here.
+*/
+qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation)
+{
+ return (orientation == Qt::Horizontal?
+ S60->screenDevice()->HorizontalPixelsToTwips(pixels)
+ :S60->screenDevice()->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint;
+}
+
+qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation)
+{
+ const int twips = points * KTwipsPerPoint;
+ return orientation == Qt::Horizontal?
+ S60->screenDevice()->HorizontalTwipsToPixels(twips)
+ :S60->screenDevice()->VerticalTwipsToPixels(twips);
+}
+
+QFontEngineMultiS60::QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies)
+ : QFontEngineMulti(fallbackFamilies.size() + 1)
+ , m_script(script)
+ , m_fallbackFamilies(fallbackFamilies)
+{
+ engines[0] = first;
+ first->ref.ref();
+ fontDef = engines[0]->fontDef;
+}
+
+void QFontEngineMultiS60::loadEngine(int at)
+{
+ Q_ASSERT(at < engines.size());
+ Q_ASSERT(engines.at(at) == 0);
+
+ QFontDef request = fontDef;
+ request.styleStrategy |= QFont::NoFontMerging;
+ request.family = m_fallbackFamilies.at(at-1);
+ engines[at] = QFontDatabase::findFont(m_script,
+ /*fontprivate*/0,
+ request);
+ Q_ASSERT(engines[at]);
+}
+
+static void initializeDb()
+{
+ QFontDatabasePrivate *db = privateDb();
+ if(!db || db->count)
+ return;
+
+#if defined(QT_NO_FREETYPE)
+ if (!db->s60Store)
+ db->s60Store = new QFontDatabaseS60StoreImplementation;
+
+ QS60WindowSurface::unlockBitmapHeap();
+ const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces();
+ const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store);
+ Q_ASSERT(store);
+ for (int i = 0; i < numTypeFaces; i++) {
+ TTypefaceSupport typefaceSupport;
+ QS60Data::screenDevice()->TypefaceSupport(typefaceSupport, i);
+ CFont *font; // We have to get a font instance in order to know all the details
+ TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11);
+ qt_symbian_throwIfError(QS60Data::screenDevice()->GetNearestFontInPixels(font, fontSpec));
+ if (font->TypeUid() == KCFbsFontUid) {
+ TOpenFontFaceAttrib faceAttrib;
+ const CFbsFont *cfbsFont = dynamic_cast<const CFbsFont *>(font);
+ Q_ASSERT(cfbsFont);
+ cfbsFont->GetFaceAttrib(faceAttrib);
+
+ QtFontStyle::Key styleKey;
+ styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal;
+ styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal;
+
+ QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length());
+ QtFontFamily *family = db->family(familyName, true);
+ family->fixedPitch = faceAttrib.IsMonoWidth();
+ QtFontFoundry *foundry = family->foundry(QString(), true);
+ QtFontStyle *style = foundry->style(styleKey, true);
+ style->smoothScalable = typefaceSupport.iIsScalable;
+ style->pixelSize(0, true);
+
+ const QFontEngineS60Extensions *extension = store->extension(familyName);
+ const QByteArray os2Table = extension->getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
+ const unsigned char* data = reinterpret_cast<const unsigned char*>(os2Table.constData());
+ const unsigned char* ulUnicodeRange = data + 42;
+ quint32 unicodeRange[4] = {
+ qFromBigEndian<quint32>(ulUnicodeRange),
+ qFromBigEndian<quint32>(ulUnicodeRange + 4),
+ qFromBigEndian<quint32>(ulUnicodeRange + 8),
+ qFromBigEndian<quint32>(ulUnicodeRange + 12)
+ };
+ const unsigned char* ulCodePageRange = data + 78;
+ quint32 codePageRange[2] = {
+ qFromBigEndian<quint32>(ulCodePageRange),
+ qFromBigEndian<quint32>(ulCodePageRange + 4)
+ };
+ const QList<QFontDatabase::WritingSystem> writingSystems =
+ determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+ foreach (const QFontDatabase::WritingSystem system, writingSystems)
+ family->writingSystems[system] = QtFontFamily::Supported;
+ }
+ QS60Data::screenDevice()->ReleaseFont(font);
+ }
+ QS60WindowSurface::lockBitmapHeap();
+#else // defined(QT_NO_FREETYPE)
+ QDir dir(QDesktopServices::storageLocation(QDesktopServices::FontsLocation));
+ dir.setNameFilters(QStringList() << QLatin1String("*.ttf")
+ << QLatin1String("*.ttc") << QLatin1String("*.pfa")
+ << QLatin1String("*.pfb"));
+ for (int i = 0; i < int(dir.count()); ++i) {
+ const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i]));
+ db->addTTFile(file);
+ }
+#endif // defined(QT_NO_FREETYPE)
+}
+
+static inline void load(const QString &family = QString(), int script = -1)
+{
+ Q_UNUSED(family)
+ Q_UNUSED(script)
+ initializeDb();
+}
+
+static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
+{
+ Q_UNUSED(fnt);
+}
+
+bool QFontDatabase::removeApplicationFont(int handle)
+{
+ Q_UNUSED(handle);
+ return false;
+}
+
+bool QFontDatabase::supportsThreadedFontRendering()
+{
+ return false;
+}
+
+static
+QFontDef cleanedFontDef(const QFontDef &req)
+{
+ QFontDef result = req;
+ if (result.pixelSize <= 0) {
+ result.pixelSize = QFontEngineS60::pointsToPixels(qMax(qreal(1.0), result.pointSize));
+ result.pointSize = 0;
+ }
+ return result;
+}
+
+QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *, const QFontDef &req)
+{
+ const QFontCache::Key key(cleanedFontDef(req), script);
+
+ if (!privateDb()->count)
+ initializeDb();
+
+ QFontEngine *fe = QFontCache::instance()->findEngine(key);
+ if (!fe) {
+ // Making sure that fe->fontDef.family will be an existing font.
+ initializeDb();
+ QFontDatabasePrivate *db = privateDb();
+ QtFontDesc desc;
+ QList<int> blacklistedFamilies;
+ match(script, req, req.family, QString(), -1, &desc, blacklistedFamilies);
+ if (!desc.family) // falling back to application font
+ desc.family = db->family(QApplication::font().defaultFamily());
+ Q_ASSERT(desc.family);
+
+ // Making sure that desc.family supports the requested script
+ QtFontDesc mappedDesc;
+ bool supportsScript = false;
+ do {
+ match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies);
+ if (mappedDesc.family == desc.family) {
+ supportsScript = true;
+ break;
+ }
+ blacklistedFamilies.append(mappedDesc.familyIndex);
+ } while (mappedDesc.family);
+ if (!supportsScript) {
+ blacklistedFamilies.clear();
+ match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies);
+ if (mappedDesc.family)
+ desc = mappedDesc;
+ }
+
+ const QString fontFamily = desc.family->name;
+ QFontDef request = req;
+ request.family = fontFamily;
+#if defined(QT_NO_FREETYPE)
+ const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store);
+ Q_ASSERT(store);
+ const QFontEngineS60Extensions *extension = store->extension(fontFamily);
+ fe = new QFontEngineS60(request, extension);
+#else
+ QFontEngine::FaceId faceId;
+ const QtFontFamily * const reqQtFontFamily = db->family(fontFamily);
+ faceId.filename = reqQtFontFamily->fontFilename;
+ faceId.index = reqQtFontFamily->fontFileIndex;
+
+ QFontEngineFTS60 *fte = new QFontEngineFTS60(cleanedFontDef(request));
+ if (fte->init(faceId, true, QFontEngineFT::Format_A8))
+ fe = fte;
+ else
+ delete fte;
+#endif
+
+ Q_ASSERT(fe);
+ if (script == QUnicodeTables::Common
+ && !(req.styleStrategy & QFont::NoFontMerging)
+ && !fe->symbol) {
+
+ QStringList commonFonts;
+ for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
+ if (scriptForWritingSystem[ws] != script)
+ continue;
+ for (int i = 0; i < db->count; ++i) {
+ if (db->families[i]->writingSystems[ws] & QtFontFamily::Supported)
+ commonFonts.append(db->families[i]->name);
+ }
+ }
+
+ // Hack: Prioritize .ccc fonts
+ const QString niceEastAsianFont(QLatin1String("Sans MT 936_S60"));
+ if (commonFonts.removeAll(niceEastAsianFont) > 0)
+ commonFonts.prepend(niceEastAsianFont);
+
+ fe = new QFontEngineMultiS60(fe, script, commonFonts);
+ }
+ }
+ fe->ref.ref();
+ QFontCache::instance()->insertEngine(key, fe);
+ return fe;
+}
+
+void QFontDatabase::load(const QFontPrivate *d, int script)
+{
+ QFontEngine *fe = 0;
+ QFontDef req = d->request;
+
+ if (!d->engineData) {
+ const QFontCache::Key key(cleanedFontDef(req), script);
+ getEngineData(d, key);
+ }
+
+ // the cached engineData could have already loaded the engine we want
+ if (d->engineData->engines[script])
+ fe = d->engineData->engines[script];
+
+ if (!fe) {
+ if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
+ fe = new QTestFontEngine(req.pixelSize);
+ fe->fontDef = req;
+ } else {
+ fe = findFont(script, d, req);
+ }
+ d->engineData->engines[script] = fe;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp
index 4c45ce9..76bd3f8 100644
--- a/src/gui/text/qfontdatabase_win.cpp
+++ b/src/gui/text/qfontdatabase_win.cpp
@@ -195,21 +195,12 @@ static QString getEnglishName(const QString &familyName)
QString i18n_name;
HDC hdc = GetDC( 0 );
- HFONT hfont;
- QT_WA( {
- LOGFONTW lf;
- memset( &lf, 0, sizeof( LOGFONTW ) );
- memcpy( lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length())*sizeof(QChar) );
- lf.lfCharSet = DEFAULT_CHARSET;
- hfont = CreateFontIndirectW( &lf );
- }, {
- LOGFONTA lf;
- memset( &lf, 0, sizeof( LOGFONTA ) );
- QByteArray lfam = familyName.toLocal8Bit();
- memcpy( lf.lfFaceName, lfam, qMin(LF_FACESIZE, lfam.size()) );
- lf.lfCharSet = DEFAULT_CHARSET;
- hfont = CreateFontIndirectA( &lf );
- } );
+ LOGFONT lf;
+ memset(&lf, 0, sizeof(LOGFONT));
+ memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t));
+ lf.lfCharSet = DEFAULT_CHARSET;
+ HFONT hfont = CreateFontIndirect(&lf);
+
if(!hfont) {
ReleaseDC(0, hdc);
return QString();
@@ -245,32 +236,6 @@ error:
return i18n_name;
}
-static void getFontSignature(const QString &familyName,
- NEWTEXTMETRICEX *textmetric,
- FONTSIGNATURE *signature)
-{
- QT_WA({
- Q_UNUSED(familyName);
- *signature = textmetric->ntmFontSig;
- }, {
- // the textmetric structure we get from EnumFontFamiliesEx on Win9x has
- // a FONTSIGNATURE, but that one is uninitialized and doesn't work. Have to go
- // the hard way and load the font to find out.
- HDC hdc = GetDC(0);
- LOGFONTA lf;
- memset(&lf, 0, sizeof(LOGFONTA));
- QByteArray lfam = familyName.toLocal8Bit();
- memcpy(lf.lfFaceName, lfam.data(), qMin(LF_FACESIZE, lfam.length()));
- lf.lfCharSet = DEFAULT_CHARSET;
- HFONT hfont = CreateFontIndirectA(&lf);
- HGDIOBJ oldobj = SelectObject(hdc, hfont);
- GetTextCharsetInfo(hdc, signature, 0);
- SelectObject(hdc, oldobj);
- DeleteObject(hfont);
- ReleaseDC(0, hdc);
- });
-}
-
static
void addFontToDatabase(QString familyName, const QString &scriptName,
TEXTMETRIC *textmetric,
@@ -288,26 +253,17 @@ void addFontToDatabase(QString familyName, const QString &scriptName,
bool scalable;
int size;
-// QString escript = QString::fromUtf16((ushort *)f->elfScript);
+// QString escript = QString::fromWCharArray(f->elfScript);
// qDebug("script=%s", escript.latin1());
- QT_WA({
- NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric;
- fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH);
- ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE);
- scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE);
- size = scalable ? SMOOTH_SCALABLE : tm->tmHeight;
- italic = tm->tmItalic;
- weight = tm->tmWeight;
- } , {
- NEWTEXTMETRICA *tm = (NEWTEXTMETRICA *)textmetric;
- fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH);
- ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE);
- scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE);
- size = scalable ? SMOOTH_SCALABLE : tm->tmHeight;
- italic = tm->tmItalic;
- weight = tm->tmWeight;
- });
+ NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric;
+ fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH);
+ ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE);
+ scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE);
+ size = scalable ? SMOOTH_SCALABLE : tm->tmHeight;
+ italic = tm->tmItalic;
+ weight = tm->tmWeight;
+
// the "@family" fonts are just the same as "family". Ignore them.
if (familyName[0] != QLatin1Char('@') && !familyName.startsWith(QLatin1String("WST_"))) {
QtFontStyle::Key styleKey;
@@ -364,7 +320,7 @@ void addFontToDatabase(QString familyName, const QString &scriptName,
signature->fsUsb[0], signature->fsUsb[1],
signature->fsUsb[2], signature->fsUsb[3]
};
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (signature->fsUsb[0] == 0) {
// If the unicode ranges bit mask is zero then
// EnumFontFamiliesEx failed to determine it properly.
@@ -420,18 +376,10 @@ static
int CALLBACK
storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, int type, LPARAM /*p*/)
{
- QString familyName;
- QT_WA({
- familyName = QString::fromUtf16((ushort*)f->elfLogFont.lfFaceName);
- },{
- ENUMLOGFONTEXA *fa = (ENUMLOGFONTEXA *)f;
- familyName = QString::fromLocal8Bit(fa->elfLogFont.lfFaceName);
- });
- QString script = QT_WA_INLINE(QString::fromUtf16((const ushort *)f->elfScript),
- QString::fromLocal8Bit((const char *)((ENUMLOGFONTEXA *)f)->elfScript));
-
- FONTSIGNATURE signature;
- getFontSignature(familyName, textmetric, &signature);
+ QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
+ QString script = QString::fromWCharArray(f->elfScript);
+
+ FONTSIGNATURE signature = textmetric->ntmFontSig;
// NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is
// identical to a TEXTMETRIC except for the last four members, which we don't use
@@ -459,33 +407,17 @@ void populate_database(const QString& fam)
HDC dummy = GetDC(0);
- QT_WA({
- LOGFONT lf;
- lf.lfCharSet = DEFAULT_CHARSET;
- if (fam.isNull()) {
- lf.lfFaceName[0] = 0;
- } else {
- memcpy(lf.lfFaceName, fam.utf16(), sizeof(TCHAR)*qMin(fam.length()+1,32)); // 32 = Windows hard-coded
- }
- lf.lfPitchAndFamily = 0;
-
- EnumFontFamiliesEx(dummy, &lf,
- (FONTENUMPROC)storeFont, (LPARAM)privateDb(), 0);
- } , {
- LOGFONTA lf;
- lf.lfCharSet = DEFAULT_CHARSET;
- if (fam.isNull()) {
- lf.lfFaceName[0] = 0;
- } else {
- QByteArray lname = fam.toLocal8Bit();
- memcpy(lf.lfFaceName,lname.data(),
- qMin(lname.length()+1,32)); // 32 = Windows hard-coded
- }
- lf.lfPitchAndFamily = 0;
+ LOGFONT lf;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ if (fam.isNull()) {
+ lf.lfFaceName[0] = 0;
+ } else {
+ memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded
+ }
+ lf.lfPitchAndFamily = 0;
- EnumFontFamiliesExA(dummy, &lf,
- (FONTENUMPROCA)storeFont, (LPARAM)privateDb(), 0);
- });
+ EnumFontFamiliesEx(dummy, &lf,
+ (FONTENUMPROC)storeFont, (LPARAM)privateDb(), 0);
ReleaseDC(0, dummy);
@@ -496,21 +428,11 @@ void populate_database(const QString& fam)
for (int j = 0; j < fnt.families.count(); ++j) {
const QString familyName = fnt.families.at(j);
HDC hdc = GetDC(0);
- HFONT hfont;
- QT_WA({
- LOGFONTW lf;
- memset(&lf, 0, sizeof(LOGFONTW));
- memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.size()));
- lf.lfCharSet = DEFAULT_CHARSET;
- hfont = CreateFontIndirectW(&lf);
- } , {
- LOGFONTA lf;
- memset(&lf, 0, sizeof(LOGFONTA));
- QByteArray lfam = familyName.toLocal8Bit();
- memcpy(lf.lfFaceName, lfam.data(), qMin(LF_FACESIZE, lfam.length()));
- lf.lfCharSet = DEFAULT_CHARSET;
- hfont = CreateFontIndirectA(&lf);
- });
+ LOGFONT lf;
+ memset(&lf, 0, sizeof(LOGFONT));
+ memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size()));
+ lf.lfCharSet = DEFAULT_CHARSET;
+ HFONT hfont = CreateFontIndirect(&lf);
HGDIOBJ oldobj = SelectObject(hdc, hfont);
TEXTMETRIC textMetrics;
@@ -598,17 +520,10 @@ static void initFontInfo(QFontEngineWin *fe, const QFontDef &request, const QFon
HDC dc = ((request.styleStrategy & QFont::PreferDevice) && fp->hdc) ? fp->hdc : shared_dc();
SelectObject(dc, fe->hfont);
- QT_WA({
- TCHAR n[64];
- GetTextFaceW(dc, 64, n);
- fe->fontDef.family = QString::fromUtf16((ushort*)n);
- fe->fontDef.fixedPitch = !(fe->tm.w.tmPitchAndFamily & TMPF_FIXED_PITCH);
- } , {
- char an[64];
- GetTextFaceA(dc, 64, an);
- fe->fontDef.family = QString::fromLocal8Bit(an);
- fe->fontDef.fixedPitch = !(fe->tm.a.tmPitchAndFamily & TMPF_FIXED_PITCH);
- });
+ wchar_t n[64];
+ GetTextFace(dc, 64, n);
+ fe->fontDef.family = QString::fromWCharArray(n);
+ fe->fontDef.fixedPitch = !(fe->tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
if (fe->fontDef.pointSize < 0) {
fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / fp->dpi;
} else if (fe->fontDef.pixelSize == -1) {
@@ -704,18 +619,13 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
HFONT hfont = 0;
if (fp->rawMode) { // will choose a stock font
- int f, deffnt;
- // ### why different?
- if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) || QSysInfo::WindowsVersion == QSysInfo::WV_32s)
- deffnt = SYSTEM_FONT;
- else
- deffnt = DEFAULT_GUI_FONT;
+ int f, deffnt = SYSTEM_FONT;
QString fam = desc->family->name.toLower();
if (fam == QLatin1String("default"))
f = deffnt;
else if (fam == QLatin1String("system"))
f = SYSTEM_FONT;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
else if (fam == QLatin1String("system_fixed"))
f = SYSTEM_FIXED_FONT;
else if (fam == QLatin1String("ansi_fixed"))
@@ -774,15 +684,11 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
int strat = OUT_DEFAULT_PRECIS;
if (request.styleStrategy & QFont::PreferBitmap) {
strat = OUT_RASTER_PRECIS;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
} else if (request.styleStrategy & QFont::PreferDevice) {
strat = OUT_DEVICE_PRECIS;
} else if (request.styleStrategy & QFont::PreferOutline) {
- QT_WA({
- strat = OUT_OUTLINE_PRECIS;
- } , {
- strat = OUT_TT_PRECIS;
- });
+ strat = OUT_OUTLINE_PRECIS;
} else if (request.styleStrategy & QFont::ForceOutline) {
strat = OUT_TT_ONLY_PRECIS;
#endif
@@ -794,14 +700,14 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
if (request.styleStrategy & QFont::PreferMatch)
qual = DRAFT_QUALITY;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
else if (request.styleStrategy & QFont::PreferQuality)
qual = PROOF_QUALITY;
#endif
if (request.styleStrategy & QFont::PreferAntialias) {
if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) {
- qual = 5; // == CLEARTYPE_QUALITY;
+ qual = CLEARTYPE_QUALITY;
preferClearTypeAA = true;
} else {
qual = ANTIALIASED_QUALITY;
@@ -827,16 +733,8 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap))
fam = QLatin1String("Courier New");
- QT_WA({
- memcpy(lf.lfFaceName, fam.utf16(), sizeof(TCHAR)*qMin(fam.length()+1,32)); // 32 = Windows hard-coded
- hfont = CreateFontIndirect(&lf);
- } , {
- // LOGFONTA and LOGFONTW are binary compatible
- QByteArray lname = fam.toLocal8Bit();
- memcpy(lf.lfFaceName,lname.data(),
- qMin(lname.length()+1,32)); // 32 = Windows hard-coded
- hfont = CreateFontIndirectA((LOGFONTA*)&lf);
- });
+ memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded
+ hfont = CreateFontIndirect(&lf);
if (!hfont)
qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect failed");
@@ -845,17 +743,12 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
int avWidth = 0;
BOOL res;
HGDIOBJ oldObj = SelectObject(hdc, hfont);
- QT_WA({
- TEXTMETRICW tm;
- res = GetTextMetricsW(hdc, &tm);
- avWidth = tm.tmAveCharWidth;
- ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE;
- } , {
- TEXTMETRICA tm;
- res = GetTextMetricsA(hdc, &tm);
- avWidth = tm.tmAveCharWidth;
- ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE;
- });
+
+ TEXTMETRIC tm;
+ res = GetTextMetrics(hdc, &tm);
+ avWidth = tm.tmAveCharWidth;
+ ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE;
+
SelectObject(hdc, oldObj);
if (hfont && (!ttf || request.stretch != 100)) {
@@ -863,16 +756,12 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
if (!res)
qErrnoWarning("QFontEngine::loadEngine: GetTextMetrics failed");
lf.lfWidth = avWidth * request.stretch/100;
- QT_WA({
- hfont = CreateFontIndirect(&lf);
- } , {
- hfont = CreateFontIndirectA((LOGFONTA*)&lf);
- });
+ hfont = CreateFontIndirect(&lf);
if (!hfont)
qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect with stretch failed");
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
if (hfont == 0) {
hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
stockFont = true;
@@ -969,12 +858,6 @@ static QFontEngine *loadWin(const QFontPrivate *d, int script, const QFontDef &r
// list of families to try
QStringList family_list = familyList(req);
- if(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based && req.family.toLower() == QLatin1String("ms sans serif")) {
- // small hack for Dos based machines to get the right font for non
- // latin text when using the default font.
- family_list << QLatin1String("Arial");
- }
-
const char *stylehint = styleHint(d->request);
if (stylehint)
family_list << QLatin1String(stylehint);
@@ -1143,6 +1026,8 @@ static void getFamiliesAndSignatures(const QByteArray &fontData, QFontDatabasePr
signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78);
signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82);
+ } else {
+ memset(&signature, 0, sizeof(signature));
}
appFont->signatures << signature;
}
@@ -1165,21 +1050,21 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
HANDLE handle = 0;
{
-#ifdef QT_NO_TEMPORARYFILE
- TCHAR lpBuffer[MAX_PATH];
+#ifdef QT_NO_TEMPORARYFILE
+ wchar_t lpBuffer[MAX_PATH];
GetTempPath(MAX_PATH, lpBuffer);
- QString s = QString::fromUtf16((const ushort *) lpBuffer);
+ QString s = QString::fromWCharArray(lpBuffer);
QFile tempfile(s + QLatin1String("/font") + QString::number(GetTickCount()) + QLatin1String(".ttf"));
if (!tempfile.open(QIODevice::ReadWrite))
#else
QTemporaryFile tempfile(QLatin1String("XXXXXXXX.ttf"));
if (!tempfile.open())
-#endif
+#endif // QT_NO_TEMPORARYFILE
return;
if (tempfile.write(fnt->data) == -1)
return;
-#ifndef QT_NO_TEMPORARYFILE
+#ifndef QT_NO_TEMPORARYFILE
tempfile.setAutoRemove(false);
#endif
fnt->fileName = QFileInfo(tempfile.fileName()).absoluteFilePath();
@@ -1191,13 +1076,11 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
}
#else
DWORD dummy = 0;
- HANDLE handle = ptrAddFontMemResourceEx((void *)fnt->data.constData(),
- fnt->data.size(),
- 0,
- &dummy);
+ HANDLE handle = ptrAddFontMemResourceEx((void *)fnt->data.constData(), fnt->data.size(), 0,
+ &dummy);
if (handle == 0)
return;
-#endif
+#endif // Q_OS_WINCE
fnt->handle = handle;
fnt->data = QByteArray();
@@ -1219,12 +1102,10 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
// supported from 2000 on, so no need to deal with the *A variant
PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"),
"AddFontResourceExW");
- if (!ptrAddFontResourceExW)
+ if (!ptrAddFontResourceExW
+ || ptrAddFontResourceExW((wchar_t*)fnt->fileName.utf16(), FR_PRIVATE, 0) == 0)
return;
-
- if (ptrAddFontResourceExW((LPCWSTR)fnt->fileName.utf16(), FR_PRIVATE, 0) == 0)
- return;
-#endif
+#endif // Q_OS_WINCE
fnt->memoryFont = false;
}
@@ -1250,12 +1131,10 @@ bool QFontDatabase::removeApplicationFont(int handle)
#else
PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)QLibrary::resolve(QLatin1String("gdi32"),
"RemoveFontMemResourceEx");
- if (!ptrRemoveFontMemResourceEx)
- return false;
-
- if (!ptrRemoveFontMemResourceEx(font.handle))
+ if (!ptrRemoveFontMemResourceEx
+ || !ptrRemoveFontMemResourceEx(font.handle))
return false;
-#endif
+#endif // Q_OS_WINCE
} else {
#ifdef Q_OS_WINCE
if (!RemoveFontResource((LPCWSTR)font.fileName.utf16()))
@@ -1263,12 +1142,10 @@ bool QFontDatabase::removeApplicationFont(int handle)
#else
PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"),
"RemoveFontResourceExW");
- if (!ptrRemoveFontResourceExW)
+ if (!ptrRemoveFontResourceExW
+ || !ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0))
return false;
-
- if (!ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0))
- return false;
-#endif
+#endif // Q_OS_WINCE
}
db->invalidate();
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index 0ed6d0a..7e2c474 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -392,7 +392,7 @@ int qt_mib_for_xlfd_encoding(const char *encoding)
int id = qt_xlfd_encoding_id(encoding);
if (id != -1) return xlfd_encoding[id].mib;
return 0;
-};
+}
int qt_encoding_id_for_mib(int mib)
{
@@ -509,9 +509,9 @@ bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi, QtFontDesc *d
fd->styleStrategy |= QFont::NoAntialias;
fd->family = QString::fromLatin1(tokens[Family]);
QString foundry = QString::fromLatin1(tokens[Foundry]);
- if (! foundry.isEmpty() && foundry != QString::fromLatin1("*") && (!desc || desc->family->count > 1))
+ if (! foundry.isEmpty() && foundry != QLatin1String("*") && (!desc || desc->family->count > 1))
fd->family +=
- QString::fromLatin1(" [") + foundry + QString::fromLatin1("]");
+ QLatin1String(" [") + foundry + QLatin1Char(']');
if (qstrlen(tokens[AddStyle]) > 0)
fd->addStyle = QString::fromLatin1(tokens[AddStyle]);
@@ -1802,30 +1802,30 @@ QFontEngine *QFontDatabase::loadXlfd(int screen, int script, const QFontDef &req
QByteArray xlfd("-");
xlfd += desc.foundry->name.isEmpty() ? QByteArray("*") : desc.foundry->name.toLatin1();
- xlfd += "-";
+ xlfd += '-';
xlfd += desc.family->name.isEmpty() ? QByteArray("*") : desc.family->name.toLatin1();
- xlfd += "-";
+ xlfd += '-';
xlfd += desc.style->weightName ? desc.style->weightName : "*";
- xlfd += "-";
+ xlfd += '-';
xlfd += (desc.style->key.style == QFont::StyleItalic
- ? "i"
- : (desc.style->key.style == QFont::StyleOblique ? "o" : "r"));
- xlfd += "-";
+ ? 'i'
+ : (desc.style->key.style == QFont::StyleOblique ? 'o' : 'r'));
+ xlfd += '-';
xlfd += desc.style->setwidthName ? desc.style->setwidthName : "*";
// ### handle add-style
xlfd += "-*-";
xlfd += QByteArray::number(px);
- xlfd += "-";
+ xlfd += '-';
xlfd += QByteArray::number(desc.encoding->xpoint);
- xlfd += "-";
+ xlfd += '-';
xlfd += QByteArray::number(desc.encoding->xres);
- xlfd += "-";
+ xlfd += '-';
xlfd += QByteArray::number(desc.encoding->yres);
- xlfd += "-";
+ xlfd += '-';
xlfd += desc.encoding->pitch;
- xlfd += "-";
+ xlfd += '-';
xlfd += QByteArray::number(desc.encoding->avgwidth);
- xlfd += "-";
+ xlfd += '-';
xlfd += xlfd_for_id(desc.encoding->encoding);
FM_DEBUG(" using XLFD: %s\n", xlfd.data());
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 89bd3ea..7a3b3e1 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -70,12 +70,6 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr
}
}
-
-
-QFontEngineGlyphCache::~QFontEngineGlyphCache()
-{
-}
-
// Harfbuzz helper functions
static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)
@@ -191,18 +185,20 @@ QFontEngine::QFontEngine()
QFontEngine::~QFontEngine()
{
- for (GlyphPointerHash::iterator it = m_glyphPointerHash.begin(), end = m_glyphPointerHash.end();
- it != end; ++it) {
- for (QList<QFontEngineGlyphCache*>::iterator it2 = it.value().begin(), end2 = it.value().end();
- it2 != end2; ++it2)
- delete *it2;
+ for (GlyphPointerHash::const_iterator it = m_glyphPointerHash.constBegin(),
+ end = m_glyphPointerHash.constEnd(); it != end; ++it) {
+ for (QList<QFontEngineGlyphCache*>::const_iterator it2 = it.value().constBegin(),
+ end2 = it.value().constEnd(); it2 != end2; ++it2) {
+ delete *it2;
+ }
}
m_glyphPointerHash.clear();
- for (GlyphIntHash::iterator it = m_glyphIntHash.begin(), end = m_glyphIntHash.end();
- it != end; ++it) {
- for (QList<QFontEngineGlyphCache*>::iterator it2 = it.value().begin(), end2 = it.value().end();
- it2 != end2; ++it2)
- delete *it2;
+ for (GlyphIntHash::const_iterator it = m_glyphIntHash.constBegin(),
+ end = m_glyphIntHash.constEnd(); it != end; ++it) {
+ for (QList<QFontEngineGlyphCache*>::const_iterator it2 = it.value().constBegin(),
+ end2 = it.value().constEnd(); it2 != end2; ++it2) {
+ delete *it2;
+ }
}
m_glyphIntHash.clear();
qHBFreeFace(hbFace);
@@ -240,8 +236,10 @@ HB_Font QFontEngine::harfbuzzFont() const
HB_Face QFontEngine::harfbuzzFace() const
{
- if (!hbFace)
+ if (!hbFace) {
hbFace = qHBNewFace(const_cast<QFontEngine *>(this), hb_getSFntTable);
+ Q_CHECK_PTR(hbFace);
+ }
return hbFace;
}
@@ -428,8 +426,7 @@ void QFontEngine::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> positioned_glyphs;
- QTransform matrix;
- matrix.translate(x, y);
+ QTransform matrix = QTransform::fromTranslate(x, y);
getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags);
}
@@ -819,7 +816,7 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(QFontEngineGlyphCache::Type key,
return 0;
}
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)
{
uint left_right = (left << 16) + right;
@@ -915,7 +912,7 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
end:
qSort(kerning_pairs);
// for (int i = 0; i < kerning_pairs.count(); ++i)
-// qDebug() << "i" << i << "left_right" << hex << kerning_pairs.at(i).left_right;
+// qDebug() << 'i' << i << "left_right" << hex << kerning_pairs.at(i).left_right;
}
#else
@@ -1041,9 +1038,8 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
return 0;
quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6);
const unsigned char *ends = cmap + 14;
- quint16 endIndex = 0;
int i = 0;
- for (; i < segCountX2/2 && (endIndex = qFromBigEndian<quint16>(ends + 2*i)) < unicode; i++) {}
+ for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2*i) < unicode; i++) {}
const unsigned char *idx = ends + segCountX2 + 2 + 2*i;
quint16 startIndex = qFromBigEndian<quint16>(idx);
@@ -1110,6 +1106,18 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
return 0;
}
+Q_GLOBAL_STATIC_WITH_INITIALIZER(QVector<QRgb>, qt_grayPalette, {
+ x->resize(256);
+ QRgb *it = x->data();
+ for (int i = 0; i < x->size(); ++i, ++it)
+ *it = 0xff000000 | i | (i<<8) | (i<<16);
+});
+
+const QVector<QRgb> &QFontEngine::grayPalette()
+{
+ return *qt_grayPalette();
+}
+
// ------------------------------------------------------------------
// The box font engine
// ------------------------------------------------------------------
@@ -1157,8 +1165,7 @@ void QFontEngineBox::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyp
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> positioned_glyphs;
- QTransform matrix;
- matrix.translate(x, y - _size);
+ QTransform matrix = QTransform::fromTranslate(x, y - _size);
getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
QSize s(_size - 3, _size - 3);
@@ -1186,8 +1193,7 @@ void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> glyphs;
- QTransform matrix;
- matrix.translate(x, y - _size);
+ QTransform matrix = QTransform::fromTranslate(x, y - _size);
ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
if (glyphs.size() == 0)
return;
@@ -1646,12 +1652,6 @@ bool QFontEngineMulti::canRender(const QChar *string, int len)
return allExist;
}
-QFontEngine *QFontEngineMulti::engine(int at) const
-{
- Q_ASSERT(at < engines.size());
- return engines.at(at);
-}
-
QImage QFontEngineMulti::alphaMapForGlyph(glyph_t)
{
Q_ASSERT(false);
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 701e91a..497158f 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -54,8 +54,6 @@
#include <private/qpdf_p.h>
#include <private/qharfbuzz_p.h>
-#include <private/qpdf_p.h>
-
#include "qfontengine_ft_p.h"
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -193,6 +191,9 @@ HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 p
/*
* One font file can contain more than one font (bold/italic for example)
* find the right one and return it.
+ *
+ * Returns the freetype face or 0 in case of an empty file or any other problems
+ * (like not being able to open the file)
*/
QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id)
{
@@ -204,8 +205,10 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id)
FT_Init_FreeType(&freetypeData->library);
QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0);
- if (!freetype) {
- freetype = new QFreetypeFace;
+ if (freetype) {
+ freetype->ref.ref();
+ } else {
+ QScopedPointer<QFreetypeFace> newFreetype(new QFreetypeFace);
FT_Face face;
QFile file(QString::fromUtf8(face_id.filename));
if (face_id.filename.startsWith(":qmemoryfonts/")) {
@@ -214,86 +217,90 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id)
QByteArray idx = face_id.filename;
idx.remove(0, 14); // remove ':qmemoryfonts/'
bool ok = false;
- freetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
+ newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
if (!ok)
- freetype->fontData = QByteArray();
+ newFreetype->fontData = QByteArray();
} else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
if (!file.open(QIODevice::ReadOnly)) {
- delete freetype;
return 0;
}
- freetype->fontData = file.readAll();
+ newFreetype->fontData = file.readAll();
}
- if (!freetype->fontData.isEmpty()) {
- if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)freetype->fontData.constData(), freetype->fontData.size(), face_id.index, &face)) {
- delete freetype;
+ if (!newFreetype->fontData.isEmpty()) {
+ if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)newFreetype->fontData.constData(), newFreetype->fontData.size(), face_id.index, &face)) {
return 0;
}
} else if (FT_New_Face(freetypeData->library, face_id.filename, face_id.index, &face)) {
- delete freetype;
return 0;
}
- freetype->face = face;
-
- freetype->hbFace = qHBNewFace(face, hb_getSFntTable);
- freetype->ref = 0;
- freetype->xsize = 0;
- freetype->ysize = 0;
- freetype->matrix.xx = 0x10000;
- freetype->matrix.yy = 0x10000;
- freetype->matrix.xy = 0;
- freetype->matrix.yx = 0;
- freetype->unicode_map = 0;
- freetype->symbol_map = 0;
+ newFreetype->face = face;
+
+ newFreetype->hbFace = qHBNewFace(face, hb_getSFntTable);
+ Q_CHECK_PTR(newFreetype->hbFace);
+ newFreetype->ref = 1;
+ newFreetype->xsize = 0;
+ newFreetype->ysize = 0;
+ newFreetype->matrix.xx = 0x10000;
+ newFreetype->matrix.yy = 0x10000;
+ newFreetype->matrix.xy = 0;
+ newFreetype->matrix.yx = 0;
+ newFreetype->unicode_map = 0;
+ newFreetype->symbol_map = 0;
#ifndef QT_NO_FONTCONFIG
- freetype->charset = 0;
+ newFreetype->charset = 0;
#endif
- memset(freetype->cmapCache, 0, sizeof(freetype->cmapCache));
+ memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache));
- for (int i = 0; i < freetype->face->num_charmaps; ++i) {
- FT_CharMap cm = freetype->face->charmaps[i];
+ for (int i = 0; i < newFreetype->face->num_charmaps; ++i) {
+ FT_CharMap cm = newFreetype->face->charmaps[i];
switch(cm->encoding) {
case FT_ENCODING_UNICODE:
- freetype->unicode_map = cm;
+ newFreetype->unicode_map = cm;
break;
case FT_ENCODING_APPLE_ROMAN:
case FT_ENCODING_ADOBE_LATIN_1:
- if (!freetype->unicode_map || freetype->unicode_map->encoding != FT_ENCODING_UNICODE)
- freetype->unicode_map = cm;
+ if (!newFreetype->unicode_map || newFreetype->unicode_map->encoding != FT_ENCODING_UNICODE)
+ newFreetype->unicode_map = cm;
break;
case FT_ENCODING_ADOBE_CUSTOM:
case FT_ENCODING_MS_SYMBOL:
- if (!freetype->symbol_map)
- freetype->symbol_map = cm;
+ if (!newFreetype->symbol_map)
+ newFreetype->symbol_map = cm;
break;
default:
break;
}
}
- if (!FT_IS_SCALABLE(freetype->face) && freetype->face->num_fixed_sizes == 1)
- FT_Set_Char_Size (face, X_SIZE(freetype->face, 0), Y_SIZE(freetype->face, 0), 0, 0);
+ if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1)
+ FT_Set_Char_Size (face, X_SIZE(newFreetype->face, 0), Y_SIZE(newFreetype->face, 0), 0, 0);
# if 0
FcChar8 *name;
FcPatternGetString(pattern, FC_FAMILY, 0, &name);
qDebug("%s: using maps: default: %x unicode: %x, symbol: %x", name,
- freetype->face->charmap ? freetype->face->charmap->encoding : 0,
- freetype->unicode_map ? freetype->unicode_map->encoding : 0,
- freetype->symbol_map ? freetype->symbol_map->encoding : 0);
+ newFreetype->face->charmap ? newFreetype->face->charmap->encoding : 0,
+ newFreetype->unicode_map ? newFreetype->unicode_map->encoding : 0,
+ newFreetype->symbol_map ? newFreetype->symbol_map->encoding : 0);
for (int i = 0; i < 256; i += 8)
qDebug(" %x: %d %d %d %d %d %d %d %d", i,
- FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i),
- FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i),
- FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i),
- FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i));
+ FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
+ FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
+ FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
+ FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i));
#endif
- FT_Set_Charmap(freetype->face, freetype->unicode_map);
- freetypeData->faces.insert(face_id, freetype);
+ FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map);
+ QT_TRY {
+ freetypeData->faces.insert(face_id, newFreetype.data());
+ } QT_CATCH(...) {
+ newFreetype.take()->release(face_id);
+ // we could return null in principle instead of throwing
+ QT_RETHROW;
+ }
+ freetype = newFreetype.take();
}
- freetype->ref.ref();
return freetype;
}
@@ -307,7 +314,8 @@ void QFreetypeFace::release(const QFontEngine::FaceId &face_id)
if (charset)
FcCharSetDestroy(charset);
#endif
- freetypeData->faces.take(face_id);
+ if(freetypeData->faces.contains(face_id))
+ freetypeData->faces.take(face_id);
delete this;
}
if (freetypeData->faces.isEmpty()) {
@@ -608,6 +616,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
kerning_pairs_loaded = false;
transform = false;
antialias = true;
+ freetype = 0;
default_load_flags = 0;
default_hint_style = HintNone;
subpixelType = Subpixel_None;
@@ -1380,8 +1389,8 @@ bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, G
FT_Face face = 0;
for (int i = 0; i < num_glyphs; ++i) {
- if (!gs->glyph_data.contains(glyphs[i])
- || gs->glyph_data.value(glyphs[i])->format != format) {
+ Glyph *glyph = gs->glyph_data.value(glyphs[i]);
+ if (glyph == 0 || glyph->format != format) {
if (!face) {
face = lockFace();
FT_Matrix m = matrix;
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 32c13b5..4cc5c5e 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -119,6 +119,7 @@ struct QFreetypeFace
static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool = false);
private:
+ friend class QScopedPointerDeleter<QFreetypeFace>;
QFreetypeFace() : _lock(QMutex::Recursive) {}
~QFreetypeFace() {}
QAtomicInt ref;
@@ -255,7 +256,7 @@ public:
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render);
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
virtual void draw(QPaintEngine * /*p*/, qreal /*x*/, qreal /*y*/, const QTextItemInt & /*si*/) {}
#endif
diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm
index 60414e6..f32810b 100644
--- a/src/gui/text/qfontengine_mac.mm
+++ b/src/gui/text/qfontengine_mac.mm
@@ -135,12 +135,12 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, con
symbolicTraits |= kCTFontItalicTrait;
break;
}
-
+
QCFString name;
ATSFontGetName(atsFontRef, kATSOptionFlagsDefault, &name);
- QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pixelSize);
- QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pixelSize, 0);
- ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, 0, symbolicTraits, symbolicTraits);
+ QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pointSize);
+ QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pointSize, 0);
+ ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pointSize, 0, symbolicTraits, symbolicTraits);
// CTFontCreateCopyWithSymbolicTraits returns NULL if we ask for a trait that does
// not exist for the given font. (for example italic)
@@ -162,7 +162,7 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, con
QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef, this);
fe->ref.ref();
engines.append(fe);
-
+
}
QCoreTextFontEngineMulti::~QCoreTextFontEngineMulti()
@@ -176,7 +176,7 @@ uint QCoreTextFontEngineMulti::fontIndexForFont(CTFontRef id) const
if (CFEqual(engineAt(i)->ctfont, id))
return i;
}
-
+
QCoreTextFontEngineMulti *that = const_cast<QCoreTextFontEngineMulti *>(this);
QCoreTextFontEngine *fe = new QCoreTextFontEngine(id, fontDef, that);
fe->ref.ref();
@@ -227,7 +227,7 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(runAttribs, NSFontAttributeName));
const uint fontIndex = (fontIndexForFont(runFont) << 24);
//NSLog(@"Run Font Name = %@", CTFontCopyFamilyName(runFont));
- QVarLengthArray<CGGlyph, 512> cgglyphs(0);
+ QVarLengthArray<CGGlyph, 512> cgglyphs(0);
const CGGlyph *tmpGlyphs = CTRunGetGlyphsPtr(run);
if (!tmpGlyphs) {
cgglyphs.resize(glyphCount);
@@ -260,7 +260,7 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
CFIndex k = 0;
CFIndex i = 0;
- for (i = stringRange.location;
+ for (i = stringRange.location;
(i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) {
if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location) {
logClusters[i] = k + firstGlyphIndex;
@@ -425,28 +425,28 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt
getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
if (glyphs.size() == 0)
return;
-
+
CGContextSetFontSize(ctx, fontDef.pixelSize);
-
+
CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
-
+
CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight);
-
+
CGAffineTransformConcat(cgMatrix, oldTextMatrix);
-
+
if (synthesisFlags & QFontEngine::SynthesizedItalic)
cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0));
-
+
// ### cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
-
+
CGContextSetTextMatrix(ctx, cgMatrix);
-
+
CGContextSetTextDrawingMode(ctx, kCGTextFill);
-
-
+
+
QVarLengthArray<CGSize> advances(glyphs.size());
QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size());
-
+
for (int i = 0; i < glyphs.size() - 1; ++i) {
advances[i].width = (positions[i + 1].x - positions[i].x).toReal();
advances[i].height = (positions[i + 1].y - positions[i].y).toReal();
@@ -455,21 +455,21 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt
advances[glyphs.size() - 1].width = 0;
advances[glyphs.size() - 1].height = 0;
cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1];
-
+
CGContextSetFont(ctx, cgFont);
//NSLog(@"Font inDraw %@ ctfont %@", CGFontCopyFullName(cgFont), CTFontCopyFamilyName(ctfont));
-
+
CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal());
-
+
CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
-
+
if (synthesisFlags & QFontEngine::SynthesizedBold) {
CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(),
positions[0].y.toReal());
-
+
CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
}
-
+
CGContextSetTextMatrix(ctx, oldTextMatrix);
}
@@ -540,14 +540,9 @@ QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph)
im.fill(0);
CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace();
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
uint cgflags = kCGImageAlphaNoneSkipFirst;
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
- if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- cgflags |= kCGBitmapByteOrder32Host;
-#endif
-#else
- CGImageAlphaInfo cgflags = kCGImageAlphaNoneSkipFirst;
+ cgflags |= kCGBitmapByteOrder32Host;
#endif
CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(),
8, im.bytesPerLine(), colorspace,
@@ -624,7 +619,7 @@ QFontEngine::FaceId QCoreTextFontEngine::faceId() const
bool QCoreTextFontEngine::canRender(const QChar *string, int len)
{
- QCFType<CTFontRef> retFont = CTFontCreateForString(ctfont,
+ QCFType<CTFontRef> retFont = CTFontCreateForString(ctfont,
QCFType<CFStringRef>(CFStringCreateWithCharactersNoCopy(0,
reinterpret_cast<const UniChar *>(string),
len, kCFAllocatorNull)),
@@ -674,7 +669,7 @@ QFontEngineMacMulti::QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, cons
} else {
if (fontDef.weight >= QFont::Bold)
fntStyle |= ::bold;
- if (fontDef.style != QFont::StyleNormal)
+ if (fontDef.style != QFont::StyleNormal)
fntStyle |= ::italic;
FMFontStyle intrinsicStyle;
@@ -957,7 +952,7 @@ bool QFontEngineMacMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *
tmpItem.length = charCount;
tmpItem.glyphs = shaperItem.glyphs.mid(glyphIdx, glyphCount);
tmpItem.log_clusters = shaperItem.log_clusters + charIdx;
- if (!stringToCMapInternal(tmpItem.string + tmpItem.from, tmpItem.length,
+ if (!stringToCMapInternal(tmpItem.string + tmpItem.from, tmpItem.length,
&tmpItem.glyphs, &glyphCount, flags,
&tmpItem)) {
*nglyphs = glyphIdx + glyphCount;
@@ -1218,12 +1213,12 @@ QFontEngineMac::QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFo
transform = multiEngine->transform;
else
transform = CGAffineTransformIdentity;
-
+
ATSUTextMeasurement metric;
ATSUGetAttribute(style, kATSUAscentTag, sizeof(metric), &metric, 0);
m_ascent = FixRound(metric);
-
+
ATSUGetAttribute(style, kATSUDescentTag, sizeof(metric), &metric, 0);
m_descent = FixRound(metric);
@@ -1419,21 +1414,21 @@ void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, in
addGlyphsToPathHelper(style, glyphs, positions, numGlyphs, path);
}
-QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
+
+/*!
+ Helper function for alphaMapForGlyph and alphaRGBMapForGlyph. The two are identical, except for
+ the subpixel antialiasing...
+*/
+QImage QFontEngineMac::imageForGlyph(glyph_t glyph, int margin, bool colorful)
{
const glyph_metrics_t br = boundingBox(glyph);
QImage im(qRound(br.width)+2, qRound(br.height)+4, QImage::Format_RGB32);
- im.fill(0);
+ im.fill(0xff000000);
CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace();
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
uint cgflags = kCGImageAlphaNoneSkipFirst;
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
- if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
- cgflags |= kCGBitmapByteOrder32Host;
-#endif
-#else
- CGImageAlphaInfo cgflags = kCGImageAlphaNoneSkipFirst;
+ cgflags |= kCGBitmapByteOrder32Host;
#endif
CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(),
8, im.bytesPerLine(), colorspace,
@@ -1441,7 +1436,7 @@ QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
CGContextSetFontSize(ctx, fontDef.pixelSize);
CGContextSetShouldAntialias(ctx, fontDef.pointSize > qt_antialiasing_threshold && !(fontDef.styleStrategy & QFont::NoAntialias));
// turn off sub-pixel hinting - no support for that in OpenGL
- CGContextSetShouldSmoothFonts(ctx, false);
+ CGContextSetShouldSmoothFonts(ctx, colorful);
CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
CGAffineTransformConcat(cgMatrix, oldTextMatrix);
@@ -1473,6 +1468,13 @@ QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
CGContextRelease(ctx);
+ return im;
+}
+
+QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
+{
+ QImage im = imageForGlyph(glyph, 2, false);
+
QImage indexed(im.width(), im.height(), QImage::Format_Indexed8);
QVector<QRgb> colors(256);
for (int i=0; i<256; ++i)
@@ -1492,6 +1494,32 @@ QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
return indexed;
}
+QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &t)
+{
+ QImage im = imageForGlyph(glyph, margin, true);
+
+ if (t.type() >= QTransform::TxScale) {
+ im = im.transformed(t);
+ }
+
+ extern uchar qt_pow_rgb_gamma[256];
+
+ // gamma correct the pixels back to linear color space...
+ for (int y=0; y<im.height(); ++y) {
+ uint *pixels = (uint *) im.scanLine(y);
+ for (int x=0; x<im.width(); ++x) {
+ uint p = pixels[x];
+ uint r = qt_pow_rgb_gamma[qRed(p)];
+ uint g = qt_pow_rgb_gamma[qGreen(p)];
+ uint b = qt_pow_rgb_gamma[qBlue(p)];
+ pixels[x] = (r << 16) | (g << 8) | b | 0xff000000;
+ }
+ }
+
+ return im;
+}
+
+
bool QFontEngineMac::canRender(const QChar *string, int len)
{
Q_ASSERT(false);
@@ -1648,7 +1676,7 @@ QFontEngine::Properties QFontEngineMac::properties() const
if (ATSFontGetTable(atsFont, MAKE_TAG('p', 'o', 's', 't'), 10, 2, &lw, 0) == noErr)
lw = qFromBigEndian<quint16>(lw);
props.lineWidth = lw;
-
+
// CTFontCopyPostScriptName
QCFString psName;
if (ATSFontGetPostScriptName(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &psName) == noErr)
@@ -1663,7 +1691,7 @@ void QFontEngineMac::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_m
ATSUCreateAndCopyStyle(style, &unscaledStyle);
int emSquare = properties().emSquare.toInt();
-
+
const int maxAttributeCount = 4;
ATSUAttributeTag tags[maxAttributeCount + 1];
ByteCount sizes[maxAttributeCount + 1];
@@ -1675,7 +1703,7 @@ void QFontEngineMac::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_m
sizes[attributeCount] = sizeof(size);
values[attributeCount] = &size;
++attributeCount;
-
+
Q_ASSERT(attributeCount < maxAttributeCount + 1);
OSStatus err = ATSUSetAttributes(unscaledStyle, attributeCount, tags, sizes, values);
Q_ASSERT(err == noErr);
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 049b3c8..d654215 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -70,7 +70,7 @@
# include "private/qcore_mac_p.h"
#endif
-#include "qfontengineglyphcache_p.h"
+#include <private/qfontengineglyphcache_p.h>
struct glyph_metrics_t;
typedef unsigned int glyph_t;
@@ -93,7 +93,6 @@ struct QGlyphLayout;
class Q_GUI_EXPORT QFontEngine : public QObject
{
- Q_OBJECT
public:
enum Type {
Box,
@@ -108,11 +107,15 @@ public:
// Apple Mac OS types
Mac,
- // Trolltech QWS types
+ // QWS types
Freetype,
QPF1,
QPF2,
Proxy,
+
+ // S60 types
+ S60FontEngine, // Cannot be simply called "S60". Reason is qt_s60Data.h
+
TestFontEngine = 0x1000
};
@@ -164,7 +167,7 @@ public:
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const {}
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
-#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
virtual void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si) = 0;
#endif
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
@@ -231,7 +234,7 @@ public:
bool symbol;
mutable HB_FontRec hbFont;
mutable HB_Face hbFace;
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
struct KernPair {
uint left_right;
QFixed adjust;
@@ -247,6 +250,9 @@ public:
int glyphFormat;
+protected:
+ static const QVector<QRgb> &grayPalette();
+
private:
/// remove old entries from the glyph cache. Helper method for the setGlyphCache ones.
void expireGlyphCache();
@@ -322,7 +328,7 @@ public:
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
-#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si);
#endif
virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags);
@@ -353,7 +359,7 @@ private:
int _size;
};
-class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine
+class QFontEngineMulti : public QFontEngine
{
public:
explicit QFontEngineMulti(int engineCount);
@@ -389,7 +395,9 @@ public:
inline virtual const char *name() const
{ return "Multi"; }
- QFontEngine *engine(int at) const;
+ QFontEngine *engine(int at) const
+ {Q_ASSERT(at < engines.size()); return engines.at(at); }
+
protected:
friend class QPSPrintEnginePrivate;
@@ -525,8 +533,11 @@ public:
virtual Properties properties() const;
virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
virtual QImage alphaMapForGlyph(glyph_t);
+ virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t);
private:
+ QImage imageForGlyph(glyph_t glyph, int margin, bool colorful);
+
ATSUFontID fontID;
QCFType<CGFontRef> cgFont;
ATSUStyle style;
@@ -614,4 +625,8 @@ QT_END_NAMESPACE
# include "private/qfontengine_win_p.h"
#endif
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+# include "private/qfontengine_ft_p.h"
+#endif
+
#endif // QFONTENGINE_P_H
diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
index 90a0c72..7c8be82 100644
--- a/src/gui/text/qfontengine_qpf.cpp
+++ b/src/gui/text/qfontengine_qpf.cpp
@@ -51,6 +51,7 @@
#if !defined(QT_NO_FREETYPE)
#include "private/qfontengine_ft_p.h"
#endif
+#include "private/qcore_unix_p.h" // overrides QT_OPEN
// for mmap
#include <stdlib.h>
@@ -65,9 +66,10 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_QWS_QPF2
-QT_BEGIN_INCLUDE_NAMESPACE
#include "qpfutil.cpp"
+QT_BEGIN_INCLUDE_NAMESPACE
+
#if defined(Q_WS_QWS)
# include "private/qwscommand_qws_p.h"
# include "qwsdisplay_qws.h"
@@ -252,7 +254,7 @@ QList<QByteArray> QFontEngineQPF::cleanUpAfterClientCrash(const QList<int> &cras
for (int i = 0; i < int(dir.count()); ++i) {
const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i]));
- int fd = ::open(fileName.constData(), O_RDONLY);
+ int fd = QT_OPEN(fileName.constData(), O_RDONLY, 0);
if (fd >= 0) {
void *header = ::mmap(0, sizeof(QFontEngineQPF::Header), PROT_READ, MAP_SHARED, fd, 0);
if (header && header != MAP_FAILED) {
@@ -265,7 +267,7 @@ QList<QByteArray> QFontEngineQPF::cleanUpAfterClientCrash(const QList<int> &cras
::munmap(header, sizeof(QFontEngineQPF::Header));
}
- ::close(fd);
+ QT_CLOSE(fd);
}
}
if (!removedFonts.isEmpty())
@@ -308,7 +310,7 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
readOnly = true;
#if defined(DEBUG_FONTENGINE)
- qDebug() << "QFontEngineQPF::QFontEngineQPF( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ")";
+ qDebug() << "QFontEngineQPF::QFontEngineQPF( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')';
#endif
#ifndef QT_FONTS_ARE_RESOURCES
@@ -316,30 +318,51 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
if (!renderingFontEngine)
return;
- fileName = fontDef.family.toLower() + QLatin1String("_")
+ fileName = fontDef.family.toLower() + QLatin1Char('_')
+ QString::number(fontDef.pixelSize)
- + QLatin1String("_") + QString::number(fontDef.weight)
+ + QLatin1Char('_') + QString::number(fontDef.weight)
+ (fontDef.style != QFont::StyleNormal ?
QLatin1String("_italic") : QLatin1String(""))
+ QLatin1String(".qsf");
fileName.replace(QLatin1Char(' '), QLatin1Char('_'));
fileName.prepend(qws_fontCacheDir());
- const QByteArray encodedName = QFile::encodeName(fileName);
- if (::access(encodedName, F_OK) == 0) {
+ encodedFileName = QFile::encodeName(fileName);
+ if (::access(encodedFileName, F_OK) == 0) {
#if defined(DEBUG_FONTENGINE)
qDebug() << "found existing qpf:" << fileName;
#endif
- if (::access(encodedName, W_OK | R_OK) == 0)
- fd = ::open(encodedName, O_RDWR);
- else if (::access(encodedName, R_OK) == 0)
- fd = ::open(encodedName, O_RDONLY);
+ if (::access(encodedFileName, W_OK | R_OK) == 0) {
+ fd = QT_OPEN(encodedFileName, O_RDWR);
+ }
+ // read-write access failed - try read-only access
+ if (fd == -1 && ::access(encodedFileName, R_OK) == 0) {
+ fd = QT_OPEN(encodedFileName, O_RDONLY);
+ if (fd == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning("QFontEngineQPF: unable to open %s", encodedName.constData());
+#endif
+ return;
+ }
+ }
+ if (fd == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qWarning("QFontEngineQPF: insufficient access rights to %s", encodedName.constData());
+#endif
+ return;
+ }
} else {
#if defined(DEBUG_FONTENGINE)
qDebug() << "creating qpf on the fly:" << fileName;
#endif
if (::access(QFile::encodeName(qws_fontCacheDir()), W_OK) == 0) {
- fd = ::open(encodedName, O_RDWR | O_EXCL | O_CREAT, 0644);
+ fd = QT_OPEN(encodedFileName, O_RDWR | O_EXCL | O_CREAT, 0644);
+ if (fd == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning(errno, "QFontEngineQPF: open() failed for %s", encodedName.constData());
+#endif
+ return;
+ }
QBuffer buffer;
buffer.open(QIODevice::ReadWrite);
@@ -347,7 +370,17 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
generator.generate();
buffer.close();
const QByteArray &data = buffer.data();
- ::write(fd, data.constData(), data.size());
+ if (QT_WRITE(fd, data.constData(), data.size()) == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning(errno, "QFontEngineQPF: write() failed for %s", encodedName.constData());
+#endif
+ return;
+ }
+ } else {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning(errno, "QFontEngineQPF: access() failed for %s", qPrintable(qws_fontCacheDir()));
+#endif
+ return;
}
}
}
@@ -355,7 +388,7 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
QT_STATBUF st;
if (QT_FSTAT(fd, &st)) {
#if defined(DEBUG_FONTENGINE)
- qDebug() << "stat failed!";
+ qErrnoWarning(errno, "QFontEngineQPF: fstat failed!");
#endif
return;
}
@@ -474,19 +507,30 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
#endif
#if defined(Q_WS_QWS)
if (isValid() && renderingFontEngine)
- qt_fbdpy->sendFontCommand(QWSFontCommand::StartedUsingFont, QFile::encodeName(fileName));
+ qt_fbdpy->sendFontCommand(QWSFontCommand::StartedUsingFont, encodedFileName);
#endif
}
QFontEngineQPF::~QFontEngineQPF()
{
#if defined(Q_WS_QWS)
- if (isValid() && renderingFontEngine)
- qt_fbdpy->sendFontCommand(QWSFontCommand::StoppedUsingFont, QFile::encodeName(fileName));
+ if (isValid() && renderingFontEngine) {
+ QT_TRY {
+ qt_fbdpy->sendFontCommand(QWSFontCommand::StoppedUsingFont, encodedFileName);
+ } QT_CATCH(...) {
+ qDebug("QFontEngineQPF::~QFontEngineQPF: Out of memory");
+ // ignore.
+ }
+ }
#endif
delete renderingFontEngine;
- if (fontData)
- munmap((void *)fontData, dataSize);
+ if (fontData) {
+ if (munmap((void *)fontData, dataSize) == -1) {
+#if defined(DEBUG_FONTENGINE)
+ qErrnoWarning(errno, "~QFontEngineQPF: Unable to munmap");
+#endif
+ }
+ }
if (fd != -1)
::close(fd);
#if !defined(QT_NO_FREETYPE)
@@ -550,7 +594,7 @@ bool QFontEngineQPF::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
#if 0 && defined(DEBUG_FONTENGINE)
QChar c(uc);
if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c))
- qDebug() << "glyph for character" << c << "/" << hex << uc << "is" << dec << glyphs[glyph_pos].glyph;
+ qDebug() << "glyph for character" << c << '/' << hex << uc << "is" << dec << glyphs[glyph_pos].glyph;
seenGlyphs.insert(c);
#endif
@@ -893,8 +937,8 @@ void QFontEngineQPF::loadGlyph(glyph_t glyph)
g.y = qRound(metrics.y);
g.advance = qRound(metrics.xoff);
- ::write(fd, &g, sizeof(g));
- ::write(fd, img.bits(), img.numBytes());
+ QT_WRITE(fd, &g, sizeof(g));
+ QT_WRITE(fd, img.bits(), img.numBytes());
glyphPos = oldSize - glyphDataOffset;
#if 0 && defined(DEBUG_FONTENGINE)
@@ -1128,6 +1172,11 @@ void QPFGenerator::writeTaggedQFixed(QFontEngineQPF::HeaderTag tag, QFixed value
#endif // QT_NO_QWS_QPF2
+/*
+ Creates a new multi qws engine.
+
+ This function takes ownership of the QFontEngine, increasing it's refcount.
+*/
QFontEngineMultiQWS::QFontEngineMultiQWS(QFontEngine *fe, int _script, const QStringList &fallbacks)
: QFontEngineMulti(fallbacks.size() + 1),
fallbackFamilies(fallbacks), script(_script)
diff --git a/src/gui/text/qfontengine_qpf_p.h b/src/gui/text/qfontengine_qpf_p.h
index bf686a7..6fa0ef7 100644
--- a/src/gui/text/qfontengine_qpf_p.h
+++ b/src/gui/text/qfontengine_qpf_p.h
@@ -243,6 +243,7 @@ private:
quint32 glyphDataOffset;
quint32 glyphDataSize;
QString fileName;
+ QByteArray encodedFileName;
bool readOnly;
QFreetypeFace *freetype;
diff --git a/src/gui/text/qfontengine_qws.cpp b/src/gui/text/qfontengine_qws.cpp
index 3c18f7a..ce84676 100644
--- a/src/gui/text/qfontengine_qws.cpp
+++ b/src/gui/text/qfontengine_qws.cpp
@@ -47,6 +47,7 @@
#include <private/qpaintengine_raster_p.h>
#include <private/qpdf_p.h>
#include "qtextengine_p.h"
+#include "private/qcore_unix_p.h" // overrides QT_OPEN
#include <qdebug.h>
@@ -387,7 +388,7 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn)
{
cache_cost = 1;
- int f = ::open( QFile::encodeName(fn), O_RDONLY );
+ int f = QT_OPEN( QFile::encodeName(fn), O_RDONLY, 0);
Q_ASSERT(f>=0);
QT_STATBUF st;
if ( QT_FSTAT( f, &st ) )
@@ -395,7 +396,7 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn)
uchar* data = (uchar*)mmap( 0, // any address
st.st_size, // whole file
PROT_READ, // read-only memory
-#if !defined(Q_OS_SOLARIS) && !defined(Q_OS_QNX4) && !defined(Q_OS_INTEGRITY)
+#if !defined(Q_OS_SOLARIS) && !defined(Q_OS_QNX4) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS)
MAP_FILE | MAP_PRIVATE, // swap-backed map from file
#else
MAP_PRIVATE,
@@ -406,7 +407,7 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn)
#endif
if ( !data || data == (uchar*)MAP_FAILED )
qFatal("Failed to mmap %s",QFile::encodeName(fn).data());
- ::close(f);
+ QT_CLOSE(f);
d = new QFontEngineQPF1Data;
memcpy(reinterpret_cast<char*>(&d->fm),data,sizeof(d->fm));
diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp
new file mode 100644
index 0000000..ed6b1c1
--- /dev/null
+++ b/src/gui/text/qfontengine_s60.cpp
@@ -0,0 +1,331 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfontengine_s60_p.h"
+#include "qtextengine_p.h"
+#include "qglobal.h"
+#include <private/qapplication_p.h>
+#include <private/qwindowsurface_s60_p.h>
+#include "qimage.h"
+#include "qt_s60_p.h"
+
+#include <e32base.h>
+#include <e32std.h>
+#include <EIKENV.H>
+#include <GDI.H>
+
+QT_BEGIN_NAMESPACE
+
+QFontEngineS60Extensions::QFontEngineS60Extensions(CFont* fontOwner, COpenFont *font)
+ : m_font(font)
+ , m_cmap(0)
+ , m_symbolCMap(false)
+ , m_fontOwner(fontOwner)
+{
+ TAny *shapingExtension = NULL;
+ m_font->ExtendedInterface(KUidOpenFontShapingExtension, shapingExtension);
+ m_shapingExtension = static_cast<MOpenFontShapingExtension*>(shapingExtension);
+ TAny *trueTypeExtension = NULL;
+ m_font->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension);
+ m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension);
+ Q_ASSERT(m_shapingExtension && m_trueTypeExtension);
+}
+
+QByteArray QFontEngineS60Extensions::getSfntTable(uint tag) const
+{
+ Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag));
+ TInt error = KErrNone;
+ TInt tableByteLength = 0;
+ TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength);
+ QByteArray result(static_cast<const char*>(table), tableByteLength);
+ m_trueTypeExtension->ReleaseTrueTypeTable(table);
+ return result;
+}
+
+const unsigned char *QFontEngineS60Extensions::cmap() const
+{
+ if (!m_cmap) {
+ m_cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
+ int size = 0;
+ m_cmap = QFontEngineS60::getCMap(reinterpret_cast<const uchar *>(m_cmapTable.constData()), m_cmapTable.size(), &m_symbolCMap, &size);
+ }
+ return m_cmap;
+}
+
+QPainterPath QFontEngineS60Extensions::glyphOutline(glyph_t glyph) const
+{
+ QPainterPath result;
+ QPolygonF polygon;
+ TInt glyphIndex = glyph;
+ TInt pointNumber = 0;
+ TInt x, y;
+ while (m_shapingExtension->GlyphPointInFontUnits(glyphIndex, pointNumber++, x, y)) {
+ const QPointF point(qreal(x) / 0xffff, qreal(y) / 0xffff);
+ if (polygon.contains(point)) {
+ result.addPolygon(polygon);
+ result.closeSubpath();
+ polygon.clear();
+ } else {
+ polygon.append(point);
+ }
+ }
+ return result;
+}
+
+CFont *QFontEngineS60Extensions::fontOwner() const
+{
+ return m_fontOwner;
+}
+
+
+// duplicated from qfontengine_xyz.cpp
+static inline unsigned int getChar(const QChar *str, int &i, const int len)
+{
+ unsigned int uc = str[i].unicode();
+ if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) {
+ uint low = str[i+1].unicode();
+ if (low >= 0xdc00 && low < 0xe000) {
+ uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
+ ++i;
+ }
+ }
+ return uc;
+}
+
+QFontEngineS60::QFontEngineS60(const QFontDef &request, const QFontEngineS60Extensions *extensions)
+ : m_extensions(extensions)
+{
+ QFontEngine::fontDef = request;
+ m_fontSizeInPixels = (request.pixelSize >= 0)?
+ request.pixelSize:pointsToPixels(request.pointSize);
+ QS60WindowSurface::unlockBitmapHeap();
+ m_textRenderBitmap = q_check_ptr(new CFbsBitmap()); // CBase derived object needs check on new
+ const TSize bitmapSize(1, 1); // It is just a dummy bitmap that I need to keep the font alive (or maybe not)
+ qt_symbian_throwIfError(m_textRenderBitmap->Create(bitmapSize, EGray256));
+ QT_TRAP_THROWING(m_textRenderBitmapDevice = CFbsBitmapDevice::NewL(m_textRenderBitmap));
+ qt_symbian_throwIfError(m_textRenderBitmapDevice->CreateContext(m_textRenderBitmapGc));
+ cache_cost = sizeof(QFontEngineS60) + bitmapSize.iHeight * bitmapSize.iWidth * 4;
+
+ TFontSpec fontSpec(qt_QString2TPtrC(request.family), m_fontSizeInPixels);
+ fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
+ fontSpec.iFontStyle.SetPosture(request.style == QFont::StyleNormal?EPostureUpright:EPostureItalic);
+ fontSpec.iFontStyle.SetStrokeWeight(request.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal);
+ const TInt errorCode = m_textRenderBitmapDevice->GetNearestFontInPixels(m_font, fontSpec);
+ Q_ASSERT(errorCode == 0);
+ m_textRenderBitmapGc->UseFont(m_font);
+ QS60WindowSurface::lockBitmapHeap();
+}
+
+QFontEngineS60::~QFontEngineS60()
+{
+ QS60WindowSurface::unlockBitmapHeap();
+ m_textRenderBitmapGc->DiscardFont();
+ delete m_textRenderBitmapGc;
+ m_textRenderBitmapGc = NULL;
+ m_textRenderBitmapDevice->ReleaseFont(m_font);
+ delete m_textRenderBitmapDevice;
+ m_textRenderBitmapDevice = NULL;
+ delete m_textRenderBitmap;
+ m_textRenderBitmap = NULL;
+ QS60WindowSurface::lockBitmapHeap();
+}
+
+bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
+{
+ if (*nglyphs < len) {
+ *nglyphs = len;
+ return false;
+ }
+
+ HB_Glyph *g = glyphs->glyphs;
+ const unsigned char* cmap = m_extensions->cmap();
+ for (int i = 0; i < len; ++i) {
+ const unsigned int uc = getChar(characters, i, len);
+ *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, uc);
+ }
+
+ glyphs->numGlyphs = g - glyphs->glyphs;
+ *nglyphs = glyphs->numGlyphs;
+
+ if (flags & QTextEngine::GlyphIndicesOnly)
+ return true;
+
+ recalcAdvances(glyphs, flags);
+ return true;
+}
+
+void QFontEngineS60::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
+{
+ Q_UNUSED(flags);
+ for (int i = 0; i < glyphs->numGlyphs; i++) {
+ const glyph_metrics_t bbox = boundingBox_const(glyphs->glyphs[i]);
+ glyphs->advances_x[i] = glyphs->offsets[i].x = bbox.xoff;
+ glyphs->advances_y[i] = glyphs->offsets[i].y = bbox.yoff;
+ }
+}
+
+QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph)
+{
+ TOpenFontCharMetrics metrics;
+ const TUint8 *glyphBitmapBytes;
+ TSize glyphBitmapSize;
+ getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize);
+ QImage result(glyphBitmapBytes, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight, glyphBitmapSize.iWidth, QImage::Format_Indexed8);
+ result.setColorTable(grayPalette());
+
+ // The above setColorTable() call detached the image data anyway, so why not shape tha data a bit, while we can.
+ // CFont::GetCharacterData() returns 8-bit data that obviously was 4-bit data before, and converted to 8-bit incorrectly.
+ // The data values are 0x00, 0x10 ... 0xe0, 0xf0. So, a real opaque 0xff is never reached, which we get punished
+ // for every time we want to blit this glyph in the raster paint engine.
+ // "Fix" is to convert all 0xf0 to 0xff. Is fine, quality wise, and I assume faster than correcting all values.
+ // Blitting is however, evidentially faster now.
+ const int bpl = result.bytesPerLine();
+ for (int row = 0; row < result.height(); ++row) {
+ uchar *scanLine = result.scanLine(row);
+ for (int column = 0; column < bpl; ++column) {
+ if (*scanLine == 0xf0)
+ *scanLine = 0xff;
+ scanLine++;
+ }
+ }
+
+ return result;
+}
+
+glyph_metrics_t QFontEngineS60::boundingBox(const QGlyphLayout &glyphs)
+{
+ if (glyphs.numGlyphs == 0)
+ return glyph_metrics_t();
+
+ QFixed w = 0;
+ for (int i = 0; i < glyphs.numGlyphs; ++i)
+ w += glyphs.effectiveAdvance(i);
+
+ return glyph_metrics_t(0, -ascent(), w, ascent()+descent()+1, w, 0);
+}
+
+glyph_metrics_t QFontEngineS60::boundingBox_const(glyph_t glyph) const
+{
+ TOpenFontCharMetrics metrics;
+ const TUint8 *glyphBitmapBytes;
+ TSize glyphBitmapSize;
+ getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize);
+ TRect glyphBounds;
+ metrics.GetHorizBounds(glyphBounds);
+ const glyph_metrics_t result(
+ glyphBounds.iTl.iX,
+ glyphBounds.iTl.iY,
+ glyphBounds.Width(),
+ glyphBounds.Height(),
+ metrics.HorizAdvance(),
+ 0
+ );
+ return result;
+}
+
+glyph_metrics_t QFontEngineS60::boundingBox(glyph_t glyph)
+{
+ return boundingBox_const(glyph);
+}
+
+QFixed QFontEngineS60::ascent() const
+{
+ return m_font->FontMaxAscent();
+}
+
+QFixed QFontEngineS60::descent() const
+{
+ return m_font->FontMaxDescent();
+}
+
+QFixed QFontEngineS60::leading() const
+{
+ return 0;
+}
+
+qreal QFontEngineS60::maxCharWidth() const
+{
+ return m_font->MaxCharWidthInPixels();
+}
+
+const char *QFontEngineS60::name() const
+{
+ return "QFontEngineS60";
+}
+
+bool QFontEngineS60::canRender(const QChar *string, int len)
+{
+ const unsigned char *cmap = m_extensions->cmap();
+ for (int i = 0; i < len; ++i) {
+ const unsigned int uc = getChar(string, i, len);
+ if (QFontEngine::getTrueTypeGlyphIndex(cmap, uc) == 0)
+ return false;
+ }
+ return true;
+}
+
+QByteArray QFontEngineS60::getSfntTable(uint tag) const
+{
+ return m_extensions->getSfntTable(tag);
+}
+
+QFontEngine::Type QFontEngineS60::type() const
+{
+ return QFontEngine::S60FontEngine;
+}
+
+void QFontEngineS60::getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const
+{
+ // Setting the most significant bit tells GetCharacterData
+ // that 'code' is a Glyph ID, rather than a UTF-16 value
+ const TUint specialCode = (TUint)glyph | 0x80000000;
+
+ const CFont::TCharacterDataAvailability availability =
+ m_font->GetCharacterData(specialCode, metrics, bitmap, bitmapSize);
+ const glyph_t fallbackGlyph = '?';
+ if (availability != CFont::EAllCharacterData) {
+ const CFont::TCharacterDataAvailability fallbackAvailability =
+ m_font->GetCharacterData(fallbackGlyph, metrics, bitmap, bitmapSize);
+ Q_ASSERT(fallbackAvailability == CFont::EAllCharacterData);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h
new file mode 100644
index 0000000..bbbc3d6
--- /dev/null
+++ b/src/gui/text/qfontengine_s60_p.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFONTENGINE_S60_P_H
+#define QFONTENGINE_S60_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 "qconfig.h"
+#include "qfontengine_p.h"
+#include "qsize.h"
+#include <OPENFONT.H>
+
+class CFbsBitmap;
+class CFbsBitmapDevice;
+class CFbsBitGc;
+class CFont;
+
+QT_BEGIN_NAMESPACE
+
+// ..gives us access to truetype tables, UTF-16<->GlyphID mapping, and glyph outlines
+class QFontEngineS60Extensions
+{
+public:
+ QFontEngineS60Extensions(CFont* fontOwner, COpenFont *font);
+
+ QByteArray getSfntTable(uint tag) const;
+ const unsigned char *cmap() const;
+ QPainterPath glyphOutline(glyph_t glyph) const;
+ CFont *fontOwner() const;
+
+private:
+ COpenFont *m_font;
+ const MOpenFontShapingExtension *m_shapingExtension;
+ mutable MOpenFontTrueTypeExtension *m_trueTypeExtension;
+ mutable const unsigned char *m_cmap;
+ mutable bool m_symbolCMap;
+ mutable QByteArray m_cmapTable;
+ CFont* m_fontOwner;
+};
+
+class QFontEngineS60 : public QFontEngine
+{
+public:
+ QFontEngineS60(const QFontDef &fontDef, const QFontEngineS60Extensions *extensions);
+ ~QFontEngineS60();
+
+ bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
+ void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const;
+
+ QImage alphaMapForGlyph(glyph_t glyph);
+
+ glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
+ glyph_metrics_t boundingBox_const(glyph_t glyph) const; // Const correctnes quirk.
+ glyph_metrics_t boundingBox(glyph_t glyph);
+
+ QFixed ascent() const;
+ QFixed descent() const;
+ QFixed leading() const;
+ qreal maxCharWidth() const;
+ qreal minLeftBearing() const { return 0; }
+ qreal minRightBearing() const { return 0; }
+
+ QByteArray getSfntTable(uint tag) const;
+
+ static qreal pixelsToPoints(qreal pixels, Qt::Orientation orientation = Qt::Horizontal);
+ static qreal pointsToPixels(qreal points, Qt::Orientation orientation = Qt::Horizontal);
+
+ const char *name() const;
+
+ bool canRender(const QChar *string, int len);
+
+ Type type() const;
+
+private:
+ friend class QFontPrivate;
+
+ QFixed glyphAdvance(HB_Glyph glyph) const;
+ void getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const;
+
+ CFbsBitmap *m_textRenderBitmap;
+ CFbsBitmapDevice *m_textRenderBitmapDevice;
+ CFbsBitGc *m_textRenderBitmapGc;
+ CFont* m_font;
+ const QFontEngineS60Extensions *m_extensions;
+ qreal m_fontSizeInPixels;
+};
+
+class QFontEngineMultiS60 : public QFontEngineMulti
+{
+public:
+ QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies);
+ void loadEngine(int at);
+
+ int m_script;
+ QStringList m_fallbackFamilies;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFONTENGINE_S60_P_H
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index f916e26..19c17ae 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -48,7 +48,6 @@
#include <qlibrary.h>
#include <qpaintdevice.h>
#include <qpainter.h>
-#include <qlibrary.h>
#include <limits.h>
#include <qendian.h>
@@ -65,7 +64,7 @@
#include <private/qpaintengine_raster_p.h>
#include <private/qnativeimage_p.h>
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qguifunctions_wince.h"
#endif
@@ -85,8 +84,6 @@
((quint32)(ch1)) \
)
-typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT);
-
// common DC for all fonts
QT_BEGIN_NAMESPACE
@@ -128,8 +125,7 @@ HDC shared_dc()
}
#endif
-static HFONT stock_sysfont = 0;
-
+typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT);
static PtrGetCharWidthI ptrGetCharWidthI = 0;
static bool resolvedGetCharWidthI = false;
@@ -141,27 +137,6 @@ static void resolveGetCharWidthI()
ptrGetCharWidthI = (PtrGetCharWidthI)QLibrary::resolve(QLatin1String("gdi32"), "GetCharWidthI");
}
-// Copy a LOGFONTW struct into a LOGFONTA by converting the face name to an 8 bit value.
-// This is needed when calling CreateFontIndirect on non-unicode windowses.
-inline static void wa_copy_logfont(LOGFONTW *lfw, LOGFONTA *lfa)
-{
- lfa->lfHeight = lfw->lfHeight;
- lfa->lfWidth = lfw->lfWidth;
- lfa->lfEscapement = lfw->lfEscapement;
- lfa->lfOrientation = lfw->lfOrientation;
- lfa->lfWeight = lfw->lfWeight;
- lfa->lfItalic = lfw->lfItalic;
- lfa->lfUnderline = lfw->lfUnderline;
- lfa->lfCharSet = lfw->lfCharSet;
- lfa->lfOutPrecision = lfw->lfOutPrecision;
- lfa->lfClipPrecision = lfw->lfClipPrecision;
- lfa->lfQuality = lfw->lfQuality;
- lfa->lfPitchAndFamily = lfw->lfPitchAndFamily;
-
- QString fam = QString::fromUtf16((const ushort*)lfw->lfFaceName);
- memcpy(lfa->lfFaceName, fam.toLocal8Bit().constData(), fam.length() + 1);
-}
-
// defined in qtextengine_win.cpp
typedef void *SCRIPT_CACHE;
typedef HRESULT (WINAPI *fScriptFreeCache)(SCRIPT_CACHE *);
@@ -187,14 +162,6 @@ static inline quint16 getUShort(unsigned char *p)
return val;
}
-static inline HFONT systemFont()
-{
- if (stock_sysfont == 0)
- stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT);
- return stock_sysfont;
-}
-
-
// general font engine
QFixed QFontEngineWin::lineThickness() const
@@ -205,33 +172,18 @@ QFixed QFontEngineWin::lineThickness() const
return QFontEngine::lineThickness();
}
-#if defined(Q_OS_WINCE)
-static OUTLINETEXTMETRICW *getOutlineTextMetric(HDC hdc)
-{
- int size;
- size = GetOutlineTextMetricsW(hdc, 0, 0);
- OUTLINETEXTMETRICW *otm = (OUTLINETEXTMETRICW *)malloc(size);
- GetOutlineTextMetricsW(hdc, size, otm);
- return otm;
-}
-#else
-static OUTLINETEXTMETRICA *getOutlineTextMetric(HDC hdc)
+static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc)
{
int size;
- size = GetOutlineTextMetricsA(hdc, 0, 0);
- OUTLINETEXTMETRICA *otm = (OUTLINETEXTMETRICA *)malloc(size);
- GetOutlineTextMetricsA(hdc, size, otm);
+ size = GetOutlineTextMetrics(hdc, 0, 0);
+ OUTLINETEXTMETRIC *otm = (OUTLINETEXTMETRIC *)malloc(size);
+ GetOutlineTextMetrics(hdc, size, otm);
return otm;
}
-#endif
void QFontEngineWin::getCMap()
{
- QT_WA({
- ttf = (bool)(tm.w.tmPitchAndFamily & TMPF_TRUETYPE);
- } , {
- ttf = (bool)(tm.a.tmPitchAndFamily & TMPF_TRUETYPE);
- });
+ ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE);
HDC hdc = shared_dc();
SelectObject(hdc, hfont);
bool symb = false;
@@ -249,11 +201,7 @@ void QFontEngineWin::getCMap()
designToDevice = 1;
_faceId.index = 0;
if(cmap) {
-#if defined(Q_OS_WINCE)
- OUTLINETEXTMETRICW *otm = getOutlineTextMetric(hdc);
-#else
- OUTLINETEXTMETRICA *otm = getOutlineTextMetric(hdc);
-#endif
+ OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc);
designToDevice = QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight);
unitsPerEm = otm->otmEMSquare;
x_height = (int)otm->otmsXHeight;
@@ -263,7 +211,7 @@ void QFontEngineWin::getCMap()
fsType = otm->otmfsType;
free(otm);
} else {
- unitsPerEm = tm.w.tmHeight;
+ unitsPerEm = tm.tmHeight;
}
}
@@ -286,7 +234,7 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
int i = 0;
int glyph_pos = 0;
if (mirrored) {
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
{
#else
if (symbol) {
@@ -303,19 +251,14 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
}
} else {
#endif
- ushort first, last;
- QT_WA({
- first = tm.w.tmFirstChar;
- last = tm.w.tmLastChar;
- }, {
- first = tm.a.tmFirstChar;
- last = tm.a.tmLastChar;
- });
+ wchar_t first = tm.tmFirstChar;
+ wchar_t last = tm.tmLastChar;
+
for (; i < numChars; ++i, ++glyph_pos) {
uint ucs = QChar::mirroredChar(getChar(str, i, numChars));
if (
-#ifdef Q_OS_WINCE
- tm.w.tmFirstChar > 60000 || // see line 375
+#ifdef Q_WS_WINCE
+ tm.tmFirstChar > 60000 || // see line 375
#endif
ucs >= first && ucs <= last)
glyphs->glyphs[glyph_pos] = ucs;
@@ -324,7 +267,7 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
}
}
} else {
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
{
#else
if (symbol) {
@@ -341,19 +284,14 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
}
} else {
#endif
- ushort first, last;
- QT_WA({
- first = tm.w.tmFirstChar;
- last = tm.w.tmLastChar;
- }, {
- first = tm.a.tmFirstChar;
- last = tm.a.tmLastChar;
- });
+ wchar_t first = tm.tmFirstChar;
+ wchar_t last = tm.tmLastChar;
+
for (; i < numChars; ++i, ++glyph_pos) {
uint uc = getChar(str, i, numChars);
if (
-#ifdef Q_OS_WINCE
- tm.w.tmFirstChar > 60000 || // see comment in QFontEngineWin
+#ifdef Q_WS_WINCE
+ tm.tmFirstChar > 60000 || // see comment in QFontEngineWin
#endif
uc >= first && uc <= last)
glyphs->glyphs[glyph_pos] = uc;
@@ -387,28 +325,16 @@ QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont
lineWidth = -1;
x_height = -1;
- BOOL res;
- QT_WA({
- res = GetTextMetricsW(hdc, &tm.w);
- } , {
- res = GetTextMetricsA(hdc, &tm.a);
- });
- fontDef.fixedPitch = !(tm.w.tmPitchAndFamily & TMPF_FIXED_PITCH);
- if (!res)
+ BOOL res = GetTextMetrics(hdc, &tm);
+ fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
+ if (!res) {
qErrnoWarning("QFontEngineWin: GetTextMetrics failed");
+ ZeroMemory(&tm, sizeof(TEXTMETRIC));
+ }
- cache_cost = tm.w.tmHeight * tm.w.tmAveCharWidth * 2000;
+ cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000;
getCMap();
- useTextOutA = false;
-#ifndef Q_OS_WINCE
- // TextOutW doesn't work for symbol fonts on Windows 95!
- // since we're using glyph indices we don't care for ttfs about this!
- if (QSysInfo::WindowsVersion == QSysInfo::WV_95 && !ttf &&
- (_name == QLatin1String("Marlett") || _name == QLatin1String("Symbol") ||
- _name == QLatin1String("Webdings") || _name == QLatin1String("Wingdings")))
- useTextOutA = true;
-#endif
widthCache = 0;
widthCacheSize = 0;
designAdvances = 0;
@@ -427,7 +353,7 @@ QFontEngineWin::~QFontEngineWin()
free(widthCache);
// make sure we aren't by accident still selected
- SelectObject(shared_dc(), systemFont());
+ SelectObject(shared_dc(), (HFONT)GetStockObject(SYSTEM_FONT));
if (!stockFont) {
if (!DeleteObject(hfont))
@@ -435,39 +361,12 @@ QFontEngineWin::~QFontEngineWin()
}
}
-HGDIOBJ QFontEngineWin::selectDesignFont(QFixed *overhang) const
+HGDIOBJ QFontEngineWin::selectDesignFont() const
{
LOGFONT f = logfont;
f.lfHeight = unitsPerEm;
- HFONT designFont;
- QT_WA({
- designFont = CreateFontIndirectW(&f);
- }, {
- LOGFONTA fa;
- wa_copy_logfont(&f, &fa);
- designFont = CreateFontIndirectA(&fa);
- });
- HGDIOBJ oldFont = SelectObject(shared_dc(), designFont);
-
- if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) {
- BOOL res;
- QT_WA({
- TEXTMETRICW tm;
- res = GetTextMetricsW(shared_dc(), &tm);
- if (!res)
- qErrnoWarning("QFontEngineWin: GetTextMetrics failed");
- *overhang = QFixed((int)tm.tmOverhang) / designToDevice;
- } , {
- TEXTMETRICA tm;
- res = GetTextMetricsA(shared_dc(), &tm);
- if (!res)
- qErrnoWarning("QFontEngineWin: GetTextMetrics failed");
- *overhang = QFixed((int)tm.tmOverhang) / designToDevice;
- });
- } else {
- *overhang = 0;
- }
- return oldFont;
+ HFONT designFont = CreateFontIndirect(&f);
+ return SelectObject(shared_dc(), designFont);
}
bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
@@ -482,12 +381,10 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
if (flags & QTextEngine::GlyphIndicesOnly)
return true;
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
HDC hdc = shared_dc();
if (flags & QTextEngine::DesignMetrics) {
HGDIOBJ oldFont = 0;
- QFixed overhang = 0;
-
int glyph_pos = 0;
for(register int i = 0; i < len; i++) {
bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1
@@ -495,16 +392,16 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
unsigned int glyph = glyphs->glyphs[glyph_pos];
if(int(glyph) >= designAdvancesSize) {
int newSize = (glyph + 256) >> 8 << 8;
- designAdvances = (QFixed *)realloc(designAdvances, newSize*sizeof(QFixed));
+ designAdvances = q_check_ptr((QFixed *)realloc(designAdvances, newSize*sizeof(QFixed)));
for(int i = designAdvancesSize; i < newSize; ++i)
designAdvances[i] = -1000000;
designAdvancesSize = newSize;
}
if(designAdvances[glyph] < -999999) {
if(!oldFont)
- oldFont = selectDesignFont(&overhang);
+ oldFont = selectDesignFont();
SIZE size = {0, 0};
- GetTextExtentPoint32W(hdc, (wchar_t *)(str+i), surrogate ? 2 : 1, &size);
+ GetTextExtentPoint32(hdc, (wchar_t *)(str+i), surrogate ? 2 : 1, &size);
designAdvances[glyph] = QFixed((int)size.cx)/designToDevice;
}
glyphs->advances_x[glyph_pos] = designAdvances[glyph];
@@ -528,7 +425,8 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
if (glyph >= widthCacheSize) {
int newSize = (glyph + 256) >> 8 << 8;
- widthCache = (unsigned char *)realloc(widthCache, newSize*sizeof(QFixed));
+ widthCache = q_check_ptr((unsigned char *)realloc(widthCache,
+ newSize*sizeof(QFixed)));
memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize);
widthCacheSize = newSize;
}
@@ -538,7 +436,7 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
SIZE size = {0, 0};
if (!oldFont)
oldFont = SelectObject(hdc, hfont);
- GetTextExtentPoint32W(hdc, (wchar_t *)str + i, surrogate ? 2 : 1, &size);
+ GetTextExtentPoint32(hdc, (wchar_t *)str + i, surrogate ? 2 : 1, &size);
glyphs->advances_x[glyph_pos] = size.cx;
// if glyph's within cache range, store it for later
if (size.cx > 0 && size.cx < 0x100)
@@ -564,46 +462,24 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
HGDIOBJ oldFont = 0;
HDC hdc = shared_dc();
if (ttf && (flags & QTextEngine::DesignMetrics)) {
- QFixed overhang = 0;
-
for(int i = 0; i < glyphs->numGlyphs; i++) {
unsigned int glyph = glyphs->glyphs[i];
if(int(glyph) >= designAdvancesSize) {
int newSize = (glyph + 256) >> 8 << 8;
- designAdvances = (QFixed *)realloc(designAdvances, newSize*sizeof(QFixed));
+ designAdvances = q_check_ptr((QFixed *)realloc(designAdvances,
+ newSize*sizeof(QFixed)));
for(int i = designAdvancesSize; i < newSize; ++i)
designAdvances[i] = -1000000;
designAdvancesSize = newSize;
}
- if(designAdvances[glyph] < -999999) {
- if(!oldFont)
- oldFont = selectDesignFont(&overhang);
+ if (designAdvances[glyph] < -999999) {
+ if (!oldFont)
+ oldFont = selectDesignFont();
- if (ptrGetCharWidthI) {
- int width = 0;
+ int width = 0;
+ if (ptrGetCharWidthI)
ptrGetCharWidthI(hdc, glyph, 1, 0, &width);
-
- designAdvances[glyph] = QFixed(width) / designToDevice;
- } else {
-#ifndef Q_OS_WINCE
- GLYPHMETRICS gm;
- DWORD res = GDI_ERROR;
- MAT2 mat;
- mat.eM11.value = mat.eM22.value = 1;
- mat.eM11.fract = mat.eM22.fract = 0;
- mat.eM21.value = mat.eM12.value = 0;
- mat.eM21.fract = mat.eM12.fract = 0;
- QT_WA({
- res = GetGlyphOutlineW(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX|GGO_NATIVE, &gm, 0, 0, &mat);
- } , {
- res = GetGlyphOutlineA(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX|GGO_NATIVE, &gm, 0, 0, &mat);
- });
-
- if (res != GDI_ERROR) {
- designAdvances[glyph] = QFixed(gm.gmCellIncX) / designToDevice;
- }
-#endif
- }
+ designAdvances[glyph] = QFixed(width) / designToDevice;
}
glyphs->advances_x[i] = designAdvances[glyph];
glyphs->advances_y[i] = 0;
@@ -611,8 +487,6 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
if(oldFont)
DeleteObject(SelectObject(hdc, oldFont));
} else {
- int overhang = (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) ? tm.a.tmOverhang : 0;
-
for(int i = 0; i < glyphs->numGlyphs; i++) {
unsigned int glyph = glyphs->glyphs[i];
@@ -620,7 +494,8 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
if (glyph >= widthCacheSize) {
int newSize = (glyph + 256) >> 8 << 8;
- widthCache = (unsigned char *)realloc(widthCache, newSize*sizeof(QFixed));
+ widthCache = q_check_ptr((unsigned char *)realloc(widthCache,
+ newSize*sizeof(QFixed)));
memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize);
widthCacheSize = newSize;
}
@@ -640,31 +515,10 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
++chrLen;
}
SIZE size = {0, 0};
- GetTextExtentPoint32W(hdc, (wchar_t *)ch, chrLen, &size);
+ GetTextExtentPoint32(hdc, (wchar_t *)ch, chrLen, &size);
width = size.cx;
} else if (ptrGetCharWidthI) {
ptrGetCharWidthI(hdc, glyph, 1, 0, &width);
-
- width -= overhang;
- } else {
-#ifndef Q_OS_WINCE
- GLYPHMETRICS gm;
- DWORD res = GDI_ERROR;
- MAT2 mat;
- mat.eM11.value = mat.eM22.value = 1;
- mat.eM11.fract = mat.eM22.fract = 0;
- mat.eM21.value = mat.eM12.value = 0;
- mat.eM21.fract = mat.eM12.fract = 0;
- QT_WA({
- res = GetGlyphOutlineW(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX, &gm, 0, 0, &mat);
- } , {
- res = GetGlyphOutlineA(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX, &gm, 0, 0, &mat);
- });
-
- if (res != GDI_ERROR) {
- width = gm.gmCellIncX;
- }
-#endif
}
glyphs->advances_x[i] = width;
// if glyph's within cache range, store it for later
@@ -687,48 +541,24 @@ glyph_metrics_t QFontEngineWin::boundingBox(const QGlyphLayout &glyphs)
for (int i = 0; i < glyphs.numGlyphs; ++i)
w += glyphs.effectiveAdvance(i);
- return glyph_metrics_t(0, -tm.w.tmAscent, w, tm.w.tmHeight, w, 0);
+ return glyph_metrics_t(0, -tm.tmAscent, w, tm.tmHeight, w, 0);
}
-
-
-#ifndef Q_OS_WINCE
-typedef HRESULT (WINAPI *pGetCharABCWidthsFloat)(HDC, UINT, UINT, LPABCFLOAT);
-static pGetCharABCWidthsFloat qt_GetCharABCWidthsFloat = 0;
-#endif
-
glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t)
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
GLYPHMETRICS gm;
HDC hdc = shared_dc();
SelectObject(hdc, hfont);
- if(!ttf) {
- SIZE s = {0, 0};
- WCHAR ch = glyph;
- int width;
- int overhang = 0;
- static bool resolved = false;
- if (!resolved) {
- QLibrary lib(QLatin1String("gdi32"));
- qt_GetCharABCWidthsFloat = (pGetCharABCWidthsFloat) lib.resolve("GetCharABCWidthsFloatW");
- resolved = true;
- }
- if (QT_WA_INLINE(true, false) && qt_GetCharABCWidthsFloat) {
- ABCFLOAT abc;
- qt_GetCharABCWidthsFloat(hdc, ch, ch, &abc);
- width = qRound(abc.abcfB);
- } else {
- GetTextExtentPoint32W(hdc, &ch, 1, &s);
- overhang = (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) ? tm.a.tmOverhang : 0;
- width = s.cx;
- }
+ if (!ttf) {
+ wchar_t ch = glyph;
+ ABCFLOAT abc;
+ GetCharABCWidthsFloat(hdc, ch, ch, &abc);
+ int width = qRound(abc.abcfB);
- return glyph_metrics_t(0, -tm.a.tmAscent,
- width, tm.a.tmHeight,
- width-overhang, 0).transformed(t);
+ return glyph_metrics_t(0, -tm.tmAscent, width, tm.tmHeight, width, 0).transformed(t);
} else {
DWORD res = 0;
MAT2 mat;
@@ -753,11 +583,8 @@ glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t)
SetWorldTransform(hdc, &xform);
}
- QT_WA({
- res = GetGlyphOutlineW(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX, &gm, 0, 0, &mat);
- } , {
- res = GetGlyphOutlineA(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX, &gm, 0, 0, &mat);
- });
+ res = GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, 0, &mat);
+
if (t.type() > QTransform::TxTranslate) {
XFORM xform;
xform.eM11 = xform.eM22 = 1;
@@ -793,28 +620,28 @@ glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t)
else
#endif
{ // fallback
- width = tm.w.tmMaxCharWidth;
+ width = tm.tmMaxCharWidth;
advance = width;
}
SelectObject(hdc, oldFont);
- return glyph_metrics_t(0, -tm.w.tmAscent, width, tm.w.tmHeight, advance, 0).transformed(t);
+ return glyph_metrics_t(0, -tm.tmAscent, width, tm.tmHeight, advance, 0).transformed(t);
#endif
}
QFixed QFontEngineWin::ascent() const
{
- return tm.w.tmAscent;
+ return tm.tmAscent;
}
QFixed QFontEngineWin::descent() const
{
- return tm.w.tmDescent;
+ return tm.tmDescent;
}
QFixed QFontEngineWin::leading() const
{
- return tm.w.tmExternalLeading;
+ return tm.tmExternalLeading;
}
@@ -827,12 +654,12 @@ QFixed QFontEngineWin::xHeight() const
QFixed QFontEngineWin::averageCharWidth() const
{
- return tm.w.tmAveCharWidth;
+ return tm.tmAveCharWidth;
}
qreal QFontEngineWin::maxCharWidth() const
{
- return tm.w.tmMaxCharWidth;
+ return tm.tmMaxCharWidth;
}
enum { max_font_count = 256 };
@@ -871,7 +698,7 @@ qreal QFontEngineWin::minLeftBearing() const
qreal QFontEngineWin::minRightBearing() const
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (rbearing == SHRT_MIN) {
int ml = 0;
int mr = 0;
@@ -879,10 +706,10 @@ qreal QFontEngineWin::minRightBearing() const
SelectObject(hdc, hfont);
if (ttf) {
ABC *abc = 0;
- int n = QT_WA_INLINE(tm.w.tmLastChar - tm.w.tmFirstChar, tm.a.tmLastChar - tm.a.tmFirstChar);
+ int n = tm.tmLastChar - tm.tmFirstChar;
if (n <= max_font_count) {
abc = new ABC[n+1];
- GetCharABCWidths(hdc, tm.w.tmFirstChar, tm.w.tmLastChar, abc);
+ GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc);
} else {
abc = new ABC[char_table_entries+1];
for(int i = 0; i < char_table_entries; i++)
@@ -898,9 +725,6 @@ qreal QFontEngineWin::minRightBearing() const
}
}
delete [] abc;
- } else {
- ml = 0;
- mr = -tm.a.tmOverhang;
}
lbearing = ml;
rbearing = mr;
@@ -915,28 +739,14 @@ qreal QFontEngineWin::minRightBearing() const
SelectObject(hdc, hfont);
if (ttf) {
ABC *abc = 0;
- int n = QT_WA_INLINE(tm.w.tmLastChar - tm.w.tmFirstChar, tm.a.tmLastChar - tm.a.tmFirstChar);
+ int n = tm.tmLastChar - tm.tmFirstChar;
if (n <= max_font_count) {
abc = new ABC[n+1];
- QT_WA({
- GetCharABCWidths(hdc, tm.w.tmFirstChar, tm.w.tmLastChar, abc);
- }, {
- GetCharABCWidthsA(hdc,tm.a.tmFirstChar,tm.a.tmLastChar,abc);
- });
+ GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc);
} else {
abc = new ABC[char_table_entries+1];
- QT_WA({
- for(int i = 0; i < char_table_entries; i++)
- GetCharABCWidths(hdc, char_table[i], char_table[i], abc+i);
- }, {
- for(int i = 0; i < char_table_entries; i++) {
- QByteArray w = QString(QChar(char_table[i])).toLocal8Bit();
- if (w.length() == 1) {
- uint ch8 = (uchar)w[0];
- GetCharABCWidthsA(hdc, ch8, ch8, abc+i);
- }
- }
- });
+ for(int i = 0; i < char_table_entries; i++)
+ GetCharABCWidths(hdc, char_table[i], char_table[i], abc + i);
n = char_table_entries;
}
ml = abc[0].abcA;
@@ -949,33 +759,28 @@ qreal QFontEngineWin::minRightBearing() const
}
delete [] abc;
} else {
- QT_WA({
- ABCFLOAT *abc = 0;
- int n = tm.w.tmLastChar - tm.w.tmFirstChar+1;
- if (n <= max_font_count) {
- abc = new ABCFLOAT[n];
- GetCharABCWidthsFloat(hdc, tm.w.tmFirstChar, tm.w.tmLastChar, abc);
- } else {
- abc = new ABCFLOAT[char_table_entries];
- for(int i = 0; i < char_table_entries; i++)
- GetCharABCWidthsFloat(hdc, char_table[i], char_table[i], abc+i);
- n = char_table_entries;
- }
- float fml = abc[0].abcfA;
- float fmr = abc[0].abcfC;
- for (int i=1; i<n; i++) {
- if (abc[i].abcfA + abc[i].abcfB + abc[i].abcfC != 0) {
- fml = qMin(fml,abc[i].abcfA);
- fmr = qMin(fmr,abc[i].abcfC);
- }
+ ABCFLOAT *abc = 0;
+ int n = tm.tmLastChar - tm.tmFirstChar+1;
+ if (n <= max_font_count) {
+ abc = new ABCFLOAT[n];
+ GetCharABCWidthsFloat(hdc, tm.tmFirstChar, tm.tmLastChar, abc);
+ } else {
+ abc = new ABCFLOAT[char_table_entries];
+ for(int i = 0; i < char_table_entries; i++)
+ GetCharABCWidthsFloat(hdc, char_table[i], char_table[i], abc+i);
+ n = char_table_entries;
+ }
+ float fml = abc[0].abcfA;
+ float fmr = abc[0].abcfC;
+ for (int i=1; i<n; i++) {
+ if (abc[i].abcfA + abc[i].abcfB + abc[i].abcfC != 0) {
+ fml = qMin(fml,abc[i].abcfA);
+ fmr = qMin(fmr,abc[i].abcfC);
}
- ml = int(fml-0.9999);
- mr = int(fmr-0.9999);
- delete [] abc;
- } , {
- ml = 0;
- mr = -tm.a.tmOverhang;
- });
+ }
+ ml = int(fml - 0.9999);
+ mr = int(fmr - 0.9999);
+ delete [] abc;
}
lbearing = ml;
rbearing = mr;
@@ -1012,17 +817,10 @@ bool QFontEngineWin::canRender(const QChar *string, int len)
return false;
}
} else {
- QT_WA({
- while(len--) {
- if (tm.w.tmFirstChar > string->unicode() || tm.w.tmLastChar < string->unicode())
- return false;
- }
- }, {
- while(len--) {
- if (tm.a.tmFirstChar > string->unicode() || tm.a.tmLastChar < string->unicode())
- return false;
- }
- });
+ while(len--) {
+ if (tm.tmFirstChar > string->unicode() || tm.tmLastChar < string->unicode())
+ return false;
+ }
}
return true;
}
@@ -1047,7 +845,7 @@ static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale) {
static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
QPainterPath *path, bool ttf, glyph_metrics_t *metric = 0, qreal scale = 1)
{
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
Q_UNUSED(glyph);
Q_UNUSED(hdc);
#endif
@@ -1064,12 +862,8 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
GLYPHMETRICS gMetric;
memset(&gMetric, 0, sizeof(GLYPHMETRICS));
int bufferSize = GDI_ERROR;
-#if !defined(Q_OS_WINCE)
- QT_WA( {
- bufferSize = GetGlyphOutlineW(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat);
- }, {
- bufferSize = GetGlyphOutlineA(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat);
- });
+#if !defined(Q_WS_WINCE)
+ bufferSize = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat);
#endif
if ((DWORD)bufferSize == GDI_ERROR) {
return false;
@@ -1077,14 +871,8 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
void *dataBuffer = new char[bufferSize];
DWORD ret = GDI_ERROR;
-#if !defined(Q_OS_WINCE)
- QT_WA( {
- ret = GetGlyphOutlineW(hdc, glyph, glyphFormat, &gMetric, bufferSize,
- dataBuffer, &mat);
- }, {
- ret = GetGlyphOutlineA(hdc, glyph, glyphFormat, &gMetric, bufferSize,
- dataBuffer, &mat);
- } );
+#if !defined(Q_WS_WINCE)
+ ret = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, bufferSize, dataBuffer, &mat);
#endif
if (ret == GDI_ERROR) {
delete [](char *)dataBuffer;
@@ -1171,14 +959,7 @@ void QFontEngineWin::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, in
// font at the correct pixel size.
lf.lfHeight = -unitsPerEm;
lf.lfWidth = 0;
- HFONT hf;
- QT_WA({
- hf = CreateFontIndirectW(&lf);
- }, {
- LOGFONTA lfa;
- wa_copy_logfont(&lf, &lfa);
- hf = CreateFontIndirectA(&lfa);
- });
+ HFONT hf = CreateFontIndirect(&lf);
HDC hdc = shared_dc();
HGDIOBJ oldfont = SelectObject(hdc, hf);
@@ -1199,8 +980,8 @@ void QFontEngineWin::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, in
void QFontEngineWin::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
QPainterPath *path, QTextItem::RenderFlags flags)
{
-#if !defined(Q_OS_WINCE)
- if(tm.w.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) {
+#if !defined(Q_WS_WINCE)
+ if(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) {
hasOutline = true;
QFontEngine::addOutlineToPath(x, y, glyphs, path, flags);
if (hasOutline) {
@@ -1234,11 +1015,11 @@ int QFontEngineWin::synthesized() const
uchar data[4];
GetFontData(hdc, HEAD, 44, &data, 4);
USHORT macStyle = getUShort(data);
- if (tm.w.tmItalic && !(macStyle & 2))
+ if (tm.tmItalic && !(macStyle & 2))
synthesized_flags = SynthesizedItalic;
if (fontDef.stretch != 100 && ttf)
synthesized_flags |= SynthesizedStretch;
- if (tm.w.tmWeight >= 500 && !(macStyle & 1))
+ if (tm.tmWeight >= 500 && !(macStyle & 1))
synthesized_flags |= SynthesizedBold;
//qDebug() << "font is" << _name <<
// "it=" << (macStyle & 2) << fontDef.style << "flags=" << synthesized_flags;
@@ -1254,24 +1035,12 @@ QFixed QFontEngineWin::emSquareSize() const
QFontEngine::Properties QFontEngineWin::properties() const
{
-
LOGFONT lf = logfont;
lf.lfHeight = unitsPerEm;
- HFONT hf;
- QT_WA({
- hf = CreateFontIndirectW(&lf);
- }, {
- LOGFONTA lfa;
- wa_copy_logfont(&lf, &lfa);
- hf = CreateFontIndirectA(&lfa);
- });
+ HFONT hf = CreateFontIndirect(&lf);
HDC hdc = shared_dc();
HGDIOBJ oldfont = SelectObject(hdc, hf);
-#if defined(Q_OS_WINCE)
- OUTLINETEXTMETRICW *otm = getOutlineTextMetric(hdc);
-#else
- OUTLINETEXTMETRICA *otm = getOutlineTextMetric(hdc);
-#endif
+ OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc);
Properties p;
p.emSquare = unitsPerEm;
p.italicAngle = otm->otmItalicAngle;
@@ -1301,14 +1070,7 @@ void QFontEngineWin::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_m
if(flags & SynthesizedItalic)
lf.lfItalic = false;
lf.lfWidth = 0;
- HFONT hf;
- QT_WA({
- hf = CreateFontIndirectW(&lf);
- }, {
- LOGFONTA lfa;
- wa_copy_logfont(&lf, &lfa);
- hf = CreateFontIndirectA(&lfa);
- });
+ HFONT hf = CreateFontIndirect(&lf);
HDC hdc = shared_dc();
HGDIOBJ oldfont = SelectObject(hdc, hf);
QFixedPoint p;
@@ -1333,10 +1095,12 @@ bool QFontEngineWin::getSfntTableData(uint tag, uchar *buffer, uint *length) con
# define CLEARTYPE_QUALITY 5
#endif
+extern bool qt_cleartype_enabled;
QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin,
const QTransform &t, QImage::Format mask_format)
{
+ Q_UNUSED(mask_format)
glyph_metrics_t gm = boundingBox(glyph);
// printf(" -> for glyph %4x\n", glyph);
@@ -1351,7 +1115,7 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin
bool has_transformation = t.type() > QTransform::TxTranslate;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
unsigned int options = ttf ? ETO_GLYPH_INDEX : 0;
XFORM xform;
@@ -1376,14 +1140,7 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin
memset(&mat, 0, sizeof(mat));
mat.eM11.value = mat.eM22.value = 1;
- int error = 0;
- QT_WA( {
- error = GetGlyphOutlineW(hdc, glyph, ggo_options, &tgm, 0, 0, &mat);
- }, {
- error = GetGlyphOutlineA(hdc, glyph, ggo_options, &tgm, 0, 0, &mat);
- } );
-
- if (error == GDI_ERROR) {
+ if (GetGlyphOutline(hdc, glyph, ggo_options, &tgm, 0, 0, &mat) == GDI_ERROR) {
qWarning("QWinFontEngine: unable to query transformed glyph metrics...");
return 0;
}
@@ -1408,7 +1165,11 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin
QNativeImage *ni = new QNativeImage(iw + 2 * margin + 4,
ih + 2 * margin + 4,
- mask_format, true);
+ QNativeImage::systemFormat(), !qt_cleartype_enabled);
+
+ /*If cleartype is enabled we use the standard system format even on Windows CE
+ and not the special textbuffer format we have to use if cleartype is disabled*/
+
ni->image.fill(0xffffffff);
HDC hdc = ni->hdc;
@@ -1425,11 +1186,11 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin
if (has_transformation) {
SetGraphicsMode(hdc, GM_ADVANCED);
SetWorldTransform(hdc, &xform);
- ExtTextOutW(hdc, 0, 0, options, 0, (LPCWSTR) &glyph, 1, 0);
+ ExtTextOut(hdc, 0, 0, options, 0, (LPCWSTR) &glyph, 1, 0);
} else
#endif
{
- ExtTextOutW(hdc, -gx + margin, -gy + margin, options, 0, (LPCWSTR) &glyph, 1, 0);
+ ExtTextOut(hdc, -gx + margin, -gy + margin, options, 0, (LPCWSTR) &glyph, 1, 0);
}
SelectObject(hdc, old_font);
@@ -1437,7 +1198,6 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin
}
-extern bool qt_cleartype_enabled;
extern uint qt_pow_gamma[256];
QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform)
@@ -1446,7 +1206,7 @@ QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform)
if (qt_cleartype_enabled) {
LOGFONT lf = logfont;
lf.lfQuality = ANTIALIASED_QUALITY;
- font = CreateFontIndirectW(&lf);
+ font = CreateFontIndirect(&lf);
}
QImage::Format mask_format = QNativeImage::systemFormat();
#ifndef Q_OS_WINCE
@@ -1553,17 +1313,9 @@ void QFontEngineMultiWin::loadEngine(int at)
QString fam = fallbacks.at(at-1);
LOGFONT lf = static_cast<QFontEngineWin *>(engines.at(0))->logfont;
- HFONT hfont;
- QT_WA({
- memcpy(lf.lfFaceName, fam.utf16(), sizeof(TCHAR)*qMin(fam.length()+1,32)); // 32 = Windows hard-coded
- hfont = CreateFontIndirectW(&lf);
- } , {
- // LOGFONTA and LOGFONTW are binary compatible
- QByteArray lname = fam.toLocal8Bit();
- memcpy(lf.lfFaceName,lname.data(),
- qMin(lname.length()+1,32)); // 32 = Windows hard-coded
- hfont = CreateFontIndirectA((LOGFONTA*)&lf);
- });
+ memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded
+ HFONT hfont = CreateFontIndirect(&lf);
+
bool stockFont = false;
if (hfont == 0) {
hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h
index 24588d7..bf84dee 100644
--- a/src/gui/text/qfontengine_win_p.h
+++ b/src/gui/text/qfontengine_win_p.h
@@ -80,7 +80,7 @@ public:
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags);
- HGDIOBJ selectDesignFont(QFixed *) const;
+ HGDIOBJ selectDesignFont() const;
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
virtual glyph_metrics_t boundingBox(glyph_t g) { return boundingBox(g, QTransform()); }
@@ -109,18 +109,14 @@ public:
int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const;
void getCMap();
- QString _name;
- HFONT hfont;
+ QString _name;
+ HFONT hfont;
LOGFONT logfont;
- uint stockFont : 1;
- uint useTextOutA : 1;
- uint ttf : 1;
+ uint stockFont : 1;
+ uint ttf : 1;
uint hasOutline : 1;
- union {
- TEXTMETRICW w;
- TEXTMETRICA a;
- } tm;
- int lw;
+ TEXTMETRIC tm;
+ int lw;
const unsigned char *cmap;
QByteArray cmapTable;
mutable qreal lbearing;
diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp
index f7a80eb..aff5400 100644
--- a/src/gui/text/qfontengine_x11.cpp
+++ b/src/gui/text/qfontengine_x11.cpp
@@ -227,7 +227,7 @@ static QFontEngine::FaceId fontFile(const QByteArray &_xname, QFreetypeFace **fr
QByteArray best_mapping;
for (QStringList::ConstIterator it = fontpath.constBegin(); it != fontpath.constEnd(); ++it) {
- if ((*it).left(1) != QLatin1String("/"))
+ if (!(*it).startsWith(QLatin1Char('/')))
continue; // not a path name, a font server
QString fontmapname;
int num = 0;
@@ -693,9 +693,8 @@ QFontEngine::FaceId QFontEngineXLFD::faceId() const
if (freetype) {
const_cast<QFontEngineXLFD *>(this)->fsType = freetype->fsType();
} else {
- QFontEngine::Properties properties = QFontEngine::properties();
face_id.index = 0;
- face_id.filename = "-" + properties.postscriptName;
+ face_id.filename = '-' + QFontEngine::properties().postscriptName;
}
}
#endif
diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h
index f207df9..37e9382 100644
--- a/src/gui/text/qfontengineglyphcache_p.h
+++ b/src/gui/text/qfontengineglyphcache_p.h
@@ -72,7 +72,7 @@
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QFontEngineGlyphCache
+class QFontEngineGlyphCache
{
public:
QFontEngineGlyphCache(const QTransform &matrix) : m_transform(matrix) { }
@@ -83,7 +83,7 @@ public:
Raster_Mono
};
- virtual ~QFontEngineGlyphCache();
+ virtual ~QFontEngineGlyphCache() { }
QTransform m_transform;
};
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 148d6c1..c9be073 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -75,9 +75,8 @@ extern int qt_defaultDpi();
\brief The QFontMetrics class provides font metrics information.
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
- \ingroup text
QFontMetrics functions calculate the size of characters and
strings for a given font. There are three ways you can create a
@@ -164,7 +163,7 @@ extern int qt_defaultDpi();
metrics that are compatible with a certain paint device.
*/
QFontMetrics::QFontMetrics(const QFont &font)
- : d(font.d)
+ : d(font.d.data())
{
d->ref.ref();
}
@@ -196,7 +195,7 @@ QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice)
d->dpi = dpi;
d->screen = screen;
} else {
- d = font.d;
+ d = font.d.data();
d->ref.ref();
}
@@ -528,12 +527,14 @@ int QFontMetrics::rightBearing(QChar ch) const
*/
int QFontMetrics::width(const QString &text, int len) const
{
+ int pos = text.indexOf(QLatin1Char('\x9c'));
+ QString txt = (pos == -1) ? text : text.left(pos);
if (len < 0)
- len = text.length();
+ len = txt.length();
if (len == 0)
return 0;
- QTextEngine layout(text, d);
+ QTextEngine layout(txt, d);
layout.ignoreBidi = true;
return qRound(layout.width(0, len));
}
@@ -557,11 +558,10 @@ int QFontMetrics::width(const QString &text, int len) const
\warning This function will produce incorrect results for Arabic
characters or non-spacing marks in the middle of a string, as the
glyph shaping and positioning of marks that happens when
- processing strings cannot be taken into account. Use charWidth()
- instead if you aren't looking for the width of isolated
- characters.
+ processing strings cannot be taken into account. When implementing
+ an interactive text control, use QTextLayout instead.
- \sa boundingRect(), charWidth()
+ \sa boundingRect()
*/
int QFontMetrics::width(QChar ch) const
{
@@ -799,7 +799,7 @@ QRect QFontMetrics::boundingRect(const QRect &rect, int flags, const QString &te
*/
QSize QFontMetrics::size(int flags, const QString &text, int tabStops, int *tabArray) const
{
- return boundingRect(QRect(0,0,0,0), flags, text, tabStops, tabArray).size();
+ return boundingRect(QRect(0,0,0,0), flags | Qt::TextLongestVariant, text, tabStops, tabArray).size();
}
/*!
@@ -858,11 +858,23 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const
right-to-left layouts, and on the left side for right-to-left
layouts. Note that this behavior is independent of the text
language.
-
*/
QString QFontMetrics::elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags) const
{
- QStackTextEngine engine(text, QFont(d));
+ QString _text = text;
+ if (!(flags & Qt::TextLongestVariant)) {
+ int posA = 0;
+ int posB = _text.indexOf(QLatin1Char('\x9c'));
+ while (posB >= 0) {
+ QString portion = _text.mid(posA, posB - posA);
+ if (size(flags, portion).width() <= width)
+ return portion;
+ posA = posB + 1;
+ posB = _text.indexOf(QLatin1Char('\x9c'), posA);
+ }
+ _text = _text.mid(posA);
+ }
+ QStackTextEngine engine(_text, QFont(d));
return engine.elidedText(mode, width, flags);
}
@@ -928,9 +940,8 @@ int QFontMetrics::lineWidth() const
\brief The QFontMetricsF class provides font metrics information.
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
- \ingroup text
QFontMetricsF functions calculate the size of characters and
strings for a given font. You can construct a QFontMetricsF object
@@ -1006,7 +1017,7 @@ QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other)
metrics that are compatible with a certain paint device.
*/
QFontMetricsF::QFontMetricsF(const QFont &font)
- : d(font.d)
+ : d(font.d.data())
{
d->ref.ref();
}
@@ -1038,7 +1049,7 @@ QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice)
d->dpi = dpi;
d->screen = screen;
} else {
- d = font.d;
+ d = font.d.data();
d->ref.ref();
}
@@ -1386,9 +1397,8 @@ qreal QFontMetricsF::width(const QString &text) const
\warning This function will produce incorrect results for Arabic
characters or non-spacing marks in the middle of a string, as the
glyph shaping and positioning of marks that happens when
- processing strings cannot be taken into account. Use charWidth()
- instead if you aren't looking for the width of isolated
- characters.
+ processing strings cannot be taken into account. When implementing
+ an interactive text control, use QTextLayout instead.
\sa boundingRect()
*/
diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp
index a09b08f..f542c38 100644
--- a/src/gui/text/qfontsubset.cpp
+++ b/src/gui/text/qfontsubset.cpp
@@ -333,17 +333,17 @@ QByteArray QFontSubset::glyphName(unsigned int glyph, const QVector<int> reverse
name[0] = 0;
}
if (name[0]) {
- s << "/" << name;
+ s << '/' << name;
} else
#endif
#if defined(Q_WS_X11)
if (fontEngine->type() == QFontEngine::XLFD) {
uint uc = static_cast<QFontEngineXLFD *>(fontEngine)->toUnicode(glyphIndex);
- s << "/" << glyphName(uc, false /* ### */);
+ s << '/' << glyphName(uc, false /* ### */);
} else
#endif
if (reverseMap[glyphIndex] && reverseMap[glyphIndex] < 0x10000) {
- s << "/" << glyphName(reverseMap[glyphIndex], false);
+ s << '/' << glyphName(reverseMap[glyphIndex], false);
} else {
s << "/gl" << (int)glyphIndex;
}
@@ -395,13 +395,13 @@ QByteArray QFontSubset::widthArray() const
int endnonlinear = startLinear ? startLinear : g;
// qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
if (endnonlinear > start) {
- s << start << "[";
+ s << start << '[';
for (int i = start; i < endnonlinear; ++i)
s << (widths[i]*scale).toInt();
s << "]\n";
}
if (startLinear)
- s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << "\n";
+ s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n';
}
s << "]\n";
}
@@ -488,14 +488,14 @@ QByteArray QFontSubset::createToUnicodeMap() const
int endnonlinear = startLinear ? startLinear : g;
// qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
if (endnonlinear > start) {
- s << "<" << QPdf::toHex((ushort)start, buf) << "> <";
+ s << '<' << QPdf::toHex((ushort)start, buf) << "> <";
s << QPdf::toHex((ushort)(endnonlinear - 1), buf) << "> ";
if (endnonlinear == start + 1) {
- s << "<" << QPdf::toHex((ushort)reverseMap[start], buf) << ">\n";
+ s << '<' << QPdf::toHex((ushort)reverseMap[start], buf) << ">\n";
} else {
- s << "[";
+ s << '[';
for (int i = start; i < endnonlinear; ++i) {
- s << "<" << QPdf::toHex((ushort)reverseMap[i], buf) << "> ";
+ s << '<' << QPdf::toHex((ushort)reverseMap[i], buf) << "> ";
}
s << "]\n";
}
@@ -508,9 +508,9 @@ QByteArray QFontSubset::createToUnicodeMap() const
int uc_end = uc_start + len - 1;
if ((uc_end >> 8) != (uc_start >> 8))
len = 256 - (uc_start & 0xff);
- s << "<" << QPdf::toHex((ushort)startLinear, buf) << "> <";
+ s << '<' << QPdf::toHex((ushort)startLinear, buf) << "> <";
s << QPdf::toHex((ushort)(startLinear + len - 1), buf) << "> ";
- s << "<" << QPdf::toHex((ushort)reverseMap[startLinear], buf) << ">\n";
+ s << '<' << QPdf::toHex((ushort)reverseMap[startLinear], buf) << ">\n";
checkRanges(ts, ranges, nranges);
startLinear += len;
}
@@ -1655,7 +1655,7 @@ QByteArray QFontSubset::toType1() const
QByteArray id = QByteArray::number(object_id);
QByteArray psname = properties.postscriptName;
- psname.replace(" ", "");
+ psname.replace(' ', "");
standard_font = false;
@@ -1681,12 +1681,12 @@ QByteArray QFontSubset::toType1() const
#endif
s << "/F" << id << "-Base\n";
if (standard_font) {
- s << "/" << psname << " findfont\n"
+ s << '/' << psname << " findfont\n"
"0 dict copy dup /NumGlyphs 0 put dup /CMap 256 array put def\n";
} else {
s << "<<\n";
if(!psname.isEmpty())
- s << "/FontName /" << psname << "\n";
+ s << "/FontName /" << psname << '\n';
s << "/FontInfo <</FsType " << (int)fontEngine->fsType << ">>\n"
"/FontType 1\n"
"/PaintType 0\n"
@@ -1722,7 +1722,7 @@ QByteArray QFontSubset::type1AddedGlyphs() const
int nGlyphs = glyph_indices.size();
QByteArray id = QByteArray::number(object_id);
- s << "F" << id << "-Base [\n";
+ s << 'F' << id << "-Base [\n";
for (int i = downloaded_glyphs; i < nGlyphs; ++i) {
glyph_t g = glyph_indices.at(i);
QPainterPath path;
diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h
index 8f3ae66..6d8c8fa 100644
--- a/src/gui/text/qfragmentmap_p.h
+++ b/src/gui/text/qfragmentmap_p.h
@@ -214,6 +214,7 @@ private:
template <class Fragment>
QFragmentMapData<Fragment>::QFragmentMapData()
+ : fragments(0)
{
init();
}
@@ -221,12 +222,19 @@ QFragmentMapData<Fragment>::QFragmentMapData()
template <class Fragment>
void QFragmentMapData<Fragment>::init()
{
- fragments = (Fragment *)malloc(64*fragmentSize);
+ // the following code will realloc an existing fragment or create a new one.
+ // it will also ignore errors when shrinking an existing fragment.
+ Fragment *newFragments = (Fragment *)realloc(fragments, 64*fragmentSize);
+ if (newFragments) {
+ fragments = newFragments;
+ head->allocated = 64;
+ }
+ Q_CHECK_PTR(fragments);
+
head->tag = (((quint32)'p') << 24) | (((quint32)'m') << 16) | (((quint32)'a') << 8) | 'p'; //TAG('p', 'm', 'a', 'p');
head->root = 0;
head->freelist = 1;
head->node_count = 0;
- head->allocated = 64;
// mark all items to the right as unused
F(head->freelist).right = 0;
}
@@ -234,7 +242,7 @@ void QFragmentMapData<Fragment>::init()
template <class Fragment>
QFragmentMapData<Fragment>::~QFragmentMapData()
{
- free(head);
+ free(fragments);
}
template <class Fragment>
@@ -247,7 +255,9 @@ uint QFragmentMapData<Fragment>::createFragment()
// need to create some free space
uint needed = qAllocMore((freePos+1)*fragmentSize, 0);
Q_ASSERT(needed/fragmentSize > head->allocated);
- fragments = (Fragment *)realloc(fragments, needed);
+ Fragment *newFragments = (Fragment *)realloc(fragments, needed);
+ Q_CHECK_PTR(newFragments);
+ fragments = newFragments;
head->allocated = needed/fragmentSize;
F(freePos).right = 0;
}
@@ -787,6 +797,8 @@ public:
QFragmentMap() {}
~QFragmentMap()
{
+ if (!data.fragments)
+ return; // in case of out-of-memory, we won't have fragments
for (Iterator it = begin(); !it.atEnd(); ++it)
it.value()->free();
}
@@ -794,7 +806,6 @@ public:
inline void clear() {
for (Iterator it = begin(); !it.atEnd(); ++it)
it.value()->free();
- ::free(data.head);
data.init();
}
diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp
index 617885c..7a53759 100644
--- a/src/gui/text/qsyntaxhighlighter.cpp
+++ b/src/gui/text/qsyntaxhighlighter.cpp
@@ -65,6 +65,18 @@ public:
void _q_reformatBlocks(int from, int charsRemoved, int charsAdded);
void reformatBlock(QTextBlock block);
+
+ inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) {
+ QObject::disconnect(doc, SIGNAL(contentsChange(int,int,int)),
+ q_func(), SLOT(_q_reformatBlocks(int,int,int)));
+ cursor.beginEditBlock();
+ int from = cursor.position();
+ cursor.movePosition(operation);
+ _q_reformatBlocks(from, 0, cursor.position() - from);
+ cursor.endEditBlock();
+ QObject::connect(doc, SIGNAL(contentsChange(int,int,int)),
+ q_func(), SLOT(_q_reformatBlocks(int,int,int)));
+ }
inline void _q_delayedRehighlight() {
if (!rehighlightPending)
@@ -207,7 +219,7 @@ void QSyntaxHighlighterPrivate::reformatBlock(QTextBlock block)
\since 4.1
- \ingroup text
+ \ingroup richtext-processing
The QSyntaxHighlighter class is a base class for implementing
QTextEdit syntax highlighters. A syntax highligher automatically
@@ -355,7 +367,9 @@ QTextDocument *QSyntaxHighlighter::document() const
/*!
\since 4.2
- Redoes the highlighting of the whole document.
+ Reapplies the highlighting to the whole document.
+
+ \sa rehighlightBlock()
*/
void QSyntaxHighlighter::rehighlight()
{
@@ -363,15 +377,25 @@ void QSyntaxHighlighter::rehighlight()
if (!d->doc)
return;
- disconnect(d->doc, SIGNAL(contentsChange(int,int,int)),
- this, SLOT(_q_reformatBlocks(int,int,int)));
QTextCursor cursor(d->doc);
- cursor.beginEditBlock();
- cursor.movePosition(QTextCursor::End);
- d->_q_reformatBlocks(0, 0, cursor.position());
- cursor.endEditBlock();
- connect(d->doc, SIGNAL(contentsChange(int,int,int)),
- this, SLOT(_q_reformatBlocks(int,int,int)));
+ d->rehighlight(cursor, QTextCursor::End);
+}
+
+/*!
+ \since 4.6
+
+ Reapplies the highlighting to the given QTextBlock \a block.
+
+ \sa rehighlight()
+*/
+void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
+{
+ Q_D(QSyntaxHighlighter);
+ if (!d->doc)
+ return;
+
+ QTextCursor cursor(block);
+ d->rehighlight(cursor, QTextCursor::EndOfBlock);
}
/*!
diff --git a/src/gui/text/qsyntaxhighlighter.h b/src/gui/text/qsyntaxhighlighter.h
index 950f9a4..ecdddba 100644
--- a/src/gui/text/qsyntaxhighlighter.h
+++ b/src/gui/text/qsyntaxhighlighter.h
@@ -78,6 +78,7 @@ public:
public Q_SLOTS:
void rehighlight();
+ void rehighlightBlock(const QTextBlock &block);
protected:
virtual void highlightBlock(const QString &text) = 0;
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 56034c0..7ee0729 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -82,7 +82,7 @@
#include "private/qapplication_p.h"
#include "private/qshortcutmap_p.h"
#include <qkeysequence.h>
-#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1String("\t") + QString(QKeySequence(k)) : QString())
+#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1Char('\t') + QString(QKeySequence(k)) : QString())
#else
#define ACCEL_KEY(k) QString()
#endif
@@ -394,7 +394,7 @@ void QTextControlPrivate::init(Qt::TextFormat format, const QString &text, QText
Q_Q(QTextControl);
setContent(format, text, document);
- QWidget *parentWidget = qobject_cast<QWidget*>(q->parent());
+ QWidget *parentWidget = qobject_cast<QWidget*>(parent);
if (parentWidget) {
QTextOption opt = doc->defaultTextOption();
opt.setTextDirection(parentWidget->layoutDirection());
@@ -1611,6 +1611,9 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF
if (cursor.position() != oldCursorPos)
emit q->cursorPositionChanged();
_q_updateCurrentCharFormatAndSelection();
+ if (QInputContext *ic = inputContext()) {
+ ic->update();
+ }
} else {
//emit q->visibilityRequest(QRectF(mousePos, QSizeF(1, 1)));
if (cursor.position() != oldCursorPos)
@@ -1712,7 +1715,7 @@ void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton butto
selectedWordOnDoubleClick = cursor;
trippleClickPoint = pos;
- trippleClickTimer.start(qApp->doubleClickInterval(), q);
+ trippleClickTimer.start(QApplication::doubleClickInterval(), q);
if (doEmit) {
selectionChanged();
#ifndef QT_NO_CLIPBOARD
@@ -1813,13 +1816,18 @@ bool QTextControlPrivate::dropEvent(const QMimeData *mimeData, const QPointF &po
void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
{
+ Q_Q(QTextControl);
if (!(interactionFlags & Qt::TextEditable) || cursor.isNull()) {
e->ignore();
return;
}
- cursor.beginEditBlock();
+ bool isGettingInput = !e->commitString().isEmpty() || !e->preeditString().isEmpty()
+ || e->replacementLength() > 0;
- cursor.removeSelectedText();
+ if (isGettingInput) {
+ cursor.beginEditBlock();
+ cursor.removeSelectedText();
+ }
// insert commit string
if (!e->commitString().isEmpty() || e->replacementLength()) {
@@ -1829,6 +1837,18 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
c.insertText(e->commitString());
}
+ for (int i = 0; i < e->attributes().size(); ++i) {
+ const QInputMethodEvent::Attribute &a = e->attributes().at(i);
+ if (a.type == QInputMethodEvent::Selection) {
+ QTextCursor oldCursor = cursor;
+ int blockStart = a.start + cursor.block().position();
+ cursor.setPosition(blockStart, QTextCursor::MoveAnchor);
+ cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
+ q->ensureCursorVisible();
+ repaintOldAndNewSelection(oldCursor);
+ }
+ }
+
QTextBlock block = cursor.block();
QTextLayout *layout = block.layout();
layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
@@ -1852,7 +1872,9 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
}
}
layout->setAdditionalFormats(overrides);
- cursor.endEditBlock();
+
+ if (isGettingInput)
+ cursor.endEditBlock();
}
QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
@@ -1865,11 +1887,15 @@ QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
case Qt::ImFont:
return QVariant(d->cursor.charFormat().font());
case Qt::ImCursorPosition:
- return QVariant(d->cursor.selectionEnd() - block.position());
+ return QVariant(d->cursor.position() - block.position());
case Qt::ImSurroundingText:
return QVariant(block.text());
case Qt::ImCurrentSelection:
return QVariant(d->cursor.selectedText());
+ case Qt::ImMaximumTextLength:
+ return QVariant(); // No limit.
+ case Qt::ImAnchorPosition:
+ return QVariant(qBound(0, d->cursor.anchor() - block.position(), block.length()));
default:
return QVariant();
}
@@ -2262,7 +2288,7 @@ void QTextControl::print(QPrinter *printer) const
{
#ifndef QT_NO_PRINTER
Q_D(const QTextControl);
- if (printer && !printer->isValid())
+ if (!printer || !printer->isValid())
return;
QTextDocument *tempDoc = 0;
const QTextDocument *doc = d->doc;
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index ce64223..9aebc64 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -125,7 +125,7 @@ QTextCursorPrivate::AdjustResult QTextCursorPrivate::adjustPosition(int position
void QTextCursorPrivate::setX()
{
- if (priv && priv->isInEditBlock()) {
+ if (priv->isInEditBlock()) {
x = -1; // mark dirty
return;
}
@@ -145,7 +145,6 @@ void QTextCursorPrivate::remove()
{
if (anchor == position)
return;
- priv->beginEditBlock();
currentCharFormat = -1;
int pos1 = position;
int pos2 = adjusted_anchor;
@@ -159,15 +158,18 @@ void QTextCursorPrivate::remove()
// deleting inside table? -> delete only content
QTextTable *table = complexSelectionTable();
if (table) {
+ priv->beginEditBlock();
int startRow, startCol, numRows, numCols;
selectedTableCells(&startRow, &numRows, &startCol, &numCols);
clearCells(table, startRow, startCol, numRows, numCols, op);
+ adjusted_anchor = anchor = position;
+ priv->endEditBlock();
} else {
priv->remove(pos1, pos2-pos1, op);
+ adjusted_anchor = anchor = position;
+ priv->finishEdit();
}
- adjusted_anchor = anchor = position;
- priv->endEditBlock();
}
void QTextCursorPrivate::clearCells(QTextTable *table, int startRow, int startCol, int numRows, int numCols, QTextUndoCommand::Operation op)
@@ -853,9 +855,9 @@ QTextLayout *QTextCursorPrivate::blockLayout(QTextBlock &block) const{
\brief The QTextCursor class offers an API to access and modify QTextDocuments.
- \ingroup text
+ \ingroup richtext-processing
\ingroup shared
- \mainclass
+
Text cursors are objects that are used to access and modify the contents
and underlying structure of text documents via a programming interface
@@ -1291,9 +1293,14 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format
QTextCharFormat format = _format;
format.clearProperty(QTextFormat::ObjectIndex);
- d->priv->beginEditBlock();
+ bool hasEditBlock = false;
+
+ if (d->anchor != d->position) {
+ hasEditBlock = true;
+ d->priv->beginEditBlock();
+ d->remove();
+ }
- d->remove();
if (!text.isEmpty()) {
QTextFormatCollection *formats = d->priv->formatCollection();
int formatIdx = formats->indexForFormat(format);
@@ -1323,6 +1330,11 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format
|| ch == QChar::ParagraphSeparator
|| ch == QLatin1Char('\r')) {
+ if (!hasEditBlock) {
+ hasEditBlock = true;
+ d->priv->beginEditBlock();
+ }
+
if (blockEnd > blockStart)
d->priv->insert(d->position, textStart + blockStart, blockEnd - blockStart, formatIdx);
@@ -1333,7 +1345,8 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format
if (textStart + blockStart < textEnd)
d->priv->insert(d->position, textStart + blockStart, textEnd - textStart - blockStart, formatIdx);
}
- d->priv->endEditBlock();
+ if (hasEditBlock)
+ d->priv->endEditBlock();
d->setX();
}
@@ -1348,12 +1361,15 @@ void QTextCursor::deleteChar()
if (!d || !d->priv)
return;
- if (d->position == d->anchor) {
- if (!d->canDelete(d->position))
- return;
- d->adjusted_anchor = d->anchor =
- d->priv->nextCursorPosition(d->anchor, QTextLayout::SkipCharacters);
+ if (d->position != d->anchor) {
+ removeSelectedText();
+ return;
}
+
+ if (!d->canDelete(d->position))
+ return;
+ d->adjusted_anchor = d->anchor =
+ d->priv->nextCursorPosition(d->anchor, QTextLayout::SkipCharacters);
d->remove();
d->setX();
}
@@ -1368,27 +1384,29 @@ void QTextCursor::deletePreviousChar()
{
if (!d || !d->priv)
return;
-
- if (d->position == d->anchor) {
- if (d->anchor < 1 || !d->canDelete(d->anchor-1))
- return;
- d->anchor--;
-
- QTextDocumentPrivate::FragmentIterator fragIt = d->priv->find(d->anchor);
- const QTextFragmentData * const frag = fragIt.value();
- int fpos = fragIt.position();
- QChar uc = d->priv->buffer().at(d->anchor - fpos + frag->stringPosition);
- if (d->anchor > fpos && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
- // second half of a surrogate, check if we have the first half as well,
- // if yes delete both at once
- uc = d->priv->buffer().at(d->anchor - 1 - fpos + frag->stringPosition);
- if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00)
- --d->anchor;
- }
-
- d->adjusted_anchor = d->anchor;
+
+ if (d->position != d->anchor) {
+ removeSelectedText();
+ return;
}
-
+
+ if (d->anchor < 1 || !d->canDelete(d->anchor-1))
+ return;
+ d->anchor--;
+
+ QTextDocumentPrivate::FragmentIterator fragIt = d->priv->find(d->anchor);
+ const QTextFragmentData * const frag = fragIt.value();
+ int fpos = fragIt.position();
+ QChar uc = d->priv->buffer().at(d->anchor - fpos + frag->stringPosition);
+ if (d->anchor > fpos && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
+ // second half of a surrogate, check if we have the first half as well,
+ // if yes delete both at once
+ uc = d->priv->buffer().at(d->anchor - 1 - fpos + frag->stringPosition);
+ if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00)
+ --d->anchor;
+ }
+
+ d->adjusted_anchor = d->anchor;
d->remove();
d->setX();
}
@@ -1504,7 +1522,9 @@ void QTextCursor::removeSelectedText()
if (!d || !d->priv || d->position == d->anchor)
return;
+ d->priv->beginEditBlock();
d->remove();
+ d->priv->endEditBlock();
d->setX();
}
@@ -1836,6 +1856,8 @@ bool QTextCursor::atStart() const
}
/*!
+ \since 4.6
+
Returns true if the cursor is at the end of the document;
otherwise returns false.
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index e183c5e..1bdaceb 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -247,8 +247,8 @@ QTextCodec *Qt::codecForHtml(const QByteArray &ba)
\brief The QTextDocument class holds formatted text that can be
viewed and edited using a QTextEdit.
- \ingroup text
- \mainclass
+ \ingroup richtext-processing
+
QTextDocument is a container for structured rich text documents, providing
support for styled text and various types of document elements, such as
@@ -2201,7 +2201,7 @@ void QTextHtmlExporter::emitTextLength(const char *attribute, const QTextLength
if (length.type() == QTextLength::PercentageLength)
html += QLatin1String("%\"");
else
- html += QLatin1String("\"");
+ html += QLatin1Char('\"');
}
void QTextHtmlExporter::emitAlignment(Qt::Alignment align)
@@ -2416,7 +2416,10 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
static bool isOrderedList(int style)
{
return style == QTextListFormat::ListDecimal || style == QTextListFormat::ListLowerAlpha
- || style == QTextListFormat::ListUpperAlpha;
+ || style == QTextListFormat::ListUpperAlpha
+ || style == QTextListFormat::ListUpperRoman
+ || style == QTextListFormat::ListLowerRoman
+ ;
}
void QTextHtmlExporter::emitBlockAttributes(const QTextBlock &block)
@@ -2513,6 +2516,8 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block)
case QTextListFormat::ListSquare: html += QLatin1String("<ul type=\"square\""); break;
case QTextListFormat::ListLowerAlpha: html += QLatin1String("<ol type=\"a\""); break;
case QTextListFormat::ListUpperAlpha: html += QLatin1String("<ol type=\"A\""); break;
+ case QTextListFormat::ListLowerRoman: html += QLatin1String("<ol type=\"i\""); break;
+ case QTextListFormat::ListUpperRoman: html += QLatin1String("<ol type=\"I\""); break;
default: html += QLatin1String("<ul"); // ### should not happen
}
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 4ea7a7f..4847235 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -60,6 +60,15 @@ QT_BEGIN_NAMESPACE
#define PMDEBUG if(0) qDebug
+// The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }
+#if !defined(Q_CC_DIAB)
+# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
+ QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6, { a7 }, a8 }
+#else
+# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
+ QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8
+#endif
+
/*
Structure of a document:
@@ -179,6 +188,7 @@ QTextDocumentPrivate::QTextDocumentPrivate()
docChangeOldLength(0),
docChangeLength(0),
framesDirty(true),
+ rtFrame(0),
initialBlockCharFormatIndex(-1) // set correctly later in init()
{
editBlock = 0;
@@ -193,6 +203,8 @@ QTextDocumentPrivate::QTextDocumentPrivate()
undoEnabled = true;
inContentsChange = false;
+ inEdit = false;
+
defaultTextOption.setTabStop(80); // same as in qtextengine.cpp
defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
@@ -207,7 +219,6 @@ QTextDocumentPrivate::QTextDocumentPrivate()
void QTextDocumentPrivate::init()
{
- rtFrame = 0;
framesDirty = false;
bool undoState = undoEnabled;
@@ -230,42 +241,48 @@ void QTextDocumentPrivate::clear()
}
QList<QTextCursorPrivate *>oldCursors = cursors;
- cursors.clear();
- changedCursors.clear();
-
- QMap<int, QTextObject *>::Iterator objectIt = objects.begin();
- while (objectIt != objects.end()) {
- if (*objectIt != rtFrame) {
- delete *objectIt;
- objectIt = objects.erase(objectIt);
- } else {
- ++objectIt;
+ QT_TRY{
+ cursors.clear();
+ changedCursors.clear();
+
+ QMap<int, QTextObject *>::Iterator objectIt = objects.begin();
+ while (objectIt != objects.end()) {
+ if (*objectIt != rtFrame) {
+ delete *objectIt;
+ objectIt = objects.erase(objectIt);
+ } else {
+ ++objectIt;
+ }
}
- }
- // also clear out the remaining root frame pointer
- // (we're going to delete the object further down)
- objects.clear();
+ // also clear out the remaining root frame pointer
+ // (we're going to delete the object further down)
+ objects.clear();
- title.clear();
- undoState = 0;
- truncateUndoStack();
- text = QString();
- unreachableCharacterCount = 0;
- modifiedState = 0;
- modified = false;
- formats = QTextFormatCollection();
- int len = fragments.length();
- fragments.clear();
- blocks.clear();
- cachedResources.clear();
- delete rtFrame;
- init();
- cursors = oldCursors;
- inContentsChange = true;
- q->contentsChange(0, len, 0);
- inContentsChange = false;
- if (lout)
- lout->documentChanged(0, len, 0);
+ title.clear();
+ undoState = 0;
+ truncateUndoStack();
+ text = QString();
+ unreachableCharacterCount = 0;
+ modifiedState = 0;
+ modified = false;
+ formats = QTextFormatCollection();
+ int len = fragments.length();
+ fragments.clear();
+ blocks.clear();
+ cachedResources.clear();
+ delete rtFrame;
+ rtFrame = 0;
+ init();
+ cursors = oldCursors;
+ inContentsChange = true;
+ q->contentsChange(0, len, 0);
+ inContentsChange = false;
+ if (lout)
+ lout->documentChanged(0, len, 0);
+ } QT_CATCH(...) {
+ cursors = oldCursors; // at least recover the cursors
+ QT_RETHROW;
+ }
}
QTextDocumentPrivate::~QTextDocumentPrivate()
@@ -404,9 +421,9 @@ int QTextDocumentPrivate::insertBlock(const QChar &blockSeparator,
int b = blocks.findNode(pos);
QTextBlockData *B = blocks.fragment(b);
- QTextUndoCommand c = { QTextUndoCommand::BlockInserted, true,
- op, charFormat, strPos, pos, { blockFormat },
- B->revision };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockInserted, (editBlock != 0),
+ op, charFormat, strPos, pos, blockFormat,
+ B->revision);
appendUndoItem(c);
Q_ASSERT(undoState == undoStack.size());
@@ -439,20 +456,20 @@ void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format
Q_ASSERT(pos >= 0 && pos < fragments.length());
Q_ASSERT(formats.format(format).isCharFormat());
- beginEditBlock();
+ beginEdit();
insert_string(pos, strPos, strLength, format, QTextUndoCommand::MoveCursor);
if (undoEnabled) {
int b = blocks.findNode(pos);
QTextBlockData *B = blocks.fragment(b);
- QTextUndoCommand c = { QTextUndoCommand::Inserted, true,
- QTextUndoCommand::MoveCursor, format, strPos, pos, { strLength },
- B->revision };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Inserted, (editBlock != 0),
+ QTextUndoCommand::MoveCursor, format, strPos, pos, strLength,
+ B->revision);
appendUndoItem(c);
B->revision = undoState;
Q_ASSERT(undoState == undoStack.size());
}
- endEditBlock();
+ finishEdit();
}
void QTextDocumentPrivate::insert(int pos, const QString &str, int format)
@@ -565,6 +582,7 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
if (pos == to)
return;
+ beginEdit();
const bool needsInsert = to != -1;
#if !defined(QT_NO_DEBUG)
@@ -584,8 +602,6 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
Q_ASSERT(startAndEndInSameFrame || endIsEndOfChildFrame || startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent || isFirstTableCell);
#endif
- beginEditBlock();
-
split(pos);
split(pos+length);
@@ -605,12 +621,12 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
int blockRevision = B->revision;
QTextFragmentData *X = fragments.fragment(x);
- QTextUndoCommand c = { QTextUndoCommand::Removed, true,
- op, X->format, X->stringPosition, key, { X->size_array[0] },
- blockRevision };
- QTextUndoCommand cInsert = { QTextUndoCommand::Inserted, true,
- op, X->format, X->stringPosition, dstKey, { X->size_array[0] },
- blockRevision };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Removed, (editBlock != 0),
+ op, X->format, X->stringPosition, key, X->size_array[0],
+ blockRevision);
+ QT_INIT_TEXTUNDOCOMMAND(cInsert, QTextUndoCommand::Inserted, (editBlock != 0),
+ op, X->format, X->stringPosition, dstKey, X->size_array[0],
+ blockRevision);
if (key+1 != blocks.position(b)) {
// qDebug("remove_string from %d length %d", key, X->size_array[0]);
@@ -648,7 +664,7 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
Q_ASSERT(blocks.length() == fragments.length());
- endEditBlock();
+ finishEdit();
}
void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operation op)
@@ -722,8 +738,8 @@ void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFor
fragment->format = newFormatIdx;
}
- QTextUndoCommand c = { QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
- 0, pos, { length }, 0 };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
+ 0, pos, length, 0);
appendUndoItem(c);
pos += length;
@@ -782,8 +798,8 @@ void QTextDocumentPrivate::setBlockFormat(const QTextBlock &from, const QTextBlo
block(it)->invalidate();
- QTextUndoCommand c = { QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
- 0, it.position(), { 1 }, 0 };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
+ 0, it.position(), 1, 0);
appendUndoItem(c);
if (group != oldGroup) {
@@ -951,14 +967,18 @@ int QTextDocumentPrivate::undoRedo(bool undo)
B->revision = c.revision;
}
- if (undo) {
- if (undoState == 0 || !undoStack[undoState-1].block)
- break;
- } else {
+ if (!undo)
++undoState;
- if (undoState == undoStack.size() || !undoStack[undoState-1].block)
- break;
- }
+
+ bool inBlock = (
+ undoState > 0
+ && undoState < undoStack.size()
+ && undoStack[undoState].block_part
+ && undoStack[undoState-1].block_part
+ && !undoStack[undoState-1].block_end
+ );
+ if (!inBlock)
+ break;
}
undoEnabled = true;
int editPos = -1;
@@ -983,7 +1003,8 @@ void QTextDocumentPrivate::appendUndoItem(QAbstractUndoItem *item)
QTextUndoCommand c;
c.command = QTextUndoCommand::Custom;
- c.block = editBlock != 0;
+ c.block_part = editBlock != 0;
+ c.block_end = 0;
c.operation = QTextUndoCommand::MoveCursor;
c.format = 0;
c.strPos = 0;
@@ -1004,8 +1025,13 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
if (!undoStack.isEmpty() && modified) {
QTextUndoCommand &last = undoStack[undoState - 1];
- if (last.tryMerge(c))
- return;
+
+ if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge
+ || (!c.block_part && !last.block_part)) { // two single undo items => can merge
+
+ if (last.tryMerge(c))
+ return;
+ }
}
if (modifiedState > undoState)
modifiedState = -1;
@@ -1013,6 +1039,9 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
undoState++;
emitUndoAvailable(true);
emitRedoAvailable(false);
+
+ if (!c.block_part)
+ emit document()->undoCommandAdded();
}
void QTextDocumentPrivate::truncateUndoStack()
@@ -1077,22 +1106,33 @@ void QTextDocumentPrivate::joinPreviousEditBlock()
beginEditBlock();
if (undoEnabled && undoState)
- undoStack[undoState - 1].block = true;
+ undoStack[undoState - 1].block_end = false;
}
void QTextDocumentPrivate::endEditBlock()
{
- Q_Q(QTextDocument);
if (--editBlock)
return;
if (undoEnabled && undoState > 0) {
- const bool wasBlocking = undoStack[undoState - 1].block;
- undoStack[undoState - 1].block = false;
- if (wasBlocking)
+ if (undoStack[undoState - 1].block_part) {
+ undoStack[undoState - 1].block_end = true;
emit document()->undoCommandAdded();
+ }
}
+ finishEdit();
+}
+
+void QTextDocumentPrivate::finishEdit()
+{
+ Q_Q(QTextDocument);
+
+ if (editBlock)
+ return;
+
+ inEdit = false;
+
if (framesDirty)
scan_frames(docChangeFrom, docChangeOldLength, docChangeLength);
@@ -1162,7 +1202,7 @@ void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOr
for (int i = 0; i < cursors.size(); ++i) {
QTextCursorPrivate *curs = cursors.at(i);
if (curs->adjustPosition(from, addedOrRemoved, op) == QTextCursorPrivate::CursorMoved) {
- if (editBlock) {
+ if (editBlock || inEdit) {
if (!changedCursors.contains(curs))
changedCursors.append(curs);
} else {
@@ -1279,8 +1319,8 @@ void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format)
if (f)
documentChange(f->firstPosition(), f->lastPosition() - f->firstPosition());
- QTextUndoCommand c = { QTextUndoCommand::GroupFormatChange, true, QTextUndoCommand::MoveCursor, oldFormatIndex,
- 0, 0, { obj->d_func()->objectIndex }, 0 };
+ QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::GroupFormatChange, (editBlock != 0), QTextUndoCommand::MoveCursor, oldFormatIndex,
+ 0, 0, obj->d_func()->objectIndex, 0);
appendUndoItem(c);
endEditBlock();
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index f068477..3c207ff 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -139,7 +139,9 @@ public:
MoveCursor = 1
};
quint16 command;
- quint8 block; ///< All undo commands that have this set to zero/false are combined with the preceding command on undo/redo.
+ uint block_part : 1; // all commands that are part of an undo block (including the first and the last one) have this set to 1
+ uint block_end : 1; // the last command in an undo block has this set to 1.
+ uint block_padding : 6; // padding since block used to be a quint8
quint8 operation;
int format;
quint32 strPos;
@@ -202,6 +204,8 @@ public:
inline void beginEditBlock() { editBlock++; }
void joinPreviousEditBlock();
void endEditBlock();
+ inline void beginEdit() { inEdit = true; }
+ void finishEdit();
inline bool isInEditBlock() const { return editBlock; }
void enableUndoRedo(bool enable);
inline bool isUndoRedoEnabled() const { return undoEnabled; }
@@ -334,8 +338,9 @@ public:
QCss::StyleSheet parsedDefaultStyleSheet;
#endif
int maximumBlockCount;
- bool needsEnsureMaximumBlockCount;
- bool inContentsChange;
+ uint needsEnsureMaximumBlockCount : 1;
+ uint inContentsChange : 1;
+ uint inEdit : 1; // between beginEdit() and finishEdit()
QSizeF pageSize;
QString title;
QString url;
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index d7a59dd..6f89b27 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -54,7 +54,11 @@
QT_BEGIN_NAMESPACE
QTextCopyHelper::QTextCopyHelper(const QTextCursor &_source, const QTextCursor &_destination, bool forceCharFormat, const QTextCharFormat &fmt)
+#if defined(Q_CC_DIAB) // compiler bug
+ : formatCollection(*_destination.d->priv->formatCollection()), originalText((const QString)_source.d->priv->buffer())
+#else
: formatCollection(*_destination.d->priv->formatCollection()), originalText(_source.d->priv->buffer())
+#endif
{
src = _source.d->priv;
dst = _destination.d->priv;
@@ -255,7 +259,7 @@ void QTextDocumentFragmentPrivate::insert(QTextCursor &_cursor) const
\brief The QTextDocumentFragment class represents a piece of formatted text
from a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
\ingroup shared
A QTextDocumentFragment is a fragment of rich text, that can be inserted into
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 074f6db..1e11f80 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -198,8 +198,8 @@ public:
if (v.isNull()) {
return cellPadding;
} else {
- Q_ASSERT(v.type() == QVariant::Double);
- return QFixed::fromReal(v.toDouble() * deviceScale);
+ Q_ASSERT(v.userType() == QVariant::Double || v.userType() == QMetaType::Float);
+ return QFixed::fromReal(v.toReal() * deviceScale);
}
}
@@ -1383,6 +1383,8 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
case QTextListFormat::ListDecimal:
case QTextListFormat::ListLowerAlpha:
case QTextListFormat::ListUpperAlpha:
+ case QTextListFormat::ListLowerRoman:
+ case QTextListFormat::ListUpperRoman:
itemText = static_cast<QTextList *>(object)->itemText(bl);
size.setWidth(fontMetrics.width(itemText));
size.setHeight(fontMetrics.height());
@@ -1426,7 +1428,9 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
switch (style) {
case QTextListFormat::ListDecimal:
case QTextListFormat::ListLowerAlpha:
- case QTextListFormat::ListUpperAlpha: {
+ case QTextListFormat::ListUpperAlpha:
+ case QTextListFormat::ListLowerRoman:
+ case QTextListFormat::ListUpperRoman: {
QTextLayout layout(itemText, font, q->paintDevice());
layout.setCacheEnabled(true);
QTextOption option(Qt::AlignLeft | Qt::AlignAbsolute);
@@ -1990,9 +1994,12 @@ void QTextDocumentLayoutPrivate::positionFloat(QTextFrame *frame, QTextLine *cur
}
}
- if (y + layoutStruct->frameY + fd->size.height > layoutStruct->pageBottom) {
+ bool frameSpansIntoNextPage = (y + layoutStruct->frameY + fd->size.height > layoutStruct->pageBottom);
+ if (frameSpansIntoNextPage && fd->size.height <= layoutStruct->pageHeight) {
layoutStruct->newPage();
y = layoutStruct->y;
+
+ frameSpansIntoNextPage = false;
}
y = findY(y, layoutStruct, fd->size.width);
@@ -2013,6 +2020,11 @@ void QTextDocumentLayoutPrivate::positionFloat(QTextFrame *frame, QTextLine *cur
// qDebug()<< "float positioned at " << fd->position.x << fd->position.y;
fd->layoutDirty = false;
+
+ // If the frame is a table, then positioning it will affect the size if it covers more than
+ // one page, because of page breaks and repeating the header.
+ if (qobject_cast<QTextTable *>(frame) != 0)
+ fd->sizeDirty = frameSpansIntoNextPage;
}
QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo, QFixed parentY)
@@ -2345,6 +2357,10 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QLayoutStru
positionFloat(c);
+ // If the size was made dirty when the position was set, layout again
+ if (cd->sizeDirty)
+ updateRect = layoutFrame(c, layoutFrom, layoutTo);
+
QRectF frameRect(cd->position.toPointF(), cd->size.toSizeF());
if (frameRect == oldFrameRect && updateRect.isValid())
@@ -2500,7 +2516,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
LDEBUG << "layoutBlock from=" << layoutFrom << "to=" << layoutTo;
-// qDebug() << "layoutBlock; width" << layoutStruct->x_right - layoutStruct->x_left << "(maxWidth is btw" << tl->maximumWidth() << ")";
+// qDebug() << "layoutBlock; width" << layoutStruct->x_right - layoutStruct->x_left << "(maxWidth is btw" << tl->maximumWidth() << ')';
if (previousBlockFormat) {
qreal margin = qMax(blockFormat.topMargin(), previousBlockFormat->bottomMargin());
@@ -2597,13 +2613,13 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
// float has been added in the meantime, redo
layoutStruct->pendingFloats.clear();
- if (haveWordOrAnyWrapMode) {
- option.setWrapMode(QTextOption::WrapAnywhere);
- tl->setTextOption(option);
- }
-
line.setLineWidth((right-left).toReal());
if (QFixed::fromReal(line.naturalTextWidth()) > right-left) {
+ if (haveWordOrAnyWrapMode) {
+ option.setWrapMode(QTextOption::WrapAnywhere);
+ tl->setTextOption(option);
+ }
+
layoutStruct->pendingFloats.clear();
// lines min width more than what we have
layoutStruct->y = findY(layoutStruct->y, layoutStruct, QFixed::fromReal(line.naturalTextWidth()));
@@ -2615,12 +2631,13 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
else
right -= text_indent;
line.setLineWidth(qMax<qreal>(line.naturalTextWidth(), (right-left).toReal()));
- }
- if (haveWordOrAnyWrapMode) {
- option.setWrapMode(QTextOption::WordWrap);
- tl->setTextOption(option);
+ if (haveWordOrAnyWrapMode) {
+ option.setWrapMode(QTextOption::WordWrap);
+ tl->setTextOption(option);
+ }
}
+
}
QFixed lineHeight = QFixed::fromReal(line.height());
@@ -3205,18 +3222,16 @@ bool QTextDocumentLayout::contentHasAlignment() const
qreal QTextDocumentLayoutPrivate::scaleToDevice(qreal value) const
{
- QPaintDevice *dev = q_func()->paintDevice();
- if (!dev)
+ if (!paintDevice)
return value;
- return value * dev->logicalDpiY() / qreal(qt_defaultDpi());
+ return value * paintDevice->logicalDpiY() / qreal(qt_defaultDpi());
}
QFixed QTextDocumentLayoutPrivate::scaleToDevice(QFixed value) const
{
- QPaintDevice *dev = q_func()->paintDevice();
- if (!dev)
+ if (!paintDevice)
return value;
- return value * QFixed(dev->logicalDpiY()) / QFixed(qt_defaultDpi());
+ return value * QFixed(paintDevice->logicalDpiY()) / QFixed(qt_defaultDpi());
}
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp
index aa4876e..e5fe6a7 100644
--- a/src/gui/text/qtextdocumentwriter.cpp
+++ b/src/gui/text/qtextdocumentwriter.cpp
@@ -76,7 +76,7 @@ public:
\brief The QTextDocumentWriter class provides a format-independent interface for writing a QTextDocument to files or other devices.
- \ingroup text
+ \ingroup richtext-processing
\ingroup io
To write a document, construct a QTextDocumentWriter object with either a
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 438a6b3..2b84c6c 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -363,7 +363,7 @@ static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiCon
#if (BIDI_DEBUG >= 2)
// qDebug() << "pos=" << current << " dir=" << directions[dir]
// << " current=" << directions[dirCurrent] << " last=" << directions[status.last]
-// << " eor=" << eor << "/" << directions[status.eor]
+// << " eor=" << eor << '/' << directions[status.eor]
// << " sor=" << sor << " lastStrong="
// << directions[status.lastStrong]
// << " level=" << (int)control.level << " override=" << (bool)control.override;
@@ -868,7 +868,7 @@ void QTextEngine::shapeText(int item) const
#if defined(Q_WS_MAC)
shapeTextMac(item);
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WINCE)
shapeTextWithCE(item);
#else
shapeTextWithHarfbuzz(item);
@@ -923,7 +923,7 @@ void QTextEngine::shapeText(int item) const
si.width += glyphs.advances_x[i];
}
-#if defined(Q_OS_WINCE) //TODO
+#if defined(Q_WS_WINCE) //TODO
// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs
// and no reordering.
// also computes logClusters heuristically
@@ -2069,10 +2069,12 @@ void QTextEngine::LayoutData::reallocate(int totalGlyphs)
int newAllocated = space_charAttributes + space_glyphs + space_logClusters;
Q_ASSERT(newAllocated >= allocated);
- void **old_mem = memory;
- memory = (void **)::realloc(memory_on_stack ? 0 : old_mem, newAllocated*sizeof(void *));
- if (memory_on_stack && memory)
- memcpy(memory, old_mem, allocated*sizeof(void *));
+ void **newMem = memory;
+ newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
+ Q_CHECK_PTR(newMem);
+ if (memory_on_stack && newMem)
+ memcpy(newMem, memory, allocated*sizeof(void *));
+ memory = newMem;
memory_on_stack = false;
void **m = memory;
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 340fc99..905bb71 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -581,7 +581,7 @@ private:
void addRequiredBoundaries() const;
void shapeText(int item) const;
void shapeTextWithHarfbuzz(int item) const;
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
void shapeTextWithCE(int item) const;
#endif
#if defined(Q_WS_MAC)
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index ff6af21..7a0d6ae 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
\brief The QTextLength class encapsulates the different types of length
used in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
When we specify a value for the length of an element in a text document,
we often need to provide some other information so that the length is
@@ -89,7 +89,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn Type QTextLength::type() const
- Returns the type of length.
+ Returns the type of this length object.
\sa QTextLength::Type
*/
@@ -129,9 +129,15 @@ QT_BEGIN_NAMESPACE
/*!
\enum QTextLength::Type
- \value VariableLength
- \value FixedLength
- \value PercentageLength
+ This enum describes the different types a length object can
+ have.
+
+ \value VariableLength The width of the object is variable
+ \value FixedLength The width of the object is fixed
+ \value PercentageLength The width of the object is in
+ percentage of the maximum width
+
+ \sa type()
*/
/*!
@@ -142,6 +148,7 @@ QTextLength::operator QVariant() const
return QVariant(QVariant::TextLength, this);
}
+#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &stream, const QTextLength &length)
{
return stream << qint32(length.lengthType) << double(length.fixedValueOrPercentage);
@@ -156,6 +163,7 @@ QDataStream &operator>>(QDataStream &stream, QTextLength &length)
length.lengthType = QTextLength::Type(type);
return stream;
}
+#endif // QT_NO_DATASTREAM
class QTextFormatPrivate : public QSharedData
{
@@ -259,10 +267,11 @@ private:
static uint variantHash(const QVariant &variant)
{
- switch (variant.type()) {
+ switch (variant.userType()) {
case QVariant::Invalid: return 0;
case QVariant::Bool: return variant.toBool();
case QVariant::Int: return variant.toInt();
+ case QMetaType::Float: return static_cast<int>(variant.toFloat());
case QVariant::Double: return static_cast<int>(variant.toDouble());
case QVariant::String: return qHash(variant.toString());
case QVariant::Color: return qHash(qvariant_cast<QColor>(variant).rgb());
@@ -317,7 +326,7 @@ void QTextFormatPrivate::recalcFont() const
f.setFamily(props.at(i).value.toString());
break;
case QTextFormat::FontPointSize:
- f.setPointSizeF(props.at(i).value.toDouble());
+ f.setPointSizeF(props.at(i).value.toReal());
break;
case QTextFormat::FontPixelSize:
f.setPixelSize(props.at(i).value.toInt());
@@ -344,10 +353,10 @@ void QTextFormatPrivate::recalcFont() const
f.setStrikeOut(props.at(i).value.toBool());
break;
case QTextFormat::FontLetterSpacing:
- f.setLetterSpacing(QFont::PercentageSpacing, props.at(i).value.toDouble());
+ f.setLetterSpacing(QFont::PercentageSpacing, props.at(i).value.toReal());
break;
case QTextFormat::FontWordSpacing:
- f.setWordSpacing(props.at(i).value.toDouble());
+ f.setWordSpacing(props.at(i).value.toReal());
break;
case QTextFormat::FontCapitalization:
f.setCapitalization(static_cast<QFont::Capitalization> (props.at(i).value.toInt()));
@@ -374,6 +383,7 @@ void QTextFormatPrivate::recalcFont() const
fontDirty = false;
}
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextFormat &fmt)
{
stream << fmt.format_type << fmt.properties();
@@ -396,6 +406,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
return stream;
}
+#endif // QT_NO_DATASTREAM
/*!
\class QTextFormat
@@ -404,7 +415,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\brief The QTextFormat class provides formatting information for a
QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
\ingroup shared
A QTextFormat is a generic class used for describing the format of
@@ -413,7 +424,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
more useful, and describe the formatting that is applied to
specific parts of the document.
- A format has a \c FormatType which specifies the kinds of thing it
+ A format has a \c FormatType which specifies the kinds of text item it
can format; e.g. a block of text, a list, a table, etc. A format
also has various properties (some specific to particular format
types), as described by the Property enum. Every property has a
@@ -437,30 +448,38 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
associate the format with a QTextObject. It is used to represent
lists, frames, and tables inside the document.
- \sa {Text Processing Classes}
+ \sa {Rich Text Processing}
*/
/*!
\enum QTextFormat::FormatType
- \value InvalidFormat
- \value BlockFormat
- \value CharFormat
- \value ListFormat
- \value TableFormat
- \value FrameFormat
+ This enum describes the text item a QTextFormat object is formatting.
+
+ \value InvalidFormat An invalid format as created by the default
+ constructor
+ \value BlockFormat The object formats a text block
+ \value CharFormat The object formats a single character
+ \value ListFormat The object formats a list
+ \value TableFormat The object formats a table
+ \value FrameFormat The object formats a frame
\value UserFormat
+
+ \sa QTextCharFormat, QTextBlockFormat, QTextListFormat,
+ QTextTableFormat, type()
*/
/*!
\enum QTextFormat::Property
- \value ObjectIndex
+ This enum describes the different properties a format can have.
+
+ \value ObjectIndex The index of the formatted object. See objectIndex().
Paragraph and character properties
- \value CssFloat
+ \value CssFloat How a frame is located relative to the surrounding text
\value LayoutDirection The layout direction of the text in the document
(Qt::LayoutDirection).
@@ -478,25 +497,25 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value BlockRightMargin
\value TextIndent
\value TabPositions Specifies the tab positions. The tab positions are structs of QTextOption::Tab which are stored in
- a QList (internally, in a QList<QVariant>).
+ a QList (internally, in a QList<QVariant>).
\value BlockIndent
\value BlockNonBreakableLines
- \value BlockTrailingHorizontalRulerWidth
+ \value BlockTrailingHorizontalRulerWidth The width of a horizontal ruler element.
Character properties
\value FontFamily
\value FontPointSize
+ \value FontPixelSize
\value FontSizeAdjustment Specifies the change in size given to the fontsize already set using
FontPointSize or FontPixelSize.
+ \value FontFixedPitch
\omitvalue FontSizeIncrement
\value FontWeight
\value FontItalic
\value FontUnderline \e{This property has been deprecated.} Use QTextFormat::TextUnderlineStyle instead.
\value FontOverline
\value FontStrikeOut
- \value FontFixedPitch
- \value FontPixelSize
\value FontCapitalization Specifies the capitalization type that is to be applied to the text.
\value FontLetterSpacing Changes the default spacing between individual letters in the font. The value is
specified in percentage, with 100 as the default value.
@@ -508,7 +527,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\omitvalue FirstFontProperty
\omitvalue LastFontProperty
-
+
\value TextUnderlineColor
\value TextVerticalAlignment
\value TextOutline
@@ -529,7 +548,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value FrameBorder
\value FrameBorderBrush
- \value FrameBorderStyle
+ \value FrameBorderStyle See the \l{QTextFrameFormat::BorderStyle}{BorderStyle} enum.
\value FrameBottomMargin
\value FrameHeight
\value FrameLeftMargin
@@ -561,33 +580,46 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
Selection properties
- \value FullWidthSelection When set on the characterFormat of a selection, the whole width of the text will be shown selected
+ \value FullWidthSelection When set on the characterFormat of a selection,
+ the whole width of the text will be shown selected.
Page break properties
- \value PageBreakPolicy
+ \value PageBreakPolicy Specifies how pages are broken. See the PageBreakFlag enum.
\value UserProperty
+
+ \sa property(), setProperty()
*/
/*!
\enum QTextFormat::ObjectTypes
+ This enum describes what kind of QTextObject this format is associated with.
+
\value NoObject
\value ImageObject
\value TableObject
\value TableCellObject
\value UserObject The first object that can be used for application-specific purposes.
+
+ \sa QTextObject, QTextTable, QTextObject::format()
*/
/*!
\enum QTextFormat::PageBreakFlag
\since 4.2
+ This enum describes how page breaking is performed when printing. It maps to the
+ corresponding css properties.
+
\value PageBreak_Auto The page break is determined automatically depending on the
available space on the current page
\value PageBreak_AlwaysBefore The page is always broken before the paragraph/table
\value PageBreak_AlwaysAfter A new page is always started after the paragraph/table
+
+ \sa QTextBlockFormat::pageBreakPolicy(), QTextFrameFormat::pageBreakPolicy(),
+ PageBreakPolicy
*/
/*!
@@ -821,7 +853,7 @@ bool QTextFormat::boolProperty(int propertyId) const
if (!d)
return false;
const QVariant prop = d->property(propertyId);
- if (prop.type() != QVariant::Bool)
+ if (prop.userType() != QVariant::Bool)
return false;
return prop.toBool();
}
@@ -837,7 +869,7 @@ int QTextFormat::intProperty(int propertyId) const
if (!d)
return 0;
const QVariant prop = d->property(propertyId);
- if (prop.type() != QVariant::Int)
+ if (prop.userType() != QVariant::Int)
return 0;
return prop.toInt();
}
@@ -854,7 +886,7 @@ qreal QTextFormat::doubleProperty(int propertyId) const
if (!d)
return 0.;
const QVariant prop = d->property(propertyId);
- if (prop.type() != QVariant::Double && prop.type() != QMetaType::Float)
+ if (prop.userType() != QVariant::Double && prop.userType() != QMetaType::Float)
return 0.;
return qVariantValue<qreal>(prop);
}
@@ -871,7 +903,7 @@ QString QTextFormat::stringProperty(int propertyId) const
if (!d)
return QString();
const QVariant prop = d->property(propertyId);
- if (prop.type() != QVariant::String)
+ if (prop.userType() != QVariant::String)
return QString();
return prop.toString();
}
@@ -889,7 +921,7 @@ QColor QTextFormat::colorProperty(int propertyId) const
if (!d)
return QColor();
const QVariant prop = d->property(propertyId);
- if (prop.type() != QVariant::Color)
+ if (prop.userType() != QVariant::Color)
return QColor();
return qvariant_cast<QColor>(prop);
}
@@ -906,7 +938,7 @@ QPen QTextFormat::penProperty(int propertyId) const
if (!d)
return QPen(Qt::NoPen);
const QVariant prop = d->property(propertyId);
- if (prop.type() != QVariant::Pen)
+ if (prop.userType() != QVariant::Pen)
return QPen(Qt::NoPen);
return qvariant_cast<QPen>(prop);
}
@@ -923,7 +955,7 @@ QBrush QTextFormat::brushProperty(int propertyId) const
if (!d)
return QBrush(Qt::NoBrush);
const QVariant prop = d->property(propertyId);
- if (prop.type() != QVariant::Brush)
+ if (prop.userType() != QVariant::Brush)
return QBrush(Qt::NoBrush);
return qvariant_cast<QBrush>(prop);
}
@@ -953,13 +985,13 @@ QVector<QTextLength> QTextFormat::lengthVectorProperty(int propertyId) const
if (!d)
return vector;
const QVariant prop = d->property(propertyId);
- if (prop.type() != QVariant::List)
+ if (prop.userType() != QVariant::List)
return vector;
QList<QVariant> propertyList = prop.toList();
for (int i=0; i<propertyList.size(); ++i) {
QVariant var = propertyList.at(i);
- if (var.type() == QVariant::TextLength)
+ if (var.userType() == QVariant::TextLength)
vector.append(qvariant_cast<QTextLength>(var));
}
@@ -968,6 +1000,8 @@ QVector<QTextLength> QTextFormat::lengthVectorProperty(int propertyId) const
/*!
Returns the property specified by the given \a propertyId.
+
+ \sa Property
*/
QVariant QTextFormat::property(int propertyId) const
{
@@ -976,6 +1010,8 @@ QVariant QTextFormat::property(int propertyId) const
/*!
Sets the property specified by the \a propertyId to the given \a value.
+
+ \sa Property
*/
void QTextFormat::setProperty(int propertyId, const QVariant &value)
{
@@ -1003,8 +1039,10 @@ void QTextFormat::setProperty(int propertyId, const QVector<QTextLength> &value)
}
/*!
- Clears the value of the property given by \a propertyId
- */
+ Clears the value of the property given by \a propertyId
+
+ \sa Property
+*/
void QTextFormat::clearProperty(int propertyId)
{
if (!d)
@@ -1016,14 +1054,18 @@ void QTextFormat::clearProperty(int propertyId)
/*!
\fn void QTextFormat::setObjectType(int type)
- Sets the text format's object \a type. See \c{ObjectTypes}.
+ Sets the text format's object type to \a type.
+
+ \sa ObjectTypes, objectType()
*/
/*!
\fn int QTextFormat::objectType() const
- Returns the text format's object type. See \c{ObjectTypes}.
+ Returns the text format's object type.
+
+ \sa ObjectTypes, setObjectType()
*/
@@ -1037,7 +1079,7 @@ int QTextFormat::objectIndex() const
if (!d)
return -1;
const QVariant prop = d->property(ObjectIndex);
- if (prop.type() != QVariant::Int) // ####
+ if (prop.userType() != QVariant::Int) // ####
return -1;
return prop.toInt();
}
@@ -1142,7 +1184,7 @@ bool QTextFormat::operator==(const QTextFormat &rhs) const
\brief The QTextCharFormat class provides formatting information for
characters in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
The character format of text in a document specifies the visual properties
of the text, as well as information about its role in a hypertext document.
@@ -1613,9 +1655,9 @@ void QTextCharFormat::setUnderlineStyle(UnderlineStyle style)
QString QTextCharFormat::anchorName() const
{
QVariant prop = property(AnchorName);
- if (prop.type() == QVariant::StringList)
+ if (prop.userType() == QVariant::StringList)
return prop.toStringList().value(0);
- else if (prop.type() != QVariant::String)
+ else if (prop.userType() != QVariant::String)
return QString();
return prop.toString();
}
@@ -1631,9 +1673,9 @@ QString QTextCharFormat::anchorName() const
QStringList QTextCharFormat::anchorNames() const
{
QVariant prop = property(AnchorName);
- if (prop.type() == QVariant::StringList)
+ if (prop.userType() == QVariant::StringList)
return prop.toStringList();
- else if (prop.type() != QVariant::String)
+ else if (prop.userType() != QVariant::String)
return QStringList();
return QStringList(prop.toString());
}
@@ -1755,7 +1797,7 @@ QFont QTextCharFormat::font() const
\brief The QTextBlockFormat class provides formatting information for
blocks of text in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
A document is composed of a list of blocks, represented by QTextBlock
objects. Each block can contain an item of some kind, such as a
@@ -2046,7 +2088,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
\brief The QTextListFormat class provides formatting information for
lists in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
A list is composed of one or more items, represented as text blocks.
The list's format specifies the appearance of items in the list.
@@ -2075,6 +2117,8 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
\value ListDecimal decimal values in ascending order
\value ListLowerAlpha lower case Latin characters in alphabetical order
\value ListUpperAlpha upper case Latin characters in alphabetical order
+ \value ListLowerRoman lower case roman numerals (supports up to 4999 items only)
+ \value ListUpperRoman upper case roman numerals (supports up to 4999 items only)
\omitvalue ListStyleUndefined
*/
@@ -2111,17 +2155,17 @@ QTextListFormat::QTextListFormat(const QTextFormat &fmt)
/*!
\fn void QTextListFormat::setStyle(Style style)
- Sets the list format's \a style. See \c{Style} for the available styles.
+ Sets the list format's \a style.
- \sa style()
+ \sa style() Style
*/
/*!
\fn Style QTextListFormat::style() const
- Returns the list format's style. See \c{Style}.
+ Returns the list format's style.
- \sa setStyle()
+ \sa setStyle() Style
*/
@@ -2154,7 +2198,7 @@ QTextListFormat::QTextListFormat(const QTextFormat &fmt)
\brief The QTextFrameFormat class provides formatting information for
frames in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
A text frame groups together one or more blocks of text, providing a layer
of structure larger than the paragraph. The format of a frame specifies
@@ -2183,16 +2227,21 @@ QTextListFormat::QTextListFormat(const QTextFormat &fmt)
/*!
\enum QTextFrameFormat::Position
+ This enum describes how a frame is located relative to the surrounding text.
+
\value InFlow
\value FloatLeft
\value FloatRight
+ \sa position() CssFloat
*/
/*!
\enum QTextFrameFormat::BorderStyle
\since 4.3
+ This enum describes different border styles for the text frame.
+
\value BorderStyle_None
\value BorderStyle_Dotted
\value BorderStyle_Dashed
@@ -2205,6 +2254,7 @@ QTextListFormat::QTextListFormat(const QTextFormat &fmt)
\value BorderStyle_Inset
\value BorderStyle_Outset
+ \sa borderStyle() FrameBorderStyle
*/
/*!
@@ -2474,7 +2524,7 @@ qreal QTextFrameFormat::rightMargin() const
\brief The QTextTableFormat class provides formatting information for
tables in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
A table is a group of cells ordered into rows and columns. Each table
contains at least one row and one column. Each cell contains a block.
@@ -2680,7 +2730,7 @@ QTextTableFormat::QTextTableFormat(const QTextFormat &fmt)
\brief The QTextImageFormat class provides formatting information for
images in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
Inline images are represented by an object replacement character
(0xFFFC in Unicode) which has an associated QTextImageFormat. The
@@ -2949,7 +2999,7 @@ QTextTableCellFormat::QTextTableCellFormat(const QTextFormat &fmt)
\brief The QTextTableCellFormat class provides formatting information for
table cells in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
The table cell format of a table cell in a document specifies the visual
properties of the table cell.
@@ -2993,12 +3043,18 @@ int QTextFormatCollection::indexForFormat(const QTextFormat &format)
int idx = formats.size();
formats.append(format);
- QTextFormat &f = formats.last();
- if (!f.d)
- f.d = new QTextFormatPrivate;
- f.d->resolveFont(defaultFnt);
+ QT_TRY{
+ QTextFormat &f = formats.last();
+ if (!f.d)
+ f.d = new QTextFormatPrivate;
+ f.d->resolveFont(defaultFnt);
+
+ hashes.insert(hash);
- hashes.insert(hash);
+ } QT_CATCH(...) {
+ formats.pop_back();
+ QT_RETHROW;
+ }
return idx;
}
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index 1b73ea5..76ab92a 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -76,8 +76,10 @@ class QTextCursor;
class QTextDocument;
class QTextLength;
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextLength &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextLength &);
+#endif
class Q_GUI_EXPORT QTextLength
{
@@ -119,8 +121,10 @@ private:
inline QTextLength::QTextLength(Type atype, qreal avalue)
: lengthType(atype), fixedValueOrPercentage(avalue) {}
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextFormat &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextFormat &);
+#endif
class Q_GUI_EXPORT QTextFormat
{
@@ -600,6 +604,8 @@ public:
ListDecimal = -4,
ListLowerAlpha = -5,
ListUpperAlpha = -6,
+ ListLowerRoman = -7,
+ ListUpperRoman = -8,
ListStyleUndefined = 0
};
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 71db7f8..1e2a94c 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -343,7 +343,7 @@ static QChar resolveEntity(const QString &entity)
return e->code;
}
-static const uint windowsLatin1ExtendedCharacters[0xA0 - 0x80] = {
+static const ushort windowsLatin1ExtendedCharacters[0xA0 - 0x80] = {
0x20ac, // 0x80
0x0081, // 0x81 direct mapping
0x201a, // 0x82
@@ -499,7 +499,7 @@ void QTextHtmlParser::dumpHtml()
{
for (int i = 0; i < count(); ++i) {
qDebug().nospace() << qPrintable(QString(depth(i)*4, QLatin1Char(' ')))
- << qPrintable(at(i).tag) << ":"
+ << qPrintable(at(i).tag) << ':'
<< quoteNewline(at(i).text);
;
}
@@ -1206,6 +1206,8 @@ void QTextHtmlParserNode::setListStyle(const QVector<QCss::Value> &cssValues)
case QCss::Value_Decimal: hasOwnListStyle = true; listStyle = QTextListFormat::ListDecimal; break;
case QCss::Value_LowerAlpha: hasOwnListStyle = true; listStyle = QTextListFormat::ListLowerAlpha; break;
case QCss::Value_UpperAlpha: hasOwnListStyle = true; listStyle = QTextListFormat::ListUpperAlpha; break;
+ case QCss::Value_LowerRoman: hasOwnListStyle = true; listStyle = QTextListFormat::ListLowerRoman; break;
+ case QCss::Value_UpperRoman: hasOwnListStyle = true; listStyle = QTextListFormat::ListUpperRoman; break;
default: break;
}
}
@@ -1441,14 +1443,13 @@ static bool setFloatAttribute(qreal *destination, const QString &value)
static void setWidthAttribute(QTextLength *width, QString value)
{
- qreal realVal;
bool ok = false;
- realVal = value.toDouble(&ok);
+ qreal realVal = value.toDouble(&ok);
if (ok) {
*width = QTextLength(QTextLength::FixedLength, realVal);
} else {
value = value.trimmed();
- if (!value.isEmpty() && value.at(value.length() - 1) == QLatin1Char('%')) {
+ if (!value.isEmpty() && value.endsWith(QLatin1Char('%'))) {
value.chop(1);
realVal = value.toDouble(&ok);
if (ok)
@@ -1540,6 +1541,10 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
node->listStyle = QTextListFormat::ListLowerAlpha;
} else if (value == QLatin1String("A")) {
node->listStyle = QTextListFormat::ListUpperAlpha;
+ } else if (value == QLatin1String("i")) {
+ node->listStyle = QTextListFormat::ListLowerRoman;
+ } else if (value == QLatin1String("I")) {
+ node->listStyle = QTextListFormat::ListUpperRoman;
} else {
value = value.toLower();
if (value == QLatin1String("square"))
diff --git a/src/gui/text/qtextimagehandler_p.h b/src/gui/text/qtextimagehandler_p.h
index 0323726..bc17e9e 100644
--- a/src/gui/text/qtextimagehandler_p.h
+++ b/src/gui/text/qtextimagehandler_p.h
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
class QTextImageFormat;
-class Q_GUI_EXPORT QTextImageHandler : public QObject,
+class QTextImageHandler : public QObject,
public QTextObjectInterface
{
Q_OBJECT
@@ -72,7 +72,7 @@ public:
virtual void drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format);
typedef QImage (*ExternalImageLoaderFunction)(const QString &name, const QString &context);
- static ExternalImageLoaderFunction externalLoader;
+ static Q_GUI_EXPORT ExternalImageLoaderFunction externalLoader; //this is needed by Qt3Support
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index a45aab7..b150f50 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -128,7 +128,7 @@ static QFixed alignLine(QTextEngine *eng, const QScriptLine &line)
\brief The QTextInlineObject class represents an inline object in
a QTextLayout.
- \ingroup text
+ \ingroup richtext-processing
This class is only used if the text layout is used to lay out
parts of a QTextDocument.
@@ -285,7 +285,7 @@ Qt::LayoutDirection QTextInlineObject::textDirection() const
\brief The QTextLayout class is used to lay out and paint a single
paragraph of text.
- \ingroup text
+ \ingroup richtext-processing
It offers most features expected from a modern text layout
engine, including Unicode compliant rendering, line breaking and
@@ -367,7 +367,7 @@ QTextLayout::QTextLayout(const QString& text, const QFont &font, QPaintDevice *p
QFont f(font);
if (paintdevice)
f = QFont(font, paintdevice);
- d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f.d);
+ d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f.d.data());
}
/*!
@@ -1368,7 +1368,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
\brief The QTextLine class represents a line of text inside a QTextLayout.
- \ingroup text
+ \ingroup richtext-processing
A text line is usually created by QTextLayout::createLine().
diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp
index 7617dae..73ec40f 100644
--- a/src/gui/text/qtextlist.cpp
+++ b/src/gui/text/qtextlist.cpp
@@ -63,7 +63,7 @@ public:
\brief The QTextList class provides a decorated list of items in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
A list contains a sequence of text blocks, each of which is marked with a
bullet point or other symbol. Multiple levels of lists can be used, and
@@ -129,8 +129,6 @@ QTextList::~QTextList()
/*!
Returns the number of items in the list.
-
- \sa isEmpty()
*/
int QTextList::count() const
{
@@ -212,6 +210,55 @@ QString QTextList::itemText(const QTextBlock &blockIt) const
}
}
break;
+ case QTextListFormat::ListLowerRoman:
+ case QTextListFormat::ListUpperRoman:
+ {
+ if (item < 5000) {
+ QByteArray romanNumeral;
+
+ // works for up to 4999 items
+ static const char romanSymbolsLower[] = "iiivixxxlxcccdcmmmm";
+ static const char romanSymbolsUpper[] = "IIIVIXXXLXCCCDCMMMM";
+ QByteArray romanSymbols; // wrap to have "mid"
+ if (style == QTextListFormat::ListLowerRoman)
+ romanSymbols = QByteArray::fromRawData(romanSymbolsLower, sizeof(romanSymbolsLower));
+ else
+ romanSymbols = QByteArray::fromRawData(romanSymbolsUpper, sizeof(romanSymbolsUpper));
+
+ int c[] = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
+ int n = item;
+ for (int i = 12; i >= 0; n %= c[i], i--) {
+ int q = n / c[i];
+ if (q > 0) {
+ int startDigit = i + (i+3)/4;
+ int numDigits;
+ if (i % 4) {
+ // c[i] == 4|5|9|40|50|90|400|500|900
+ if ((i-2) % 4) {
+ // c[i] == 4|9|40|90|400|900 => with substraction (IV, IX, XL, XC, ...)
+ numDigits = 2;
+ }
+ else {
+ // c[i] == 5|50|500 (V, L, D)
+ numDigits = 1;
+ }
+ }
+ else {
+ // c[i] == 1|10|100|1000 (I, II, III, X, XX, ...)
+ numDigits = q;
+ }
+
+ romanNumeral.append(romanSymbols.mid(startDigit, numDigits));
+ }
+ }
+ result = QString::fromLatin1(romanNumeral);
+ }
+ else {
+ result = QLatin1String("?");
+ }
+
+ }
+ break;
default:
Q_ASSERT(false);
}
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index 4ad1148..03da6cd 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
\brief The QTextObject class is a base class for different kinds
of objects that can group parts of a QTextDocument together.
- \ingroup text
+ \ingroup richtext-processing
The common grouping text objects are lists (QTextList), frames
(QTextFrame), and tables (QTextTable). A text object has an
@@ -183,7 +183,7 @@ QTextDocumentPrivate *QTextObject::docHandle() const
\brief The QTextBlockGroup class provides a container for text blocks within
a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
Block groups can be used to organize blocks of text within a document.
They maintain an up-to-date list of the text blocks that belong to
@@ -305,7 +305,7 @@ QTextFrameLayoutData::~QTextFrameLayoutData()
\brief The QTextFrame class represents a frame in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
Text frames provide structure for the text in a document. They are used
as generic containers for other document elements.
@@ -599,7 +599,7 @@ void QTextFramePrivate::remove_me()
\brief The iterator class provides an iterator for reading
the contents of a QTextFrame.
- \ingroup text
+ \ingroup richtext-processing
A frame consists of an arbitrary sequence of \l{QTextBlock}s and
child \l{QTextFrame}s. This class provides a way to iterate over the
@@ -799,7 +799,7 @@ QTextFrame::iterator &QTextFrame::iterator::operator--()
\brief The QTextBlockUserData class is used to associate custom data with blocks of text.
\since 4.1
- \ingroup text
+ \ingroup richtext-processing
QTextBlockUserData provides an abstract interface for container classes that are used
to associate application-specific user data with text blocks in a QTextDocument.
@@ -829,7 +829,7 @@ QTextBlockUserData::~QTextBlockUserData()
\brief The QTextBlock class provides a container for text fragments in a
QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
A text block encapsulates a block or paragraph of text in a QTextDocument.
QTextBlock provides read-only access to the block/paragraph structure of
@@ -924,7 +924,7 @@ QTextBlockUserData::~QTextBlockUserData()
\brief The QTextBlock::iterator class provides an iterator for reading
the contents of a QTextBlock.
- \ingroup text
+ \ingroup richtext-processing
A block consists of a sequence of text fragments. This class provides
a way to iterate over these, and read their contents. It does not provide
@@ -1525,7 +1525,7 @@ QTextBlock::iterator &QTextBlock::iterator::operator--()
\brief The QTextFragment class holds a piece of text in a
QTextDocument with a single QTextCharFormat.
- \ingroup text
+ \ingroup richtext-processing
A text fragment describes a piece of text that is stored with a single
character format. Text in which the character format changes can be
diff --git a/src/gui/text/qtextobject_p.h b/src/gui/text/qtextobject_p.h
index f1ace63..83f2523 100644
--- a/src/gui/text/qtextobject_p.h
+++ b/src/gui/text/qtextobject_p.h
@@ -94,8 +94,7 @@ class QTextFramePrivate : public QTextObjectPrivate
Q_DECLARE_PUBLIC(QTextFrame)
public:
QTextFramePrivate(QTextDocument *doc)
- : QTextObjectPrivate(doc), fragment_start(0), fragment_end(0),
- parentFrame(0), layoutData(0)
+ : QTextObjectPrivate(doc), fragment_start(0), fragment_end(0), parentFrame(0), layoutData(0)
{
}
virtual void fragmentAdded(const QChar &type, uint fragment);
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index d2e99bb..ff3d85b 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -174,6 +174,10 @@ static QString bulletChar(QTextListFormat::Style style)
return QString::fromLatin1("a");
case QTextListFormat::ListUpperAlpha:
return QString::fromLatin1("A");
+ case QTextListFormat::ListLowerRoman:
+ return QString::fromLatin1("i");
+ case QTextListFormat::ListUpperRoman:
+ return QString::fromLatin1("I");
default:
case QTextListFormat::ListStyleUndefined:
return QString();
@@ -295,28 +299,13 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
writer.writeAttribute(textNS, QString::fromLatin1("style-name"), QString::fromLatin1("c%1")
.arg(frag.fragment().charFormatIndex()));
bool escapeNextSpace = true;
- int precedingSpaces = 0, precedingTabs = 0;
+ int precedingSpaces = 0;
int exportedIndex = 0;
for (int i=0; i <= fragmentText.count(); ++i) {
- bool isTab = false, isSpace = false;
- if (i < fragmentText.count()) {
+ bool isSpace = false;
QChar character = fragmentText[i];
- isTab = character.unicode() == '\t';
isSpace = character.unicode() == ' ';
- if (character.unicode() == 0x2028) { // soft-return
- writer.writeCharacters(fragmentText.mid(exportedIndex, i));
- writer.writeEmptyElement(textNS, QString::fromLatin1("line-break"));
- exportedIndex = i+1;
- continue;
- }
- if (isSpace) {
- ++precedingSpaces;
- escapeNextSpace = true;
- }
- else if (isTab) {
- precedingTabs++;
- }
- }
+
// find more than one space. -> <text:s text:c="2" />
if (!isSpace && escapeNextSpace && precedingSpaces > 1) {
const bool startParag = exportedIndex == 0 && i == precedingSpaces;
@@ -329,17 +318,27 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
precedingSpaces = 0;
exportedIndex = i;
}
- // find tabs. -> <text:tab text:tab-ref="3" /> or <text:tab/>
- if (!isTab && precedingTabs) {
- writer.writeCharacters(fragmentText.mid(exportedIndex, i - precedingTabs - exportedIndex));
- writer.writeEmptyElement(textNS, QString::fromLatin1("tab"));
- if (precedingTabs > 1)
- writer.writeAttribute(textNS, QString::fromLatin1("tab-ref"), QString::number(precedingTabs));
- precedingTabs = 0;
- exportedIndex = i;
+
+ if (i < fragmentText.count()) {
+ if (character.unicode() == 0x2028) { // soft-return
+ //if (exportedIndex < i)
+ writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
+ writer.writeEmptyElement(textNS, QString::fromLatin1("line-break"));
+ exportedIndex = i+1;
+ continue;
+ } else if (character.unicode() == '\t') { // Tab
+ //if (exportedIndex < i)
+ writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
+ writer.writeEmptyElement(textNS, QString::fromLatin1("tab"));
+ exportedIndex = i+1;
+ precedingSpaces = 0;
+ } else if (isSpace) {
+ ++precedingSpaces;
+ escapeNextSpace = true;
+ } else if (!isSpace) {
+ precedingSpaces = 0;
+ }
}
- if (!isSpace && !isTab)
- precedingSpaces = 0;
}
writer.writeCharacters(fragmentText.mid(exportedIndex));
@@ -477,7 +476,7 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat
if (format.hasProperty(QTextFormat::BlockRightMargin))
writer.writeAttribute(foNS, QString::fromLatin1("margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) );
if (format.hasProperty(QTextFormat::TextIndent))
- writer.writeAttribute(foNS, QString::fromLatin1("text-indent"), QString::number(format.textIndent()));
+ writer.writeAttribute(foNS, QString::fromLatin1("text-indent"), pixelToPoint(format.textIndent()));
if (format.hasProperty(QTextFormat::PageBreakPolicy)) {
if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysBefore)
writer.writeAttribute(foNS, QString::fromLatin1("break-before"), QString::fromLatin1("page"));
@@ -624,7 +623,9 @@ void QTextOdfWriter::writeListFormat(QXmlStreamWriter &writer, QTextListFormat f
QTextListFormat::Style style = format.style();
if (style == QTextListFormat::ListDecimal || style == QTextListFormat::ListLowerAlpha
- || style == QTextListFormat::ListUpperAlpha) {
+ || style == QTextListFormat::ListUpperAlpha
+ || style == QTextListFormat::ListLowerRoman
+ || style == QTextListFormat::ListUpperRoman) {
writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-number"));
writer.writeAttribute(styleNS, QString::fromLatin1("num-format"), bulletChar(style));
writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), QString::fromLatin1("."));
diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp
index a217595..616e76a 100644
--- a/src/gui/text/qtextoption.cpp
+++ b/src/gui/text/qtextoption.cpp
@@ -117,7 +117,13 @@ QTextOption &QTextOption::operator=(const QTextOption &o)
{
if (this == &o)
return *this;
- delete d; d = 0;
+
+ QTextOptionPrivate* dNew = 0;
+ if (o.d)
+ dNew = new QTextOptionPrivate(*o.d);
+ delete d;
+ d = dNew;
+
align = o.align;
wordWrap = o.wordWrap;
design = o.design;
@@ -125,8 +131,6 @@ QTextOption &QTextOption::operator=(const QTextOption &o)
unused = o.unused;
f = o.f;
tab = o.tab;
- if (o.d)
- d = new QTextOptionPrivate(*o.d);
return *this;
}
@@ -197,7 +201,7 @@ QList<QTextOption::Tab> QTextOption::tabs() const
\brief The QTextOption class provides a description of general rich text
properties.
- \ingroup text
+ \ingroup richtext-processing
QTextOption is used to encapsulate common rich text properties in a single
object. It contains information about text alignment, layout direction,
diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp
index 92fa3f4..3f61e300 100644
--- a/src/gui/text/qtexttable.cpp
+++ b/src/gui/text/qtexttable.cpp
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
\brief The QTextTableCell class represents the properties of a
cell in a QTextTable.
- \ingroup text
+ \ingroup richtext-processing
Table cells are pieces of document structure that belong to a table.
The table orders cells into particular rows and columns; cells can
@@ -432,6 +432,13 @@ void QTextTablePrivate::fragmentRemoved(const QChar &type, uint fragment)
QTextFramePrivate::fragmentRemoved(type, fragment);
}
+/*!
+ /fn void QTextTablePrivate::update() const
+
+ This function is usually called when the table is "dirty".
+ It seems to update all kind of table information.
+
+*/
void QTextTablePrivate::update() const
{
Q_Q(const QTextTable);
@@ -439,7 +446,7 @@ void QTextTablePrivate::update() const
nRows = (cells.size() + nCols-1)/nCols;
// qDebug(">>>> QTextTablePrivate::update, nRows=%d, nCols=%d", nRows, nCols);
- grid = (int *)realloc(grid, nRows*nCols*sizeof(int));
+ grid = q_check_ptr((int *)realloc(grid, nRows*nCols*sizeof(int)));
memset(grid, 0, nRows*nCols*sizeof(int));
QTextDocumentPrivate *p = pieceTable;
@@ -463,7 +470,7 @@ void QTextTablePrivate::update() const
cellIndices[i] = cell;
if (r + rowspan > nRows) {
- grid = (int *)realloc(grid, sizeof(int)*(r + rowspan)*nCols);
+ grid = q_check_ptr((int *)realloc(grid, sizeof(int)*(r + rowspan)*nCols));
memset(grid + (nRows*nCols), 0, sizeof(int)*(r+rowspan-nRows)*nCols);
nRows = r + rowspan;
}
@@ -492,7 +499,7 @@ void QTextTablePrivate::update() const
\brief The QTextTable class represents a table in a QTextDocument.
- \ingroup text
+ \ingroup richtext-processing
A table is a group of cells ordered into rows and columns. Each table
contains at least one row and one column. Each cell contains a block, and
diff --git a/src/gui/text/qtexttable_p.h b/src/gui/text/qtexttable_p.h
index 4f4e4a6..15f8aef 100644
--- a/src/gui/text/qtexttable_p.h
+++ b/src/gui/text/qtexttable_p.h
@@ -62,7 +62,7 @@ class QTextTablePrivate : public QTextFramePrivate
{
Q_DECLARE_PUBLIC(QTextTable)
public:
- QTextTablePrivate(QTextDocument *document) : QTextFramePrivate(document), grid(0), nRows(0), dirty(true), blockFragmentUpdates(false) {}
+ QTextTablePrivate(QTextDocument *document) : QTextFramePrivate(document), grid(0), nRows(0), nCols(0), dirty(true), blockFragmentUpdates(false) {}
~QTextTablePrivate();
static QTextTable *createTable(QTextDocumentPrivate *, int pos, int rows, int cols, const QTextTableFormat &tableFormat);
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index 3829490..b01fdb1 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -56,13 +56,23 @@
#if defined(Q_OS_WIN)
#undef S_IFREG
#define S_IFREG 0100000
-# define S_ISDIR(x) ((x) & 0040000) > 0
-# define S_ISREG(x) ((x) & 0170000) == S_IFREG
+# ifndef S_ISDIR
+# define S_ISDIR(x) ((x) & 0040000) > 0
+# endif
+# ifndef S_ISREG
+# define S_ISREG(x) ((x) & 0170000) == S_IFREG
+# endif
# define S_IFLNK 020000
# define S_ISLNK(x) ((x) & S_IFLNK) > 0
-# define S_IRUSR 0400
-# define S_IWUSR 0200
-# define S_IXUSR 0100
+# ifndef S_IRUSR
+# define S_IRUSR 0400
+# endif
+# ifndef S_IWUSR
+# define S_IWUSR 0200
+# endif
+# ifndef S_IXUSR
+# define S_IXUSR 0100
+# endif
# define S_IRGRP 0040
# define S_IWGRP 0020
# define S_IXGRP 0010
@@ -695,7 +705,7 @@ void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const
*/
QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode)
{
- QFile *f = new QFile(archive);
+ QScopedPointer<QFile> f(new QFile(archive));
f->open(mode);
QZipReader::Status status;
if (f->error() == QFile::NoError)
@@ -711,7 +721,8 @@ QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode)
status = FileError;
}
- d = new QZipReaderPrivate(f, /*ownDevice=*/true);
+ d = new QZipReaderPrivate(f.data(), /*ownDevice=*/true);
+ f.take();
d->status = status;
}
@@ -761,7 +772,7 @@ QList<QZipReader::FileInfo> QZipReader::fileInfoList() const
{
d->scanFiles();
QList<QZipReader::FileInfo> files;
- for (int i = 0; d && i < d->fileHeaders.size(); ++i) {
+ for (int i = 0; i < d->fileHeaders.size(); ++i) {
QZipReader::FileInfo fi;
d->fillFileInfo(i, fi);
files.append(fi);
@@ -969,7 +980,7 @@ void QZipReader::close()
*/
QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode)
{
- QFile *f = new QFile(fileName);
+ QScopedPointer<QFile> f(new QFile(fileName));
f->open(mode);
QZipWriter::Status status;
if (f->error() == QFile::NoError)
@@ -985,7 +996,8 @@ QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode)
status = QZipWriter::FileError;
}
- d = new QZipWriterPrivate(f, /*ownDevice=*/true);
+ d = new QZipWriterPrivate(f.data(), /*ownDevice=*/true);
+ f.take();
d->status = status;
}
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index fc33d43..b28ecd7 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -106,9 +106,27 @@ embedded {
DEFINES += QT_NO_FONTCONFIG
}
+symbian {
+ SOURCES += \
+ text/qfont_s60.cpp
+ contains(QT_CONFIG, freetype) {
+ SOURCES += \
+ text/qfontengine_ft.cpp
+ HEADERS += \
+ text/qfontengine_ft_p.h
+ DEFINES += \
+ QT_NO_FONTCONFIG
+ } else {
+ SOURCES += \
+ text/qfontengine_s60.cpp
+ HEADERS += \
+ text/qfontengine_s60_p.h
+ LIBS += -lfntstr -lecom
+ }
+}
+
contains(QT_CONFIG, freetype) {
SOURCES += \
- ../3rdparty/freetype/builds/unix/ftsystem.c \
../3rdparty/freetype/src/base/ftbase.c \
../3rdparty/freetype/src/base/ftbbox.c \
../3rdparty/freetype/src/base/ftdebug.c \
@@ -152,10 +170,19 @@ contains(QT_CONFIG, freetype) {
../3rdparty/freetype/src/autofit/afloader.c\
../3rdparty/freetype/src/autofit/autofit.c
+ symbian {
+ SOURCES += \
+ ../3rdparty/freetype/src/base/ftsystem.c
+ } else {
+ SOURCES += \
+ ../3rdparty/freetype/builds/unix/ftsystem.c
+ INCLUDEPATH += \
+ ../3rdparty/freetype/builds/unix
+ }
+
INCLUDEPATH += \
../3rdparty/freetype/src \
- ../3rdparty/freetype/include \
- ../3rdparty/freetype/builds/unix
+ ../3rdparty/freetype/include
DEFINES += FT2_BUILD_LIBRARY FT_CONFIG_OPTION_SYSTEM_ZLIB
@@ -164,7 +191,7 @@ contains(QT_CONFIG, freetype) {
embedded:CONFIG += opentype
# pull in the proper freetype2 include directory
include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri)
- LIBS += -lfreetype
+ LIBS_PRIVATE += -lfreetype
} else {
DEFINES *= QT_NO_FREETYPE
}
diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp
index 6c10104..6196f0f 100644
--- a/src/gui/util/qcompleter.cpp
+++ b/src/gui/util/qcompleter.cpp
@@ -134,7 +134,7 @@
To provide completions, QCompleter needs to know the path from an index.
This is provided by pathFromIndex(). The default implementation of
- pathFromIndex(), returns the data for the \l{Qt::EditRole}{edit role}
+ pathFromIndex(), returns the data for the \l{Qt::EditRole}{edit role}
for list models and the absolute file path if the mode is a QDirModel.
\sa QAbstractItemModel, QLineEdit, QComboBox, {Completer Example}
@@ -158,7 +158,7 @@ QT_BEGIN_NAMESPACE
QCompletionModel::QCompletionModel(QCompleterPrivate *c, QObject *parent)
: QAbstractProxyModel(*new QCompletionModelPrivate, parent),
- c(c), engine(0), showAll(false)
+ c(c), showAll(false)
{
createEngine();
}
@@ -208,11 +208,10 @@ void QCompletionModel::createEngine()
break;
}
- delete engine;
if (sortedEngine)
- engine = new QSortedModelEngine(c);
+ engine.reset(new QSortedModelEngine(c));
else
- engine = new QUnsortedModelEngine(c);
+ engine.reset(new QUnsortedModelEngine(c));
}
QModelIndex QCompletionModel::mapToSource(const QModelIndex& index) const
@@ -482,7 +481,7 @@ QMatchData QCompletionEngine::filterHistory()
for (int i = 0; i < source->rowCount(); i++) {
QString str = source->index(i, c->column).data().toString();
if (str.startsWith(c->prefix, c->cs)
-#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN)
&& (!dirModel || QDir::toNativeSeparators(str) != QDir::separator())
#endif
)
@@ -772,7 +771,7 @@ QMatchData QUnsortedModelEngine::filter(const QString& part, const QModelIndex&
///////////////////////////////////////////////////////////////////////////////
QCompleterPrivate::QCompleterPrivate()
: widget(0), proxy(0), popup(0), cs(Qt::CaseSensitive), role(Qt::EditRole), column(0),
- sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true)
+ maxVisibleItems(7), sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true)
{
}
@@ -824,6 +823,9 @@ void QCompleterPrivate::_q_complete(QModelIndex index, bool highlighted)
Q_Q(QCompleter);
QString completion;
+ if (!(index.flags() & Qt::ItemIsEnabled))
+ return;
+
if (!index.isValid() || (!proxy->showAll && (index.row() >= proxy->engine->matchCount()))) {
completion = prefix;
} else {
@@ -861,7 +863,7 @@ void QCompleterPrivate::showPopup(const QRect& rect)
Qt::LayoutDirection dir = widget->layoutDirection();
QPoint pos;
int rw, rh, w;
- int h = (popup->sizeHintForRow(0) * qMin(7, popup->model()->rowCount()) + 3) + 3;
+ int h = (popup->sizeHintForRow(0) * qMin(maxVisibleItems, popup->model()->rowCount()) + 3) + 3;
QScrollBar *hsb = popup->horizontalScrollBar();
if (hsb && hsb->isVisible())
h += popup->horizontalScrollBar()->sizeHint().height();
@@ -987,7 +989,7 @@ void QCompleter::setModel(QAbstractItemModel *model)
delete oldModel;
#ifndef QT_NO_DIRMODEL
if (qobject_cast<QDirModel *>(model)) {
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
setCaseSensitivity(Qt::CaseInsensitive);
#else
setCaseSensitivity(Qt::CaseSensitive);
@@ -1102,7 +1104,8 @@ void QCompleter::setPopup(QAbstractItemView *popup)
QObject::connect(popup, SIGNAL(clicked(QModelIndex)),
this, SLOT(_q_complete(QModelIndex)));
- QObject::connect(popup, SIGNAL(clicked(QModelIndex)), popup, SLOT(hide()));
+ QObject::connect(this, SIGNAL(activated(QModelIndex)),
+ popup, SLOT(hide()));
QObject::connect(popup->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(_q_completionSelected(QItemSelection)));
@@ -1182,7 +1185,7 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e)
case Qt::Key_Up:
if (!curIndex.isValid()) {
int rowCount = d->proxy->rowCount();
- QModelIndex lastIndex = d->proxy->index(rowCount - 1, 0);
+ QModelIndex lastIndex = d->proxy->index(rowCount - 1, d->column);
d->setCurrentIndex(lastIndex);
return true;
} else if (curIndex.row() == 0) {
@@ -1194,7 +1197,7 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e)
case Qt::Key_Down:
if (!curIndex.isValid()) {
- QModelIndex firstIndex = d->proxy->index(0, 0);
+ QModelIndex firstIndex = d->proxy->index(0, d->column);
d->setCurrentIndex(firstIndex);
return true;
} else if (curIndex.row() == d->proxy->rowCount() - 1) {
@@ -1510,6 +1513,30 @@ bool QCompleter::wrapAround() const
}
/*!
+ \property QCompleter::maxVisibleItems
+ \brief the maximum allowed size on screen of the completer, measured in items
+ \since 4.6
+
+ By default, this property has a value of 7.
+*/
+int QCompleter::maxVisibleItems() const
+{
+ Q_D(const QCompleter);
+ return d->maxVisibleItems;
+}
+
+void QCompleter::setMaxVisibleItems(int maxItems)
+{
+ Q_D(QCompleter);
+ if (maxItems < 0) {
+ qWarning("QCompleter::setMaxVisibleItems: "
+ "Invalid max visible items (%d) must be >= 0", maxItems);
+ return;
+ }
+ d->maxVisibleItems = maxItems;
+}
+
+/*!
\property QCompleter::caseSensitivity
\brief the case sensitivity of the matching
@@ -1582,6 +1609,10 @@ QString QCompleter::currentCompletion() const
that contains all the possible matches for the current completion prefix.
The completion model is auto-updated to reflect the current completions.
+ \note The return value of this function is defined to be an QAbstractItemModel
+ purely for generality. This actual kind of model returned is an instance of an
+ QAbstractProxyModel subclass.
+
\sa completionPrefix, model()
*/
QAbstractItemModel *QCompleter::completionModel() const
@@ -1624,7 +1655,7 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const
idx = parent.sibling(parent.row(), index.column());
} while (idx.isValid());
-#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN)
if (list.count() == 1) // only the separator or some other text
return list[0];
list[0].clear() ; // the join below will provide the separator
@@ -1658,7 +1689,10 @@ QStringList QCompleter::splitPath(const QString& path) const
QString pathCopy = QDir::toNativeSeparators(path);
QString sep = QDir::separator();
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_SYMBIAN)
+ if (pathCopy == QLatin1String("\\"))
+ return QStringList(pathCopy);
+#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\"))
return QStringList(pathCopy);
QString doubleSlash(QLatin1String("\\\\"));
@@ -1668,10 +1702,12 @@ QStringList QCompleter::splitPath(const QString& path) const
doubleSlash.clear();
#endif
- QRegExp re(QLatin1String("[") + QRegExp::escape(sep) + QLatin1String("]"));
+ QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']'));
QStringList parts = pathCopy.split(re);
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_SYMBIAN)
+ // Do nothing
+#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
if (!doubleSlash.isEmpty())
parts[0].prepend(doubleSlash);
#else
diff --git a/src/gui/util/qcompleter.h b/src/gui/util/qcompleter.h
index 5be2fed..abfba25 100644
--- a/src/gui/util/qcompleter.h
+++ b/src/gui/util/qcompleter.h
@@ -69,6 +69,7 @@ class Q_GUI_EXPORT QCompleter : public QObject
Q_PROPERTY(CompletionMode completionMode READ completionMode WRITE setCompletionMode)
Q_PROPERTY(int completionColumn READ completionColumn WRITE setCompletionColumn)
Q_PROPERTY(int completionRole READ completionRole WRITE setCompletionRole)
+ Q_PROPERTY(int maxVisibleItems READ maxVisibleItems WRITE setMaxVisibleItems)
Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity)
Q_PROPERTY(bool wrapAround READ wrapAround WRITE setWrapAround)
@@ -118,6 +119,9 @@ public:
bool wrapAround() const;
+ int maxVisibleItems() const;
+ void setMaxVisibleItems(int maxItems);
+
int completionCount() const;
bool setCurrentRow(int row);
int currentRow() const;
diff --git a/src/gui/util/qcompleter_p.h b/src/gui/util/qcompleter_p.h
index 758d4de..f0204bf 100644
--- a/src/gui/util/qcompleter_p.h
+++ b/src/gui/util/qcompleter_p.h
@@ -87,6 +87,7 @@ public:
Qt::CaseSensitivity cs;
int role;
int column;
+ int maxVisibleItems;
QCompleter::ModelSorting sorting;
bool wrap;
@@ -213,7 +214,6 @@ class QCompletionModel : public QAbstractProxyModel
public:
QCompletionModel(QCompleterPrivate *c, QObject *parent);
- ~QCompletionModel() { delete engine; }
void createEngine();
void setFiltered(bool);
@@ -236,7 +236,7 @@ public:
QModelIndex mapFromSource(const QModelIndex& sourceIndex) const;
QCompleterPrivate *c;
- QCompletionEngine *engine;
+ QScopedPointer<QCompletionEngine> engine;
bool showAll;
Q_DECLARE_PRIVATE(QCompletionModel)
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 48d2f17..76f583d 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -53,6 +53,8 @@
#include "qdesktopservices_win.cpp"
#elif defined(Q_WS_MAC)
#include "qdesktopservices_mac.cpp"
+#elif defined(Q_OS_SYMBIAN)
+#include "qdesktopservices_s60.cpp"
#endif
#include <qhash.h>
@@ -286,6 +288,12 @@ void QDesktopServices::unsetUrlHandler(const QString &scheme)
\note The storage location returned can be a directory that does not exist; i.e., it
may need to be created by the system or the user.
+ \note On Symbian OS, ApplicationsLocation always point /sys/bin folder on the same drive
+ with executable. FontsLocation always points to folder on ROM drive. Symbian OS does not
+ have desktop concept, DesktopLocation returns same path as DocumentsLocation.
+ Rest of the standard locations point to folder on same drive with executable, except
+ that if executable is in ROM the folder from C drive is returned.
+
\note On Mac OS X, DataLocation does not include QCoreApplication::organizationName.
Use code like this to add it:
diff --git a/src/gui/util/qdesktopservices_mac.cpp b/src/gui/util/qdesktopservices_mac.cpp
index f2fa550..4d932f6 100644
--- a/src/gui/util/qdesktopservices_mac.cpp
+++ b/src/gui/util/qdesktopservices_mac.cpp
@@ -96,7 +96,7 @@ OSType translateLocation(QDesktopServices::StandardLocation type)
static bool lsOpen(const QUrl &url)
{
- if (!url.isValid())
+ if (!url.isValid() || url.scheme().isEmpty())
return false;
QCFType<CFURLRef> cfUrl = CFURLCreateWithString(0, QCFString(QString::fromLatin1(url.toEncoded())), 0);
@@ -134,13 +134,15 @@ static QString getFullPath(const FSRef &ref)
QString QDesktopServices::storageLocation(StandardLocation type)
{
- if (QDesktopServices::HomeLocation == type)
+ if (type == HomeLocation)
return QDir::homePath();
+ if (type == TempLocation)
+ return QDir::tempPath();
+
short domain = kOnAppropriateDisk;
- if (QDesktopServices::DataLocation == type
- || QDesktopServices::CacheLocation == type)
+ if (type == DataLocation || type == CacheLocation)
domain = kUserDomain;
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
@@ -152,9 +154,8 @@ QString QDesktopServices::storageLocation(StandardLocation type)
QString path = getFullPath(ref);
QString appName = QCoreApplication::applicationName();
- if (!appName.isEmpty() &&
- (QDesktopServices::DataLocation == type || QDesktopServices::CacheLocation == type))
- path += QLatin1String("/") + appName;
+ if (!appName.isEmpty() && (type == DataLocation || type == CacheLocation))
+ path += QLatin1Char('/') + appName;
return path;
}
diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp
new file mode 100644
index 0000000..f171390
--- /dev/null
+++ b/src/gui/util/qdesktopservices_s60.cpp
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This flag changes the implementation to use S60 CDcoumentHandler
+// instead of apparch when opening the files
+#undef USE_DOCUMENTHANDLER
+
+#include <qcoreapplication.h>
+#include <qdir.h>
+#include <qurl.h>
+#include <private/qcore_symbian_p.h>
+
+#include <miutset.h> // KUidMsgTypeSMTP
+#include <txtrich.h> // CRichText
+#include <f32file.h> // TDriveUnit etc
+#include <eikenv.h> // CEikonEnv
+#include <apgcli.h> // RApaLsSession
+#include <apgtask.h> // TApaTaskList, TApaTask
+#include <rsendas.h> // RSendAs
+#include <rsendasmessage.h> // RSendAsMessage
+
+#ifdef Q_WS_S60
+# include <pathinfo.h> // PathInfo
+# ifdef USE_DOCUMENTHANDLER
+# include <documenthandler.h> // CDocumentHandler
+# endif
+#elif defined(USE_DOCUMENTHANDLER)
+# error CDocumentHandler requires support for S60
+#endif
+
+QT_BEGIN_NAMESPACE
+
+_LIT(KCacheSubDir, "Cache\\");
+_LIT(KSysBin, "\\Sys\\Bin\\");
+_LIT(KTempDir, "\\System\\Temp\\");
+_LIT(KBrowserPrefix, "4 " );
+_LIT(KFontsDir, "z:\\resource\\Fonts\\");
+const TUid KUidBrowser = { 0x10008D39 };
+
+template<class R>
+class QAutoClose
+{
+public:
+ QAutoClose(R& aObj) : mPtr(&aObj) {}
+ ~QAutoClose()
+ {
+ if (mPtr)
+ mPtr->Close();
+ }
+ void Forget()
+ {
+ mPtr = 0;
+ }
+private:
+ QAutoClose(const QAutoClose&);
+ QAutoClose& operator=(const QAutoClose&);
+private:
+ R* mPtr;
+};
+
+static void handleMailtoSchemeLX(const QUrl &url)
+{
+ // this function has many intermingled leaves and throws. Qt and Symbian objects do not have
+ // destructor dependencies, and cleanup object is used to prevent cleanup stack dependency on stack.
+ QString recipient = url.path();
+ QString subject = url.queryItemValue("subject");
+ QString body = url.queryItemValue("body");
+ QString to = url.queryItemValue("to");
+ QString cc = url.queryItemValue("cc");
+ QString bcc = url.queryItemValue("bcc");
+
+ // these fields might have comma separated addresses
+ QStringList recipients = recipient.split(",", QString::SkipEmptyParts);
+ QStringList tos = to.split(",", QString::SkipEmptyParts);
+ QStringList ccs = cc.split(",", QString::SkipEmptyParts);
+ QStringList bccs = bcc.split(",", QString::SkipEmptyParts);
+
+
+ RSendAs sendAs;
+ User::LeaveIfError(sendAs.Connect());
+ QAutoClose<RSendAs> sendAsCleanup(sendAs);
+
+
+ CSendAsAccounts* accounts = CSendAsAccounts::NewL();
+ CleanupStack::PushL(accounts);
+ sendAs.AvailableAccountsL(KUidMsgTypeSMTP, *accounts);
+ TInt count = accounts->Count();
+ CleanupStack::PopAndDestroy(accounts);
+
+ if(!count) {
+ // TODO: Task 259192: We should try to create account if count == 0
+ // CSendUi would provide account creation service for us, but it requires ridicilous
+ // capabilities: LocalServices NetworkServices ReadDeviceData ReadUserData WriteDeviceData WriteUserData
+ User::Leave(KErrNotSupported);
+ } else {
+ RSendAsMessage sendAsMessage;
+ sendAsMessage.CreateL(sendAs, KUidMsgTypeSMTP);
+ QAutoClose<RSendAsMessage> sendAsMessageCleanup(sendAsMessage);
+
+
+ // Subject
+ sendAsMessage.SetSubjectL(qt_QString2TPtrC(subject));
+
+ // Body
+ sendAsMessage.SetBodyTextL(qt_QString2TPtrC(body));
+
+ // To
+ foreach(QString item, recipients)
+ sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);
+
+ foreach(QString item, tos)
+ sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);
+
+ // Cc
+ foreach(QString item, ccs)
+ sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientCc);
+
+ // Bcc
+ foreach(QString item, bccs)
+ sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientBcc);
+
+ // send the message
+ sendAsMessage.LaunchEditorAndCloseL();
+ // sendAsMessage is already closed
+ sendAsMessageCleanup.Forget();
+ }
+}
+
+static bool handleMailtoScheme(const QUrl &url)
+{
+ TRAPD(err, QT_TRYCATCH_LEAVING(handleMailtoSchemeLX(url)));
+ return err ? false : true;
+}
+
+static void handleOtherSchemesL(const TDesC& aUrl)
+{
+ // Other schemes are at the moment passed to WEB browser
+ HBufC* buf16 = HBufC::NewLC(aUrl.Length() + KBrowserPrefix.iTypeLength);
+ buf16->Des().Copy(KBrowserPrefix); // Prefix used to launch correct browser view
+ buf16->Des().Append(aUrl);
+
+ TApaTaskList taskList(CEikonEnv::Static()->WsSession());
+ TApaTask task = taskList.FindApp(KUidBrowser);
+ if (task.Exists()){
+ // Switch to existing browser instance
+ HBufC8* param8 = HBufC8::NewLC(buf16->Length());
+ param8->Des().Append(buf16->Des());
+ task.SendMessage(TUid::Uid( 0 ), *param8); // Uid is not used
+ CleanupStack::PopAndDestroy(param8);
+ } else {
+ // Start a new browser instance
+ RApaLsSession appArcSession;
+ User::LeaveIfError(appArcSession.Connect());
+ CleanupClosePushL<RApaLsSession>(appArcSession);
+ TThreadId id;
+ appArcSession.StartDocument(*buf16, KUidBrowser, id);
+ CleanupStack::PopAndDestroy(); // appArcSession
+ }
+
+ CleanupStack::PopAndDestroy(buf16);
+}
+
+static bool handleOtherSchemes(const QUrl &url)
+{
+ QString encUrl(url.toEncoded());
+ TPtrC urlPtr(qt_QString2TPtrC(encUrl));
+ TRAPD( err, handleOtherSchemesL(urlPtr));
+ return err ? false : true;
+}
+
+static TDriveUnit exeDrive()
+{
+ RProcess me;
+ TFileName processFileName = me.FileName();
+ TDriveUnit drive(processFileName);
+ return drive;
+}
+
+static TDriveUnit writableExeDrive()
+{
+ TDriveUnit drive = exeDrive();
+ if(drive.operator TInt() == EDriveZ)
+ return TDriveUnit(EDriveC);
+ return drive;
+}
+
+static TPtrC writableDataRoot()
+{
+ TDriveUnit drive = exeDrive();
+#ifdef Q_WS_S60
+ switch(drive.operator TInt()){
+ case EDriveC:
+ return PathInfo::PhoneMemoryRootPath();
+ break;
+ case EDriveE:
+ return PathInfo::MemoryCardRootPath();
+ break;
+ case EDriveZ:
+ // It is not possible to write on ROM drive ->
+ // return phone mem root path instead
+ return PathInfo::PhoneMemoryRootPath();
+ break;
+ default:
+ return PathInfo::PhoneMemoryRootPath();
+ break;
+ }
+#else
+#warning No fallback implementation of writableDataRoot()
+ return 0;
+#endif
+}
+
+static void openDocumentL(const TDesC& aUrl)
+{
+#ifndef USE_DOCUMENTHANDLER
+ // Start app associated to file MIME type by using RApaLsSession
+ // Apparc base method cannot be used to open app in embedded mode,
+ // but seems to be most stable way at the moment
+ RApaLsSession appArcSession;
+ User::LeaveIfError(appArcSession.Connect());
+ CleanupClosePushL<RApaLsSession>(appArcSession);
+ TThreadId id;
+ // ESwitchFiles means do not start another instance
+ // Leaves if file does not exist, leave is trapped in openDocument and false returned to user.
+ User::LeaveIfError(appArcSession.StartDocument(aUrl, id,
+ RApaLsSession::ESwitchFiles)); // ELaunchNewApp
+ CleanupStack::PopAndDestroy(); // appArcSession
+#else
+ // This is an alternative way to launch app associated to MIME type
+ // CDocumentHandler would support opening apps in embedded mode,
+ // but our Qt application window group seems to always get switched on top of embedded one
+ // -> Cannot use menus etc of embedded app -> used
+
+ CDocumentHandler* docHandler = CDocumentHandler::NewLC();
+ TDataType temp;
+ //Standalone file opening fails for some file-types at least in S60 3.1 emulator
+ //For example .txt file fails with KErrAlreadyInUse and music files with KERN-EXEC 0
+ //Workaround is to use OpenFileEmbeddedL
+ //docHandler->OpenFileL(aUrl, temp);
+
+ // Opening file with CDocumentHandler will leave if file does not exist
+ // Leave is trapped in openDocument and false returned to user.
+ docHandler->OpenFileEmbeddedL(aUrl, temp);
+ CleanupStack::PopAndDestroy(docHandler);
+#endif
+}
+
+#ifdef USE_SCHEMEHANDLER
+// The schemehandler component only exist in private SDK. This implementation
+// exist here just for convenience in case that we need to use it later on
+// The schemehandle based implementation is not yet tested.
+
+// The biggest advantage of schemehandler is that it can handle
+// wide range of schemes and is extensible by plugins
+static bool handleUrl(const QUrl &url)
+{
+ if (!url.isValid())
+ return false;
+
+ QString urlString(url.toString());
+ TPtrC urlPtr(qt_QString2TPtrC(urlString));
+ TRAPD( err, handleUrlL(urlPtr));
+ return err ? false : true;
+}
+
+static void handleUrlL(const TDesC& aUrl)
+{
+ CSchemeHandler* schemeHandler = CSchemeHandler::NewL(aUrl);
+ CleanupStack::PushL(schemeHandler);
+ schemeHandler->HandleUrlStandaloneL(); // Process the Url in standalone mode
+ CleanupStack::PopAndDestroy();
+}
+static bool launchWebBrowser(const QUrl &url)
+{
+ return handleUrl(url);
+}
+
+static bool openDocument(const QUrl &file)
+{
+ return handleUrl(url);
+}
+#endif
+
+static bool launchWebBrowser(const QUrl &url)
+{
+ if (!url.isValid())
+ return false;
+
+ if (url.scheme() == QLatin1String("mailto")) {
+ return handleMailtoScheme(url);
+ }
+ return handleOtherSchemes( url );
+}
+
+static bool openDocument(const QUrl &file)
+{
+ if (!file.isValid())
+ return false;
+
+ QString filePath = file.toLocalFile();
+ filePath = QDir::toNativeSeparators(filePath);
+ TPtrC filePathPtr(qt_QString2TPtrC(filePath));
+ TRAPD(err, openDocumentL(filePathPtr));
+ return err ? false : true;
+}
+
+QString QDesktopServices::storageLocation(StandardLocation type)
+{
+ TFileName path;
+
+ switch (type) {
+ case DesktopLocation:
+ qWarning("No desktop concept in Symbian OS");
+ // But lets still use some feasible default
+ path.Append(writableDataRoot());
+ break;
+ case DocumentsLocation:
+ path.Append(writableDataRoot());
+ break;
+ case FontsLocation:
+ path.Append(KFontsDir);
+ break;
+ case ApplicationsLocation:
+ path.Append(exeDrive().Name());
+ path.Append(KSysBin);
+ break;
+ case MusicLocation:
+ path.Append(writableDataRoot());
+#ifdef Q_WS_S60
+ path.Append(PathInfo::SoundsPath());
+#endif
+ break;
+ case MoviesLocation:
+ path.Append(writableDataRoot());
+#ifdef Q_WS_S60
+ path.Append(PathInfo::VideosPath());
+#endif
+ break;
+ case PicturesLocation:
+ path.Append(writableDataRoot());
+#ifdef Q_WS_S60
+ path.Append(PathInfo::ImagesPath());
+#endif
+ break;
+ case TempLocation:
+ path.Append(writableExeDrive().Name());
+ path.Append(KTempDir);
+ //return QDir::tempPath(); break;
+ break;
+ case HomeLocation:
+ path.Append(writableDataRoot());
+ //return QDir::homePath(); break;
+ break;
+ case DataLocation:
+ CEikonEnv::Static()->FsSession().PrivatePath(path);
+ path.Insert(0, writableExeDrive().Name());
+ break;
+ case CacheLocation:
+ CEikonEnv::Static()->FsSession().PrivatePath(path);
+ path.Insert(0, writableExeDrive().Name());
+ path.Append(KCacheSubDir);
+ break;
+ default:
+ // Lets use feasible default
+ path.Append(writableDataRoot());
+ break;
+ }
+
+ // Convert to cross-platform format and clean the path
+ QString nativePath = QString::fromUtf16(path.Ptr(), path.Length());
+ QString qtPath = QDir::fromNativeSeparators(nativePath);
+ qtPath = QDir::cleanPath(qtPath);
+
+ // Note: The storage location returned can be a directory that does not exist;
+ // i.e., it may need to be created by the system or the user.
+ return qtPath;
+}
+
+typedef QString (*LocalizerFunc)(QString&);
+
+static QString defaultLocalizedDirectoryName(QString&)
+{
+ return QString();
+}
+
+QString QDesktopServices::displayName(StandardLocation type)
+{
+ static LocalizerFunc ptrLocalizerFunc = NULL;
+
+ if (!ptrLocalizerFunc) {
+ ptrLocalizerFunc = reinterpret_cast<LocalizerFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_LocalizedDirectoryName));
+ if (!ptrLocalizerFunc)
+ ptrLocalizerFunc = &defaultLocalizedDirectoryName;
+ }
+
+ QString rawPath = storageLocation(type);
+ return ptrLocalizerFunc(rawPath);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp
index 341e914..eaaab7d 100644
--- a/src/gui/util/qdesktopservices_win.cpp
+++ b/src/gui/util/qdesktopservices_win.cpp
@@ -47,7 +47,7 @@
#include <qtemporaryfile.h>
#include <qcoreapplication.h>
-#include <windows.h>
+#include <qt_windows.h>
#include <shlobj.h>
#if !defined(Q_OS_WINCE)
# include <intshcut.h>
@@ -62,33 +62,25 @@
QT_BEGIN_NAMESPACE
-//#undef UNICODE
-
static bool openDocument(const QUrl &file)
{
if (!file.isValid())
return false;
-
- quintptr returnValue;
- QT_WA({
- returnValue = (quintptr)ShellExecute(0, 0, (TCHAR *)file.toString().utf16(), 0, 0, SW_SHOWNORMAL);
- } , {
- returnValue = (quintptr)ShellExecuteA(0, 0, file.toString().toLocal8Bit().constData(), 0, 0, SW_SHOWNORMAL);
- });
+ QString filePath = file.toLocalFile();
+ if (filePath.isEmpty())
+ filePath = file.toString();
+ quintptr returnValue = (quintptr)ShellExecute(0, 0, (wchar_t*)filePath.utf16(), 0, 0, SW_SHOWNORMAL);
return (returnValue > 32); //ShellExecute returns a value greater than 32 if successful
}
static QString expandEnvStrings(const QString &command)
{
-
#if defined(Q_OS_WINCE)
return command;
#else
- QByteArray path = command.toLocal8Bit();
- char commandValue[2 * MAX_PATH] = {0};
- DWORD returnValue = ExpandEnvironmentStringsA(path.data(), commandValue, MAX_PATH);
- if (returnValue)
- return QString::fromLocal8Bit(commandValue);
+ wchar_t buffer[MAX_PATH];
+ if (ExpandEnvironmentStrings((wchar_t*)command.utf16(), buffer, MAX_PATH))
+ return QString::fromWCharArray(buffer);
else
return command;
#endif
@@ -98,36 +90,40 @@ static bool launchWebBrowser(const QUrl &url)
{
if (url.scheme() == QLatin1String("mailto")) {
//Retrieve the commandline for the default mail client
- //the key used below is the command line for the mailto: shell command
+ //the default key used below is the command line for the mailto: shell command
DWORD bufferSize = 2 * MAX_PATH;
long returnValue = -1;
QString command;
HKEY handle;
LONG res;
- QT_WA ({
- res = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"mailto\\Shell\\Open\\Command", 0, KEY_READ, &handle);
- if (res != ERROR_SUCCESS)
- return false;
-
- wchar_t keyValue[2 * MAX_PATH] = {0};
- returnValue = RegQueryValueExW(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
- if (!returnValue)
- command = QString::fromRawData((QChar*)keyValue, bufferSize);
- }, {
- res = RegOpenKeyExA(HKEY_CLASSES_ROOT, "mailto\\Shell\\Open\\Command", 0, KEY_READ, &handle);
- if (res != ERROR_SUCCESS)
- return false;
-
- char keyValue[2 * MAX_PATH] = {0};
- returnValue = RegQueryValueExA(handle, "", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
+ wchar_t keyValue[2 * MAX_PATH] = {0};
+ QString keyName(QLatin1String("mailto"));
+
+ //Check if user has set preference, otherwise use default.
+ res = RegOpenKeyExW(HKEY_CURRENT_USER,
+ L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\mailto\\UserChoice",
+ 0, KEY_READ, &handle);
+ if (res == ERROR_SUCCESS) {
+ returnValue = RegQueryValueEx(handle, L"Progid", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
if (!returnValue)
- command = QString::fromLocal8Bit(keyValue);
- });
+ keyName = QString::fromUtf16((const ushort*)keyValue);
+ RegCloseKey(handle);
+ }
+ keyName += QLatin1String("\\Shell\\Open\\Command");
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, (const wchar_t*)keyName.utf16(), 0, KEY_READ, &handle);
+ if (res != ERROR_SUCCESS)
+ return false;
+
+ bufferSize = 2 * MAX_PATH;
+ returnValue = RegQueryValueExW(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
+ if (!returnValue)
+ command = QString::fromRawData((QChar*)keyValue, bufferSize);
RegCloseKey(handle);
- if(returnValue)
+ if (returnValue)
return false;
+
command = expandEnvStrings(command);
command = command.trimmed();
//Make sure the path for the process is in quotes
@@ -145,19 +141,11 @@ static bool launchWebBrowser(const QUrl &url)
//start the process
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
- QT_WA ({
- STARTUPINFO si;
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
-
- returnValue = CreateProcess(NULL, (TCHAR*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
- }, {
- STARTUPINFOA si;
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
+ STARTUPINFO si;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
- returnValue = CreateProcessA(NULL, command.toLocal8Bit().data(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
- });
+ returnValue = CreateProcess(NULL, (wchar_t*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (!returnValue)
return false;
@@ -170,12 +158,11 @@ static bool launchWebBrowser(const QUrl &url)
if (!url.isValid())
return false;
- quintptr returnValue;
- QT_WA ({
- returnValue = (quintptr)ShellExecute(0, 0, (TCHAR *) QString::fromUtf8(url.toEncoded().constData()).utf16(), 0, 0, SW_SHOWNORMAL);
- } , {
- returnValue = (quintptr)ShellExecuteA(0, 0, url.toEncoded().constData(), 0, 0, SW_SHOWNORMAL);
- });
+ if (url.scheme().isEmpty())
+ return openDocument(url);
+
+ quintptr returnValue = (quintptr)ShellExecute(0, 0, (wchar_t *)QString::fromUtf8(url.toEncoded().constData()).utf16(),
+ 0, 0, SW_SHOWNORMAL);
return (returnValue > 32);
}
diff --git a/src/gui/util/qdesktopservices_x11.cpp b/src/gui/util/qdesktopservices_x11.cpp
index b55a433..ba3c1b2 100644
--- a/src/gui/util/qdesktopservices_x11.cpp
+++ b/src/gui/util/qdesktopservices_x11.cpp
@@ -56,7 +56,11 @@ QT_BEGIN_NAMESPACE
inline static bool launch(const QUrl &url, const QString &client)
{
+#if !defined(QT_NO_PROCESS)
return (QProcess::startDetached(client + QLatin1Char(' ') + QString::fromLatin1(url.toEncoded().constData())));
+#else
+ return (::system((client + QLatin1Char(' ') + QString::fromLatin1(url.toEncoded().constData())).toLocal8Bit().constData()) != -1);
+#endif
}
static bool openDocument(const QUrl &url)
@@ -164,8 +168,8 @@ QString QDesktopServices::storageLocation(StandardLocation type)
QString key = lst.at(1);
QString value = lst.at(2);
if (value.length() > 2
- && value.startsWith(QLatin1String("\""))
- && value.endsWith(QLatin1String("\"")))
+ && value.startsWith(QLatin1Char('\"'))
+ && value.endsWith(QLatin1Char('\"')))
value = value.mid(1, value.length() - 2);
// Store the key and value: "DESKTOP", "$HOME/Desktop"
lines[key] = value;
diff --git a/src/gui/util/qsystemtrayicon.cpp b/src/gui/util/qsystemtrayicon.cpp
index 67d6ff5..7e2d291 100644
--- a/src/gui/util/qsystemtrayicon.cpp
+++ b/src/gui/util/qsystemtrayicon.cpp
@@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE
\class QSystemTrayIcon
\brief The QSystemTrayIcon class provides an icon for an application in the system tray.
\since 4.2
- \ingroup application
\ingroup desktop
Modern operating systems usually provide a special area on the desktop,
@@ -434,13 +433,13 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
titleLabel->setText(title);
QFont f = titleLabel->font();
f.setBold(true);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
f.setPointSize(f.pointSize() - 2);
#endif
titleLabel->setFont(f);
titleLabel->setTextFormat(Qt::PlainText); // to maintain compat with windows
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
const int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize);
const int closeButtonSize = style()->pixelMetric(QStyle::PM_SmallIconSize) - 2;
#else
@@ -456,7 +455,7 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
QObject::connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
QLabel *msgLabel = new QLabel;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
f.setBold(false);
msgLabel->setFont(f);
#endif
@@ -466,7 +465,7 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
msgLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
// smart size for the message label
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
int limit = QApplication::desktop()->availableGeometry(msgLabel).size().width() / 2;
#else
int limit = QApplication::desktop()->availableGeometry(msgLabel).size().width() / 3;
@@ -481,7 +480,7 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
control->document()->setDefaultTextOption(opt);
}
}
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
// Make sure that the text isn't wrapped "somewhere" in the balloon widget
// in the case that we have a long title label.
setMaximumWidth(limit);
diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp
index 375ba47..ddb676f 100644
--- a/src/gui/util/qsystemtrayicon_win.cpp
+++ b/src/gui/util/qsystemtrayicon_win.cpp
@@ -41,8 +41,7 @@
#include "qsystemtrayicon_p.h"
#ifndef QT_NO_SYSTEMTRAYICON
-//#define _WIN32_IE 0x0500
-#define _WIN32_IE 0x0600 //required for NOTIFYICONDATAW_V2_SIZE
+#define _WIN32_IE 0x0600 //required for NOTIFYICONDATA_V2_SIZE
//missing defines for MINGW :
#ifndef NIN_BALLOONTIMEOUT
@@ -62,13 +61,13 @@
#include <QDesktopWidget>
#include <QSettings>
-#if defined(Q_OS_WINCE) && !defined(STANDARDSHELL_UI_MODEL)
+#if defined(Q_WS_WINCE) && !defined(STANDARDSHELL_UI_MODEL)
# include <streams.h>
#endif
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
static const UINT q_uNOTIFYICONID = 13; // IDs from 0 to 12 are reserved on WinCE.
#else
static const UINT q_uNOTIFYICONID = 0;
@@ -77,25 +76,14 @@ static const UINT q_uNOTIFYICONID = 0;
static uint MYWM_TASKBARCREATED = 0;
#define MYWM_NOTIFYICON (WM_APP+101)
-typedef BOOL (WINAPI *PtrShell_NotifyIcon)(DWORD,PNOTIFYICONDATA);
-static PtrShell_NotifyIcon ptrShell_NotifyIcon = 0;
+struct Q_NOTIFYICONIDENTIFIER {
+ DWORD cbSize;
+ HWND hWnd;
+ UINT uID;
+ GUID guidItem;
+};
-static void resolveLibs()
-{
- static bool triedResolve = false;
-#if defined Q_OS_WINCE
- QString libName(QLatin1String("coredll"));
- const char* funcName = "Shell_NotifyIcon";
-#else
- QString libName(QLatin1String("shell32"));
- const char* funcName = "Shell_NotifyIconW";
-#endif
- if (!triedResolve) {
- QLibrary lib(libName);
- triedResolve = true;
- ptrShell_NotifyIcon = (PtrShell_NotifyIcon) lib.resolve(funcName);
- }
-}
+typedef HRESULT (WINAPI *PtrShell_NotifyIconGetRect)(const Q_NOTIFYICONIDENTIFIER* identifier, RECT* iconLocation);
class QSystemTrayIconSys : QWidget
{
@@ -103,37 +91,27 @@ public:
QSystemTrayIconSys(QSystemTrayIcon *object);
~QSystemTrayIconSys();
bool winEvent( MSG *m, long *result );
- bool trayMessageA(DWORD msg);
- bool trayMessageW(DWORD msg);
bool trayMessage(DWORD msg);
bool iconDrawItem(LPDRAWITEMSTRUCT lpdi);
- void setIconContentsW(NOTIFYICONDATAW &data);
- void setIconContentsA(NOTIFYICONDATAA &data);
- bool showMessageW(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs);
- bool showMessageA(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs);
+ void setIconContents(NOTIFYICONDATA &data);
+ bool showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs);
bool allowsMessages();
bool supportsMessages();
QRect findIconGeometry(const int a_iButtonID);
- QRect findTrayGeometry();
HBITMAP createIconMask(const QBitmap &bitmap);
void createIcon();
- int detectShellVersion() const;
HICON hIcon;
QPoint globalPos;
QSystemTrayIcon *q;
private:
- uint notifyIconSizeW;
- uint notifyIconSizeA;
- int currentShellVersion;
+ uint notifyIconSize;
int maxTipLength;
+ bool ignoreNextMouseRelease;
};
-// Checks for the shell32 dll version number, since only version
-// 5 or later of supports ballon messages
bool QSystemTrayIconSys::allowsMessages()
{
#ifndef QT_NO_SETTINGS
-
QSettings settings(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft"
"\\Windows\\CurrentVersion\\Explorer\\Advanced"), QSettings::NativeFormat);
return settings.value(QLatin1String("EnableBalloonTips"), true).toBool();
@@ -142,63 +120,29 @@ bool QSystemTrayIconSys::allowsMessages()
#endif
}
-// Checks for the shell32 dll version number, since only version
-// 5 or later of supports ballon messages
bool QSystemTrayIconSys::supportsMessages()
{
-#if NOTIFYICON_VERSION >= 3
- if (currentShellVersion >= 5)
- return allowsMessages();
- else
-#endif
- return false;
-}
-
-//Returns the runtime major version of the shell32 dll
-int QSystemTrayIconSys::detectShellVersion() const
-{
#ifndef Q_OS_WINCE
- int shellVersion = 4; //NT 4.0 and W95
- DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)QLibrary::resolve(
- QLatin1String("shell32"), "DllGetVersion");
- if (pDllGetVersion)
- {
- DLLVERSIONINFO dvi;
- HRESULT hr;
- ZeroMemory(&dvi, sizeof(dvi));
- dvi.cbSize = sizeof(dvi);
- hr = (*pDllGetVersion)(&dvi);
- if (SUCCEEDED(hr)) {
- if (dvi.dwMajorVersion >= 5)
- {
- shellVersion = dvi.dwMajorVersion;
- }
- }
- }
- return shellVersion;
+ return allowsMessages();
#endif
- return 4; //No ballonMessages and MaxTipLength = 64 for WindowsCE
+ return false;
}
QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *object)
- : hIcon(0), q(object)
+ : hIcon(0), q(object), ignoreNextMouseRelease(false)
+
{
- currentShellVersion = detectShellVersion();
- notifyIconSizeA = FIELD_OFFSET(NOTIFYICONDATAA, szTip[64]); // NOTIFYICONDATAA_V1_SIZE
- notifyIconSizeW = FIELD_OFFSET(NOTIFYICONDATAW, szTip[64]); // NOTIFYICONDATAW_V1_SIZE;
+#ifndef Q_OS_WINCE
+ notifyIconSize = FIELD_OFFSET(NOTIFYICONDATA, guidItem); // NOTIFYICONDATAW_V2_SIZE;
+ maxTipLength = 128;
+#else
+ notifyIconSize = FIELD_OFFSET(NOTIFYICONDATA, szTip[64]); // NOTIFYICONDATAW_V1_SIZE;
maxTipLength = 64;
-
-#if NOTIFYICON_VERSION >= 3
- if (currentShellVersion >=5) {
- notifyIconSizeA = FIELD_OFFSET(NOTIFYICONDATAA, guidItem); // NOTIFYICONDATAA_V2_SIZE
- notifyIconSizeW = FIELD_OFFSET(NOTIFYICONDATAW, guidItem); // NOTIFYICONDATAW_V2_SIZE;
- maxTipLength = 128;
- }
#endif
// For restoring the tray icon after explorer crashes
if (!MYWM_TASKBARCREATED) {
- MYWM_TASKBARCREATED = QT_WA_INLINE(RegisterWindowMessageW(L"TaskbarCreated"),RegisterWindowMessageA("TaskbarCreated"));
+ MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
}
}
@@ -208,118 +152,60 @@ QSystemTrayIconSys::~QSystemTrayIconSys()
DestroyIcon(hIcon);
}
-void QSystemTrayIconSys::setIconContentsW(NOTIFYICONDATAW &tnd)
+void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd)
{
- tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
+ tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
tnd.uCallbackMessage = MYWM_NOTIFYICON;
tnd.hIcon = hIcon;
QString tip = q->toolTip();
if (!tip.isNull()) {
- // Tip is limited to maxTipLength - NULL; lstrcpyn appends a NULL terminator.
tip = tip.left(maxTipLength - 1) + QChar();
-#if defined(Q_OS_WINCE)
- wcsncpy(tnd.szTip, reinterpret_cast<const wchar_t *> (tip.utf16()), qMin(tip.length()+1, maxTipLength));
-#else
- lstrcpynW(tnd.szTip, (TCHAR*)tip.utf16(), qMin(tip.length()+1, maxTipLength));
-#endif
+ memcpy(tnd.szTip, tip.utf16(), qMin(tip.length() + 1, maxTipLength) * sizeof(wchar_t));
}
}
-void QSystemTrayIconSys::setIconContentsA(NOTIFYICONDATAA &tnd)
+static int iconFlag( QSystemTrayIcon::MessageIcon icon )
{
- tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
- tnd.uCallbackMessage = MYWM_NOTIFYICON;
- tnd.hIcon = hIcon;
- QString tip = q->toolTip();
-
- if (!tip.isNull()) {
- // Tip is limited to maxTipLength - NULL; lstrcpyn appends a NULL terminator.
- tip = tip.left(maxTipLength - 1) + QChar();
-#if defined(Q_OS_WINCE)
- strncpy(tnd.szTip, tip.toLocal8Bit().constData(), qMin(tip.length()+1, maxTipLength));
-#else
- lstrcpynA(tnd.szTip, tip.toLocal8Bit().constData(), qMin(tip.length()+1, maxTipLength));
-#endif
- }
-}
-
-int iconFlag( QSystemTrayIcon::MessageIcon icon )
-{
- int flag = 0;
#if NOTIFYICON_VERSION >= 3
switch (icon) {
- case QSystemTrayIcon::NoIcon:
- break;
- case QSystemTrayIcon::Critical:
- flag = NIIF_ERROR;
- break;
- case QSystemTrayIcon::Warning:
- flag = NIIF_WARNING;
- break;
case QSystemTrayIcon::Information:
- default : // fall through
- flag = NIIF_INFO;
+ return NIIF_INFO;
+ case QSystemTrayIcon::Warning:
+ return NIIF_WARNING;
+ case QSystemTrayIcon::Critical:
+ return NIIF_ERROR;
+ case QSystemTrayIcon::NoIcon:
+ return NIIF_NONE;
+ default:
+ Q_ASSERT_X(false, "QSystemTrayIconSys::showMessage", "Invalid QSystemTrayIcon::MessageIcon value");
+ return NIIF_NONE;
}
#else
Q_UNUSED(icon);
+ return 0;
#endif
- return flag;
}
-bool QSystemTrayIconSys::showMessageW(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs)
+bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs)
{
-#if NOTIFYICON_VERSION>=3
+#if NOTIFYICON_VERSION >= 3
NOTIFYICONDATA tnd;
- memset(&tnd, 0, notifyIconSizeW);
+ memset(&tnd, 0, notifyIconSize);
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
- setIconContentsW(tnd);
-#if defined(Q_OS_WINCE)
- wcsncpy(tnd.szInfo, message.utf16(), qMin(message.length() + 1, 256));
- wcsncpy(tnd.szInfoTitle, title.utf16(), qMin(title.length()+1, 64));
-#else
- lstrcpynW(tnd.szInfo, (TCHAR*)message.utf16(), qMin(message.length() + 1, 256));
- lstrcpynW(tnd.szInfoTitle, (TCHAR*)title.utf16(), qMin(title.length() + 1, 64));
-#endif
- tnd.uID = q_uNOTIFYICONID;
- tnd.dwInfoFlags = iconFlag(type);
- tnd.cbSize = notifyIconSizeW;
- tnd.hWnd = winId();
- tnd.uTimeout = uSecs;
- tnd.uFlags = NIF_INFO;
- return ptrShell_NotifyIcon(NIM_MODIFY, &tnd);
-#else
- Q_UNUSED(title);
- Q_UNUSED(message);
- Q_UNUSED(type);
- Q_UNUSED(uSecs);
- return false;
-#endif
-}
-
-bool QSystemTrayIconSys::showMessageA(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs)
-{
-#if NOTIFYICON_VERSION>=3
- NOTIFYICONDATAA tnd;
- memset(&tnd, 0, notifyIconSizeA);
- Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ setIconContents(tnd);
+ memcpy(tnd.szInfo, message.utf16(), qMin(message.length() + 1, 256) * sizeof(wchar_t));
+ memcpy(tnd.szInfoTitle, title.utf16(), qMin(title.length() + 1, 64) * sizeof(wchar_t));
- setIconContentsA(tnd);
-#if defined(Q_OS_WINCE)
- strncpy(tnd.szInfo, message.toLocal8Bit().constData(), qMin(message.length() + 1, 256));
- strncpy(tnd.szInfoTitle, title.toLocal8Bit().constData(), qMin(title.length()+1, 64));
-#else
- lstrcpynA(tnd.szInfo, message.toLocal8Bit().constData(), qMin(message.length() + 1, 256));
- lstrcpynA(tnd.szInfoTitle, title.toLocal8Bit().constData(), qMin(title.length() + 1, 64));
-#endif
tnd.uID = q_uNOTIFYICONID;
tnd.dwInfoFlags = iconFlag(type);
- tnd.cbSize = notifyIconSizeA;
+ tnd.cbSize = notifyIconSize;
tnd.hWnd = winId();
tnd.uTimeout = uSecs;
tnd.uFlags = NIF_INFO;
- return Shell_NotifyIconA(NIM_MODIFY, &tnd);
+
+ return Shell_NotifyIcon(NIM_MODIFY, &tnd);
#else
Q_UNUSED(title);
Q_UNUSED(message);
@@ -329,53 +215,21 @@ bool QSystemTrayIconSys::showMessageA(const QString &title, const QString &messa
#endif
}
-bool QSystemTrayIconSys::trayMessageA(DWORD msg)
+bool QSystemTrayIconSys::trayMessage(DWORD msg)
{
-#if !defined(Q_OS_WINCE)
- NOTIFYICONDATAA tnd;
- memset(&tnd, 0, notifyIconSizeA);
+ NOTIFYICONDATA tnd;
+ memset(&tnd, 0, notifyIconSize);
tnd.uID = q_uNOTIFYICONID;
- tnd.cbSize = notifyIconSizeA;
+ tnd.cbSize = notifyIconSize;
tnd.hWnd = winId();
- Q_ASSERT(testAttribute(Qt::WA_WState_Created));
- if (msg != NIM_DELETE) {
- setIconContentsA(tnd);
- }
- return Shell_NotifyIconA(msg, &tnd);
-#else
- Q_UNUSED(msg);
- return false;
-#endif
-}
-
-bool QSystemTrayIconSys::trayMessageW(DWORD msg)
-{
- NOTIFYICONDATAW tnd;
- memset(&tnd, 0, notifyIconSizeW);
- tnd.uID = q_uNOTIFYICONID;
- tnd.cbSize = notifyIconSizeW;
- tnd.hWnd = winId();
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
if (msg != NIM_DELETE) {
- setIconContentsW(tnd);
+ setIconContents(tnd);
}
- return ptrShell_NotifyIcon(msg, &tnd);
-}
-bool QSystemTrayIconSys::trayMessage(DWORD msg)
-{
- resolveLibs();
- if (!(ptrShell_NotifyIcon))
- return false;
-
- QT_WA({
- return trayMessageW(msg);
- },
- {
- return trayMessageA(msg);
- });
+ return Shell_NotifyIcon(msg, &tnd);
}
bool QSystemTrayIconSys::iconDrawItem(LPDRAWITEMSTRUCT lpdi)
@@ -459,31 +313,45 @@ bool QSystemTrayIconSys::winEvent( MSG *m, long *result )
switch (m->lParam) {
case WM_LBUTTONUP:
- emit q->activated(QSystemTrayIcon::Trigger);
+ if (ignoreNextMouseRelease)
+ ignoreNextMouseRelease = false;
+ else
+ emit q->activated(QSystemTrayIcon::Trigger);
break;
-#if !defined(Q_OS_WINCE)
case WM_LBUTTONDBLCLK:
+ ignoreNextMouseRelease = true; // Since DBLCLICK Generates a second mouse
+ // release we must ignore it
emit q->activated(QSystemTrayIcon::DoubleClick);
break;
case WM_RBUTTONUP:
if (q->contextMenu()) {
q->contextMenu()->popup(gpos);
+#if defined(Q_WS_WINCE)
+ // We must ensure that the popup menu doesn't show up behind the task bar.
+ QRect desktopRect = qApp->desktop()->availableGeometry();
+ int maxY = desktopRect.y() + desktopRect.height() - q->contextMenu()->height();
+ if (gpos.y() > maxY) {
+ gpos.ry() = maxY;
+ q->contextMenu()->move(gpos);
+ }
+#endif
q->contextMenu()->activateWindow();
//Must be activated for proper keyboardfocus and menu closing on windows:
}
emit q->activated(QSystemTrayIcon::Context);
break;
+#if !defined(Q_WS_WINCE)
case NIN_BALLOONUSERCLICK:
emit q->messageClicked();
break;
+#endif
case WM_MBUTTONUP:
emit q->activated(QSystemTrayIcon::MiddleClick);
break;
-#endif
default:
break;
}
@@ -514,33 +382,6 @@ void QSystemTrayIconPrivate::install_sys()
}
}
-//fallback on win 95/98
-QRect QSystemTrayIconSys::findTrayGeometry()
-{
- //Use lower right corner as fallback
- QPoint brCorner = qApp->desktop()->screenGeometry().bottomRight();
- QRect ret(brCorner.x() - 10, brCorner.y() - 10, 10, 10);
-#if defined(Q_OS_WINCE)
- HWND trayHandle = FindWindowW(L"Shell_TrayWnd", NULL);
-#else
- HWND trayHandle = FindWindowA("Shell_TrayWnd", NULL);
-#endif
- if (trayHandle) {
-#if defined(Q_OS_WINCE)
- trayHandle = FindWindowW(L"TrayNotifyWnd", NULL);
-#else
- trayHandle = FindWindowExA(trayHandle, NULL, "TrayNotifyWnd", NULL);
-#endif
- if (trayHandle) {
- RECT r;
- if (GetWindowRect(trayHandle, &r)) {
- ret = QRect(r.left, r.top, r.right- r.left, r.bottom - r.top);
- }
- }
- }
- return ret;
-}
-
/*
* This function tries to determine the icon geometry from the tray
*
@@ -548,26 +389,39 @@ QRect QSystemTrayIconSys::findTrayGeometry()
*/
QRect QSystemTrayIconSys::findIconGeometry(const int iconId)
{
+ static PtrShell_NotifyIconGetRect Shell_NotifyIconGetRect =
+ (PtrShell_NotifyIconGetRect)QLibrary::resolve(QLatin1String("shell32"), "Shell_NotifyIconGetRect");
+
+ if (Shell_NotifyIconGetRect) {
+ Q_NOTIFYICONIDENTIFIER nid;
+ memset(&nid, 0, sizeof(nid));
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = winId();
+ nid.uID = iconId;
+
+ RECT rect;
+ HRESULT hr = Shell_NotifyIconGetRect(&nid, &rect);
+ if (SUCCEEDED(hr)) {
+ return QRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+
QRect ret;
TBBUTTON buttonData;
DWORD processID = 0;
-#if defined(Q_OS_WINCE)
- HWND trayHandle = FindWindowW(L"Shell_TrayWnd", NULL);
-#else
- HWND trayHandle = FindWindowA("Shell_TrayWnd", NULL);
-#endif
+ HWND trayHandle = FindWindow(L"Shell_TrayWnd", NULL);
//find the toolbar used in the notification area
if (trayHandle) {
#if defined(Q_OS_WINCE)
- trayHandle = FindWindowW(L"TrayNotifyWnd", NULL);
+ trayHandle = FindWindow(L"TrayNotifyWnd", NULL);
#else
- trayHandle = FindWindowExA(trayHandle, NULL, "TrayNotifyWnd", NULL);
+ trayHandle = FindWindowEx(trayHandle, NULL, L"TrayNotifyWnd", NULL);
#endif
if (trayHandle) {
#if defined(Q_OS_WINCE)
- HWND hwnd = FindWindowW(L"SysPager", NULL);
+ HWND hwnd = FindWindow(L"SysPager", NULL);
#else
HWND hwnd = FindWindowEx(trayHandle, NULL, L"SysPager", NULL);
#endif
@@ -612,10 +466,10 @@ QRect QSystemTrayIconSys::findIconGeometry(const int iconId)
DWORD appData[2] = { 0, 0 };
SendMessage(trayHandle, TB_GETBUTTON, toolbarButton , (LPARAM)data);
- if(!ReadProcessMemory(trayProcess, data, &buttonData, sizeof(TBBUTTON), &numBytes))
+ if (!ReadProcessMemory(trayProcess, data, &buttonData, sizeof(TBBUTTON), &numBytes))
continue;
- if(!ReadProcessMemory(trayProcess, (LPVOID) buttonData.dwData, appData, sizeof(appData), &numBytes))
+ if (!ReadProcessMemory(trayProcess, (LPVOID) buttonData.dwData, appData, sizeof(appData), &numBytes))
continue;
int currentIconId = appData[1];
@@ -646,7 +500,6 @@ QRect QSystemTrayIconSys::findIconGeometry(const int iconId)
return ret;
}
-
void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, int timeOut)
{
if (!sys || !sys->allowsMessages())
@@ -657,12 +510,10 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString
uSecs = 10000; //10 sec default
else uSecs = (int)timeOut;
- resolveLibs();
-
//message is limited to 255 chars + NULL
QString messageString;
if (message.isEmpty() && !title.isEmpty())
- messageString = QLatin1String(" "); //ensures that the message shows when only title is set
+ messageString = QLatin1Char(' '); //ensures that the message shows when only title is set
else
messageString = message.left(255) + QChar();
@@ -670,20 +521,12 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString
QString titleString = title.left(63) + QChar();
if (sys->supportsMessages()) {
- QT_WA({
- sys->showMessageW(titleString, messageString, type, (unsigned int)uSecs);
- }, {
- sys->showMessageA(titleString, messageString, type, (unsigned int)uSecs);
- });
+ sys->showMessage(titleString, messageString, type, (unsigned int)uSecs);
} else {
- //use fallbacks
- QRect iconPos = sys->findIconGeometry(0);
+ //use fallback
+ QRect iconPos = sys->findIconGeometry(q_uNOTIFYICONID);
if (iconPos.isValid()) {
QBalloonTip::showBalloon(type, title, message, sys->q, iconPos.center(), uSecs, true);
- } else {
- QRect trayRect = sys->findTrayGeometry();
- QBalloonTip::showBalloon(type, title, message, sys->q, QPoint(trayRect.left(),
- trayRect.center().y()), uSecs, false);
}
}
}
@@ -692,7 +535,7 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
{
if (!sys)
return QRect();
- return sys->findIconGeometry(0);
+ return sys->findIconGeometry(q_uNOTIFYICONID);
}
void QSystemTrayIconPrivate::remove_sys()
@@ -726,7 +569,7 @@ void QSystemTrayIconPrivate::updateMenu_sys()
void QSystemTrayIconPrivate::updateToolTip_sys()
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
// Calling sys->trayMessage(NIM_MODIFY) on an existing icon is broken on Windows CE.
// So we need to call updateIcon_sys() which creates a new icon handle.
updateIcon_sys();
diff --git a/src/gui/util/qundogroup.cpp b/src/gui/util/qundogroup.cpp
index 3693552..e5a65a7 100644
--- a/src/gui/util/qundogroup.cpp
+++ b/src/gui/util/qundogroup.cpp
@@ -61,7 +61,6 @@ public:
\class QUndoGroup
\brief The QUndoGroup class is a group of QUndoStack objects.
\since 4.2
- \ingroup misc
For an overview of the Qt's undo framework, see the
\link qundo.html overview\endlink.
diff --git a/src/gui/util/qundostack.cpp b/src/gui/util/qundostack.cpp
index 5742345..be8dd34 100644
--- a/src/gui/util/qundostack.cpp
+++ b/src/gui/util/qundostack.cpp
@@ -52,7 +52,6 @@ QT_BEGIN_NAMESPACE
\class QUndoCommand
\brief The QUndoCommand class is the base class of all commands stored on a QUndoStack.
\since 4.2
- \ingroup misc
For an overview of Qt's Undo Framework, see the
\l{Overview of Qt's Undo Framework}{overview document}.
@@ -292,7 +291,6 @@ const QUndoCommand *QUndoCommand::child(int index) const
\class QUndoStack
\brief The QUndoStack class is a stack of QUndoCommand objects.
\since 4.2
- \ingroup misc
For an overview of Qt's Undo Framework, see the
\l{Overview of Qt's Undo Framework}{overview document}.
diff --git a/src/gui/util/qundoview.cpp b/src/gui/util/qundoview.cpp
index bb4e4a0..81384e1 100644
--- a/src/gui/util/qundoview.cpp
+++ b/src/gui/util/qundoview.cpp
@@ -253,7 +253,7 @@ QIcon QUndoModel::cleanIcon() const
\class QUndoView
\brief The QUndoView class displays the contents of a QUndoStack.
\since 4.2
- \ingroup misc
+
\ingroup advanced
QUndoView is a QListView which displays the list of commands pushed on an undo stack.
diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
index e628229..cdbb7cc 100644
--- a/src/gui/util/util.pri
+++ b/src/gui/util/util.pri
@@ -38,3 +38,8 @@ embedded {
!embedded:!x11:mac {
OBJECTIVE_SOURCES += util/qsystemtrayicon_mac.mm
}
+
+symbian {
+ LIBS += -lsendas2 -letext -lapmime
+ contains(QT_CONFIG, s60): LIBS += -lplatformenv -lcommonui
+}
diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp
index 3a89628..989f781 100644
--- a/src/gui/widgets/qabstractbutton.cpp
+++ b/src/gui/widgets/qabstractbutton.cpp
@@ -215,11 +215,8 @@ void QButtonGroup::setExclusive(bool exclusive)
d->exclusive = exclusive;
}
-/*!
- Adds the given \a button to the end of the group's internal list of buttons.
- \sa removeButton()
-*/
+// TODO: Qt 5: Merge with addButton(QAbstractButton *button, int id)
void QButtonGroup::addButton(QAbstractButton *button)
{
addButton(button, -1);
@@ -232,8 +229,18 @@ void QButtonGroup::addButton(QAbstractButton *button, int id)
previous->removeButton(button);
button->d_func()->group = this;
d->buttonList.append(button);
- if (id != -1)
+ if (id == -1) {
+ QList<int> ids = d->mapping.values();
+ if (ids.isEmpty())
+ d->mapping[button] = -2;
+ else {
+ qSort(ids);
+ d->mapping[button] = ids.first()-1;
+ }
+ } else {
d->mapping[button] = id;
+ }
+
if (d->exclusive && button->isChecked())
button->d_func()->notifyChecked();
}
@@ -312,20 +319,16 @@ QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
return group->d_func()->buttonList;
#endif
- Q_Q(const QAbstractButton);
- QList<QAbstractButton*>candidates;
- if (q->parentWidget()) {
- candidates = qFindChildren<QAbstractButton *>(q->parentWidget());
- if (autoExclusive) {
- for (int i = candidates.count() - 1; i >= 0; --i) {
- QAbstractButton *candidate = candidates.at(i);
- if (!candidate->autoExclusive()
+ QList<QAbstractButton*>candidates = qFindChildren<QAbstractButton *>(parent);
+ if (autoExclusive) {
+ for (int i = candidates.count() - 1; i >= 0; --i) {
+ QAbstractButton *candidate = candidates.at(i);
+ if (!candidate->autoExclusive()
#ifndef QT_NO_BUTTONGROUP
- || candidate->group()
+ || candidate->group()
#endif
- )
- candidates.removeAt(i);
- }
+ )
+ candidates.removeAt(i);
}
}
return candidates;
@@ -376,7 +379,7 @@ void QAbstractButtonPrivate::moveFocus(int key)
#else
bool exclusive = autoExclusive;
#endif
- QWidget *f = qApp->focusWidget();
+ QWidget *f = QApplication::focusWidget();
QAbstractButton *fb = qobject_cast<QAbstractButton *>(f);
if (!fb || !buttonList.contains(fb))
return;
@@ -1236,7 +1239,9 @@ void QAbstractButton::timerEvent(QTimerEvent *e)
d->repeatTimer.start(d->autoRepeatInterval, this);
if (d->down) {
QPointer<QAbstractButton> guard(this);
- d->emitReleased();
+ nextCheckState();
+ if (guard)
+ d->emitReleased();
if (guard)
d->emitClicked();
if (guard)
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp
index 57cdd6d..770e769 100644
--- a/src/gui/widgets/qabstractscrollarea.cpp
+++ b/src/gui/widgets/qabstractscrollarea.cpp
@@ -52,9 +52,15 @@
#include "qboxlayout.h"
#include "qpainter.h"
+#ifdef Q_WS_WIN
+#include "qstandardgestures.h"
+#endif
+
#include "qabstractscrollarea_p.h"
#include <qwidget.h>
+#include <private/qapplication_p.h>
+
#ifdef Q_WS_MAC
#include <private/qt_mac_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
@@ -157,6 +163,9 @@ QAbstractScrollAreaPrivate::QAbstractScrollAreaPrivate()
:hbar(0), vbar(0), vbarpolicy(Qt::ScrollBarAsNeeded), hbarpolicy(Qt::ScrollBarAsNeeded),
viewport(0), cornerWidget(0), left(0), top(0), right(0), bottom(0),
xoffset(0), yoffset(0), viewportFilter(0)
+#ifdef Q_WS_WIN
+ , panGesture(0), singleFingerPanEnabled(false)
+#endif
{
}
@@ -281,15 +290,28 @@ void QAbstractScrollAreaPrivate::init()
scrollBarContainers[Qt::Vertical]->setVisible(false);
QObject::connect(vbar, SIGNAL(valueChanged(int)), q, SLOT(_q_vslide(int)));
QObject::connect(vbar, SIGNAL(rangeChanged(int,int)), q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
- viewportFilter = new QAbstractScrollAreaFilter(this);
- viewport->installEventFilter(viewportFilter);
+ viewportFilter.reset(new QAbstractScrollAreaFilter(this));
+ viewport->installEventFilter(viewportFilter.data());
viewport->setFocusProxy(q);
q->setFocusPolicy(Qt::WheelFocus);
q->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
layoutChildren();
+
+#ifdef Q_WS_WIN
+ panGesture = new QPanGesture(viewport);
+ QObject::connect(panGesture, SIGNAL(triggered()), q, SLOT(_q_gestureTriggered()));
+#endif // Q_WS_WIN
}
+#ifdef Q_WS_WIN
+void QAbstractScrollAreaPrivate::setSingleFingerPanEnabled(bool on)
+{
+ singleFingerPanEnabled = on;
+ winSetupGestures();
+}
+#endif // Q_WS_WIN
+
void QAbstractScrollAreaPrivate::layoutChildren()
{
Q_Q(QAbstractScrollArea);
@@ -459,9 +481,6 @@ void QAbstractScrollAreaPrivate::layoutChildren()
viewport->setGeometry(QStyle::visualRect(opt.direction, opt.rect, viewportRect)); // resize the viewport last
}
-// ### Fix for 4.4, talk to Bjoern E or Girish.
-void QAbstractScrollAreaPrivate::scrollBarPolicyChanged(Qt::Orientation, Qt::ScrollBarPolicy) {}
-
/*!
\internal
@@ -471,7 +490,12 @@ QAbstractScrollArea::QAbstractScrollArea(QAbstractScrollAreaPrivate &dd, QWidget
:QFrame(dd, parent)
{
Q_D(QAbstractScrollArea);
- d->init();
+ QT_TRY {
+ d->init();
+ } QT_CATCH(...) {
+ d->viewportFilter.reset();
+ QT_RETHROW;
+ }
}
/*!
@@ -483,7 +507,12 @@ QAbstractScrollArea::QAbstractScrollArea(QWidget *parent)
:QFrame(*new QAbstractScrollAreaPrivate, parent)
{
Q_D(QAbstractScrollArea);
- d->init();
+ QT_TRY {
+ d->init();
+ } QT_CATCH(...) {
+ d->viewportFilter.reset();
+ QT_RETHROW;
+ }
}
@@ -493,7 +522,8 @@ QAbstractScrollArea::QAbstractScrollArea(QWidget *parent)
QAbstractScrollArea::~QAbstractScrollArea()
{
Q_D(QAbstractScrollArea);
- delete d->viewportFilter;
+ // reset it here, otherwise we'll have a dangling pointer in ~QWidget
+ d->viewportFilter.reset();
}
@@ -517,11 +547,14 @@ void QAbstractScrollArea::setViewport(QWidget *widget)
d->viewport = widget;
d->viewport->setParent(this);
d->viewport->setFocusProxy(this);
- d->viewport->installEventFilter(d->viewportFilter);
+ d->viewport->installEventFilter(d->viewportFilter.data());
d->layoutChildren();
if (isVisible())
d->viewport->show();
QMetaObject::invokeMethod(this, "setupViewport", Q_ARG(QWidget *, widget));
+#ifdef Q_WS_WIN
+ d->panGesture->setGestureTarget(widget);
+#endif
delete oldViewport;
}
}
@@ -873,21 +906,22 @@ bool QAbstractScrollArea::event(QEvent *e)
case QEvent::Resize:
d->layoutChildren();
break;
- case QEvent::Paint:
+ case QEvent::Paint: {
+ QStyleOption option;
+ option.initFrom(this);
if (d->cornerPaintingRect.isValid()) {
- QStyleOption option;
option.rect = d->cornerPaintingRect;
QPainter p(this);
style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
}
#ifdef Q_WS_MAC
if (d->reverseCornerPaintingRect.isValid()) {
- QStyleOption option;
option.rect = d->reverseCornerPaintingRect;
QPainter p(this);
style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
}
#endif
+ }
QFrame::paintEvent((QPaintEvent*)e);
break;
#ifndef QT_NO_CONTEXTMENU
@@ -908,6 +942,10 @@ bool QAbstractScrollArea::event(QEvent *e)
case QEvent::DragMove:
case QEvent::DragLeave:
#endif
+ // ignore touch events in case they have been propagated from the viewport
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
return false;
case QEvent::StyleChange:
case QEvent::LayoutDirectionChange:
@@ -948,6 +986,9 @@ bool QAbstractScrollArea::viewportEvent(QEvent *e)
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
case QEvent::MouseMove:
case QEvent::ContextMenu:
#ifndef QT_NO_WHEELEVENT
@@ -1237,6 +1278,11 @@ void QAbstractScrollAreaPrivate::_q_vslide(int y)
void QAbstractScrollAreaPrivate::_q_showOrHideScrollBars()
{
layoutChildren();
+#ifdef Q_OS_WIN
+ // Need to re-subscribe to gestures as the content changes to make sure we
+ // enable/disable panning when needed.
+ winSetupGestures();
+#endif // Q_OS_WIN
}
QPoint QAbstractScrollAreaPrivate::contentsOffset() const
@@ -1264,6 +1310,12 @@ QSize QAbstractScrollArea::minimumSizeHint() const
int hsbExt = d->hbar->sizeHint().height();
int vsbExt = d->vbar->sizeHint().width();
int extra = 2 * d->frameWidth;
+ QStyleOption opt;
+ opt.initFrom(this);
+ if ((d->frameStyle != QFrame::NoFrame)
+ && style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, this)) {
+ extra += style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, this);
+ }
return QSize(d->scrollBarContainers[Qt::Horizontal]->sizeHint().width() + vsbExt + extra,
d->scrollBarContainers[Qt::Vertical]->sizeHint().height() + hsbExt + extra);
}
@@ -1295,6 +1347,27 @@ void QAbstractScrollArea::setupViewport(QWidget *viewport)
Q_UNUSED(viewport);
}
+#ifdef Q_WS_WIN
+void QAbstractScrollAreaPrivate::_q_gestureTriggered()
+{
+ Q_Q(QAbstractScrollArea);
+ QPanGesture *g = qobject_cast<QPanGesture*>(q->sender());
+ if (!g)
+ return;
+ QScrollBar *hBar = q->horizontalScrollBar();
+ QScrollBar *vBar = q->verticalScrollBar();
+ QSizeF delta = g->lastOffset();
+ if (!delta.isNull()) {
+ if (QApplication::isRightToLeft())
+ delta.rwidth() *= -1;
+ int newX = hBar->value() - delta.width();
+ int newY = vBar->value() - delta.height();
+ hbar->setValue(newX);
+ vbar->setValue(newY);
+ }
+}
+#endif
+
QT_END_NAMESPACE
#include "moc_qabstractscrollarea.cpp"
diff --git a/src/gui/widgets/qabstractscrollarea.h b/src/gui/widgets/qabstractscrollarea.h
index 1cf04cb..69b91a4 100644
--- a/src/gui/widgets/qabstractscrollarea.h
+++ b/src/gui/widgets/qabstractscrollarea.h
@@ -129,7 +129,12 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_vslide(int))
Q_PRIVATE_SLOT(d_func(), void _q_showOrHideScrollBars())
+#ifdef Q_WS_WIN
+ Q_PRIVATE_SLOT(d_func(), void _q_gestureTriggered())
+#endif
+
friend class QStyleSheetStyle;
+ friend class QWidgetPrivate;
};
#endif // QT_NO_SCROLLAREA
diff --git a/src/gui/widgets/qabstractscrollarea_p.h b/src/gui/widgets/qabstractscrollarea_p.h
index ba823b3..000da74 100644
--- a/src/gui/widgets/qabstractscrollarea_p.h
+++ b/src/gui/widgets/qabstractscrollarea_p.h
@@ -60,9 +60,10 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_SCROLLAREA
+class QPanGesture;
class QScrollBar;
class QAbstractScrollAreaScrollBarContainer;
-class Q_GUI_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate
+class Q_AUTOTEST_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate
{
Q_DECLARE_PUBLIC(QAbstractScrollArea)
@@ -88,7 +89,7 @@ public:
void init();
void layoutChildren();
// ### Fix for 4.4, talk to Bjoern E or Girish.
- virtual void scrollBarPolicyChanged(Qt::Orientation, Qt::ScrollBarPolicy);
+ virtual void scrollBarPolicyChanged(Qt::Orientation, Qt::ScrollBarPolicy) {}
void _q_hslide(int);
void _q_vslide(int);
@@ -98,7 +99,14 @@ public:
inline bool viewportEvent(QEvent *event)
{ return q_func()->viewportEvent(event); }
- QObject *viewportFilter;
+ QScopedPointer<QObject> viewportFilter;
+
+#ifdef Q_WS_WIN
+ QPanGesture *panGesture;
+ virtual void _q_gestureTriggered();
+ bool singleFingerPanEnabled;
+ void setSingleFingerPanEnabled(bool on = true);
+#endif
};
class QAbstractScrollAreaFilter : public QObject
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index 45e256c..4680718 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -688,7 +688,6 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e)
e->ignore();
if (e->orientation() != d->orientation && !rect().contains(e->pos()))
return;
-
static qreal offset = 0;
static QAbstractSlider *offset_owner = 0;
if (offset_owner != this){
diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp
index c333ef7..1365f71 100644
--- a/src/gui/widgets/qabstractspinbox.cpp
+++ b/src/gui/widgets/qabstractspinbox.cpp
@@ -57,6 +57,9 @@
#include <qpalette.h>
#include <qstylepainter.h>
#include <qdebug.h>
+#ifndef QT_NO_ACCESSIBILITY
+# include <qaccessible.h>
+#endif
#if defined(Q_WS_X11)
#include <limits.h>
@@ -193,6 +196,7 @@ void QAbstractSpinBox::setButtonSymbols(ButtonSymbols buttonSymbols)
Q_D(QAbstractSpinBox);
if (d->buttonSymbols != buttonSymbols) {
d->buttonSymbols = buttonSymbols;
+ d->updateEditFieldGeometry();
update();
}
}
@@ -659,7 +663,6 @@ void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit)
d->edit->setParent(this);
d->edit->setFrame(false);
- d->edit->setAttribute(Qt::WA_InputMethodEnabled, false);
d->edit->setFocusProxy(this);
d->edit->setAcceptDrops(false);
@@ -690,6 +693,18 @@ void QAbstractSpinBox::interpretText()
d->interpret(EmitIfChanged);
}
+/*
+ Reimplemented in 4.6, so be careful.
+ */
+/*!
+ \reimp
+*/
+QVariant QAbstractSpinBox::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ Q_D(const QAbstractSpinBox);
+ return d->edit->inputMethodQuery(query);
+}
+
/*!
\reimp
*/
@@ -950,6 +965,9 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
d->buttonState = (Keyboard | (up ? Up : Down));
}
stepBy(steps);
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::ValueChanged);
+#endif
return;
}
#ifdef QT_KEYPAD_NAVIGATION
@@ -969,7 +987,7 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
#endif
case Qt::Key_Enter:
case Qt::Key_Return:
- d->edit->d_func()->modifiedState = d->edit->d_func()->undoState = 0;
+ d->edit->d_func()->control->clearUndo();
d->interpret(d->keyboardTracking ? AlwaysEmit : EmitIfChanged);
selectAll();
event->ignore();
@@ -1547,6 +1565,9 @@ void QAbstractSpinBoxPrivate::updateState(bool up)
spinClickThresholdTimerId = q->startTimer(spinClickThresholdTimerInterval);
buttonState = (up ? (Mouse | Up) : (Mouse | Down));
q->stepBy(up ? 1 : -1);
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged);
+#endif
}
}
@@ -1567,7 +1588,7 @@ void QAbstractSpinBox::initStyleOption(QStyleOptionSpinBox *option) const
option->initFrom(this);
option->activeSubControls = QStyle::SC_None;
option->buttonSymbols = d->buttonSymbols;
- option->subControls = QStyle::SC_SpinBoxFrame;
+ option->subControls = QStyle::SC_SpinBoxFrame | QStyle::SC_SpinBoxEditField;
if (d->buttonSymbols != QAbstractSpinBox::NoButtons) {
option->subControls |= QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown;
if (d->buttonState & Up) {
@@ -1695,6 +1716,8 @@ void QAbstractSpinBoxPrivate::updateEdit()
void QAbstractSpinBoxPrivate::setRange(const QVariant &min, const QVariant &max)
{
+ Q_Q(QAbstractSpinBox);
+
clearCache();
minimum = min;
maximum = (variantCompare(min, max) < 0 ? max : min);
@@ -1706,6 +1729,8 @@ void QAbstractSpinBoxPrivate::setRange(const QVariant &min, const QVariant &max)
} else if (value == minimum && !specialValueText.isEmpty()) {
updateEdit();
}
+
+ q->updateGeometry();
}
/*!
@@ -1780,8 +1805,8 @@ void QAbstractSpinBoxPrivate::interpret(EmitPolicy ep)
q->fixup(tmp);
QASBDEBUG() << "QAbstractSpinBoxPrivate::interpret() text '"
<< edit->displayText()
- << "' >> '" << copy << "'"
- << "' >> '" << tmp << "'";
+ << "' >> '" << copy << '\''
+ << "' >> '" << tmp << '\'';
doInterpret = tmp != copy && (q->validate(tmp, pos) == QValidator::Acceptable);
if (!doInterpret) {
diff --git a/src/gui/widgets/qabstractspinbox.h b/src/gui/widgets/qabstractspinbox.h
index 19bb057..bcbc363 100644
--- a/src/gui/widgets/qabstractspinbox.h
+++ b/src/gui/widgets/qabstractspinbox.h
@@ -122,6 +122,8 @@ public:
void interpretText();
bool event(QEvent *event);
+ QVariant inputMethodQuery(Qt::InputMethodQuery) const;
+
virtual QValidator::State validate(QString &input, int &pos) const;
virtual void fixup(QString &input) const;
diff --git a/src/gui/widgets/qactiontokeyeventmapper.cpp b/src/gui/widgets/qactiontokeyeventmapper.cpp
new file mode 100644
index 0000000..9de2bd6
--- /dev/null
+++ b/src/gui/widgets/qactiontokeyeventmapper.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#include "qevent.h"
+#include "qactiontokeyeventmapper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QActionToKeyEventMapper::QActionToKeyEventMapper(QAction *softKeyAction, Qt::Key key, QObject *parent)
+ : QObject(parent)
+ , m_softKeyAction(softKeyAction)
+ , m_key(key)
+{
+
+}
+
+QString QActionToKeyEventMapper::roleText(QAction::SoftKeyRole role)
+{
+ switch (role) {
+ case QAction::OptionsSoftKey:
+ return QAction::tr("Options");
+ case QAction::SelectSoftKey:
+ return QAction::tr("Select");
+ case QAction::BackSoftKey:
+ return QAction::tr("Back");
+ case QAction::NextSoftKey:
+ return QAction::tr("Next");
+ case QAction::PreviousSoftKey:
+ return QAction::tr("Previous");
+ case QAction::OkSoftKey:
+ return QAction::tr("Ok");
+ case QAction::CancelSoftKey:
+ return QAction::tr("Cancel");
+ case QAction::EditSoftKey:
+ return QAction::tr("Edit");
+ case QAction::ViewSoftKey:
+ return QAction::tr("View");
+ default:
+ return QString();
+ };
+}
+void QActionToKeyEventMapper::addSoftKey(QAction::SoftKeyRole standardRole, Qt::Key key, QWidget *actionWidget)
+{
+ QAction *action = new QAction(actionWidget);
+ action->setSoftKeyRole(standardRole);
+ action->setText(roleText(standardRole));
+ QActionToKeyEventMapper *softKey = new QActionToKeyEventMapper(action, key, actionWidget);
+ connect(action, SIGNAL(triggered()), softKey, SLOT(sendKeyEvent()));
+ connect(action, SIGNAL(destroyed()), softKey, SLOT(deleteLater()));
+ actionWidget->setSoftKey(action);
+}
+
+void QActionToKeyEventMapper::removeSoftkey(QWidget *focussedWidget)
+{
+ focussedWidget->setSoftKey(0);
+}
+
+void QActionToKeyEventMapper::sendKeyEvent()
+{
+ QApplication::postEvent(parent(), new QKeyEvent(QEvent::KeyPress, m_key, Qt::NoModifier));
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/widgets/qactiontokeyeventmapper_p.h b/src/gui/widgets/qactiontokeyeventmapper_p.h
new file mode 100644
index 0000000..2cc1698
--- /dev/null
+++ b/src/gui/widgets/qactiontokeyeventmapper_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTIONTOKEYEVENTMAPPER_P_H
+#define QACTIONTOKEYEVENTMAPPER_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/qobject.h>
+#include "QtGui/qaction.h"
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QActionToKeyEventMapper : public QObject
+{
+ Q_OBJECT
+public:
+ QActionToKeyEventMapper(QAction *softKeyAction, Qt::Key key, QObject *parent);
+ static QString roleText(QAction::SoftKeyRole role);
+ static void addSoftKey(QAction::SoftKeyRole standardRole, Qt::Key key, QWidget *actionWidget);
+ static void removeSoftkey(QWidget *focussedWidget);
+private:
+ QAction *m_softKeyAction;
+ Qt::Key m_key;
+private Q_SLOTS:
+ void sendKeyEvent();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QACTIONTOKEYEVENTMAPPER_P_H
diff --git a/src/gui/widgets/qbuttongroup.cpp b/src/gui/widgets/qbuttongroup.cpp
index 090266e..a7aec00 100644
--- a/src/gui/widgets/qbuttongroup.cpp
+++ b/src/gui/widgets/qbuttongroup.cpp
@@ -48,8 +48,6 @@
\ingroup organizers
\ingroup geomanagement
- \ingroup appearance
- \mainclass
QButtonGroup provides an abstract container into which button widgets can
be placed. It does not provide a visual representation of this container
@@ -176,11 +174,22 @@
*/
/*!
- \fn void QButtonGroup::addButton(QAbstractButton *button, int id = -1);
+ \fn void QButtonGroup::addButton(QAbstractButton *button);
+
+ Adds the given \a button to the end of the group's internal list
+ of buttons. An id will be assigned to the button by this
+ QButtonGroup. Automatically assigned ids are guaranteed to be
+ negative, starting with -2. If you are also assigning your own
+ ids, use positive values to avoid conflicts.
+
+ \sa removeButton() buttons()
+*/
+
+/*!
+ \fn void QButtonGroup::addButton(QAbstractButton *button, int id);
Adds the given \a button to the button group, with the given \a
- id. If \a id is -1 (the default), an id will be assigned to the
- button by this QButtonGroup.
+ id. It is recommended to assign only positive ids.
\sa removeButton() buttons()
*/
diff --git a/src/gui/widgets/qcalendarwidget.cpp b/src/gui/widgets/qcalendarwidget.cpp
index 30aa5e4..dfd8639 100644
--- a/src/gui/widgets/qcalendarwidget.cpp
+++ b/src/gui/widgets/qcalendarwidget.cpp
@@ -198,7 +198,7 @@ QString QCalendarDayValidator::text() const
{
QString str;
if (m_day / 10 == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
str += QString::number(m_day);
return highlightString(str, m_pos);
}
@@ -210,7 +210,7 @@ QString QCalendarDayValidator::text(const QDate &date, int repeat) const
} else if (repeat == 2) {
QString str;
if (date.day() / 10 == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
return str + QString::number(date.day());
} else if (repeat == 3) {
return m_locale.dayName(date.dayOfWeek(), QLocale::ShortFormat);
@@ -316,7 +316,7 @@ QString QCalendarMonthValidator::text() const
{
QString str;
if (m_month / 10 == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
str += QString::number(m_month);
return highlightString(str, m_pos);
}
@@ -328,14 +328,13 @@ QString QCalendarMonthValidator::text(const QDate &date, int repeat) const
} else if (repeat == 2) {
QString str;
if (date.month() / 10 == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
return str + QString::number(date.month());
} else if (repeat == 3) {
return m_locale.standaloneMonthName(date.month(), QLocale::ShortFormat);
- } else if (repeat >= 4) {
+ } else /*if (repeat >= 4)*/ {
return m_locale.standaloneMonthName(date.month(), QLocale::LongFormat);
}
- return QString();
}
//////////////////////////////////
@@ -432,7 +431,7 @@ QString QCalendarYearValidator::text() const
int pow = 10;
for (int i = 0; i < 3; i++) {
if (m_year / pow == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
pow *= 10;
}
str += QString::number(m_year);
@@ -445,7 +444,7 @@ QString QCalendarYearValidator::text(const QDate &date, int repeat) const
QString str;
int year = date.year() % 100;
if (year / 10 == 0)
- str = QLatin1String("0");
+ str = QLatin1Char('0');
return str + QString::number(year);
}
return QString::number(date.year());
@@ -577,7 +576,7 @@ void QCalendarDateValidator::setFormat(const QString &format)
clear();
int pos = 0;
- const QLatin1String quote("'");
+ const QLatin1Char quote('\'');
bool quoting = false;
QString separator;
while (pos < format.size()) {
@@ -1961,7 +1960,7 @@ void QCalendarWidgetPrivate::_q_editingFinished()
\brief The QCalendarWidget class provides a monthly based
calendar widget allowing the user to select a date.
\since 4.2
- \mainclass
+
\ingroup advanced
\image cleanlooks-calendarwidget.png
@@ -2142,14 +2141,11 @@ QSize QCalendarWidget::minimumSizeHint() const
int end = 53;
int rows = 7;
int cols = 8;
- int startRow = 0;
- int startCol = 0;
const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) * 2;
if (horizontalHeaderFormat() == QCalendarWidget::NoHorizontalHeader) {
rows = 6;
- startRow = 1;
} else {
for (int i = 1; i <= 7; i++) {
QFontMetrics fm(d->m_model->formatForCell(0, i).font());
@@ -2160,7 +2156,6 @@ QSize QCalendarWidget::minimumSizeHint() const
if (verticalHeaderFormat() == QCalendarWidget::NoVerticalHeader) {
cols = 7;
- startCol = 1;
} else {
for (int i = 1; i <= 6; i++) {
QFontMetrics fm(d->m_model->formatForCell(i, 0).font());
@@ -2527,13 +2522,6 @@ void QCalendarWidget::setDateRange(const QDate &min, const QDate &max)
if (!min.isValid() || !max.isValid())
return;
- QDate minimum = min;
- QDate maximum = max;
- if (min > max) {
- minimum = max;
- maximum = min;
- }
-
QDate oldDate = d->m_model->m_date;
d->m_model->setRange(min, max);
d->yearEdit->setMinimum(d->m_model->m_minimumDate.year());
diff --git a/src/gui/widgets/qcheckbox.cpp b/src/gui/widgets/qcheckbox.cpp
index 992e2cb..a5937af 100644
--- a/src/gui/widgets/qcheckbox.cpp
+++ b/src/gui/widgets/qcheckbox.cpp
@@ -73,54 +73,62 @@ public:
\brief The QCheckBox widget provides a checkbox with a text label.
\ingroup basicwidgets
- \mainclass
- A QCheckBox is an option button that can be switched on (checked)
- or off (unchecked). Checkboxes are typically used to represent
- features in an application that can be enabled or disabled without
- affecting others, but different types of behavior can be
- implemented.
- A QButtonGroup can be used to group check buttons visually.
+ A QCheckBox is an option button that can be switched on (checked) or off
+ (unchecked). Checkboxes are typically used to represent features in an
+ application that can be enabled or disabled without affecting others, but
+ different types of behavior can be implemented. For example, a
+ QButtonGroup can be used to group check buttons logically, allowing
+ exclusive checkboxes. However, QButtonGroup does not provide any visual
+ representation.
+
+ The image below further illustrates the differences between exclusive and
+ non-exclusive checkboxes.
+
+ \table
+ \row \o \inlineimage checkboxes-exclusive.png
+ \o \inlineimage checkboxes-non-exclusive.png
+ \endtable
Whenever a checkbox is checked or cleared it emits the signal
- stateChanged(). Connect to this signal if you want to trigger an
- action each time the checkbox changes state. You can use
- isChecked() to query whether or not a checkbox is checked.
-
- In addition to the usual checked and unchecked states, QCheckBox
- optionally provides a third state to indicate "no change". This
- is useful whenever you need to give the user the option of neither
- checking nor unchecking a checkbox. If you need this third state,
- enable it with setTristate(), and use checkState() to query the current
- toggle state.
-
- Just like QPushButton, a checkbox displays text, and optionally a
- small icon. The icon is set with setIcon(). The text can be set in
- the constructor or with setText(). A shortcut key can be specified
- by preceding the preferred character with an ampersand. For
- example:
+ stateChanged(). Connect to this signal if you want to trigger an action
+ each time the checkbox changes state. You can use isChecked() to query
+ whether or not a checkbox is checked.
+
+ In addition to the usual checked and unchecked states, QCheckBox optionally
+ provides a third state to indicate "no change". This is useful whenever you
+ need to give the user the option of neither checking nor unchecking a
+ checkbox. If you need this third state, enable it with setTristate(), and
+ use checkState() to query the current toggle state.
+
+ Just like QPushButton, a checkbox displays text, and optionally a small
+ icon. The icon is set with setIcon(). The text can be set in the
+ constructor or with setText(). A shortcut key can be specified by preceding
+ the preferred character with an ampersand. For example:
\snippet doc/src/snippets/code/src_gui_widgets_qcheckbox.cpp 0
- In this example the shortcut is \e{Alt+A}. See the \l
- {QShortcut#mnemonic}{QShortcut} documentation for details (to
- display an actual ampersand, use '&&').
+ In this example the shortcut is \e{Alt+A}. See the \l{QShortcut#mnemonic}
+ {QShortcut} documentation for details (to display an actual ampersand,
+ use '&&').
- Important inherited functions: text(), setText(), text(),
- pixmap(), setPixmap(), accel(), setAccel(), isToggleButton(),
- setDown(), isDown(), isOn(), checkState(), autoRepeat(),
- isExclusiveToggle(), group(), setAutoRepeat(), toggle(),
- pressed(), released(), clicked(), toggled(), checkState(), and
- stateChanged().
+ Important inherited functions: text(), setText(), text(), pixmap(),
+ setPixmap(), accel(), setAccel(), isToggleButton(), setDown(), isDown(),
+ isOn(), checkState(), autoRepeat(), isExclusiveToggle(), group(),
+ setAutoRepeat(), toggle(), pressed(), released(), clicked(), toggled(),
+ checkState(), and stateChanged().
\table 100%
- \row \o \inlineimage macintosh-checkbox.png Screenshot of a Macintosh style checkbox
- \o A checkbox shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
- \row \o \inlineimage windows-checkbox.png Screenshot of a Windows XP style checkbox
- \o A checkbox shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
- \row \o \inlineimage plastique-checkbox.png Screenshot of a Plastique style checkbox
- \o A checkbox shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
+ \row
+ \o \inlineimage macintosh-checkbox.png Screenshot of a Macintosh style checkbox
+ \o A checkbox shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
+ \row
+ \o \inlineimage windows-checkbox.png Screenshot of a Windows XP style checkbox
+ \o A checkbox shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
+ \row
+ \o \inlineimage plastique-checkbox.png Screenshot of a Plastique style checkbox
+ \o A checkbox shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
\endtable
\sa QAbstractButton, QRadioButton, {fowler}{GUI Design Handbook: Check Box}
@@ -138,8 +146,8 @@ public:
/*!
\fn void QCheckBox::stateChanged(int state)
- This signal is emitted whenever the check box's state changes,
- i.e. whenever the user checks or unchecks it.
+ This signal is emitted whenever the check box's state changes, i.e.
+ whenever the user checks or unchecks it.
\a state contains the check box's new Qt::CheckState.
*/
@@ -161,9 +169,9 @@ void QCheckBoxPrivate::init()
}
/*!
- Initialize \a option with the values from this QCheckBox. This method is useful
- for subclasses when they need a QStyleOptionButton, but don't want to fill
- in all the information themselves.
+ Initializes \a option with the values from this QCheckBox. This method is
+ useful for subclasses that require a QStyleOptionButton, but do not want
+ to fill in all the information themselves.
\sa QStyleOption::initFrom()
*/
@@ -193,7 +201,7 @@ void QCheckBox::initStyleOption(QStyleOptionButton *option) const
/*!
Constructs a checkbox with the given \a parent, but with no text.
- The \a parent argument is passed on to the QAbstractButton constructor.
+ \a parent is passed on to the QAbstractButton constructor.
*/
QCheckBox::QCheckBox(QWidget *parent)
@@ -206,7 +214,7 @@ QCheckBox::QCheckBox(QWidget *parent)
/*!
Constructs a checkbox with the given \a parent and \a text.
- The \a parent argument is passed on to the QAbstractButton constructor.
+ \a parent is passed on to the QAbstractButton constructor.
*/
QCheckBox::QCheckBox(const QString &text, QWidget *parent)
@@ -231,10 +239,8 @@ bool QCheckBox::isTristate() const
/*!
- Returns the check box's check state.
- If you do not need tristate support, you can also
- use \l QAbstractButton::isChecked() which returns
- a boolean.
+ Returns the check box's check state. If you do not need tristate support,
+ you can also use \l QAbstractButton::isChecked() which returns a boolean.
\sa setCheckState() Qt::CheckState
*/
@@ -247,10 +253,9 @@ Qt::CheckState QCheckBox::checkState() const
}
/*!
- Sets the check box's check state to \a state.
- If you do not need tristate support, you can also
- use \l QAbstractButton::setChecked() which takes
- a boolean.
+ Sets the check box's check state to \a state. If you do not need tristate
+ support, you can also use \l QAbstractButton::setChecked() which takes a
+ boolean.
\sa checkState() Qt::CheckState
*/
@@ -274,7 +279,8 @@ void QCheckBox::setCheckState(Qt::CheckState state)
}
-/*!\reimp
+/*!
+ \reimp
*/
QSize QCheckBox::sizeHint() const
{
@@ -294,7 +300,8 @@ QSize QCheckBox::sizeHint() const
return d->sizeHint;
}
-/*!\reimp
+/*!
+ \reimp
*/
void QCheckBox::paintEvent(QPaintEvent *)
{
@@ -325,7 +332,9 @@ void QCheckBox::mouseMoveEvent(QMouseEvent *e)
}
-/*!\reimp*/
+/*!
+ \reimp
+*/
bool QCheckBox::hitButton(const QPoint &pos) const
{
QStyleOptionButton opt;
@@ -333,7 +342,9 @@ bool QCheckBox::hitButton(const QPoint &pos) const
return style()->subElementRect(QStyle::SE_CheckBoxClickRect, &opt, this).contains(pos);
}
-/*!\reimp*/
+/*!
+ \reimp
+*/
void QCheckBox::checkStateSet()
{
Q_D(QCheckBox);
@@ -345,7 +356,9 @@ void QCheckBox::checkStateSet()
}
}
-/*!\reimp*/
+/*!
+ \reimp
+*/
void QCheckBox::nextCheckState()
{
Q_D(QCheckBox);
diff --git a/src/gui/widgets/qcocoamenu_mac.mm b/src/gui/widgets/qcocoamenu_mac.mm
index be0feab..bda9352 100644
--- a/src/gui/widgets/qcocoamenu_mac.mm
+++ b/src/gui/widgets/qcocoamenu_mac.mm
@@ -98,7 +98,9 @@ QT_USE_NAMESPACE
while (QWidget *popup
= QApplication::activePopupWidget())
popup->close();
- qt_mac_emit_menuSignals(((QT_MANGLE_NAMESPACE(QCocoaMenu) *)menu)->qmenu, true);
+ QMenu *qtmenu = static_cast<QT_MANGLE_NAMESPACE(QCocoaMenu) *>(menu)->qmenu;
+ qt_mac_emit_menuSignals(qtmenu, true);
+ qt_mac_menu_collapseSeparators(menu, qtmenu->separatorsCollapsible());
}
- (void)menuWillClose:(NSMenu*)menu;
diff --git a/src/gui/widgets/qcocoatoolbardelegate_mac.mm b/src/gui/widgets/qcocoatoolbardelegate_mac.mm
index 2b52290..67c893a 100644
--- a/src/gui/widgets/qcocoatoolbardelegate_mac.mm
+++ b/src/gui/widgets/qcocoatoolbardelegate_mac.mm
@@ -43,6 +43,7 @@
#ifdef QT_MAC_USE_COCOA
#include <private/qmainwindowlayout_p.h>
#include <private/qt_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
#include <private/qcocoaview_mac_p.h>
#include <private/qwidget_p.h>
#include <qtoolbar.h>
@@ -99,7 +100,8 @@ QT_FORWARD_DECLARE_CLASS(QCFString);
{
Q_UNUSED(flag);
Q_UNUSED(nstoolbar);
- QToolBar *tb = mainWindowLayout->cocoaItemIDToToolbarHash.value(QCFString::toQString(CFStringRef(itemIdentifier)));
+ QToolBar *tb = mainWindowLayout->cocoaItemIDToToolbarHash.value(
+ QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)(itemIdentifier));
NSToolbarItem *item = nil;
if (tb) {
item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
@@ -111,7 +113,8 @@ QT_FORWARD_DECLARE_CLASS(QCFString);
- (void)toolbarWillAddItem:(NSNotification *)notification
{
NSToolbarItem *item = [[notification userInfo] valueForKey:@"item"];
- QToolBar *tb = mainWindowLayout->cocoaItemIDToToolbarHash.value(QCFString::toQString(CFStringRef([item itemIdentifier])));
+ QToolBar *tb = mainWindowLayout->cocoaItemIDToToolbarHash.value(
+ QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)([item itemIdentifier]));
if (!tb)
return; // I can't really do anything about this.
[item retain];
@@ -119,12 +122,9 @@ QT_FORWARD_DECLARE_CLASS(QCFString);
NSArray *items = [[qt_mac_window_for(mainWindowLayout->layoutState.mainWindow->window()) toolbar] items];
int someIndex = 0;
- bool foundItem = false;
for (NSToolbarItem *i in items) {
- if (i == item) {
- foundItem = true;
+ if (i == item)
break;
- }
++someIndex;
}
mainWindowLayout->toolbarItemsCopy.insert(someIndex, item);
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index c80a225..4c22975 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -59,11 +59,12 @@
#ifndef QT_NO_IM
#include "qinputcontext.h"
#endif
+#include <private/qapplication_p.h>
#include <private/qcombobox_p.h>
#include <private/qabstractitemmodel_p.h>
#include <private/qabstractscrollarea_p.h>
#include <qdebug.h>
-
+#include <private/qactiontokeyeventmapper_p.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
#endif
@@ -77,8 +78,6 @@
#endif
QT_BEGIN_NAMESPACE
-extern QHash<QByteArray, QFont> *qt_app_fonts_hash();
-
QComboBoxPrivate::QComboBoxPrivate()
: QWidgetPrivate(),
model(0),
@@ -149,8 +148,10 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt
menuOption.rect = option.rect;
// Make sure fonts set on the combo box also overrides the font for the popup menu.
- if (mCombo->testAttribute(Qt::WA_SetFont) || mCombo->testAttribute(Qt::WA_MacSmallSize)
- || mCombo->testAttribute(Qt::WA_MacMiniSize))
+ if (mCombo->testAttribute(Qt::WA_SetFont)
+ || mCombo->testAttribute(Qt::WA_MacSmallSize)
+ || mCombo->testAttribute(Qt::WA_MacMiniSize)
+ || mCombo->font() != qt_app_fonts_hash()->value("QComboBox", QFont()))
menuOption.font = mCombo->font();
else
menuOption.font = qt_app_fonts_hash()->value("QComboMenuItem", mCombo->font());
@@ -628,6 +629,9 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
case Qt::Key_Select:
#endif
if (view->currentIndex().isValid() && (view->currentIndex().flags() & Qt::ItemIsEnabled) ) {
+#ifdef QT_KEYPAD_NAVIGATION
+ QActionToKeyEventMapper::removeSoftkey(this);
+#endif
combo->hidePopup();
emit itemSelected(view->currentIndex());
}
@@ -640,6 +644,7 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
case Qt::Key_Escape:
#ifdef QT_KEYPAD_NAVIGATION
case Qt::Key_Back:
+ QActionToKeyEventMapper::removeSoftkey(this);
#endif
combo->hidePopup();
return true;
@@ -862,7 +867,7 @@ QComboBox::QComboBox(bool rw, QWidget *parent, const char *name)
\brief The QComboBox widget is a combined button and popup list.
\ingroup basicwidgets
- \mainclass
+
A QComboBox provides a means of presenting a list of options to the user
in a way that takes up the minimum amount of screen space.
@@ -949,6 +954,7 @@ QComboBoxPrivateContainer* QComboBoxPrivate::viewContainer()
container->itemView()->setTextElideMode(Qt::ElideMiddle);
updateDelegate(true);
updateLayoutDirection();
+ updateViewContainerPaletteAndOpacity();
QObject::connect(container, SIGNAL(itemSelected(QModelIndex)),
q, SLOT(_q_itemSelected(QModelIndex)));
QObject::connect(container->itemView()->selectionModel(),
@@ -1051,6 +1057,27 @@ void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/,
}
+void QComboBoxPrivate::updateViewContainerPaletteAndOpacity()
+{
+ if (!container)
+ return;
+ Q_Q(QComboBox);
+ QStyleOptionComboBox opt;
+ q->initStyleOption(&opt);
+#ifndef QT_NO_MENU
+ if (q->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, q)) {
+ QMenu menu;
+ menu.ensurePolished();
+ container->setPalette(menu.palette());
+ container->setWindowOpacity(menu.windowOpacity());
+ } else
+#endif
+ {
+ container->setPalette(q->palette());
+ container->setWindowOpacity(1.0);
+ }
+}
+
/*!
Initialize \a option with the values from this QComboBox. This method
is useful for subclasses when they need a QStyleOptionComboBox, but don't want
@@ -1224,8 +1251,12 @@ QComboBox::~QComboBox()
// ### check delegateparent and delete delegate if us?
Q_D(QComboBox);
- disconnect(d->model, SIGNAL(destroyed()),
- this, SLOT(_q_modelDestroyed()));
+ QT_TRY {
+ disconnect(d->model, SIGNAL(destroyed()),
+ this, SLOT(_q_modelDestroyed()));
+ } QT_CATCH(...) {
+ ; // objects can't throw in destructor
+ }
}
/*!
@@ -2443,6 +2474,11 @@ void QComboBox::showPopup()
#endif
container->update();
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::keypadNavigationEnabled())
+ view()->setEditFocus(true);
+ QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, view());
+#endif
}
/*!
@@ -2594,20 +2630,7 @@ void QComboBox::changeEvent(QEvent *e)
hidePopup();
break;
case QEvent::PaletteChange: {
- QStyleOptionComboBox opt;
- initStyleOption(&opt);
-#ifndef QT_NO_MENU
- if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
- QMenu menu;
- menu.ensurePolished();
- d->viewContainer()->setPalette(menu.palette());
- d->viewContainer()->setWindowOpacity(menu.windowOpacity());
- } else
-#endif
- {
- d->viewContainer()->setPalette(palette());
- d->viewContainer()->setWindowOpacity(1.0);
- }
+ d->updateViewContainerPaletteAndOpacity();
break;
}
case QEvent::FontChange:
diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h
index 9b6597b..ee30b12 100644
--- a/src/gui/widgets/qcombobox_p.h
+++ b/src/gui/widgets/qcombobox_p.h
@@ -290,7 +290,7 @@ public:
QComboBoxDelegate(QObject *parent, QComboBox *cmb) : QItemDelegate(parent), mCombo(cmb) {}
static bool isSeparator(const QModelIndex &index) {
- return index.data(Qt::AccessibleDescriptionRole).toString() == QString::fromLatin1("separator");
+ return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator");
}
static void setSeparator(QAbstractItemModel *model, const QModelIndex &index) {
model->setData(index, QString::fromLatin1("separator"), Qt::AccessibleDescriptionRole);
@@ -370,6 +370,7 @@ public:
void updateDelegate(bool force = false);
void keyboardSearchString(const QString &text);
void modelChanged();
+ void updateViewContainerPaletteAndOpacity();
QAbstractItemModel *model;
QLineEdit *lineEdit;
diff --git a/src/gui/widgets/qcommandlinkbutton.cpp b/src/gui/widgets/qcommandlinkbutton.cpp
index 62628f9..f1b7902 100644
--- a/src/gui/widgets/qcommandlinkbutton.cpp
+++ b/src/gui/widgets/qcommandlinkbutton.cpp
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
\brief The QCommandLinkButton widget provides a Vista style command link button.
\ingroup basicwidgets
- \mainclass
+
The command link is a new control that was introduced by Windows Vista. It's
intended use is similar to that of a radio button in that it is used to choose
@@ -140,10 +140,12 @@ QFont QCommandLinkButtonPrivate::titleFont() const
Q_Q(const QCommandLinkButton);
QFont font = q->font();
if (usingVistaStyle()) {
- font.setPointSizeF(12.0);
+ if (!q->testAttribute(Qt::WA_SetFont))
+ font.setPointSizeF(12.0);
} else {
font.setBold(true);
- font.setPointSizeF(9.0);
+ if (!q->testAttribute(Qt::WA_SetFont))
+ font.setPointSizeF(9.0);
}
return font;
}
@@ -152,7 +154,8 @@ QFont QCommandLinkButtonPrivate::descriptionFont() const
{
Q_Q(const QCommandLinkButton);
QFont font = q->font();
- font.setPointSizeF(9.0);
+ if (!q->testAttribute(Qt::WA_SetFont))
+ font.setPointSizeF(9.0);
return font;
}
@@ -202,7 +205,9 @@ void QCommandLinkButtonPrivate::init()
q->setSizePolicy(policy);
q->setIconSize(QSize(20, 20));
- q->setIcon(q->style()->standardIcon(QStyle::SP_CommandLink));
+ QStyleOptionButton opt;
+ q->initStyleOption(&opt);
+ q->setIcon(q->style()->standardIcon(QStyle::SP_CommandLink, &opt));
}
// Calculates the height of the description text based on widget width
diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp
index bfeea30..f8308ba 100644
--- a/src/gui/widgets/qdatetimeedit.cpp
+++ b/src/gui/widgets/qdatetimeedit.cpp
@@ -1,4 +1,4 @@
-/****************************************************************************)
+/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
@@ -75,7 +75,7 @@ QT_BEGIN_NAMESPACE
\brief The QDateTimeEdit class provides a widget for editing dates and times.
\ingroup basicwidgets
- \mainclass
+
QDateTimeEdit allows the user to edit dates by using the keyboard or
the arrow keys to increase and decrease date and time values. The
@@ -220,6 +220,9 @@ QDateTimeEdit::QDateTimeEdit(const QVariant &var, QVariant::Type parserType, QWi
\property QDateTimeEdit::dateTime
\brief the QDateTime that is set in the QDateTimeEdit
+ When setting this property the timespec of the QDateTimeEdit remains the same
+ and the timespec of the new QDateTime is ignored.
+
By default, this property contains a date that refers to January 1,
2000 and a time of 00:00:00 and 0 milliseconds.
@@ -239,7 +242,7 @@ void QDateTimeEdit::setDateTime(const QDateTime &datetime)
d->clearCache();
if (!(d->sections & DateSections_Mask))
setDateRange(datetime.date(), datetime.date());
- d->setValue(QVariant(datetime), EmitIfChanged);
+ d->setValue(QDateTime(datetime.date(), datetime.time(), d->spec), EmitIfChanged);
}
}
@@ -932,9 +935,6 @@ void QDateTimeEdit::setCalendarPopup(bool enable)
\property QDateTimeEdit::timeSpec
\brief the current timespec used by the date time edit.
\since 4.4
-
- All dates/passed to the date time edit will be converted to this
- timespec.
*/
Qt::TimeSpec QDateTimeEdit::timeSpec() const
@@ -1086,10 +1086,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
//hide cursor
d->edit->d_func()->setCursorVisible(false);
- if (d->edit->d_func()->cursorTimer > 0)
- killTimer(d->edit->d_func()->cursorTimer);
- d->edit->d_func()->cursorTimer = 0;
-
+ d->edit->d_func()->control->setCursorBlinkPeriod(0);
d->setSelected(0);
}
}
@@ -1110,10 +1107,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
//hide cursor
d->edit->d_func()->setCursorVisible(false);
- if (d->edit->d_func()->cursorTimer > 0)
- killTimer(d->edit->d_func()->cursorTimer);
- d->edit->d_func()->cursorTimer = 0;
-
+ d->edit->d_func()->control->setCursorBlinkPeriod(0);
d->setSelected(0);
oldCurrent = 0;
}
@@ -1126,23 +1120,25 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
case Qt::Key_Left:
case Qt::Key_Right:
if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) {
+ if (
#ifdef QT_KEYPAD_NAVIGATION
- if (!QApplication::keypadNavigationEnabled() || !hasEditFocus()) {
- select = false;
- break;
- }
-#else
- if (!(event->modifiers() & Qt::ControlModifier)) {
+ QApplication::keypadNavigationEnabled() && !hasEditFocus()
+ || !QApplication::keypadNavigationEnabled() &&
+#endif
+ !(event->modifiers() & Qt::ControlModifier)) {
select = false;
break;
}
#ifdef Q_WS_MAC
- else {
+ else
+#ifdef QT_KEYPAD_NAVIGATION
+ if (!QApplication::keypadNavigationEnabled())
+#endif
+ {
select = (event->modifiers() & Qt::ShiftModifier);
break;
}
#endif
-#endif // QT_KEYPAD_NAVIGATION
}
// else fall through
case Qt::Key_Backtab:
@@ -1510,7 +1506,7 @@ void QDateTimeEdit::mousePressEvent(QMouseEvent *event)
the QDateTimeEdit widget.
\ingroup basicwidgets
- \mainclass
+
Many of the properties and functions provided by QTimeEdit are implemented in
QDateTimeEdit. The following properties are most relevant to users of this
@@ -1572,7 +1568,7 @@ QTimeEdit::QTimeEdit(const QTime &time, QWidget *parent)
the QDateTimeEdit widget.
\ingroup basicwidgets
- \mainclass
+
Many of the properties and functions provided by QDateEdit are implemented in
QDateTimeEdit. The following properties are most relevant to users of this
@@ -1647,7 +1643,6 @@ QDateTimeEditPrivate::QDateTimeEditPrivate()
cachedDay = -1;
currentSectionIndex = FirstSectionIndex;
- layoutDirection = QApplication::layoutDirection();
first.type = FirstSection;
last.type = LastSection;
none.type = NoSection;
@@ -1934,7 +1929,6 @@ QDateTime QDateTimeEditPrivate::validateAndInterpret(QString &input, int &positi
/*!
\internal
- \reimp
*/
QString QDateTimeEditPrivate::textFromValue(const QVariant &f) const
@@ -1945,7 +1939,6 @@ QString QDateTimeEditPrivate::textFromValue(const QVariant &f) const
/*!
\internal
- \reimp
This function's name is slightly confusing; it is not to be confused
with QAbstractSpinBox::valueFromText().
@@ -2103,7 +2096,6 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c
/*!
\internal
- \reimp
*/
void QDateTimeEditPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
@@ -2133,7 +2125,6 @@ void QDateTimeEditPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
/*!
\internal
- \reimp
*/
void QDateTimeEditPrivate::_q_editorCursorPositionChanged(int oldpos, int newpos)
@@ -2278,6 +2269,7 @@ void QDateTimeEdit::paintEvent(QPaintEvent *event)
optCombo.init(this);
optCombo.editable = true;
+ optCombo.frame = opt.frame;
optCombo.subControls = opt.subControls;
optCombo.activeSubControls = opt.activeSubControls;
optCombo.state = opt.state;
@@ -2390,6 +2382,7 @@ void QDateTimeEditPrivate::init(const QVariant &var)
q->setCalendarPopup(true);
#endif
updateTimeSpec();
+ q->setInputMethodHints(Qt::ImhPreferNumbers);
setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem);
}
diff --git a/src/gui/widgets/qdatetimeedit_p.h b/src/gui/widgets/qdatetimeedit_p.h
index a46de93..7e1c24d 100644
--- a/src/gui/widgets/qdatetimeedit_p.h
+++ b/src/gui/widgets/qdatetimeedit_p.h
@@ -132,7 +132,6 @@ public:
mutable bool cacheGuard;
QString defaultDateFormat, defaultTimeFormat, defaultDateTimeFormat, unreversedFormat;
- Qt::LayoutDirection layoutDirection;
mutable QVariant conflictGuard;
bool hasHadFocus, formatExplicitlySet, calendarPopup;
QStyle::StateFlag arrowState;
diff --git a/src/gui/widgets/qdial.cpp b/src/gui/widgets/qdial.cpp
index 1491b55..4d3705a 100644
--- a/src/gui/widgets/qdial.cpp
+++ b/src/gui/widgets/qdial.cpp
@@ -168,7 +168,7 @@ int QDialPrivate::valueFromPoint(const QPoint &p) const
\brief The QDial class provides a rounded range control (like a speedometer or potentiometer).
\ingroup basicwidgets
- \mainclass
+
QDial is used when the user needs to control a value within a
program-definable range, and the range either wraps around
diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp
index ed6649f..c036106 100644
--- a/src/gui/widgets/qdialogbuttonbox.cpp
+++ b/src/gui/widgets/qdialogbuttonbox.cpp
@@ -57,8 +57,8 @@ QT_BEGIN_NAMESPACE
\brief The QDialogButtonBox class is a widget that presents buttons in a
layout that is appropriate to the current widget style.
- \ingroup application
- \mainclass
+ \ingroup dialog-classes
+
Dialogs and message boxes typically present buttons in a layout that
conforms to the interface guidelines for that platform. Invariably,
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index bc08415..3d1d3b1 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -155,6 +155,11 @@ QSize QDockAreaLayoutItem::maximumSize() const
return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
}
+bool QDockAreaLayoutItem::hasFixedSize(Qt::Orientation o) const
+{
+ return perp(o, minimumSize()) == perp(o, maximumSize());
+}
+
bool QDockAreaLayoutItem::expansive(Qt::Orientation o) const
{
if ((flags & GapItem) || placeHolderItem != 0)
@@ -216,9 +221,9 @@ static quintptr tabId(const QDockAreaLayoutItem &item)
#endif
QDockAreaLayoutInfo::QDockAreaLayoutInfo()
- : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), rect(0, 0, -1, -1), mainWindow(0)
+ : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
#ifndef QT_NO_TABBAR
- , tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth)
+ , tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth), tabBarVisible(false)
#endif
{
}
@@ -226,9 +231,9 @@ QDockAreaLayoutInfo::QDockAreaLayoutInfo()
QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos,
Qt::Orientation _o, int tbshape,
QMainWindow *window)
- : sep(_sep), dockPos(_dockPos), o(_o), rect(0, 0, -1, -1), mainWindow(window)
+ : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
#ifndef QT_NO_TABBAR
- , tabbed(false), tabBar(0), tabBarShape(static_cast<QTabBar::Shape>(tbshape))
+ , tabbed(false), tabBar(0), tabBarShape(static_cast<QTabBar::Shape>(tbshape)), tabBarVisible(false)
#endif
{
#ifdef QT_NO_TABBAR
@@ -244,7 +249,7 @@ QSize QDockAreaLayoutInfo::size() const
void QDockAreaLayoutInfo::clear()
{
item_list.clear();
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
#ifndef QT_NO_TABBAR
tabbed = false;
tabBar = 0;
@@ -388,10 +393,9 @@ QSize QDockAreaLayoutInfo::sizeHint() const
return QSize(0, 0);
int a = 0, b = 0;
- bool prev_gap = false;
- bool first = true;
int min_perp = 0;
int max_perp = QWIDGETSIZE_MAX;
+ const QDockAreaLayoutItem *previous = 0;
for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
@@ -409,14 +413,15 @@ QSize QDockAreaLayoutInfo::sizeHint() const
} else
#endif
{
- if (!first && !gap && !prev_gap)
+ if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
+ && !previous->hasFixedSize(o)) {
a += sep;
+ }
a += gap ? item.size : pick(o, size_hint);
}
b = qMax(b, perp(o, size_hint));
- prev_gap = gap;
- first = false;
+ previous = &item;
}
max_perp = qMax(max_perp, min_perp);
@@ -539,21 +544,20 @@ void QDockAreaLayoutInfo::fitItems()
int max_size = realMaxSize(*this);
int last_index = -1;
- bool prev_gap = false;
- bool first = true;
+ const QDockAreaLayoutItem *previous = 0;
for (int i = 0; i < item_list.size(); ++i) {
QDockAreaLayoutItem &item = item_list[i];
if (item.skip())
continue;
bool gap = item.flags & QDockAreaLayoutItem::GapItem;
- if (!first && !gap && !prev_gap) {
- QLayoutStruct &ls = layout_struct_list[j++];
- ls.init();
- ls.minimumSize = sep;
- ls.maximumSize = sep;
- ls.sizeHint = sep;
- ls.empty = false;
+ if (previous && !gap) {
+ if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
+ QLayoutStruct &ls = layout_struct_list[j++];
+ ls.init();
+ ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : sep;
+ ls.empty = false;
+ }
}
if (item.flags & QDockAreaLayoutItem::KeepSize) {
@@ -592,8 +596,7 @@ void QDockAreaLayoutInfo::fitItems()
}
item.flags &= ~QDockAreaLayoutItem::KeepSize;
- prev_gap = gap;
- first = false;
+ previous = &item;
}
layout_struct_list.resize(j);
@@ -607,8 +610,8 @@ void QDockAreaLayoutInfo::fitItems()
qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
j = 0;
- prev_gap = false;
- first = true;
+ bool prev_gap = false;
+ bool first = true;
for (int i = 0; i < item_list.size(); ++i) {
QDockAreaLayoutItem &item = item_list[i];
if (item.skip())
@@ -921,43 +924,41 @@ static int separatorMoveHelper(QVector<QLayoutStruct> &list, int index, int delt
return delta;
}
-int QDockAreaLayoutInfo::separatorMove(int index, int delta, QVector<QLayoutStruct> *cache)
+int QDockAreaLayoutInfo::separatorMove(int index, int delta)
{
#ifndef QT_NO_TABBAR
Q_ASSERT(!tabbed);
#endif
- if (cache->isEmpty()) {
- QVector<QLayoutStruct> &list = *cache;
- list.resize(item_list.size());
- for (int i = 0; i < item_list.size(); ++i) {
- const QDockAreaLayoutItem &item = item_list.at(i);
- QLayoutStruct &ls = list[i];
- Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
- if (item.skip()) {
- ls.empty = true;
- } else {
- ls.empty = false;
- ls.pos = item.pos;
- ls.size = item.size;
- ls.minimumSize = pick(o, item.minimumSize());
- ls.maximumSize = pick(o, item.maximumSize());
- }
+ QVector<QLayoutStruct> list(item_list.size());
+ for (int i = 0; i < list.size(); ++i) {
+ const QDockAreaLayoutItem &item = item_list.at(i);
+ QLayoutStruct &ls = list[i];
+ Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
+ if (item.skip()) {
+ ls.empty = true;
+ } else {
+ const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+ ls.empty = false;
+ ls.pos = item.pos;
+ ls.size = item.size + separatorSpace;
+ ls.minimumSize = pick(o, item.minimumSize()) + separatorSpace;
+ ls.maximumSize = pick(o, item.maximumSize()) + separatorSpace;
+
}
}
- QVector<QLayoutStruct> list = *cache;
-
- delta = separatorMoveHelper(list, index, delta, sep);
+ //the separator space has been added to the size, so we pass 0 as a parameter
+ delta = separatorMoveHelper(list, index, delta, 0 /*separator*/);
- for (int i = 0; i < item_list.size(); ++i) {
+ for (int i = 0; i < list.size(); ++i) {
QDockAreaLayoutItem &item = item_list[i];
if (item.skip())
continue;
QLayoutStruct &ls = list[i];
- item.size = ls.size;
+ const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+ item.size = ls.size - separatorSpace;
item.pos = ls.pos;
-
if (item.subinfo != 0) {
item.subinfo->rect = itemRect(i);
item.subinfo->fitItems();
@@ -993,15 +994,15 @@ void QDockAreaLayoutInfo::unnest(int index)
}
}
-void QDockAreaLayoutInfo::remove(QList<int> path)
+void QDockAreaLayoutInfo::remove(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
if (path.count() > 1) {
- int index = path.takeFirst();
+ const int index = path.first();
QDockAreaLayoutItem &item = item_list[index];
Q_ASSERT(item.subinfo != 0);
- item.subinfo->remove(path);
+ item.subinfo->remove(path.mid(1));
unnest(index);
} else {
int index = path.first();
@@ -1009,18 +1010,18 @@ void QDockAreaLayoutInfo::remove(QList<int> path)
}
}
-QLayoutItem *QDockAreaLayoutInfo::plug(QList<int> path)
+QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
- int index = path.takeFirst();
+ int index = path.first();
if (index < 0)
index = -index - 1;
- if (!path.isEmpty()) {
+ if (path.count() > 1) {
const QDockAreaLayoutItem &item = item_list.at(index);
Q_ASSERT(item.subinfo != 0);
- return item.subinfo->plug(path);
+ return item.subinfo->plug(path.mid(1));
}
QDockAreaLayoutItem &item = item_list[index];
@@ -1058,18 +1059,17 @@ QLayoutItem *QDockAreaLayoutInfo::plug(QList<int> path)
return item.widgetItem;
}
-QLayoutItem *QDockAreaLayoutInfo::unplug(QList<int> path)
+QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
+ const int index = path.first();
if (path.count() > 1) {
- int index = path.takeFirst();
const QDockAreaLayoutItem &item = item_list.at(index);
Q_ASSERT(item.subinfo != 0);
- return item.subinfo->unplug(path);
+ return item.subinfo->unplug(path.mid(1));
}
- int index = path.first();
QDockAreaLayoutItem &item = item_list[index];
int prev = this->prev(index);
int next = this->next(index);
@@ -1141,12 +1141,12 @@ static QRect dockedGeometry(QWidget *widget)
return result;
}
-bool QDockAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *dockWidgetItem)
+bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
{
Q_ASSERT(!path.isEmpty());
bool insert_tabbed = false;
- int index = path.takeFirst();
+ int index = path.first();
if (index < 0) {
insert_tabbed = true;
index = -index - 1;
@@ -1154,7 +1154,7 @@ bool QDockAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *dockWidgetItem
// dump(qDebug() << "insertGap() before:" << index << tabIndex, *this, QString());
- if (!path.isEmpty()) {
+ if (path.count() > 1) {
QDockAreaLayoutItem &item = item_list[index];
if (item.subinfo == 0
@@ -1193,8 +1193,7 @@ bool QDockAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *dockWidgetItem
#endif
}
- bool result = item.subinfo->insertGap(path, dockWidgetItem);
- return result;
+ return item.subinfo->insertGap(path.mid(1), dockWidgetItem);
}
// create the gap item
@@ -1294,16 +1293,16 @@ QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QWidget *widget)
return 0;
}
-QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QList<int> path)
+QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(const QList<int> &path)
{
- int index = path.takeFirst();
+ int index = path.first();
if (index < 0)
index = -index - 1;
if (index >= item_list.count())
return this;
- if (path.isEmpty() || item_list.at(index).subinfo == 0)
+ if (path.count() == 1 || item_list.at(index).subinfo == 0)
return this;
- return item_list.at(index).subinfo->info(path);
+ return item_list.at(index).subinfo->info(path.mid(1));
}
QRect QDockAreaLayoutInfo::itemRect(int index) const
@@ -1334,17 +1333,18 @@ QRect QDockAreaLayoutInfo::itemRect(int index) const
return result;
}
-QRect QDockAreaLayoutInfo::itemRect(QList<int> path) const
+QRect QDockAreaLayoutInfo::itemRect(const QList<int> &path) const
{
Q_ASSERT(!path.isEmpty());
+ const int index = path.first();
if (path.count() > 1) {
- const QDockAreaLayoutItem &item = item_list.at(path.takeFirst());
+ const QDockAreaLayoutItem &item = item_list.at(index);
Q_ASSERT(item.subinfo != 0);
- return item.subinfo->itemRect(path);
+ return item.subinfo->itemRect(path.mid(1));
}
- return itemRect(path.first());
+ return itemRect(index);
}
QRect QDockAreaLayoutInfo::separatorRect(int index) const
@@ -1366,16 +1366,17 @@ QRect QDockAreaLayoutInfo::separatorRect(int index) const
return QRect(pos, s);
}
-QRect QDockAreaLayoutInfo::separatorRect(QList<int> path) const
+QRect QDockAreaLayoutInfo::separatorRect(const QList<int> &path) const
{
Q_ASSERT(!path.isEmpty());
+ const int index = path.first();
if (path.count() > 1) {
- const QDockAreaLayoutItem &item = item_list.at(path.takeFirst());
+ const QDockAreaLayoutItem &item = item_list.at(index);
Q_ASSERT(item.subinfo != 0);
- return item.subinfo->separatorRect(path);
+ return item.subinfo->separatorRect(path.mid(1));
}
- return separatorRect(path.first());
+ return separatorRect(index);
}
QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
@@ -1408,11 +1409,12 @@ QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
continue;
- int margin = (sep == 1? 2 : 0);
- if (pos >= item.pos + item.size - margin && item.pos + item.size + sep + margin > pos) {
- QList<int> result;
- result.append(i);
- return result;
+ QRect sepRect = separatorRect(i);
+ if (!sepRect.isNull() && sep == 1)
+ sepRect.adjust(-2, -2, 2, 2);
+ //we also make sure we don't find a separator that's not there
+ if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
+ return QList<int>() << i;
}
}
@@ -1478,9 +1480,15 @@ QMainWindowLayout *QDockAreaLayoutInfo::mainWindowLayout() const
return result;
}
+bool QDockAreaLayoutInfo::hasFixedSize() const
+{
+ return perp(o, minimumSize()) == perp(o, maximumSize());
+}
+
+
void QDockAreaLayoutInfo::apply(bool animate)
{
- QWidgetAnimator *widgetAnimator = mainWindowLayout()->widgetAnimator;
+ QWidgetAnimator &widgetAnimator = mainWindowLayout()->widgetAnimator;
#ifndef QT_NO_TABBAR
if (tabbed) {
@@ -1513,7 +1521,7 @@ void QDockAreaLayoutInfo::apply(bool animate)
}
}
- widgetAnimator->animate(tabBar, tab_rect, animate);
+ widgetAnimator.animate(tabBar, tab_rect, animate);
}
#endif // QT_NO_TABBAR
@@ -1536,8 +1544,8 @@ void QDockAreaLayoutInfo::apply(bool animate)
QWidget *w = item.widgetItem->widget();
QRect geo = w->geometry();
- widgetAnimator->animate(w, r, animate);
- if (!w->isHidden()) {
+ widgetAnimator.animate(w, r, animate);
+ if (!w->isHidden() && w->window()->isVisible()) {
QDockWidget *dw = qobject_cast<QDockWidget*>(w);
if (!r.isValid() && geo.right() >= 0 && geo.bottom() >= 0) {
dw->lower();
@@ -1629,7 +1637,7 @@ void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
if (next == -1)
break;
QRect r = separatorRect(i);
- if (clip.contains(r))
+ if (clip.contains(r) && !item.hasFixedSize(o))
paintSep(p, widget, r, o, r.contains(mouse));
}
}
@@ -1694,15 +1702,16 @@ void QDockAreaLayoutInfo::split(int index, Qt::Orientation orientation,
}
}
-QDockAreaLayoutItem &QDockAreaLayoutInfo::item(QList<int> path)
+QDockAreaLayoutItem &QDockAreaLayoutInfo::item(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
+ const int index = path.first();
if (path.count() > 1) {
- QDockAreaLayoutItem &item = item_list[path.takeFirst()];
+ const QDockAreaLayoutItem &item = item_list[index];
Q_ASSERT(item.subinfo != 0);
- return item.subinfo->item(path);
+ return item.subinfo->item(path.mid(1));
}
- return item_list[path.first()];
+ return item_list[index];
}
QLayoutItem *QDockAreaLayoutInfo::itemAt(int *x, int index) const
@@ -1964,7 +1973,6 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
} else {
int dummy;
stream >> item.pos >> item.size >> dummy >> dummy;
- // qDebug() << widget << item.pos << item.size;
if (!testing) {
widget->setFloating(false);
widget->setVisible(flags & StateFlagVisible);
@@ -2009,10 +2017,8 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
void QDockAreaLayoutInfo::updateSeparatorWidgets() const
{
- QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
-
if (tabbed) {
- that->separatorWidgets.clear();
+ separatorWidgets.clear();
return;
}
@@ -2040,7 +2046,7 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
sepWidget = separatorWidgets.at(j);
} else {
sepWidget = mainWindowLayout()->getSeparatorWidget();
- that->separatorWidgets.append(sepWidget);
+ separatorWidgets.append(sepWidget);
}
j++;
@@ -2053,10 +2059,10 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
sepWidget->show();
}
- for (int k = j; k < that->separatorWidgets.size(); ++k) {
- that->separatorWidgets[k]->hide();
+ for (int k = j; k < separatorWidgets.size(); ++k) {
+ separatorWidgets[k]->hide();
}
- that->separatorWidgets.resize(j);
+ separatorWidgets.resize(j);
Q_ASSERT(separatorWidgets.size() == j);
}
@@ -2068,7 +2074,7 @@ void QDockAreaLayoutInfo::updateTabBar() const
QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
- if (tabBar == 0) {
+ if (that->tabBar == 0) {
that->tabBar = mainWindowLayout()->getTabBar();
that->tabBar->setShape(static_cast<QTabBar::Shape>(tabBarShape));
that->tabBar->setDrawBase(true);
@@ -2202,8 +2208,8 @@ QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets() const
{
QSet<QWidget*> result;
- foreach (QWidget *sepWidget, separatorWidgets)
- result << sepWidget;
+ for (int i = 0; i < separatorWidgets.count(); ++i)
+ result << separatorWidgets.at(i);
for (int i = 0; i < item_list.count(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
@@ -2271,7 +2277,7 @@ QDockAreaLayout::QDockAreaLayout(QMainWindow *win)
docks[QInternal::BottomDock]
= QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
centralWidgetItem = 0;
- centralWidgetRect = QRect(0, 0, -1, -1);
+
corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
@@ -2442,9 +2448,9 @@ QList<int> QDockAreaLayout::findSeparator(const QPoint &pos) const
if (info.isEmpty())
continue;
QRect rect = separatorRect(i);
- if (sep == 1)
+ if (!rect.isNull() && sep == 1)
rect.adjust(-2, -2, 2, 2);
- if (rect.contains(pos)) {
+ if (rect.contains(pos) && !info.hasFixedSize()) {
result << i;
break;
} else if (info.rect.contains(pos)) {
@@ -2469,44 +2475,45 @@ QDockAreaLayoutInfo *QDockAreaLayout::info(QWidget *widget)
return 0;
}
-QDockAreaLayoutInfo *QDockAreaLayout::info(QList<int> path)
+QDockAreaLayoutInfo *QDockAreaLayout::info(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
- int index = path.takeFirst();
+ const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- if (path.isEmpty())
+ if (path.count() == 1)
return &docks[index];
- return docks[index].info(path);
+ return docks[index].info(path.mid(1));
}
-const QDockAreaLayoutInfo *QDockAreaLayout::info(QList<int> path) const
+const QDockAreaLayoutInfo *QDockAreaLayout::info(const QList<int> &path) const
{
return const_cast<QDockAreaLayout*>(this)->info(path);
}
-QDockAreaLayoutItem &QDockAreaLayout::item(QList<int> path)
+QDockAreaLayoutItem &QDockAreaLayout::item(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
- int index = path.takeFirst();
+ const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- return docks[index].item(path);
+ return docks[index].item(path.mid(1));
}
-QRect QDockAreaLayout::itemRect(QList<int> path) const
+QRect QDockAreaLayout::itemRect(const QList<int> &path) const
{
Q_ASSERT(!path.isEmpty());
- int index = path.takeFirst();
+ const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- return docks[index].itemRect(path);
+ return docks[index].itemRect(path.mid(1));
}
QRect QDockAreaLayout::separatorRect(int index) const
{
- if (docks[index].isEmpty())
+ const QDockAreaLayoutInfo &dock = docks[index];
+ if (dock.isEmpty())
return QRect();
- QRect r = docks[index].rect;
+ QRect r = dock.rect;
switch (index) {
case QInternal::LeftDock:
return QRect(r.right() + 1, r.top(), sep, r.height());
@@ -2522,49 +2529,49 @@ QRect QDockAreaLayout::separatorRect(int index) const
return QRect();
}
-QRect QDockAreaLayout::separatorRect(QList<int> path) const
+QRect QDockAreaLayout::separatorRect(const QList<int> &path) const
{
Q_ASSERT(!path.isEmpty());
- int index = path.takeFirst();
+ const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- if (path.isEmpty())
+ if (path.count() == 1)
return separatorRect(index);
else
- return docks[index].separatorRect(path);
+ return docks[index].separatorRect(path.mid(1));
}
-bool QDockAreaLayout::insertGap(QList<int> path, QLayoutItem *dockWidgetItem)
+bool QDockAreaLayout::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
{
Q_ASSERT(!path.isEmpty());
- int index = path.takeFirst();
+ const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- return docks[index].insertGap(path, dockWidgetItem);
+ return docks[index].insertGap(path.mid(1), dockWidgetItem);
}
-QLayoutItem *QDockAreaLayout::plug(QList<int> path)
+QLayoutItem *QDockAreaLayout::plug(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
- int index = path.takeFirst();
+ const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- return docks[index].plug(path);
+ return docks[index].plug(path.mid(1));
}
-QLayoutItem *QDockAreaLayout::unplug(QList<int> path)
+QLayoutItem *QDockAreaLayout::unplug(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
- int index = path.takeFirst();
+ const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- return docks[index].unplug(path);
+ return docks[index].unplug(path.mid(1));
}
-void QDockAreaLayout::remove(QList<int> path)
+void QDockAreaLayout::remove(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
- int index = path.takeFirst();
+ const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- docks[index].remove(path);
+ docks[index].remove(path.mid(1));
}
static inline int qMin(int i1, int i2, int i3) { return qMin(i1, qMin(i2, i3)); }
@@ -2854,8 +2861,8 @@ void QDockAreaLayout::clear()
for (int i = 0; i < QInternal::DockCount; ++i)
docks[i].clear();
- rect = QRect(0, 0, -1, -1);
- centralWidgetRect = QRect(0, 0, -1, -1);
+ rect = QRect();
+ centralWidgetRect = QRect();
}
QSize QDockAreaLayout::sizeHint() const
@@ -3057,13 +3064,13 @@ void QDockAreaLayout::splitDockWidget(QDockWidget *after,
void QDockAreaLayout::apply(bool animate)
{
- QWidgetAnimator *widgetAnimator
+ QWidgetAnimator &widgetAnimator
= qobject_cast<QMainWindowLayout*>(mainWindow->layout())->widgetAnimator;
for (int i = 0; i < QInternal::DockCount; ++i)
docks[i].apply(animate);
if (centralWidgetItem != 0 && !centralWidgetItem->isEmpty()) {
- widgetAnimator->animate(centralWidgetItem->widget(), centralWidgetRect,
+ widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect,
animate);
}
@@ -3080,7 +3087,7 @@ void QDockAreaLayout::paintSeparators(QPainter *p, QWidget *widget,
if (dock.isEmpty())
continue;
QRect r = separatorRect(i);
- if (clip.contains(r)) {
+ if (clip.contains(r) && !dock.hasFixedSize()) {
Qt::Orientation opposite = dock.o == Qt::Horizontal
? Qt::Vertical : Qt::Horizontal;
paintSep(p, widget, r, opposite, r.contains(mouse));
@@ -3105,9 +3112,8 @@ QRegion QDockAreaLayout::separatorRegion() const
return result;
}
-int QDockAreaLayout::separatorMove(QList<int> separator, const QPoint &origin,
- const QPoint &dest,
- QVector<QLayoutStruct> *cache)
+int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &origin,
+ const QPoint &dest)
{
int delta = 0;
int index = separator.last();
@@ -3116,21 +3122,18 @@ int QDockAreaLayout::separatorMove(QList<int> separator, const QPoint &origin,
QDockAreaLayoutInfo *info = this->info(separator);
delta = pick(info->o, dest - origin);
if (delta != 0)
- delta = info->separatorMove(index, delta, cache);
+ delta = info->separatorMove(index, delta);
info->apply(false);
return delta;
}
- if (cache->isEmpty()) {
- QVector<QLayoutStruct> &list = *cache;
+ QVector<QLayoutStruct> list;
- if (index == QInternal::LeftDock || index == QInternal::RightDock)
- getGrid(0, &list);
- else
- getGrid(&list, 0);
- }
+ if (index == QInternal::LeftDock || index == QInternal::RightDock)
+ getGrid(0, &list);
+ else
+ getGrid(&list, 0);
- QVector<QLayoutStruct> list = *cache;
int sep_index = index == QInternal::LeftDock || index == QInternal::TopDock
? 0 : 1;
Qt::Orientation o = index == QInternal::LeftDock || index == QInternal::RightDock
@@ -3154,8 +3157,6 @@ int QDockAreaLayout::separatorMove(QList<int> separator, const QPoint &origin,
// Allocates new sepearator widgets with getSeparatorWidget
void QDockAreaLayout::updateSeparatorWidgets() const
{
- QDockAreaLayout *that = const_cast<QDockAreaLayout*>(this);
-
int j = 0;
for (int i = 0; i < QInternal::DockCount; ++i) {
@@ -3168,7 +3169,7 @@ void QDockAreaLayout::updateSeparatorWidgets() const
sepWidget = separatorWidgets.at(j);
} else {
sepWidget = qobject_cast<QMainWindowLayout*>(mainWindow->layout())->getSeparatorWidget();
- that->separatorWidgets.append(sepWidget);
+ separatorWidgets.append(sepWidget);
}
j++;
@@ -3183,7 +3184,7 @@ void QDockAreaLayout::updateSeparatorWidgets() const
for (int i = j; i < separatorWidgets.size(); ++i)
separatorWidgets.at(i)->hide();
- that->separatorWidgets.resize(j);
+ separatorWidgets.resize(j);
}
QLayoutItem *QDockAreaLayout::itemAt(int *x, int index) const
@@ -3244,8 +3245,8 @@ QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const
{
QSet<QWidget*> result;
- foreach (QWidget *sepWidget, separatorWidgets)
- result << sepWidget;
+ for (int i = 0; i < separatorWidgets.count(); ++i)
+ result << separatorWidgets.at(i);
for (int i = 0; i < QInternal::DockCount; ++i) {
const QDockAreaLayoutInfo &dock = docks[i];
result += dock.usedSeparatorWidgets();
@@ -3253,7 +3254,7 @@ QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const
return result;
}
-QRect QDockAreaLayout::gapRect(QList<int> path) const
+QRect QDockAreaLayout::gapRect(const QList<int> &path) const
{
const QDockAreaLayoutInfo *info = this->info(path);
if (info == 0)
diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h
index 7b07f75..5a90a7e 100644
--- a/src/gui/widgets/qdockarealayout_p.h
+++ b/src/gui/widgets/qdockarealayout_p.h
@@ -103,6 +103,7 @@ struct QDockAreaLayoutItem
QSize maximumSize() const;
QSize sizeHint() const;
bool expansive(Qt::Orientation o) const;
+ bool hasFixedSize(Qt::Orientation o) const;
QLayoutItem *widgetItem;
QDockAreaLayoutInfo *subinfo;
@@ -135,18 +136,18 @@ public:
QSize sizeHint() const;
QSize size() const;
- bool insertGap(QList<int> path, QLayoutItem *dockWidgetItem);
- QLayoutItem *plug(QList<int> path);
- QLayoutItem *unplug(QList<int> path);
+ bool insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem);
+ QLayoutItem *plug(const QList<int> &path);
+ QLayoutItem *unplug(const QList<int> &path);
enum TabMode { NoTabs, AllowTabs, ForceTabs };
QList<int> gapIndex(const QPoint &pos, bool nestingEnabled,
TabMode tabMode) const;
- void remove(QList<int> path);
+ void remove(const QList<int> &path);
void unnest(int index);
void split(int index, Qt::Orientation orientation, QLayoutItem *dockWidgetItem);
void tab(int index, QLayoutItem *dockWidgetItem);
- QDockAreaLayoutItem &item(QList<int> path);
- QDockAreaLayoutInfo *info(QList<int> path);
+ QDockAreaLayoutItem &item(const QList<int> &path);
+ QDockAreaLayoutInfo *info(const QList<int> &path);
QDockAreaLayoutInfo *info(QWidget *widget);
enum { // sentinel values used to validate state data
@@ -161,12 +162,13 @@ public:
bool expansive(Qt::Orientation o) const;
int changeSize(int index, int size, bool below);
QRect itemRect(int index) const;
- QRect itemRect(QList<int> path) const;
+ QRect itemRect(const QList<int> &path) const;
QRect separatorRect(int index) const;
- QRect separatorRect(QList<int> path) const;
+ QRect separatorRect(const QList<int> &path) const;
void clear();
bool isEmpty() const;
+ bool hasFixedSize() const;
QList<int> findSeparator(const QPoint &pos) const;
int next(int idx) const;
int prev(int idx) const;
@@ -179,7 +181,7 @@ public:
void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip,
const QPoint &mouse) const;
QRegion separatorRegion() const;
- int separatorMove(int index, int delta, QVector<QLayoutStruct> *cache);
+ int separatorMove(int index, int delta);
QLayoutItem *itemAt(int *x, int index) const;
QLayoutItem *takeAt(int *x, int index);
@@ -188,7 +190,7 @@ public:
QMainWindowLayout *mainWindowLayout() const;
int sep;
- QVector<QWidget*> separatorWidgets;
+ mutable QVector<QWidget*> separatorWidgets;
QInternal::DockPosition dockPos;
Qt::Orientation o;
QRect rect;
@@ -231,7 +233,7 @@ public:
QDockAreaLayout(QMainWindow *win);
QDockAreaLayoutInfo docks[4];
int sep; // separator extent
- QVector<QWidget*> separatorWidgets;
+ mutable QVector<QWidget*> separatorWidgets;
bool isValid() const;
@@ -244,18 +246,18 @@ public:
QList<int> gapIndex(const QPoint &pos) const;
QList<int> findSeparator(const QPoint &pos) const;
- QDockAreaLayoutItem &item(QList<int> path);
- QDockAreaLayoutInfo *info(QList<int> path);
- const QDockAreaLayoutInfo *info(QList<int> path) const;
+ QDockAreaLayoutItem &item(const QList<int> &path);
+ QDockAreaLayoutInfo *info(const QList<int> &path);
+ const QDockAreaLayoutInfo *info(const QList<int> &path) const;
QDockAreaLayoutInfo *info(QWidget *widget);
- QRect itemRect(QList<int> path) const;
+ QRect itemRect(const QList<int> &path) const;
QRect separatorRect(int index) const;
- QRect separatorRect(QList<int> path) const;
+ QRect separatorRect(const QList<int> &path) const;
- bool insertGap(QList<int> path, QLayoutItem *dockWidgetItem);
- QLayoutItem *plug(QList<int> path);
- QLayoutItem *unplug(QList<int> path);
- void remove(QList<int> path);
+ bool insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem);
+ QLayoutItem *plug(const QList<int> &path);
+ QLayoutItem *unplug(const QList<int> &path);
+ void remove(const QList<int> &path);
void fitLayout();
@@ -275,8 +277,7 @@ public:
void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip,
const QPoint &mouse) const;
QRegion separatorRegion() const;
- int separatorMove(QList<int> separator, const QPoint &origin, const QPoint &dest,
- QVector<QLayoutStruct> *cache);
+ int separatorMove(const QList<int> &separator, const QPoint &origin, const QPoint &dest);
void updateSeparatorWidgets() const;
QLayoutItem *itemAt(int *x, int index) const;
@@ -288,7 +289,7 @@ public:
void setGrid(QVector<QLayoutStruct> *ver_struct_list,
QVector<QLayoutStruct> *hor_struct_list);
- QRect gapRect(QList<int> path) const;
+ QRect gapRect(const QList<int> &path) const;
void keepSize(QDockWidget *w);
diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp
index ad67ab9..e832e87 100644
--- a/src/gui/widgets/qdockwidget.cpp
+++ b/src/gui/widgets/qdockwidget.cpp
@@ -59,6 +59,7 @@
#include "qdockwidget_p.h"
#include "qmainwindowlayout_p.h"
#ifdef Q_WS_MAC
+#include <private/qapplication_p.h>
#include <private/qt_mac_p.h>
#include <qmacstyle_mac.h>
#endif
@@ -67,7 +68,8 @@ QT_BEGIN_NAMESPACE
extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*); // qwidget.cpp
-extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp
+static inline bool hasFeature(const QDockWidgetPrivate *priv, QDockWidget::DockWidgetFeature feature)
+{ return (priv->features & feature) == feature; }
static inline bool hasFeature(const QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature)
{ return (dockwidget->features() & feature) == feature; }
@@ -203,7 +205,7 @@ bool QDockWidgetLayout::nativeWindowDeco() const
bool QDockWidgetLayout::nativeWindowDeco(bool floating) const
{
-#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_WINCE)
+#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_WINCE)
Q_UNUSED(floating);
return false;
#else
@@ -221,7 +223,8 @@ void QDockWidgetLayout::addItem(QLayoutItem*)
QLayoutItem *QDockWidgetLayout::itemAt(int index) const
{
int cnt = 0;
- foreach (QLayoutItem *item, item_list) {
+ for (int i = 0; i < item_list.count(); ++i) {
+ QLayoutItem *item = item_list.at(i);
if (item == 0)
continue;
if (index == cnt++)
@@ -250,8 +253,8 @@ QLayoutItem *QDockWidgetLayout::takeAt(int index)
int QDockWidgetLayout::count() const
{
int result = 0;
- foreach (QLayoutItem *item, item_list) {
- if (item != 0)
+ for (int i = 0; i < item_list.count(); ++i) {
+ if (item_list.at(i))
++result;
}
return result;
@@ -646,25 +649,25 @@ void QDockWidgetPrivate::_q_toggleView(bool b)
void QDockWidgetPrivate::updateButtons()
{
Q_Q(QDockWidget);
- QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout());
+ QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout);
QStyleOptionDockWidget opt;
q->initStyleOption(&opt);
- bool customTitleBar = layout->widgetForRole(QDockWidgetLayout::TitleBar) != 0;
- bool nativeDeco = layout->nativeWindowDeco();
+ bool customTitleBar = dwLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0;
+ bool nativeDeco = dwLayout->nativeWindowDeco();
bool hideButtons = nativeDeco || customTitleBar;
- bool canClose = hasFeature(q, QDockWidget::DockWidgetClosable);
- bool canFloat = hasFeature(q, QDockWidget::DockWidgetFloatable);
+ bool canClose = hasFeature(this, QDockWidget::DockWidgetClosable);
+ bool canFloat = hasFeature(this, QDockWidget::DockWidgetFloatable);
QAbstractButton *button
- = qobject_cast<QAbstractButton*>(layout->widgetForRole(QDockWidgetLayout::FloatButton));
+ = qobject_cast<QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::FloatButton));
button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q));
button->setVisible(canFloat && !hideButtons);
button
- = qobject_cast <QAbstractButton*>(layout->widgetForRole(QDockWidgetLayout::CloseButton));
+ = qobject_cast <QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::CloseButton));
button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, q));
button->setVisible(canClose && !hideButtons);
@@ -687,7 +690,7 @@ void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca)
if (state != 0)
return;
- QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *win = qobject_cast<QMainWindow*>(parent);
Q_ASSERT(win != 0);
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
Q_ASSERT(layout != 0);
@@ -740,15 +743,15 @@ void QDockWidgetPrivate::endDrag(bool abort)
q->releaseMouse();
if (state->dragging) {
- QMainWindowLayout *layout =
+ QMainWindowLayout *mwLayout =
qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout());
- Q_ASSERT(layout != 0);
+ Q_ASSERT(mwLayout != 0);
- if (abort || !layout->plug(state->widgetItem)) {
- if (hasFeature(q, QDockWidget::DockWidgetFloatable)) {
+ if (abort || !mwLayout->plug(state->widgetItem)) {
+ if (hasFeature(this, QDockWidget::DockWidgetFloatable)) {
if (state->ownWidgetItem)
delete state->widgetItem;
- layout->restore();
+ mwLayout->restore();
#ifdef Q_WS_X11
// get rid of the X11BypassWindowManager window flag and activate the resizer
Qt::WindowFlags flags = q->windowFlags();
@@ -758,14 +761,14 @@ void QDockWidgetPrivate::endDrag(bool abort)
q->show();
#else
QDockWidgetLayout *myLayout
- = qobject_cast<QDockWidgetLayout*>(q->layout());
+ = qobject_cast<QDockWidgetLayout*>(layout);
resizer->setActive(QWidgetResizeHandler::Resize,
myLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0);
#endif
undockedGeometry = q->geometry();
q->activateWindow();
} else {
- layout->revert(state->widgetItem);
+ mwLayout->revert(state->widgetItem);
}
}
}
@@ -777,7 +780,7 @@ bool QDockWidgetPrivate::isAnimating() const
{
Q_Q(const QDockWidget);
- QMainWindow *mainWin = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *mainWin = qobject_cast<QMainWindow*>(parent);
if (mainWin == 0)
return false;
@@ -794,18 +797,18 @@ bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event)
#if !defined(QT_NO_MAINWINDOW)
Q_Q(QDockWidget);
- QDockWidgetLayout *layout
- = qobject_cast<QDockWidgetLayout*>(q->layout());
+ QDockWidgetLayout *dwLayout
+ = qobject_cast<QDockWidgetLayout*>(layout);
- if (!layout->nativeWindowDeco()) {
- QRect titleArea = layout->titleArea();
+ if (!dwLayout->nativeWindowDeco()) {
+ QRect titleArea = dwLayout->titleArea();
if (event->button() != Qt::LeftButton ||
!titleArea.contains(event->pos()) ||
// check if the tool window is movable... do nothing if it
// is not (but allow moving if the window is floating)
- (!hasFeature(q, QDockWidget::DockWidgetMovable) && !q->isFloating()) ||
- qobject_cast<QMainWindow*>(q->parentWidget()) == 0 ||
+ (!hasFeature(this, QDockWidget::DockWidgetMovable) && !q->isFloating()) ||
+ qobject_cast<QMainWindow*>(parent) == 0 ||
isAnimating() || state != 0) {
return false;
}
@@ -813,7 +816,7 @@ bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event)
initDrag(event->pos(), false);
if (state)
- state->ctrlDrag = hasFeature(q, QDockWidget::DockWidgetFloatable) && event->modifiers() & Qt::ControlModifier;
+ state->ctrlDrag = hasFeature(this, QDockWidget::DockWidgetFloatable) && event->modifiers() & Qt::ControlModifier;
return true;
}
@@ -824,15 +827,13 @@ bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event)
bool QDockWidgetPrivate::mouseDoubleClickEvent(QMouseEvent *event)
{
- Q_Q(QDockWidget);
+ QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout);
- QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout());
-
- if (!layout->nativeWindowDeco()) {
- QRect titleArea = layout->titleArea();
+ if (!dwLayout->nativeWindowDeco()) {
+ QRect titleArea = dwLayout->titleArea();
if (event->button() == Qt::LeftButton && titleArea.contains(event->pos()) &&
- hasFeature(q, QDockWidget::DockWidgetFloatable)) {
+ hasFeature(this, QDockWidget::DockWidgetFloatable)) {
_q_toggleTopLevel();
return true;
}
@@ -850,7 +851,7 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
return ret;
QDockWidgetLayout *dwlayout
- = qobject_cast<QDockWidgetLayout*>(q->layout());
+ = qobject_cast<QDockWidgetLayout*>(layout);
QMainWindowLayout *mwlayout
= qobject_cast<QMainWindowLayout*>(q->parentWidget()->layout());
if (!dwlayout->nativeWindowDeco()) {
@@ -923,7 +924,7 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
break;
if (state != 0)
break;
- if (qobject_cast<QMainWindow*>(q->parentWidget()) == 0)
+ if (qobject_cast<QMainWindow*>(parent) == 0)
break;
if (isAnimating())
break;
@@ -996,9 +997,9 @@ void QDockWidgetPrivate::unplug(const QRect &rect)
Q_Q(QDockWidget);
QRect r = rect;
r.moveTopLeft(q->mapToGlobal(QPoint(0, 0)));
- QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout());
- if (layout->nativeWindowDeco(true))
- r.adjust(0, layout->titleHeight(), 0, 0);
+ QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout);
+ if (dwLayout->nativeWindowDeco(true))
+ r.adjust(0, dwLayout->titleHeight(), 0, 0);
setWindowState(true, true, r);
}
@@ -1019,12 +1020,12 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
Qt::WindowFlags flags = floating ? Qt::Tool : Qt::Widget;
- QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout());
- const bool nativeDeco = layout->nativeWindowDeco(floating);
+ QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout);
+ const bool nativeDeco = dwLayout->nativeWindowDeco(floating);
if (nativeDeco) {
flags |= Qt::CustomizeWindowHint | Qt::WindowTitleHint;
- if (hasFeature(q, QDockWidget::DockWidgetClosable))
+ if (hasFeature(this, QDockWidget::DockWidgetClosable))
flags |= Qt::WindowCloseButtonHint;
} else {
flags |= Qt::FramelessWindowHint;
@@ -1051,7 +1052,7 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
if (floating != wasFloating) {
emit q->topLevelChanged(floating);
- if (!floating && q->parentWidget()) {
+ if (!floating && parent) {
QMainWindowLayout *mwlayout = qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout());
if (mwlayout)
emit q->dockLocationChanged(mwlayout->dockWidgetArea(q));
@@ -1068,7 +1069,7 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
inside a QMainWindow or floated as a top-level window on the
desktop.
- \ingroup application
+ \ingroup mainwindow-classes
QDockWidget provides the concept of dock widgets, also know as
tool palettes or utility windows. Dock windows are secondary
@@ -1321,8 +1322,7 @@ void QDockWidget::changeEvent(QEvent *event)
QMainWindow *win = qobject_cast<QMainWindow*>(parentWidget());
if (QMainWindowLayout *winLayout =
(win ? qobject_cast<QMainWindowLayout*>(win->layout()) : 0))
- if (QDockAreaLayoutInfo *info =
- (winLayout ? winLayout->layoutState.dockAreaLayout.info(this) : 0))
+ if (QDockAreaLayoutInfo *info = winLayout->layoutState.dockAreaLayout.info(this))
info->updateTabBar();
}
#endif // QT_NO_TABBAR
@@ -1390,7 +1390,7 @@ bool QDockWidget::event(QEvent *event)
break;
case QEvent::Show:
d->toggleViewAction->setChecked(true);
- emit visibilityChanged(true);
+ emit visibilityChanged(geometry().right() >= 0 && geometry().bottom() >= 0);
break;
#endif
case QEvent::ApplicationLayoutDirectionChange:
diff --git a/src/gui/widgets/qeffects.cpp b/src/gui/widgets/qeffects.cpp
index 09ea336..a1c1083 100644
--- a/src/gui/widgets/qeffects.cpp
+++ b/src/gui/widgets/qeffects.cpp
@@ -126,9 +126,9 @@ QAlphaWidget::QAlphaWidget(QWidget* w, Qt::WindowFlags f)
QAlphaWidget::~QAlphaWidget()
{
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
// Restore user-defined opacity value
- if (widget && QSysInfo::WindowsVersion >= QSysInfo::WV_2000 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
+ if (widget)
widget->setWindowOpacity(windowOpacity);
#endif
}
@@ -160,43 +160,40 @@ void QAlphaWidget::run(int time)
checkTime.start();
showWidget = true;
-#if defined(Q_OS_WIN)
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_2000 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) {
- qApp->installEventFilter(this);
- widget->setWindowOpacity(0.0);
- widget->show();
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ qApp->installEventFilter(this);
+ widget->setWindowOpacity(0.0);
+ widget->show();
+ connect(&anim, SIGNAL(timeout()), this, SLOT(render()));
+ anim.start(1);
+#else
+ //This is roughly equivalent to calling setVisible(true) without actually showing the widget
+ widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true);
+ widget->setAttribute(Qt::WA_WState_Hidden, false);
+
+ qApp->installEventFilter(this);
+
+ move(widget->geometry().x(),widget->geometry().y());
+ resize(widget->size().width(), widget->size().height());
+
+ frontImage = QPixmap::grabWidget(widget).toImage();
+ backImage = QPixmap::grabWindow(QApplication::desktop()->winId(),
+ widget->geometry().x(), widget->geometry().y(),
+ widget->geometry().width(), widget->geometry().height()).toImage();
+
+ if (!backImage.isNull() && checkTime.elapsed() < duration / 2) {
+ mixedImage = backImage.copy();
+ pm = QPixmap::fromImage(mixedImage);
+ show();
+ setEnabled(false);
+
connect(&anim, SIGNAL(timeout()), this, SLOT(render()));
anim.start(1);
- } else
-#endif
- {
- //This is roughly equivalent to calling setVisible(true) without actually showing the widget
- widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true);
- widget->setAttribute(Qt::WA_WState_Hidden, false);
-
- qApp->installEventFilter(this);
-
- move(widget->geometry().x(),widget->geometry().y());
- resize(widget->size().width(), widget->size().height());
-
- frontImage = QPixmap::grabWidget(widget).toImage();
- backImage = QPixmap::grabWindow(QApplication::desktop()->winId(),
- widget->geometry().x(), widget->geometry().y(),
- widget->geometry().width(), widget->geometry().height()).toImage();
-
- if (!backImage.isNull() && checkTime.elapsed() < duration / 2) {
- mixedImage = backImage.copy();
- pm = QPixmap::fromImage(mixedImage);
- show();
- setEnabled(false);
-
- connect(&anim, SIGNAL(timeout()), this, SLOT(render()));
- anim.start(1);
- } else {
- duration = 0;
- render();
- }
+ } else {
+ duration = 0;
+ render();
}
+#endif
}
/*
@@ -270,19 +267,17 @@ void QAlphaWidget::render()
else
alpha = 1;
-#if defined(Q_OS_WIN)
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_2000 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) {
- if (alpha >= windowOpacity || !showWidget) {
- anim.stop();
- qApp->removeEventFilter(this);
- widget->setWindowOpacity(windowOpacity);
- q_blend = 0;
- deleteLater();
- } else {
- widget->setWindowOpacity(alpha);
- }
- } else
-#endif
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ if (alpha >= windowOpacity || !showWidget) {
+ anim.stop();
+ qApp->removeEventFilter(this);
+ widget->setWindowOpacity(windowOpacity);
+ q_blend = 0;
+ deleteLater();
+ } else {
+ widget->setWindowOpacity(alpha);
+ }
+#else
if (alpha >= 1 || !showWidget) {
anim.stop();
qApp->removeEventFilter(this);
@@ -292,7 +287,7 @@ void QAlphaWidget::render()
#ifdef Q_WS_WIN
setEnabled(true);
setFocus();
-#endif
+#endif // Q_WS_WIN
widget->hide();
} else {
//Since we are faking the visibility of the widget
@@ -309,6 +304,7 @@ void QAlphaWidget::render()
pm = QPixmap::fromImage(mixedImage);
repaint();
}
+#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
}
/*
@@ -588,8 +584,8 @@ void qScrollEffect(QWidget* w, QEffects::DirFlags orient, int time)
if (!w)
return;
- qApp->sendPostedEvents(w, QEvent::Move);
- qApp->sendPostedEvents(w, QEvent::Resize);
+ QApplication::sendPostedEvents(w, QEvent::Move);
+ QApplication::sendPostedEvents(w, QEvent::Resize);
Qt::WindowFlags flags = Qt::ToolTip;
// those can be popups - they would steal the focus, but are disabled
@@ -610,8 +606,8 @@ void qFadeEffect(QWidget* w, int time)
if (!w)
return;
- qApp->sendPostedEvents(w, QEvent::Move);
- qApp->sendPostedEvents(w, QEvent::Resize);
+ QApplication::sendPostedEvents(w, QEvent::Move);
+ QApplication::sendPostedEvents(w, QEvent::Resize);
Qt::WindowFlags flags = Qt::ToolTip;
diff --git a/src/gui/widgets/qfocusframe.cpp b/src/gui/widgets/qfocusframe.cpp
index becc21b..504da0c 100644
--- a/src/gui/widgets/qfocusframe.cpp
+++ b/src/gui/widgets/qfocusframe.cpp
@@ -118,7 +118,7 @@ void QFocusFrame::initStyleOption(QStyleOption *option) const
outside of a widget's normal paintable area.
\ingroup basicwidgets
- \mainclass
+
Normally an application will not need to create its own
QFocusFrame as QStyle will handle this detail for
diff --git a/src/gui/widgets/qfontcombobox.cpp b/src/gui/widgets/qfontcombobox.cpp
index efd7fa5..44fcf08 100644
--- a/src/gui/widgets/qfontcombobox.cpp
+++ b/src/gui/widgets/qfontcombobox.cpp
@@ -263,7 +263,7 @@ void QFontComboBoxPrivate::_q_currentChanged(const QString &text)
{
Q_Q(QFontComboBox);
QFont newFont(text);
- if (currentFont != newFont) {
+ if (currentFont.family() != newFont.family()) {
currentFont = newFont;
emit q->currentFontChanged(currentFont);
}
@@ -276,7 +276,6 @@ void QFontComboBoxPrivate::_q_currentChanged(const QString &text)
\since 4.2
\ingroup basicwidgets
- \ingroup text
The combobox is populated with an alphabetized list of font
family names, such as Arial, Helvetica, and Times New Roman.
diff --git a/src/gui/widgets/qframe.cpp b/src/gui/widgets/qframe.cpp
index 1d50a38..84bdf3f 100644
--- a/src/gui/widgets/qframe.cpp
+++ b/src/gui/widgets/qframe.cpp
@@ -59,8 +59,7 @@ QFramePrivate::QFramePrivate()
midLineWidth(0),
frameWidth(0),
leftFrameWidth(0), rightFrameWidth(0),
- topFrameWidth(0), bottomFrameWidth(0),
- oldFrameStyle(QFrame::NoFrame | QFrame::Plain)
+ topFrameWidth(0), bottomFrameWidth(0)
{
}
@@ -74,7 +73,7 @@ inline void QFramePrivate::init()
\brief The QFrame class is the base class of widgets that can have a frame.
\ingroup abstractwidgets
- \mainclass
+
QMenu uses this to "raise" the menu above the surrounding
screen. QProgressBar has a "sunken" look. QLabel has a flat look.
@@ -136,7 +135,7 @@ inline void QFramePrivate::init()
\value VLine QFrame draws a vertical line that frames nothing
(useful as separator)
\value WinPanel draws a rectangular panel that can be raised or
- sunken like those in Windows 95. Specifying this shape sets
+ sunken like those in Windows 2000. Specifying this shape sets
the line width to 2 pixels. WinPanel is provided for compatibility.
For GUI style independence we recommend using StyledPanel instead.
@@ -333,7 +332,6 @@ void QFrame::setFrameStyle(int style)
d->frameStyle = (short)style;
update();
d->updateFrameWidth();
- d->oldFrameStyle = (short)style;
}
/*!
diff --git a/src/gui/widgets/qframe_p.h b/src/gui/widgets/qframe_p.h
index 6cea5d3..bcda9ac 100644
--- a/src/gui/widgets/qframe_p.h
+++ b/src/gui/widgets/qframe_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QFramePrivate : public QWidgetPrivate
+class QFramePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QFrame)
public:
@@ -74,7 +74,6 @@ public:
short frameWidth;
short leftFrameWidth, rightFrameWidth;
short topFrameWidth, bottomFrameWidth;
- short oldFrameStyle;
inline void init();
diff --git a/src/gui/widgets/qgroupbox.cpp b/src/gui/widgets/qgroupbox.cpp
index 3adc921..608bd1a 100644
--- a/src/gui/widgets/qgroupbox.cpp
+++ b/src/gui/widgets/qgroupbox.cpp
@@ -147,8 +147,6 @@ void QGroupBoxPrivate::click()
\ingroup organizers
\ingroup geomanagement
- \ingroup appearance
- \mainclass
A group box provides a frame, a title and a keyboard shortcut, and
displays various other widgets inside itself. The title is on top,
@@ -431,7 +429,7 @@ void QGroupBoxPrivate::_q_fixFocus(Qt::FocusReason reason)
{
Q_Q(QGroupBox);
QWidget *fw = q->focusWidget();
- if (!fw) {
+ if (!fw || fw == q) {
QWidget * best = 0;
QWidget * candidate = 0;
QWidget * w = q;
@@ -449,8 +447,7 @@ void QGroupBoxPrivate::_q_fixFocus(Qt::FocusReason reason)
}
if (best)
fw = best;
- else
- if (candidate)
+ else if (candidate)
fw = candidate;
}
if (fw)
@@ -640,15 +637,11 @@ bool QGroupBox::isChecked() const
void QGroupBox::setChecked(bool b)
{
Q_D(QGroupBox);
- if (d->checkable) {
- if (d->checked != b)
- update();
- bool wasToggled = (b != d->checked);
+ if (d->checkable && b != d->checked) {
+ update();
d->checked = b;
- if (wasToggled) {
- d->_q_setChildrenEnabled(b);
- emit toggled(b);
- }
+ d->_q_setChildrenEnabled(b);
+ emit toggled(b);
}
}
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp
index cf2c5dd..af39d10 100644
--- a/src/gui/widgets/qlabel.cpp
+++ b/src/gui/widgets/qlabel.cpp
@@ -61,8 +61,6 @@ QT_BEGIN_NAMESPACE
\brief The QLabel widget provides a text or image display.
\ingroup basicwidgets
- \ingroup text
- \mainclass
QLabel is used for displaying text or an image. No user
interaction functionality is provided. The visual appearance of
@@ -971,6 +969,13 @@ void QLabel::paintEvent(QPaintEvent *)
#endif
if (d->isTextLabel) {
QRectF lr = d->layoutRect();
+ QStyleOption opt;
+ opt.initFrom(this);
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) {
+ cssStyle->styleSheetPalette(this, &opt, &opt.palette);
+ }
+#endif
if (d->control) {
#ifndef QT_NO_SHORTCUT
const bool underline = (bool)style->styleHint(QStyle::SH_UnderlineShortcut, 0, this, 0);
@@ -984,11 +989,9 @@ void QLabel::paintEvent(QPaintEvent *)
d->ensureTextLayouted();
QAbstractTextDocumentLayout::PaintContext context;
- QStyleOption opt(0);
- opt.init(this);
if (!isEnabled() && style->styleHint(QStyle::SH_EtchDisabledText, &opt, this)) {
- context.palette = palette();
+ context.palette = opt.palette;
context.palette.setColor(QPalette::Text, context.palette.light().color());
painter.save();
painter.translate(lr.x() + 1, lr.y() + 1);
@@ -999,12 +1002,7 @@ void QLabel::paintEvent(QPaintEvent *)
}
// Adjust the palette
- context.palette = palette();
-#ifndef QT_NO_STYLE_STYLESHEET
- if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) {
- cssStyle->focusPalette(this, &opt, &context.palette);
- }
-#endif
+ context.palette = opt.palette;
if (foregroundRole() != QPalette::Text && isEnabled())
context.palette.setColor(QPalette::Text, context.palette.color(foregroundRole()));
@@ -1019,12 +1017,10 @@ void QLabel::paintEvent(QPaintEvent *)
int flags = align;
if (d->hasShortcut) {
flags |= Qt::TextShowMnemonic;
- QStyleOption opt;
- opt.initFrom(this);
if (!style->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
flags |= Qt::TextHideMnemonic;
}
- style->drawItemText(&painter, lr.toRect(), flags, palette(), isEnabled(), d->text, foregroundRole());
+ style->drawItemText(&painter, lr.toRect(), flags, opt.palette, isEnabled(), d->text, foregroundRole());
}
} else
#ifndef QT_NO_PICTURE
@@ -1172,7 +1168,7 @@ void QLabelPrivate::updateShortcut()
shortcutCursor.deleteChar(); // remove the ampersand
shortcutCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
} else {
- if (!text.contains(QLatin1String("&")))
+ if (!text.contains(QLatin1Char('&')))
return;
hasShortcut = true;
shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
diff --git a/src/gui/widgets/qlcdnumber.cpp b/src/gui/widgets/qlcdnumber.cpp
index 4454ac6..6b8bac2 100644
--- a/src/gui/widgets/qlcdnumber.cpp
+++ b/src/gui/widgets/qlcdnumber.cpp
@@ -74,7 +74,7 @@ public:
\brief The QLCDNumber widget displays a number with LCD-like digits.
\ingroup basicwidgets
- \mainclass
+
It can display a number in just about any size. It can display
decimal, hexadecimal, octal or binary numbers. It is easy to
@@ -403,7 +403,7 @@ QLCDNumber::QLCDNumber(QWidget *parent)
Constructs an LCD number, sets the number of digits to \a
numDigits, the base to decimal, the decimal point mode to 'small'
and the frame style to a raised box. The segmentStyle() is set to
- \c Outline.
+ \c Filled.
The \a parent argument is passed to the QFrame constructor.
@@ -427,7 +427,7 @@ void QLCDNumberPrivate::init()
base = QLCDNumber::Dec;
smallPoint = false;
q->setNumDigits(ndigits);
- q->setSegmentStyle(QLCDNumber::Outline);
+ q->setSegmentStyle(QLCDNumber::Filled);
q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
}
@@ -756,6 +756,10 @@ void QLCDNumber::paintEvent(QPaintEvent *)
Q_D(QLCDNumber);
QPainter p(this);
drawFrame(&p);
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->shadow)
+ p.translate(0.5, 0.5);
+
if (d->smallPoint)
d->drawString(d->digitStr, p, &d->points, false);
else
@@ -1070,7 +1074,7 @@ void QLCDNumberPrivate::drawSegment(const QPoint &pos, char segmentNo, QPainter
q->objectName().toLocal8Bit().constData(), segmentNo);
}
// End exact copy
- p.setPen(fgColor);
+ p.setPen(Qt::NoPen);
p.setBrush(fgColor);
p.drawPolygon(a);
p.setBrush(Qt::NoBrush);
@@ -1218,8 +1222,8 @@ void QLCDNumberPrivate::drawSegment(const QPoint &pos, char segmentNo, QPainter
\header \i Style \i Result
\row \i \c Outline
\i Produces raised segments filled with the background color
- (this is the default).
\row \i \c Filled
+ (this is the default).
\i Produces raised segments filled with the foreground color.
\row \i \c Flat
\i Produces flat segments filled with the foreground color.
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
new file mode 100644
index 0000000..dfd19ab
--- /dev/null
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -0,0 +1,1779 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlinecontrol_p.h"
+
+#ifndef QT_NO_LINEEDIT
+
+#include "qabstractitemview.h"
+#include "qclipboard.h"
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#ifndef QT_NO_IM
+#include "qinputcontext.h"
+#include "qlist.h"
+#endif
+#include "qapplication.h"
+#ifndef QT_NO_GRAPHICSVIEW
+#include "qgraphicssceneevent.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+
+ Updates the display text based of the current edit text
+ If the text has changed will emit displayTextChanged()
+*/
+void QLineControl::updateDisplayText()
+{
+ QString orig = m_textLayout.text();
+ QString str;
+ if (m_echoMode == QLineEdit::NoEcho)
+ str = QString::fromLatin1("");
+ else
+ str = m_text;
+
+ if (m_echoMode == QLineEdit::Password || (m_echoMode == QLineEdit::PasswordEchoOnEdit
+ && !m_passwordEchoEditing))
+ str.fill(m_passwordCharacter);
+
+ // replace certain non-printable characters with spaces (to avoid
+ // drawing boxes when using fonts that don't have glyphs for such
+ // characters)
+ QChar* uc = str.data();
+ for (int i = 0; i < (int)str.length(); ++i) {
+ if ((uc[i] < 0x20 && uc[i] != 0x09)
+ || uc[i] == QChar::LineSeparator
+ || uc[i] == QChar::ParagraphSeparator
+ || uc[i] == QChar::ObjectReplacementCharacter)
+ uc[i] = QChar(0x0020);
+ }
+
+ m_textLayout.setText(str);
+
+ QTextOption option;
+ option.setTextDirection(m_layoutDirection);
+ option.setFlags(QTextOption::IncludeTrailingSpaces);
+ m_textLayout.setTextOption(option);
+
+ m_textLayout.beginLayout();
+ QTextLine l = m_textLayout.createLine();
+ m_textLayout.endLayout();
+ m_ascent = qRound(l.ascent());
+
+ if (str != orig)
+ emit displayTextChanged(str);
+}
+
+#ifndef QT_NO_CLIPBOARD
+/*!
+ \internal
+
+ Copies the currently selected text into the clipboard using the given
+ \a mode.
+
+ \note If the echo mode is set to a mode other than Normal then copy
+ will not work. This is to prevent using copy as a method of bypassing
+ password features of the line control.
+*/
+void QLineControl::copy(QClipboard::Mode mode) const
+{
+ QString t = selectedText();
+ if (!t.isEmpty() && m_echoMode == QLineEdit::Normal) {
+ disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
+ QApplication::clipboard()->setText(t, mode);
+ connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
+ this, SLOT(_q_clipboardChanged()));
+ }
+}
+
+/*!
+ \internal
+
+ Inserts the text stored in the application clipboard into the line
+ control.
+
+ \sa insert()
+*/
+void QLineControl::paste()
+{
+ insert(QApplication::clipboard()->text(QClipboard::Clipboard));
+}
+
+#endif // !QT_NO_CLIPBOARD
+
+/*!
+ \internal
+
+ Handles the behavior for the backspace key or function.
+ Removes the current selection if there is a selection, otherwise
+ removes the character prior to the cursor position.
+
+ \sa del()
+*/
+void QLineControl::backspace()
+{
+ int priorState = m_undoState;
+ if (hasSelectedText()) {
+ removeSelectedText();
+ } else if (m_cursor) {
+ --m_cursor;
+ if (m_maskData)
+ m_cursor = prevMaskBlank(m_cursor);
+ QChar uc = m_text.at(m_cursor);
+ if (m_cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
+ // second half of a surrogate, check if we have the first half as well,
+ // if yes delete both at once
+ uc = m_text.at(m_cursor - 1);
+ if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
+ internalDelete(true);
+ --m_cursor;
+ }
+ }
+ internalDelete(true);
+ }
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Handles the behavior for the delete key or function.
+ Removes the current selection if there is a selection, otherwise
+ removes the character after the cursor position.
+
+ \sa del()
+*/
+void QLineControl::del()
+{
+ int priorState = m_undoState;
+ if (hasSelectedText()) {
+ removeSelectedText();
+ } else {
+ int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor;
+ while (n--)
+ internalDelete();
+ }
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Inserts the given \a newText at the current cursor position.
+ If there is any selected text it is removed prior to insertion of
+ the new text.
+*/
+void QLineControl::insert(const QString &newText)
+{
+ int priorState = m_undoState;
+ removeSelectedText();
+ internalInsert(newText);
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Clears the line control text.
+*/
+void QLineControl::clear()
+{
+ int priorState = m_undoState;
+ m_selstart = 0;
+ m_selend = m_text.length();
+ removeSelectedText();
+ separate();
+ finishChange(priorState, /*update*/false, /*edited*/false);
+}
+
+/*!
+ \internal
+
+ Sets \a length characters from the given \a start position as selected.
+ The given \a start position must be within the current text for
+ the line control. If \a length characters cannot be selected, then
+ the selection will extend to the end of the current text.
+*/
+void QLineControl::setSelection(int start, int length)
+{
+ if(start < 0 || start > (int)m_text.length()){
+ qWarning("QLineControl::setSelection: Invalid start position");
+ return;
+ }
+
+ if (length > 0) {
+ if (start == m_selstart && start + length == m_selend)
+ return;
+ m_selstart = start;
+ m_selend = qMin(start + length, (int)m_text.length());
+ m_cursor = m_selend;
+ } else {
+ if (start == m_selend && start + length == m_selstart)
+ return;
+ m_selstart = qMax(start + length, 0);
+ m_selend = start;
+ m_cursor = m_selstart;
+ }
+ emit selectionChanged();
+ emitCursorPositionChanged();
+}
+
+void QLineControl::_q_clipboardChanged()
+{
+}
+
+void QLineControl::_q_deleteSelected()
+{
+ if (!hasSelectedText())
+ return;
+
+ int priorState = m_undoState;
+ emit resetInputContext();
+ removeSelectedText();
+ separate();
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Initializes the line control with a starting text value of \a txt.
+*/
+void QLineControl::init(const QString &txt)
+{
+ m_text = txt;
+ updateDisplayText();
+ m_cursor = m_text.length();
+}
+
+/*!
+ \internal
+
+ Sets the password echo editing to \a editing. If password echo editing
+ is true, then the text of the password is displayed even if the echo
+ mode is set to QLineEdit::PasswordEchoOnEdit. Password echoing editing
+ does not affect other echo modes.
+*/
+void QLineControl::updatePasswordEchoEditing(bool editing)
+{
+ m_passwordEchoEditing = editing;
+ updateDisplayText();
+}
+
+/*!
+ \internal
+
+ Returns the cursor position of the given \a x pixel value in relation
+ to the displayed text. The given \a betweenOrOn specified what kind
+ of cursor position is requested.
+*/
+int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
+{
+ return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn);
+}
+
+/*!
+ \internal
+
+ Returns the bounds of the current cursor, as defined as a
+ between characters cursor.
+*/
+QRect QLineControl::cursorRect() const
+{
+ QTextLine l = m_textLayout.lineAt(0);
+ int c = m_cursor;
+ if (m_preeditCursor != -1)
+ c += m_preeditCursor;
+ int cix = qRound(l.cursorToX(c));
+ int w = m_cursorWidth;
+ int ch = l.height() + 1;
+
+ return QRect(cix-5, 0, w+9, ch);
+}
+
+/*!
+ \internal
+
+ Fixes the current text so that it is valid given any set validators.
+
+ Returns true if the text was changed. Otherwise returns false.
+*/
+bool QLineControl::fixup() // this function assumes that validate currently returns != Acceptable
+{
+#ifndef QT_NO_VALIDATOR
+ if (m_validator) {
+ QString textCopy = m_text;
+ int cursorCopy = m_cursor;
+ m_validator->fixup(textCopy);
+ if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
+ if (textCopy != m_text || cursorCopy != m_cursor)
+ internalSetText(textCopy, cursorCopy);
+ return true;
+ }
+ }
+#endif
+ return false;
+}
+
+/*!
+ \internal
+
+ Moves the cursor to the given position \a pos. If \a mark is true will
+ adjust the currently selected text.
+*/
+void QLineControl::moveCursor(int pos, bool mark)
+{
+ if (pos != m_cursor) {
+ separate();
+ if (m_maskData)
+ pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
+ }
+ if (mark) {
+ int anchor;
+ if (m_selend > m_selstart && m_cursor == m_selstart)
+ anchor = m_selend;
+ else if (m_selend > m_selstart && m_cursor == m_selend)
+ anchor = m_selstart;
+ else
+ anchor = m_cursor;
+ m_selstart = qMin(anchor, pos);
+ m_selend = qMax(anchor, pos);
+ updateDisplayText();
+ } else {
+ internalDeselect();
+ }
+ m_cursor = pos;
+ if (mark || m_selDirty) {
+ m_selDirty = false;
+ emit selectionChanged();
+ }
+ emitCursorPositionChanged();
+}
+
+/*!
+ \internal
+
+ Applies the given input method event \a event to the text of the line
+ control
+*/
+void QLineControl::processInputMethodEvent(QInputMethodEvent *event)
+{
+ int priorState = 0;
+ bool isGettingInput = !event->commitString().isEmpty() || !event->preeditString().isEmpty()
+ || event->replacementLength() > 0;
+ bool cursorPositionChanged = false;
+
+ if (isGettingInput) {
+ // If any text is being input, remove selected text.
+ priorState = m_undoState;
+ removeSelectedText();
+ }
+
+
+ int c = m_cursor; // cursor position after insertion of commit string
+ if (event->replacementStart() <= 0)
+ c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength());
+
+ m_cursor += event->replacementStart();
+
+ // insert commit string
+ if (event->replacementLength()) {
+ m_selstart = m_cursor;
+ m_selend = m_selstart + event->replacementLength();
+ removeSelectedText();
+ }
+ if (!event->commitString().isEmpty()) {
+ insert(event->commitString());
+ cursorPositionChanged = true;
+ }
+
+ m_cursor = qMin(c, m_text.length());
+
+ for (int i = 0; i < event->attributes().size(); ++i) {
+ const QInputMethodEvent::Attribute &a = event->attributes().at(i);
+ if (a.type == QInputMethodEvent::Selection) {
+ m_cursor = qBound(0, a.start + a.length, m_text.length());
+ if (a.length) {
+ m_selstart = qMax(0, qMin(a.start, m_text.length()));
+ m_selend = m_cursor;
+ if (m_selend < m_selstart) {
+ qSwap(m_selstart, m_selend);
+ }
+ } else {
+ m_selstart = m_selend = 0;
+ }
+ cursorPositionChanged = true;
+ }
+ }
+
+ setPreeditArea(m_cursor, event->preeditString());
+ m_preeditCursor = event->preeditString().length();
+ m_hideCursor = false;
+ QList<QTextLayout::FormatRange> formats;
+ for (int i = 0; i < event->attributes().size(); ++i) {
+ const QInputMethodEvent::Attribute &a = event->attributes().at(i);
+ if (a.type == QInputMethodEvent::Cursor) {
+ m_preeditCursor = a.start;
+ m_hideCursor = !a.length;
+ } else if (a.type == QInputMethodEvent::TextFormat) {
+ QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
+ if (f.isValid()) {
+ QTextLayout::FormatRange o;
+ o.start = a.start + m_cursor;
+ o.length = a.length;
+ o.format = f;
+ formats.append(o);
+ }
+ }
+ }
+ m_textLayout.setAdditionalFormats(formats);
+ updateDisplayText();
+ if (cursorPositionChanged)
+ emitCursorPositionChanged();
+ if (isGettingInput)
+ finishChange(priorState);
+}
+
+/*!
+ \internal
+
+ Draws the display text for the line control using the given
+ \a painter, \a clip, and \a offset. Which aspects of the display text
+ are drawn is specified by the given \a flags.
+
+ If the flags contain DrawSelections, then the selection or input mask
+ backgrounds and foregrounds will be applied before drawing the text.
+
+ If the flags contain DrawCursor a cursor of the current cursorWidth()
+ will be drawn after drawing the text.
+
+ The display text will only be drawn if the flags contain DrawText
+*/
+void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &clip, int flags)
+{
+ QVector<QTextLayout::FormatRange> selections;
+ if (flags & DrawSelections) {
+ QTextLayout::FormatRange o;
+ if (m_selstart < m_selend) {
+ o.start = m_selstart;
+ o.length = m_selend - m_selstart;
+ o.format.setBackground(m_palette.brush(QPalette::Highlight));
+ o.format.setForeground(m_palette.brush(QPalette::HighlightedText));
+ } else {
+ // mask selection
+ o.start = m_cursor;
+ o.length = 1;
+ o.format.setBackground(m_palette.brush(QPalette::Text));
+ o.format.setForeground(m_palette.brush(QPalette::Window));
+ }
+ selections.append(o);
+ }
+
+ if (flags & DrawText)
+ m_textLayout.draw(painter, offset, selections, clip);
+
+ if (flags & DrawCursor){
+ if(!m_blinkPeriod || m_blinkStatus)
+ m_textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth);
+ }
+}
+
+/*!
+ \internal
+
+ Sets the selection to cover the word at the given cursor position.
+ The word boundries is defined by the behavior of QTextLayout::SkipWords
+ cursor mode.
+*/
+void QLineControl::selectWordAtPos(int cursor)
+{
+ int c = m_textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords);
+ moveCursor(c, false);
+ // ## text layout should support end of words.
+ int end = m_textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords);
+ while (end > cursor && m_text[end-1].isSpace())
+ --end;
+ moveCursor(end, true);
+}
+
+/*!
+ \internal
+
+ Completes a change to the line control text. If the change is not valid
+ will undo the line control state back to the given \a validateFromState.
+
+ If \a edited is true and the change is valid, will emit textEdited() in
+ addition to textChanged(). Otherwise only emits textChanged() on a valid
+ change.
+
+ The \a update value is currently unused.
+*/
+bool QLineControl::finishChange(int validateFromState, bool update, bool edited)
+{
+ Q_UNUSED(update)
+ bool lineDirty = m_selDirty;
+ if (m_textDirty) {
+ // do validation
+ bool wasValidInput = m_validInput;
+ m_validInput = true;
+#ifndef QT_NO_VALIDATOR
+ if (m_validator) {
+ m_validInput = false;
+ QString textCopy = m_text;
+ int cursorCopy = m_cursor;
+ m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
+ if (m_validInput) {
+ if (m_text != textCopy) {
+ internalSetText(textCopy, cursorCopy);
+ return true;
+ }
+ m_cursor = cursorCopy;
+ }
+ }
+#endif
+ if (validateFromState >= 0 && wasValidInput && !m_validInput) {
+ if (m_transactions.count())
+ return false;
+ internalUndo(validateFromState);
+ m_history.resize(m_undoState);
+ if (m_modifiedState > m_undoState)
+ m_modifiedState = -1;
+ m_validInput = true;
+ m_textDirty = false;
+ }
+ updateDisplayText();
+ lineDirty |= m_textDirty;
+ if (m_textDirty) {
+ m_textDirty = false;
+ QString actualText = text();
+ if (edited)
+ emit textEdited(actualText);
+ emit textChanged(actualText);
+ }
+ }
+ if (m_selDirty) {
+ m_selDirty = false;
+ emit selectionChanged();
+ }
+ emitCursorPositionChanged();
+ return true;
+}
+
+/*!
+ \internal
+
+ An internal function for setting the text of the line control.
+*/
+void QLineControl::internalSetText(const QString &txt, int pos, bool edited)
+{
+ internalDeselect();
+ emit resetInputContext();
+ QString oldText = m_text;
+ if (m_maskData) {
+ m_text = maskString(0, txt, true);
+ m_text += clearString(m_text.length(), m_maxLength - m_text.length());
+ } else {
+ m_text = txt.isEmpty() ? txt : txt.left(m_maxLength);
+ }
+ m_history.clear();
+ m_modifiedState = m_undoState = 0;
+ m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos;
+ m_textDirty = (oldText != m_text);
+ finishChange(-1, true, edited);
+}
+
+
+/*!
+ \internal
+
+ Adds the given \a command to the undo history
+ of the line control. Does not apply the command.
+*/
+void QLineControl::addCommand(const Command &cmd)
+{
+ if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) {
+ m_history.resize(m_undoState + 2);
+ m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend);
+ } else {
+ m_history.resize(m_undoState + 1);
+ }
+ m_separator = false;
+ m_history[m_undoState++] = cmd;
+}
+
+/*!
+ \internal
+
+ Inserts the given string \a s into the line
+ control.
+
+ Also adds the appropriate commands into the undo history.
+ This function does not call finishChange(), and may leave the text
+ in an invalid state.
+*/
+void QLineControl::internalInsert(const QString &s)
+{
+ if (hasSelectedText())
+ addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
+ if (m_maskData) {
+ QString ms = maskString(m_cursor, s);
+ for (int i = 0; i < (int) ms.length(); ++i) {
+ addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1));
+ addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1));
+ }
+ m_text.replace(m_cursor, ms.length(), ms);
+ m_cursor += ms.length();
+ m_cursor = nextMaskBlank(m_cursor);
+ m_textDirty = true;
+ } else {
+ int remaining = m_maxLength - m_text.length();
+ if (remaining != 0) {
+ m_text.insert(m_cursor, s.left(remaining));
+ for (int i = 0; i < (int) s.left(remaining).length(); ++i)
+ addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1));
+ m_textDirty = true;
+ }
+ }
+}
+
+/*!
+ \internal
+
+ deletes a single character from the current text. If \a wasBackspace,
+ the character prior to the cursor is removed. Otherwise the character
+ after the cursor is removed.
+
+ Also adds the appropriate commands into the undo history.
+ This function does not call finishChange(), and may leave the text
+ in an invalid state.
+*/
+void QLineControl::internalDelete(bool wasBackspace)
+{
+ if (m_cursor < (int) m_text.length()) {
+ if (hasSelectedText())
+ addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
+ addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)),
+ m_cursor, m_text.at(m_cursor), -1, -1));
+ if (m_maskData) {
+ m_text.replace(m_cursor, 1, clearString(m_cursor, 1));
+ addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1));
+ } else {
+ m_text.remove(m_cursor, 1);
+ }
+ m_textDirty = true;
+ }
+}
+
+/*!
+ \internal
+
+ removes the currently selected text from the line control.
+
+ Also adds the appropriate commands into the undo history.
+ This function does not call finishChange(), and may leave the text
+ in an invalid state.
+*/
+void QLineControl::removeSelectedText()
+{
+ if (m_selstart < m_selend && m_selend <= (int) m_text.length()) {
+ separate();
+ int i ;
+ addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
+ if (m_selstart <= m_cursor && m_cursor < m_selend) {
+ // cursor is within the selection. Split up the commands
+ // to be able to restore the correct cursor position
+ for (i = m_cursor; i >= m_selstart; --i)
+ addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1));
+ for (i = m_selend - 1; i > m_cursor; --i)
+ addCommand (Command(DeleteSelection, i - m_cursor + m_selstart - 1, m_text.at(i), -1, -1));
+ } else {
+ for (i = m_selend-1; i >= m_selstart; --i)
+ addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1));
+ }
+ if (m_maskData) {
+ m_text.replace(m_selstart, m_selend - m_selstart, clearString(m_selstart, m_selend - m_selstart));
+ for (int i = 0; i < m_selend - m_selstart; ++i)
+ addCommand(Command(Insert, m_selstart + i, m_text.at(m_selstart + i), -1, -1));
+ } else {
+ m_text.remove(m_selstart, m_selend - m_selstart);
+ }
+ if (m_cursor > m_selstart)
+ m_cursor -= qMin(m_cursor, m_selend) - m_selstart;
+ internalDeselect();
+ m_textDirty = true;
+ }
+}
+
+/*!
+ \internal
+
+ Parses the input mask specified by \a maskFields to generate
+ the mask data used to handle input masks.
+*/
+void QLineControl::parseInputMask(const QString &maskFields)
+{
+ int delimiter = maskFields.indexOf(QLatin1Char(';'));
+ if (maskFields.isEmpty() || delimiter == 0) {
+ if (m_maskData) {
+ delete [] m_maskData;
+ m_maskData = 0;
+ m_maxLength = 32767;
+ internalSetText(QString());
+ }
+ return;
+ }
+
+ if (delimiter == -1) {
+ m_blank = QLatin1Char(' ');
+ m_inputMask = maskFields;
+ } else {
+ m_inputMask = maskFields.left(delimiter);
+ m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
+ }
+
+ // calculate m_maxLength / m_maskData length
+ m_maxLength = 0;
+ QChar c = 0;
+ for (int i=0; i<m_inputMask.length(); i++) {
+ c = m_inputMask.at(i);
+ if (i > 0 && m_inputMask.at(i-1) == QLatin1Char('\\')) {
+ m_maxLength++;
+ continue;
+ }
+ if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
+ c != QLatin1Char('<') && c != QLatin1Char('>') &&
+ c != QLatin1Char('{') && c != QLatin1Char('}') &&
+ c != QLatin1Char('[') && c != QLatin1Char(']'))
+ m_maxLength++;
+ }
+
+ delete [] m_maskData;
+ m_maskData = new MaskInputData[m_maxLength];
+
+ MaskInputData::Casemode m = MaskInputData::NoCaseMode;
+ c = 0;
+ bool s;
+ bool escape = false;
+ int index = 0;
+ for (int i = 0; i < m_inputMask.length(); i++) {
+ c = m_inputMask.at(i);
+ if (escape) {
+ s = true;
+ m_maskData[index].maskChar = c;
+ m_maskData[index].separator = s;
+ m_maskData[index].caseMode = m;
+ index++;
+ escape = false;
+ } else if (c == QLatin1Char('<')) {
+ m = MaskInputData::Lower;
+ } else if (c == QLatin1Char('>')) {
+ m = MaskInputData::Upper;
+ } else if (c == QLatin1Char('!')) {
+ m = MaskInputData::NoCaseMode;
+ } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
+ switch (c.unicode()) {
+ case 'A':
+ case 'a':
+ case 'N':
+ case 'n':
+ case 'X':
+ case 'x':
+ case '9':
+ case '0':
+ case 'D':
+ case 'd':
+ case '#':
+ case 'H':
+ case 'h':
+ case 'B':
+ case 'b':
+ s = false;
+ break;
+ case '\\':
+ escape = true;
+ default:
+ s = true;
+ break;
+ }
+
+ if (!escape) {
+ m_maskData[index].maskChar = c;
+ m_maskData[index].separator = s;
+ m_maskData[index].caseMode = m;
+ index++;
+ }
+ }
+ }
+ internalSetText(m_text);
+}
+
+
+/*!
+ \internal
+
+ checks if the key is valid compared to the inputMask
+*/
+bool QLineControl::isValidInput(QChar key, QChar mask) const
+{
+ switch (mask.unicode()) {
+ case 'A':
+ if (key.isLetter())
+ return true;
+ break;
+ case 'a':
+ if (key.isLetter() || key == m_blank)
+ return true;
+ break;
+ case 'N':
+ if (key.isLetterOrNumber())
+ return true;
+ break;
+ case 'n':
+ if (key.isLetterOrNumber() || key == m_blank)
+ return true;
+ break;
+ case 'X':
+ if (key.isPrint())
+ return true;
+ break;
+ case 'x':
+ if (key.isPrint() || key == m_blank)
+ return true;
+ break;
+ case '9':
+ if (key.isNumber())
+ return true;
+ break;
+ case '0':
+ if (key.isNumber() || key == m_blank)
+ return true;
+ break;
+ case 'D':
+ if (key.isNumber() && key.digitValue() > 0)
+ return true;
+ break;
+ case 'd':
+ if ((key.isNumber() && key.digitValue() > 0) || key == m_blank)
+ return true;
+ break;
+ case '#':
+ if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_blank)
+ return true;
+ break;
+ case 'B':
+ if (key == QLatin1Char('0') || key == QLatin1Char('1'))
+ return true;
+ break;
+ case 'b':
+ if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == m_blank)
+ return true;
+ break;
+ case 'H':
+ if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
+ return true;
+ break;
+ case 'h':
+ if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == m_blank)
+ return true;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+/*!
+ \internal
+
+ Returns true if the given text \a str is valid for any
+ validator or input mask set for the line control.
+
+ Otherwise returns false
+*/
+bool QLineControl::hasAcceptableInput(const QString &str) const
+{
+#ifndef QT_NO_VALIDATOR
+ QString textCopy = str;
+ int cursorCopy = m_cursor;
+ if (m_validator && m_validator->validate(textCopy, cursorCopy)
+ != QValidator::Acceptable)
+ return false;
+#endif
+
+ if (!m_maskData)
+ return true;
+
+ if (str.length() != m_maxLength)
+ return false;
+
+ for (int i=0; i < m_maxLength; ++i) {
+ if (m_maskData[i].separator) {
+ if (str.at(i) != m_maskData[i].maskChar)
+ return false;
+ } else {
+ if (!isValidInput(str.at(i), m_maskData[i].maskChar))
+ return false;
+ }
+ }
+ return true;
+}
+
+/*!
+ \internal
+
+ Applies the inputMask on \a str starting from position \a pos in the mask. \a clear
+ specifies from where characters should be gotten when a separator is met in \a str - true means
+ that blanks will be used, false that previous input is used.
+ Calling this when no inputMask is set is undefined.
+*/
+QString QLineControl::maskString(uint pos, const QString &str, bool clear) const
+{
+ if (pos >= (uint)m_maxLength)
+ return QString::fromLatin1("");
+
+ QString fill;
+ fill = clear ? clearString(0, m_maxLength) : m_text;
+
+ int strIndex = 0;
+ QString s = QString::fromLatin1("");
+ int i = pos;
+ while (i < m_maxLength) {
+ if (strIndex < str.length()) {
+ if (m_maskData[i].separator) {
+ s += m_maskData[i].maskChar;
+ if (str[(int)strIndex] == m_maskData[i].maskChar)
+ strIndex++;
+ ++i;
+ } else {
+ if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) {
+ switch (m_maskData[i].caseMode) {
+ case MaskInputData::Upper:
+ s += str[(int)strIndex].toUpper();
+ break;
+ case MaskInputData::Lower:
+ s += str[(int)strIndex].toLower();
+ break;
+ default:
+ s += str[(int)strIndex];
+ }
+ ++i;
+ } else {
+ // search for separator first
+ int n = findInMask(i, true, true, str[(int)strIndex]);
+ if (n != -1) {
+ if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) {
+ s += fill.mid(i, n-i+1);
+ i = n + 1; // update i to find + 1
+ }
+ } else {
+ // search for valid m_blank if not
+ n = findInMask(i, true, false, str[(int)strIndex]);
+ if (n != -1) {
+ s += fill.mid(i, n-i);
+ switch (m_maskData[n].caseMode) {
+ case MaskInputData::Upper:
+ s += str[(int)strIndex].toUpper();
+ break;
+ case MaskInputData::Lower:
+ s += str[(int)strIndex].toLower();
+ break;
+ default:
+ s += str[(int)strIndex];
+ }
+ i = n + 1; // updates i to find + 1
+ }
+ }
+ }
+ ++strIndex;
+ }
+ } else
+ break;
+ }
+
+ return s;
+}
+
+
+
+/*!
+ \internal
+
+ Returns a "cleared" string with only separators and blank chars.
+ Calling this when no inputMask is set is undefined.
+*/
+QString QLineControl::clearString(uint pos, uint len) const
+{
+ if (pos >= (uint)m_maxLength)
+ return QString();
+
+ QString s;
+ int end = qMin((uint)m_maxLength, pos + len);
+ for (int i = pos; i < end; ++i)
+ if (m_maskData[i].separator)
+ s += m_maskData[i].maskChar;
+ else
+ s += m_blank;
+
+ return s;
+}
+
+/*!
+ \internal
+
+ Strips blank parts of the input in a QLineControl when an inputMask is set,
+ separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1".
+*/
+QString QLineControl::stripString(const QString &str) const
+{
+ if (!m_maskData)
+ return str;
+
+ QString s;
+ int end = qMin(m_maxLength, (int)str.length());
+ for (int i = 0; i < end; ++i)
+ if (m_maskData[i].separator)
+ s += m_maskData[i].maskChar;
+ else
+ if (str[i] != m_blank)
+ s += str[i];
+
+ return s;
+}
+
+/*!
+ \internal
+ searches forward/backward in m_maskData for either a separator or a m_blank
+*/
+int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
+{
+ if (pos >= m_maxLength || pos < 0)
+ return -1;
+
+ int end = forward ? m_maxLength : -1;
+ int step = forward ? 1 : -1;
+ int i = pos;
+
+ while (i != end) {
+ if (findSeparator) {
+ if (m_maskData[i].separator && m_maskData[i].maskChar == searchChar)
+ return i;
+ } else {
+ if (!m_maskData[i].separator) {
+ if (searchChar.isNull())
+ return i;
+ else if (isValidInput(searchChar, m_maskData[i].maskChar))
+ return i;
+ }
+ }
+ i += step;
+ }
+ return -1;
+}
+
+void QLineControl::internalUndo(int until)
+{
+ if (!isUndoAvailable())
+ return;
+ internalDeselect();
+ while (m_undoState && m_undoState > until) {
+ Command& cmd = m_history[--m_undoState];
+ switch (cmd.type) {
+ case Insert:
+ m_text.remove(cmd.pos, 1);
+ m_cursor = cmd.pos;
+ break;
+ case SetSelection:
+ m_selstart = cmd.selStart;
+ m_selend = cmd.selEnd;
+ m_cursor = cmd.pos;
+ break;
+ case Remove:
+ case RemoveSelection:
+ m_text.insert(cmd.pos, cmd.uc);
+ m_cursor = cmd.pos + 1;
+ break;
+ case Delete:
+ case DeleteSelection:
+ m_text.insert(cmd.pos, cmd.uc);
+ m_cursor = cmd.pos;
+ break;
+ case Separator:
+ continue;
+ }
+ if (until < 0 && m_undoState) {
+ Command& next = m_history[m_undoState-1];
+ if (next.type != cmd.type && next.type < RemoveSelection
+ && (cmd.type < RemoveSelection || next.type == Separator))
+ break;
+ }
+ }
+ m_textDirty = true;
+ emitCursorPositionChanged();
+}
+
+void QLineControl::internalRedo()
+{
+ if (!isRedoAvailable())
+ return;
+ internalDeselect();
+ while (m_undoState < (int)m_history.size()) {
+ Command& cmd = m_history[m_undoState++];
+ switch (cmd.type) {
+ case Insert:
+ m_text.insert(cmd.pos, cmd.uc);
+ m_cursor = cmd.pos + 1;
+ break;
+ case SetSelection:
+ m_selstart = cmd.selStart;
+ m_selend = cmd.selEnd;
+ m_cursor = cmd.pos;
+ break;
+ case Remove:
+ case Delete:
+ case RemoveSelection:
+ case DeleteSelection:
+ m_text.remove(cmd.pos, 1);
+ m_selstart = cmd.selStart;
+ m_selend = cmd.selEnd;
+ m_cursor = cmd.pos;
+ break;
+ case Separator:
+ m_selstart = cmd.selStart;
+ m_selend = cmd.selEnd;
+ m_cursor = cmd.pos;
+ break;
+ }
+ if (m_undoState < (int)m_history.size()) {
+ Command& next = m_history[m_undoState];
+ if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator
+ && (next.type < RemoveSelection || cmd.type == Separator))
+ break;
+ }
+ }
+ m_textDirty = true;
+ emitCursorPositionChanged();
+}
+
+/*!
+ \internal
+
+ If the current cursor position differs from the last emited cursor
+ position, emits cursorPositionChanged().
+*/
+void QLineControl::emitCursorPositionChanged()
+{
+ if (m_cursor != m_lastCursorPos) {
+ const int oldLast = m_lastCursorPos;
+ m_lastCursorPos = m_cursor;
+ cursorPositionChanged(oldLast, m_cursor);
+ }
+}
+
+#ifndef QT_NO_COMPLETER
+// iterating forward(dir=1)/backward(dir=-1) from the
+// current row based. dir=0 indicates a new completion prefix was set.
+bool QLineControl::advanceToEnabledItem(int dir)
+{
+ int start = m_completer->currentRow();
+ if (start == -1)
+ return false;
+ int i = start + dir;
+ if (dir == 0) dir = 1;
+ do {
+ if (!m_completer->setCurrentRow(i)) {
+ if (!m_completer->wrapAround())
+ break;
+ i = i > 0 ? 0 : m_completer->completionCount() - 1;
+ } else {
+ QModelIndex currentIndex = m_completer->currentIndex();
+ if (m_completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
+ return true;
+ i += dir;
+ }
+ } while (i != start);
+
+ m_completer->setCurrentRow(start); // restore
+ return false;
+}
+
+void QLineControl::complete(int key)
+{
+ if (!m_completer || isReadOnly() || echoMode() != QLineEdit::Normal)
+ return;
+
+ QString text = this->text();
+ if (m_completer->completionMode() == QCompleter::InlineCompletion) {
+ if (key == Qt::Key_Backspace)
+ return;
+ int n = 0;
+ if (key == Qt::Key_Up || key == Qt::Key_Down) {
+ if (textAfterSelection().length())
+ return;
+ QString prefix = hasSelectedText() ? textBeforeSelection()
+ : text;
+ if (text.compare(m_completer->currentCompletion(), m_completer->caseSensitivity()) != 0
+ || prefix.compare(m_completer->completionPrefix(), m_completer->caseSensitivity()) != 0) {
+ m_completer->setCompletionPrefix(prefix);
+ } else {
+ n = (key == Qt::Key_Up) ? -1 : +1;
+ }
+ } else {
+ m_completer->setCompletionPrefix(text);
+ }
+ if (!advanceToEnabledItem(n))
+ return;
+ } else {
+#ifndef QT_KEYPAD_NAVIGATION
+ if (text.isEmpty()) {
+ m_completer->popup()->hide();
+ return;
+ }
+#endif
+ m_completer->setCompletionPrefix(text);
+ }
+
+ m_completer->complete();
+}
+#endif
+
+void QLineControl::setCursorBlinkPeriod(int msec)
+{
+ if (msec == m_blinkPeriod)
+ return;
+ if (m_blinkTimer) {
+ killTimer(m_blinkTimer);
+ }
+ if (msec) {
+ m_blinkTimer = startTimer(msec / 2);
+ m_blinkStatus = 1;
+ } else {
+ m_blinkTimer = 0;
+ if (m_blinkStatus == 0)
+ emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect());
+ }
+ m_blinkPeriod = msec;
+}
+
+void QLineControl::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == m_blinkTimer) {
+ m_blinkStatus = !m_blinkStatus;
+ emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect());
+ } else if (event->timerId() == m_deleteAllTimer) {
+ killTimer(m_deleteAllTimer);
+ m_deleteAllTimer = 0;
+ clear();
+ } else if (event->timerId() == m_tripleClickTimer) {
+ killTimer(m_tripleClickTimer);
+ m_tripleClickTimer = 0;
+ }
+}
+
+bool QLineControl::processEvent(QEvent* ev)
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::keypadNavigationEnabled()) {
+ if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) {
+ QKeyEvent *ke = (QKeyEvent *)ev;
+ if (ke->key() == Qt::Key_Back) {
+ if (ke->isAutoRepeat()) {
+ // Swallow it. We don't want back keys running amok.
+ ke->accept();
+ return true;
+ }
+ if ((ev->type() == QEvent::KeyRelease)
+ && !isReadOnly()
+ && m_deleteAllTimer) {
+ killTimer(m_deleteAllTimer);
+ m_deleteAllTimer = 0;
+ backspace();
+ ke->accept();
+ return true;
+ }
+ }
+ }
+ }
+#endif
+ switch(ev->type()){
+#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMousePress:{
+ QGraphicsSceneMouseEvent *gvEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
+ QMouseEvent* mouse = new QMouseEvent(ev->type(),
+ gvEv->pos().toPoint(), gvEv->button(), gvEv->buttons(), gvEv->modifiers());
+ processMouseEvent(mouse); break;
+ }
+#endif
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ processMouseEvent(static_cast<QMouseEvent*>(ev)); break;
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ processKeyEvent(static_cast<QKeyEvent*>(ev)); break;
+ case QEvent::InputMethod:
+ processInputMethodEvent(static_cast<QInputMethodEvent*>(ev)); break;
+#ifndef QT_NO_SHORTCUT
+ case QEvent::ShortcutOverride:{
+ QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
+ if (ke == QKeySequence::Copy
+ || ke == QKeySequence::Paste
+ || ke == QKeySequence::Cut
+ || ke == QKeySequence::Redo
+ || ke == QKeySequence::Undo
+ || ke == QKeySequence::MoveToNextWord
+ || ke == QKeySequence::MoveToPreviousWord
+ || ke == QKeySequence::MoveToStartOfDocument
+ || ke == QKeySequence::MoveToEndOfDocument
+ || ke == QKeySequence::SelectNextWord
+ || ke == QKeySequence::SelectPreviousWord
+ || ke == QKeySequence::SelectStartOfLine
+ || ke == QKeySequence::SelectEndOfLine
+ || ke == QKeySequence::SelectStartOfBlock
+ || ke == QKeySequence::SelectEndOfBlock
+ || ke == QKeySequence::SelectStartOfDocument
+ || ke == QKeySequence::SelectAll
+ || ke == QKeySequence::SelectEndOfDocument) {
+ ke->accept();
+ } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
+ || ke->modifiers() == Qt::KeypadModifier) {
+ if (ke->key() < Qt::Key_Escape) {
+ ke->accept();
+ } else {
+ switch (ke->key()) {
+ case Qt::Key_Delete:
+ case Qt::Key_Home:
+ case Qt::Key_End:
+ case Qt::Key_Backspace:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ ke->accept();
+ default:
+ break;
+ }
+ }
+ }
+ }
+#endif
+ default:
+ return false;
+ }
+ return true;
+}
+
+void QLineControl::processMouseEvent(QMouseEvent* ev)
+{
+
+ switch (ev->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::MouseButtonPress:{
+ if (m_tripleClickTimer
+ && (ev->pos() - m_tripleClick).manhattanLength()
+ < QApplication::startDragDistance()) {
+ selectAll();
+ return;
+ }
+ if (ev->button() == Qt::RightButton)
+ return;
+
+ bool mark = ev->modifiers() & Qt::ShiftModifier;
+ int cursor = xToPos(ev->pos().x());
+ moveCursor(cursor, mark);
+ break;
+ }
+ case QEvent::MouseButtonDblClick:
+ if (ev->button() == Qt::LeftButton) {
+ selectWordAtPos(xToPos(ev->pos().x()));
+ if (m_tripleClickTimer)
+ killTimer(m_tripleClickTimer);
+ m_tripleClickTimer = startTimer(QApplication::doubleClickInterval());
+ m_tripleClick = ev->pos();
+ }
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::MouseButtonRelease:
+#ifndef QT_NO_CLIPBOARD
+ if (QApplication::clipboard()->supportsSelection()) {
+ if (ev->button() == Qt::LeftButton) {
+ copy(QClipboard::Selection);
+ } else if (!isReadOnly() && ev->button() == Qt::MidButton) {
+ deselect();
+ insert(QApplication::clipboard()->text(QClipboard::Selection));
+ }
+ }
+#endif
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::MouseMove:
+ if (ev->buttons() & Qt::LeftButton) {
+ moveCursor(xToPos(ev->pos().x()), true);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void QLineControl::processKeyEvent(QKeyEvent* event)
+{
+ bool inlineCompletionAccepted = false;
+
+#ifndef QT_NO_COMPLETER
+ if (m_completer) {
+ QCompleter::CompletionMode completionMode = m_completer->completionMode();
+ if ((completionMode == QCompleter::PopupCompletion
+ || completionMode == QCompleter::UnfilteredPopupCompletion)
+ && m_completer->popup()
+ && m_completer->popup()->isVisible()) {
+ // The following keys are forwarded by the completer to the widget
+ // Ignoring the events lets the completer provide suitable default behavior
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ event->ignore();
+ return;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_F4:
+#ifdef QT_KEYPAD_NAVIGATION
+ case Qt::Key_Select:
+ if (!QApplication::keypadNavigationEnabled())
+ break;
+#endif
+ m_completer->popup()->hide(); // just hide. will end up propagating to parent
+ default:
+ break; // normal key processing
+ }
+ } else if (completionMode == QCompleter::InlineCompletion) {
+ switch (event->key()) {
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_F4:
+#ifdef QT_KEYPAD_NAVIGATION
+ case Qt::Key_Select:
+ if (!QApplication::keypadNavigationEnabled())
+ break;
+#endif
+ if (!m_completer->currentCompletion().isEmpty() && hasSelectedText()
+ && textAfterSelection().isEmpty()) {
+ setText(m_completer->currentCompletion());
+ inlineCompletionAccepted = true;
+ }
+ default:
+ break; // normal key processing
+ }
+ }
+ }
+#endif // QT_NO_COMPLETER
+
+ if (echoMode() == QLineEdit::PasswordEchoOnEdit
+ && !passwordEchoEditing()
+ && !isReadOnly()
+ && !event->text().isEmpty()
+#ifdef QT_KEYPAD_NAVIGATION
+ && event->key() != Qt::Key_Select
+ && event->key() != Qt::Key_Up
+ && event->key() != Qt::Key_Down
+ && event->key() != Qt::Key_Back
+#endif
+ && !(event->modifiers() & Qt::ControlModifier)) {
+ // Clear the edit and reset to normal echo mode while editing; the
+ // echo mode switches back when the edit loses focus
+ // ### resets current content. dubious code; you can
+ // navigate with keys up, down, back, and select(?), but if you press
+ // "left" or "right" it clears?
+ updatePasswordEchoEditing(true);
+ clear();
+ }
+
+ if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
+ if (hasAcceptableInput() || fixup()) {
+ emit accepted();
+ emit editingFinished();
+ }
+ if (inlineCompletionAccepted)
+ event->accept();
+ else
+ event->ignore();
+ return;
+ }
+ bool unknown = false;
+
+ if (false) {
+ }
+#ifndef QT_NO_SHORTCUT
+ else if (event == QKeySequence::Undo) {
+ if (!isReadOnly())
+ undo();
+ }
+ else if (event == QKeySequence::Redo) {
+ if (!isReadOnly())
+ redo();
+ }
+ else if (event == QKeySequence::SelectAll) {
+ selectAll();
+ }
+#ifndef QT_NO_CLIPBOARD
+ else if (event == QKeySequence::Copy) {
+ copy();
+ }
+ else if (event == QKeySequence::Paste) {
+ if (!isReadOnly())
+ paste();
+ }
+ else if (event == QKeySequence::Cut) {
+ if (!isReadOnly()) {
+ copy();
+ del();
+ }
+ }
+ else if (event == QKeySequence::DeleteEndOfLine) {
+ if (!isReadOnly()) {
+ setSelection(cursor(), end());
+ copy();
+ del();
+ }
+ }
+#endif //QT_NO_CLIPBOARD
+ else if (event == QKeySequence::MoveToStartOfLine) {
+ home(0);
+ }
+ else if (event == QKeySequence::MoveToEndOfLine) {
+ end(0);
+ }
+ else if (event == QKeySequence::SelectStartOfLine) {
+ home(1);
+ }
+ else if (event == QKeySequence::SelectEndOfLine) {
+ end(1);
+ }
+ else if (event == QKeySequence::MoveToNextChar) {
+#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
+ if (hasSelectedText()) {
+#else
+ if (hasSelectedText() && m_completer
+ && m_completer->completionMode() == QCompleter::InlineCompletion) {
+#endif
+ moveCursor(selectionEnd(), false);
+ } else {
+ cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
+ }
+ }
+ else if (event == QKeySequence::SelectNextChar) {
+ cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
+ }
+ else if (event == QKeySequence::MoveToPreviousChar) {
+#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
+ if (hasSelectedText()) {
+#else
+ if (hasSelectedText() && m_completer
+ && m_completer->completionMode() == QCompleter::InlineCompletion) {
+#endif
+ moveCursor(selectionStart(), false);
+ } else {
+ cursorForward(0, layoutDirection() == Qt::LeftToRight ? -1 : 1);
+ }
+ }
+ else if (event == QKeySequence::SelectPreviousChar) {
+ cursorForward(1, layoutDirection() == Qt::LeftToRight ? -1 : 1);
+ }
+ else if (event == QKeySequence::MoveToNextWord) {
+ if (echoMode() == QLineEdit::Normal)
+ layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
+ else
+ layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
+ }
+ else if (event == QKeySequence::MoveToPreviousWord) {
+ if (echoMode() == QLineEdit::Normal)
+ layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0);
+ else if (!isReadOnly()) {
+ layoutDirection() == Qt::LeftToRight ? home(0) : end(0);
+ }
+ }
+ else if (event == QKeySequence::SelectNextWord) {
+ if (echoMode() == QLineEdit::Normal)
+ layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
+ else
+ layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
+ }
+ else if (event == QKeySequence::SelectPreviousWord) {
+ if (echoMode() == QLineEdit::Normal)
+ layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
+ else
+ layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
+ }
+ else if (event == QKeySequence::Delete) {
+ if (!isReadOnly())
+ del();
+ }
+ else if (event == QKeySequence::DeleteEndOfWord) {
+ if (!isReadOnly()) {
+ cursorWordForward(true);
+ del();
+ }
+ }
+ else if (event == QKeySequence::DeleteStartOfWord) {
+ if (!isReadOnly()) {
+ cursorWordBackward(true);
+ del();
+ }
+ }
+#endif // QT_NO_SHORTCUT
+ else {
+#ifdef Q_WS_MAC
+ if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) {
+ Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier);
+ if (myModifiers & Qt::ShiftModifier) {
+ if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier)
+ || myModifiers == (Qt::AltModifier|Qt::ShiftModifier)
+ || myModifiers == Qt::ShiftModifier) {
+
+ event->key() == Qt::Key_Up ? home(1) : end(1);
+ }
+ } else {
+ if ((myModifiers == Qt::ControlModifier
+ || myModifiers == Qt::AltModifier
+ || myModifiers == Qt::NoModifier)) {
+ event->key() == Qt::Key_Up ? home(0) : end(0);
+ }
+ }
+ }
+#endif
+ if (event->modifiers() & Qt::ControlModifier) {
+ switch (event->key()) {
+ case Qt::Key_Backspace:
+ if (!isReadOnly()) {
+ cursorWordBackward(true);
+ del();
+ }
+ break;
+#ifndef QT_NO_COMPLETER
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ complete(event->key());
+ break;
+#endif
+#if defined(Q_WS_X11)
+ case Qt::Key_E:
+ end(0);
+ break;
+
+ case Qt::Key_U:
+ if (!isReadOnly()) {
+ setSelection(0, text().size());
+#ifndef QT_NO_CLIPBOARD
+ copy();
+#endif
+ del();
+ }
+ break;
+#endif
+ default:
+ unknown = true;
+ }
+ } else { // ### check for *no* modifier
+ switch (event->key()) {
+ case Qt::Key_Backspace:
+ if (!isReadOnly()) {
+ backspace();
+#ifndef QT_NO_COMPLETER
+ complete(Qt::Key_Backspace);
+#endif
+ }
+ break;
+#ifdef QT_KEYPAD_NAVIGATION
+ case Qt::Key_Back:
+ if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat()
+ && !isReadOnly()) {
+ if (text().length() == 0) {
+ setText(m_cancelText);
+
+ if (passwordEchoEditing())
+ updatePasswordEchoEditing(false);
+
+ emit editFocusChange(false);
+ } else if (!m_deleteAllTimer) {
+ m_deleteAllTimer = startTimer(750);
+ }
+ } else {
+ unknown = true;
+ }
+ break;
+#endif
+
+ default:
+ unknown = true;
+ }
+ }
+ }
+
+ if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
+ setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
+ unknown = false;
+ }
+
+ if (unknown && !isReadOnly()) {
+ QString t = event->text();
+ if (!t.isEmpty() && t.at(0).isPrint()) {
+ insert(t);
+#ifndef QT_NO_COMPLETER
+ complete(event->key());
+#endif
+ event->accept();
+ return;
+ }
+ }
+
+ if (unknown)
+ event->ignore();
+ else
+ event->accept();
+}
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h
new file mode 100644
index 0000000..0db6279
--- /dev/null
+++ b/src/gui/widgets/qlinecontrol_p.h
@@ -0,0 +1,744 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLINECONTROL_P_H
+#define QLINECONTROL_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/qglobal.h"
+
+#ifndef QT_NO_LINEEDIT
+#include "private/qwidget_p.h"
+#include "QtGui/qlineedit.h"
+#include "QtGui/qtextlayout.h"
+#include "QtGui/qstyleoption.h"
+#include "QtCore/qpointer.h"
+#include "QtGui/qlineedit.h"
+#include "QtGui/qclipboard.h"
+#include "QtCore/qpoint.h"
+#include "QtGui/qcompleter.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class Q_GUI_EXPORT QLineControl : public QObject
+{
+ Q_OBJECT
+
+public:
+ QLineControl(const QString &txt = QString())
+ : m_cursor(0), m_preeditCursor(0), m_cursorWidth(0), m_layoutDirection(Qt::LeftToRight),
+ m_hideCursor(false), m_separator(0), m_readOnly(0),
+ m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0),
+ m_validInput(1), m_blinkStatus(0), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0),
+ m_ascent(0), m_maxLength(32767), m_lastCursorPos(-1),
+ m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0),
+ m_selstart(0), m_selend(0), m_passwordEchoEditing(false)
+ {
+ init(txt);
+ }
+
+ ~QLineControl()
+ {
+ delete [] m_maskData;
+ }
+
+ int nextMaskBlank(int pos);
+ int prevMaskBlank(int pos);
+
+ bool isUndoAvailable() const;
+ bool isRedoAvailable() const;
+ void clearUndo();
+ bool isModified() const;
+ void setModified(bool modified);
+
+ bool allSelected() const;
+ bool hasSelectedText() const;
+
+ int width() const;
+ int height() const;
+ int ascent() const;
+
+ void setSelection(int start, int length);
+
+ QString selectedText() const;
+ QString textBeforeSelection() const;
+ QString textAfterSelection() const;
+
+ int selectionStart() const;
+ int selectionEnd() const;
+ bool inSelection(int x) const;
+
+ void removeSelection();
+
+ int start() const;
+ int end() const;
+
+#ifndef QT_NO_CLIPBOARD
+ void copy(QClipboard::Mode mode = QClipboard::Clipboard) const;
+ void paste();
+#endif
+
+ int cursor() const;
+ int preeditCursor() const;
+
+ int cursorWidth() const;
+ void setCursorWidth(int value);
+
+ void moveCursor(int pos, bool mark = false);
+ void cursorForward(bool mark, int steps);
+ void cursorWordForward(bool mark);
+ void cursorWordBackward(bool mark);
+ void home(bool mark);
+ void end(bool mark);
+
+ int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
+ QRect cursorRect() const;
+
+ qreal cursorToX(int cursor) const;
+ qreal cursorToX() const;
+
+ bool isReadOnly() const;
+ void setReadOnly(bool enable);
+
+ QString text() const;
+ void setText(const QString &txt);
+
+ QString displayText() const;
+
+ void backspace();
+ void del();
+ void deselect();
+ void selectAll();
+ void insert(const QString &);
+ void clear();
+ void undo();
+ void redo();
+ void selectWordAtPos(int);
+
+ uint echoMode() const;
+ void setEchoMode(uint mode);
+
+ void setMaxLength(int maxLength);
+ int maxLength() const;
+
+ const QValidator *validator() const;
+ void setValidator(const QValidator *);
+
+#ifndef QT_NO_COMPLETER
+ QCompleter *completer() const;
+ void setCompleter(const QCompleter*);
+ void complete(int key);
+#endif
+
+ void setCursorPosition(int pos);
+ int cursorPosition() const;
+
+ bool hasAcceptableInput() const;
+ bool fixup();
+
+ QString inputMask() const;
+ void setInputMask(const QString &mask);
+
+ // input methods
+#ifndef QT_NO_IM
+ bool composeMode() const;
+ void setPreeditArea(int cursor, const QString &text);
+#endif
+
+ QString preeditAreaText() const;
+
+ void updatePasswordEchoEditing(bool editing);
+ bool passwordEchoEditing() const;
+
+ QChar passwordCharacter() const;
+ void setPasswordCharacter(const QChar &character);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection(Qt::LayoutDirection direction);
+ void setFont(const QFont &font);
+
+ void processInputMethodEvent(QInputMethodEvent *event);
+ void processMouseEvent(QMouseEvent* ev);
+ void processKeyEvent(QKeyEvent* ev);
+
+ int cursorBlinkPeriod() const;
+ void setCursorBlinkPeriod(int msec);
+
+ QString cancelText() const;
+ void setCancelText(const QString &text);
+
+ enum DrawFlags {
+ DrawText = 0x01,
+ DrawSelections = 0x02,
+ DrawCursor = 0x04,
+ DrawAll = DrawText | DrawSelections | DrawCursor
+ };
+ void draw(QPainter *, const QPoint &, const QRect &, int flags = DrawAll);
+
+ bool processEvent(QEvent *ev);
+
+private:
+ void init(const QString &txt);
+ void removeSelectedText();
+ void internalSetText(const QString &txt, int pos = -1, bool edited = true);
+ void updateDisplayText();
+
+ void internalInsert(const QString &s);
+ void internalDelete(bool wasBackspace = false);
+ void internalRemove(int pos);
+
+ inline void internalDeselect()
+ {
+ m_selDirty |= (m_selend > m_selstart);
+ m_selstart = m_selend = 0;
+ }
+
+ void internalUndo(int until = -1);
+ void internalRedo();
+
+ QString m_text;
+ QPalette m_palette;
+ int m_cursor;
+ int m_preeditCursor;
+ int m_cursorWidth;
+ Qt::LayoutDirection m_layoutDirection;
+ uint m_hideCursor : 1; // used to hide the m_cursor inside preedit areas
+ uint m_separator : 1;
+ uint m_readOnly : 1;
+ uint m_dragEnabled : 1;
+ uint m_echoMode : 2;
+ uint m_textDirty : 1;
+ uint m_selDirty : 1;
+ uint m_validInput : 1;
+ uint m_blinkStatus : 1;
+ int m_blinkPeriod; // 0 for non-blinking cursor
+ int m_blinkTimer;
+ int m_deleteAllTimer;
+ int m_ascent;
+ int m_maxLength;
+ int m_lastCursorPos;
+ QList<int> m_transactions;
+ QPoint m_tripleClick;
+ int m_tripleClickTimer;
+ QString m_cancelText;
+
+ void emitCursorPositionChanged();
+
+ bool finishChange(int validateFromState = -1, bool update = false, bool edited = true);
+
+ QPointer<QValidator> m_validator;
+ QPointer<QCompleter> m_completer;
+#ifndef QT_NO_COMPLETER
+ bool advanceToEnabledItem(int dir);
+#endif
+
+ struct MaskInputData {
+ enum Casemode { NoCaseMode, Upper, Lower };
+ QChar maskChar; // either the separator char or the inputmask
+ bool separator;
+ Casemode caseMode;
+ };
+ QString m_inputMask;
+ QChar m_blank;
+ MaskInputData *m_maskData;
+
+ // undo/redo handling
+ enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection };
+ struct Command {
+ inline Command() {}
+ inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {}
+ uint type : 4;
+ QChar uc;
+ int pos, selStart, selEnd;
+ };
+ int m_modifiedState;
+ int m_undoState;
+ QVector<Command> m_history;
+ void addCommand(const Command& cmd);
+
+ inline void separate() { m_separator = true; }
+
+ // selection
+ int m_selstart;
+ int m_selend;
+
+ // masking
+ void parseInputMask(const QString &maskFields);
+ bool isValidInput(QChar key, QChar mask) const;
+ bool hasAcceptableInput(const QString &text) const;
+ QString maskString(uint pos, const QString &str, bool clear = false) const;
+ QString clearString(uint pos, uint len) const;
+ QString stripString(const QString &str) const;
+ int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const;
+
+ // complex text layout
+ QTextLayout m_textLayout;
+
+ bool m_passwordEchoEditing;
+ QChar m_passwordCharacter;
+
+Q_SIGNALS:
+ void cursorPositionChanged(int, int);
+ void selectionChanged();
+
+ void displayTextChanged(const QString &);
+ void textChanged(const QString &);
+ void textEdited(const QString &);
+
+ void resetInputContext();
+
+ void accepted();
+ void editingFinished();
+ void updateNeeded(const QRect &);
+
+#ifdef QT_KEYPAD_NAVIGATION
+ void editFocusChange(bool);
+#endif
+protected:
+ virtual void timerEvent(QTimerEvent *event);
+
+private Q_SLOTS:
+ void _q_clipboardChanged();
+ void _q_deleteSelected();
+
+};
+
+inline int QLineControl::nextMaskBlank(int pos)
+{
+ int c = findInMask(pos, true, false);
+ m_separator |= (c != pos);
+ return (c != -1 ? c : m_maxLength);
+}
+
+inline int QLineControl::prevMaskBlank(int pos)
+{
+ int c = findInMask(pos, false, false);
+ m_separator |= (c != pos);
+ return (c != -1 ? c : 0);
+}
+
+inline bool QLineControl::isUndoAvailable() const
+{
+ return !m_readOnly && m_undoState;
+}
+
+inline bool QLineControl::isRedoAvailable() const
+{
+ return !m_readOnly && m_undoState < (int)m_history.size();
+}
+
+inline void QLineControl::clearUndo()
+{
+ m_history.clear();
+ m_modifiedState = m_undoState = 0;
+}
+
+inline bool QLineControl::isModified() const
+{
+ return m_modifiedState != m_undoState;
+}
+
+inline void QLineControl::setModified(bool modified)
+{
+ m_modifiedState = modified ? -1 : m_undoState;
+}
+
+inline bool QLineControl::allSelected() const
+{
+ return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length();
+}
+
+inline bool QLineControl::hasSelectedText() const
+{
+ return !m_text.isEmpty() && m_selend > m_selstart;
+}
+
+inline int QLineControl::width() const
+{
+ return qRound(m_textLayout.lineAt(0).width()) + 1;
+}
+
+inline int QLineControl::height() const
+{
+ return qRound(m_textLayout.lineAt(0).height()) + 1;
+}
+
+inline int QLineControl::ascent() const
+{
+ return m_ascent;
+}
+
+inline QString QLineControl::selectedText() const
+{
+ if (hasSelectedText())
+ return m_text.mid(m_selstart, m_selend - m_selstart);
+ return QString();
+}
+
+inline QString QLineControl::textBeforeSelection() const
+{
+ if (hasSelectedText())
+ return m_text.left(m_selstart);
+ return QString();
+}
+
+inline QString QLineControl::textAfterSelection() const
+{
+ if (hasSelectedText())
+ return m_text.mid(m_selend);
+ return QString();
+}
+
+inline int QLineControl::selectionStart() const
+{
+ return hasSelectedText() ? m_selstart : -1;
+}
+
+inline int QLineControl::selectionEnd() const
+{
+ return hasSelectedText() ? m_selend : -1;
+}
+
+inline int QLineControl::start() const
+{
+ return 0;
+}
+
+inline int QLineControl::end() const
+{
+ return m_text.length();
+}
+
+inline void QLineControl::removeSelection()
+{
+ int priorState = m_undoState;
+ removeSelectedText();
+ finishChange(priorState);
+}
+
+inline bool QLineControl::inSelection(int x) const
+{
+ if (m_selstart >= m_selend)
+ return false;
+ int pos = xToPos(x, QTextLine::CursorOnCharacter);
+ return pos >= m_selstart && pos < m_selend;
+}
+
+inline int QLineControl::cursor() const
+{
+ return m_cursor;
+}
+
+inline int QLineControl::preeditCursor() const
+{
+ return m_preeditCursor;
+}
+
+inline int QLineControl::cursorWidth() const
+{
+ return m_cursorWidth;
+}
+
+inline void QLineControl::setCursorWidth(int value)
+{
+ m_cursorWidth = value;
+}
+
+inline void QLineControl::cursorForward(bool mark, int steps)
+{
+ int c = m_cursor;
+ if (steps > 0) {
+ while (steps--)
+ c = m_textLayout.nextCursorPosition(c);
+ } else if (steps < 0) {
+ while (steps++)
+ c = m_textLayout.previousCursorPosition(c);
+ }
+ moveCursor(c, mark);
+}
+
+inline void QLineControl::cursorWordForward(bool mark)
+{
+ moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark);
+}
+
+inline void QLineControl::home(bool mark)
+{
+ moveCursor(0, mark);
+}
+
+inline void QLineControl::end(bool mark)
+{
+ moveCursor(text().length(), mark);
+}
+
+inline void QLineControl::cursorWordBackward(bool mark)
+{
+ moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark);
+}
+
+inline qreal QLineControl::cursorToX(int cursor) const
+{
+ return m_textLayout.lineAt(0).cursorToX(cursor);
+}
+
+inline qreal QLineControl::cursorToX() const
+{
+ return cursorToX(m_cursor);
+}
+
+inline bool QLineControl::isReadOnly() const
+{
+ return m_readOnly;
+}
+
+inline void QLineControl::setReadOnly(bool enable)
+{
+ m_readOnly = enable;
+}
+
+inline QString QLineControl::text() const
+{
+ QString res = m_maskData ? stripString(m_text) : m_text;
+ return (res.isNull() ? QString::fromLatin1("") : res);
+}
+
+inline void QLineControl::setText(const QString &txt)
+{
+ internalSetText(txt, -1, false);
+}
+
+inline QString QLineControl::displayText() const
+{
+ return m_textLayout.text();
+}
+
+inline void QLineControl::deselect()
+{
+ internalDeselect();
+ finishChange();
+}
+
+inline void QLineControl::selectAll()
+{
+ m_selstart = m_selend = m_cursor = 0;
+ moveCursor(m_text.length(), true);
+}
+
+inline void QLineControl::undo()
+{
+ internalUndo();
+ finishChange(-1, true);
+}
+
+inline void QLineControl::redo()
+{
+ internalRedo();
+ finishChange();
+}
+
+inline uint QLineControl::echoMode() const
+{
+ return m_echoMode;
+}
+
+inline void QLineControl::setEchoMode(uint mode)
+{
+ m_echoMode = mode;
+ m_passwordEchoEditing = false;
+ updateDisplayText();
+}
+
+inline void QLineControl::setMaxLength(int maxLength)
+{
+ if (m_maskData)
+ return;
+ m_maxLength = maxLength;
+ setText(m_text);
+}
+
+inline int QLineControl::maxLength() const
+{
+ return m_maxLength;
+}
+
+inline const QValidator *QLineControl::validator() const
+{
+ return m_validator;
+}
+
+inline void QLineControl::setValidator(const QValidator *v)
+{
+ m_validator = const_cast<QValidator*>(v);
+}
+
+#ifndef QT_NO_COMPLETER
+inline QCompleter *QLineControl::completer() const
+{
+ return m_completer;
+}
+
+/* Note that you must set the widget for the completer seperately */
+inline void QLineControl::setCompleter(const QCompleter* c)
+{
+ m_completer = const_cast<QCompleter*>(c);
+}
+#endif
+
+inline void QLineControl::setCursorPosition(int pos)
+{
+ if (pos < 0)
+ pos = 0;
+ if (pos <= m_text.length())
+ moveCursor(pos);
+}
+
+inline int QLineControl::cursorPosition() const
+{
+ return m_cursor;
+}
+
+inline bool QLineControl::hasAcceptableInput() const
+{
+ return hasAcceptableInput(m_text);
+}
+
+inline QString QLineControl::inputMask() const
+{
+ return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString();
+}
+
+inline void QLineControl::setInputMask(const QString &mask)
+{
+ parseInputMask(mask);
+ if (m_maskData)
+ moveCursor(nextMaskBlank(0));
+}
+
+// input methods
+#ifndef QT_NO_IM
+inline bool QLineControl::composeMode() const
+{
+ return !m_textLayout.preeditAreaText().isEmpty();
+}
+
+inline void QLineControl::setPreeditArea(int cursor, const QString &text)
+{
+ m_textLayout.setPreeditArea(cursor, text);
+}
+#endif
+
+inline QString QLineControl::preeditAreaText() const
+{
+ return m_textLayout.preeditAreaText();
+}
+
+inline bool QLineControl::passwordEchoEditing() const
+{
+ return m_passwordEchoEditing;
+}
+
+inline QChar QLineControl::passwordCharacter() const
+{
+ return m_passwordCharacter;
+}
+
+inline void QLineControl::setPasswordCharacter(const QChar &character)
+{
+ m_passwordCharacter = character;
+ updateDisplayText();
+}
+
+inline Qt::LayoutDirection QLineControl::layoutDirection() const
+{
+ return m_layoutDirection;
+}
+
+inline void QLineControl::setLayoutDirection(Qt::LayoutDirection direction)
+{
+ if (direction != m_layoutDirection) {
+ m_layoutDirection = direction;
+ updateDisplayText();
+ }
+}
+
+inline void QLineControl::setFont(const QFont &font)
+{
+ m_textLayout.setFont(font);
+ updateDisplayText();
+}
+
+inline int QLineControl::cursorBlinkPeriod() const
+{
+ return m_blinkPeriod;
+}
+
+inline QString QLineControl::cancelText() const
+{
+ return m_cancelText;
+}
+
+inline void QLineControl::setCancelText(const QString &text)
+{
+ m_cancelText = text;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_LINEEDIT
+
+#endif // QLINECONTROL_P_H
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index 8959562..3065c7f 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -79,28 +79,19 @@
#include "private/qapplication_p.h"
#include "private/qshortcutmap_p.h"
#include "qkeysequence.h"
-#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1String("\t") + QString(QKeySequence(k)) : QString())
+#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1Char('\t') + QString(QKeySequence(k)) : QString())
#else
#define ACCEL_KEY(k) QString()
#endif
#include <limits.h>
-#define verticalMargin 1
-#define horizontalMargin 2
-
QT_BEGIN_NAMESPACE
#ifdef Q_WS_MAC
extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp
#endif
-static inline bool shouldEnableInputMethod(QLineEdit *lineedit)
-{
- const QLineEdit::EchoMode mode = lineedit->echoMode();
- return !lineedit->isReadOnly() && (mode == QLineEdit::Normal || mode == QLineEdit::PasswordEchoOnEdit);
-}
-
/*!
Initialize \a option with the values from this QLineEdit. This method
is useful for subclasses when they need a QStyleOptionFrame or QStyleOptionFrameV2, but don't want
@@ -122,7 +113,7 @@ void QLineEdit::initStyleOption(QStyleOptionFrame *option) const
: 0;
option->midLineWidth = 0;
option->state |= QStyle::State_Sunken;
- if (d->readOnly)
+ if (d->control->isReadOnly())
option->state |= QStyle::State_ReadOnly;
#ifdef QT_KEYPAD_NAVIGATION
if (hasEditFocus())
@@ -137,7 +128,7 @@ void QLineEdit::initStyleOption(QStyleOptionFrame *option) const
\brief The QLineEdit widget is a one-line text editor.
\ingroup basicwidgets
- \mainclass
+
A line edit allows the user to enter and edit a single line of
plain text with a useful collection of editing functions,
@@ -350,14 +341,9 @@ QLineEdit::QLineEdit(const QString& contents, const QString &inputMask, QWidget*
{
Q_D(QLineEdit);
setObjectName(QString::fromAscii(name));
- d->parseInputMask(inputMask);
- if (d->maskData) {
- QString ms = d->maskString(0, contents);
- d->init(ms + d->clearString(ms.length(), d->maxLength - ms.length()));
- d->cursor = d->nextMaskBlank(ms.length());
- } else {
- d->init(contents);
- }
+ d->init(contents);
+ d->control->setInputMask(inputMask);
+ d->control->moveCursor(d->control->nextMaskBlank(contents.length()));
}
#endif
@@ -388,19 +374,13 @@ QLineEdit::~QLineEdit()
QString QLineEdit::text() const
{
Q_D(const QLineEdit);
- QString res = d->text;
- if (d->maskData)
- res = d->stripString(d->text);
- return (res.isNull() ? QString::fromLatin1("") : res);
+ return d->control->text();
}
void QLineEdit::setText(const QString& text)
{
Q_D(QLineEdit);
- d->setText(text, -1, false);
-#ifdef QT_KEYPAD_NAVIGATION
- d->origText = d->text;
-#endif
+ d->control->setText(text);
}
@@ -421,17 +401,7 @@ void QLineEdit::setText(const QString& text)
QString QLineEdit::displayText() const
{
Q_D(const QLineEdit);
- if (d->echoMode == NoEcho)
- return QString::fromLatin1("");
- QString res = d->text;
-
- if (d->echoMode == Password || (d->echoMode == PasswordEchoOnEdit
- && !d->passwordEchoEditing)) {
- QStyleOptionFrameV2 opt;
- initStyleOption(&opt);
- res.fill(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
- }
- return (res.isNull() ? QString::fromLatin1("") : res);
+ return d->control->displayText();
}
@@ -456,20 +426,15 @@ QString QLineEdit::displayText() const
int QLineEdit::maxLength() const
{
Q_D(const QLineEdit);
- return d->maxLength;
+ return d->control->maxLength();
}
void QLineEdit::setMaxLength(int maxLength)
{
Q_D(QLineEdit);
- if (d->maskData)
- return;
- d->maxLength = maxLength;
- setText(d->text);
+ d->control->setMaxLength(maxLength);
}
-
-
/*!
\property QLineEdit::frame
\brief whether the line edit draws itself with a frame
@@ -536,22 +501,26 @@ void QLineEdit::setFrame(bool enable)
QLineEdit::EchoMode QLineEdit::echoMode() const
{
Q_D(const QLineEdit);
- return (EchoMode) d->echoMode;
+ return (EchoMode) d->control->echoMode();
}
void QLineEdit::setEchoMode(EchoMode mode)
{
Q_D(QLineEdit);
- if (mode == (EchoMode)d->echoMode)
+ if (mode == (EchoMode)d->control->echoMode())
return;
- setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
- d->echoMode = mode;
- d->passwordEchoEditing = false;
- d->updateTextLayout();
+ Qt::InputMethodHints imHints = inputMethodHints();
+ if (mode == Password) {
+ imHints |= Qt::ImhHiddenText;
+ } else {
+ imHints &= ~Qt::ImhHiddenText;
+ }
+ setInputMethodHints(imHints);
+ d->control->setEchoMode(mode);
update();
#ifdef Q_WS_MAC
if (hasFocus())
- qt_mac_secure_keyboard(d->echoMode == Password || d->echoMode == NoEcho);
+ qt_mac_secure_keyboard(mode == Password || mode == NoEcho);
#endif
}
@@ -567,7 +536,7 @@ void QLineEdit::setEchoMode(EchoMode mode)
const QValidator * QLineEdit::validator() const
{
Q_D(const QLineEdit);
- return d->validator;
+ return d->control->validator();
}
/*!
@@ -585,7 +554,7 @@ const QValidator * QLineEdit::validator() const
void QLineEdit::setValidator(const QValidator *v)
{
Q_D(QLineEdit);
- d->validator = const_cast<QValidator*>(v);
+ d->control->setValidator(v);
}
#endif // QT_NO_VALIDATOR
@@ -609,23 +578,23 @@ void QLineEdit::setValidator(const QValidator *v)
void QLineEdit::setCompleter(QCompleter *c)
{
Q_D(QLineEdit);
- if (c == d->completer)
+ if (c == d->control->completer())
return;
- if (d->completer) {
- disconnect(d->completer, 0, this, 0);
- d->completer->setWidget(0);
- if (d->completer->parent() == this)
- delete d->completer;
+ if (d->control->completer()) {
+ disconnect(d->control->completer(), 0, this, 0);
+ d->control->completer()->setWidget(0);
+ if (d->control->completer()->parent() == this)
+ delete d->control->completer();
}
- d->completer = c;
+ d->control->setCompleter(c);
if (!c)
return;
if (c->widget() == 0)
c->setWidget(this);
if (hasFocus()) {
- QObject::connect(d->completer, SIGNAL(activated(QString)),
+ QObject::connect(d->control->completer(), SIGNAL(activated(QString)),
this, SLOT(setText(QString)));
- QObject::connect(d->completer, SIGNAL(highlighted(QString)),
+ QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)),
this, SLOT(_q_completionHighlighted(QString)));
}
}
@@ -638,83 +607,9 @@ void QLineEdit::setCompleter(QCompleter *c)
QCompleter *QLineEdit::completer() const
{
Q_D(const QLineEdit);
- return d->completer;
+ return d->control->completer();
}
-// looks for an enabled item iterating forward(dir=1)/backward(dir=-1) from the
-// current row based. dir=0 indicates a new completion prefix was set.
-bool QLineEditPrivate::advanceToEnabledItem(int dir)
-{
- int start = completer->currentRow();
- if (start == -1)
- return false;
- int i = start + dir;
- if (dir == 0) dir = 1;
- do {
- if (!completer->setCurrentRow(i)) {
- if (!completer->wrapAround())
- break;
- i = i > 0 ? 0 : completer->completionCount() - 1;
- } else {
- QModelIndex currentIndex = completer->currentIndex();
- if (completer->completionModel()->flags(currentIndex) & Qt::ItemIsEnabled)
- return true;
- i += dir;
- }
- } while (i != start);
-
- completer->setCurrentRow(start); // restore
- return false;
-}
-
-void QLineEditPrivate::complete(int key)
-{
- if (!completer || readOnly || echoMode != QLineEdit::Normal)
- return;
-
- if (completer->completionMode() == QCompleter::InlineCompletion) {
- if (key == Qt::Key_Backspace)
- return;
- int n = 0;
- if (key == Qt::Key_Up || key == Qt::Key_Down) {
- if (selend != 0 && selend != text.length())
- return;
- QString prefix = hasSelectedText() ? text.left(selstart) : text;
- if (text.compare(completer->currentCompletion(), completer->caseSensitivity()) != 0
- || prefix.compare(completer->completionPrefix(), completer->caseSensitivity()) != 0) {
- completer->setCompletionPrefix(prefix);
- } else {
- n = (key == Qt::Key_Up) ? -1 : +1;
- }
- } else {
- completer->setCompletionPrefix(text);
- }
- if (!advanceToEnabledItem(n))
- return;
- } else {
-#ifndef QT_KEYPAD_NAVIGATION
- if (text.isEmpty()) {
- completer->popup()->hide();
- return;
- }
-#endif
- completer->setCompletionPrefix(text);
- }
-
- completer->complete();
-}
-
-void QLineEditPrivate::_q_completionHighlighted(QString newText)
-{
- Q_Q(QLineEdit);
- if (completer->completionMode() != QCompleter::InlineCompletion)
- q->setText(newText);
- else {
- int c = cursor;
- q->setText(text.left(c) + newText.mid(c));
- q->setSelection(text.length(), c - newText.length());
- }
-}
#endif // QT_NO_COMPLETER
/*!
@@ -729,10 +624,10 @@ QSize QLineEdit::sizeHint() const
Q_D(const QLineEdit);
ensurePolished();
QFontMetrics fm(font());
- int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin
+ int h = qMax(fm.lineSpacing(), 14) + 2*d->verticalMargin
+ d->topTextMargin + d->bottomTextMargin
+ d->topmargin + d->bottommargin;
- int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin
+ int w = fm.width(QLatin1Char('x')) * 17 + 2*d->horizontalMargin
+ d->leftTextMargin + d->rightTextMargin
+ d->leftmargin + d->rightmargin; // "some"
QStyleOptionFrameV2 opt;
@@ -753,7 +648,7 @@ QSize QLineEdit::minimumSizeHint() const
Q_D(const QLineEdit);
ensurePolished();
QFontMetrics fm = fontMetrics();
- int h = fm.height() + qMax(2*verticalMargin, fm.leading())
+ int h = fm.height() + qMax(2*d->verticalMargin, fm.leading())
+ d->topmargin + d->bottommargin;
int w = fm.maxWidth() + d->leftmargin + d->rightmargin;
QStyleOptionFrameV2 opt;
@@ -775,17 +670,13 @@ QSize QLineEdit::minimumSizeHint() const
int QLineEdit::cursorPosition() const
{
Q_D(const QLineEdit);
- return d->cursor;
+ return d->control->cursorPosition();
}
void QLineEdit::setCursorPosition(int pos)
{
Q_D(QLineEdit);
- if (pos < 0)
- pos = 0;
-
- if (pos <= d->text.length())
- d->moveCursor(pos);
+ d->control->setCursorPosition(pos);
}
/*!
@@ -807,22 +698,17 @@ int QLineEdit::cursorPositionAt(const QPoint &pos)
bool QLineEdit::validateAndSet(const QString &newText, int newPos,
int newMarkAnchor, int newMarkDrag)
{
- Q_D(QLineEdit);
- int priorState = d->undoState;
- d->selstart = 0;
- d->selend = d->text.length();
- d->removeSelectedText();
- d->insert(newText);
- d->finishChange(priorState);
- if (d->undoState > priorState) {
- d->cursor = newPos;
- d->selstart = qMin(newMarkAnchor, newMarkDrag);
- d->selend = qMax(newMarkAnchor, newMarkDrag);
- update();
- d->emitCursorPositionChanged();
- return true;
+ // The suggested functions above in the docs don't seem to validate,
+ // below code tries to mimic previous behaviour.
+ QString oldText = text();
+ setText(newText);
+ if(!hasAcceptableInput()){
+ setText(oldText);
+ return false;
}
- return false;
+ setCursorPosition(newPos);
+ setSelection(qMin(newMarkAnchor, newMarkDrag), qAbs(newMarkAnchor - newMarkDrag));
+ return true;
}
#endif //QT3_SUPPORT
@@ -863,15 +749,7 @@ void QLineEdit::setAlignment(Qt::Alignment alignment)
void QLineEdit::cursorForward(bool mark, int steps)
{
Q_D(QLineEdit);
- int cursor = d->cursor;
- if (steps > 0) {
- while(steps--)
- cursor = d->textLayout.nextCursorPosition(cursor);
- } else if (steps < 0) {
- while (steps++)
- cursor = d->textLayout.previousCursorPosition(cursor);
- }
- d->moveCursor(cursor, mark);
+ d->control->cursorForward(mark, steps);
}
@@ -896,7 +774,7 @@ void QLineEdit::cursorBackward(bool mark, int steps)
void QLineEdit::cursorWordForward(bool mark)
{
Q_D(QLineEdit);
- d->moveCursor(d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
+ d->control->cursorWordForward(mark);
}
/*!
@@ -909,7 +787,7 @@ void QLineEdit::cursorWordForward(bool mark)
void QLineEdit::cursorWordBackward(bool mark)
{
Q_D(QLineEdit);
- d->moveCursor(d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords), mark);
+ d->control->cursorWordBackward(mark);
}
@@ -924,26 +802,7 @@ void QLineEdit::cursorWordBackward(bool mark)
void QLineEdit::backspace()
{
Q_D(QLineEdit);
- int priorState = d->undoState;
- if (d->hasSelectedText()) {
- d->removeSelectedText();
- } else if (d->cursor) {
- --d->cursor;
- if (d->maskData)
- d->cursor = d->prevMaskBlank(d->cursor);
- QChar uc = d->text.at(d->cursor);
- if (d->cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
- // second half of a surrogate, check if we have the first half as well,
- // if yes delete both at once
- uc = d->text.at(d->cursor - 1);
- if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
- d->del(true);
- --d->cursor;
- }
- }
- d->del(true);
- }
- d->finishChange(priorState);
+ d->control->backspace();
}
/*!
@@ -957,15 +816,7 @@ void QLineEdit::backspace()
void QLineEdit::del()
{
Q_D(QLineEdit);
- int priorState = d->undoState;
- if (d->hasSelectedText()) {
- d->removeSelectedText();
- } else {
- int n = d->textLayout.nextCursorPosition(d->cursor) - d->cursor;
- while (n--)
- d->del();
- }
- d->finishChange(priorState);
+ d->control->del();
}
/*!
@@ -980,7 +831,7 @@ void QLineEdit::del()
void QLineEdit::home(bool mark)
{
Q_D(QLineEdit);
- d->moveCursor(0, mark);
+ d->control->home(mark);
}
/*!
@@ -995,7 +846,7 @@ void QLineEdit::home(bool mark)
void QLineEdit::end(bool mark)
{
Q_D(QLineEdit);
- d->moveCursor(d->text.length(), mark);
+ d->control->end(mark);
}
@@ -1020,16 +871,13 @@ void QLineEdit::end(bool mark)
bool QLineEdit::isModified() const
{
Q_D(const QLineEdit);
- return d->modifiedState != d->undoState;
+ return d->control->isModified();
}
void QLineEdit::setModified(bool modified)
{
Q_D(QLineEdit);
- if (modified)
- d->modifiedState = -1;
- else
- d->modifiedState = d->undoState;
+ d->control->setModified(modified);
}
@@ -1057,7 +905,7 @@ Use setModified(false) instead.
bool QLineEdit::hasSelectedText() const
{
Q_D(const QLineEdit);
- return d->hasSelectedText();
+ return d->control->hasSelectedText();
}
/*!
@@ -1075,9 +923,7 @@ bool QLineEdit::hasSelectedText() const
QString QLineEdit::selectedText() const
{
Q_D(const QLineEdit);
- if (d->hasSelectedText())
- return d->text.mid(d->selstart, d->selend - d->selstart);
- return QString();
+ return d->control->selectedText();
}
/*!
@@ -1090,7 +936,7 @@ QString QLineEdit::selectedText() const
int QLineEdit::selectionStart() const
{
Q_D(const QLineEdit);
- return d->hasSelectedText() ? d->selstart : -1;
+ return d->control->selectionStart();
}
@@ -1120,9 +966,10 @@ void QLineEdit::setEdited(bool on) { setModified(on); }
int QLineEdit::characterAt(int xpos, QChar *chr) const
{
Q_D(const QLineEdit);
- int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + horizontalMargin);
- if (chr && pos < (int) d->text.length())
- *chr = d->text.at(pos);
+ int pos = d->xToPos(xpos + contentsRect().x() - d->hscroll + d->horizontalMargin);
+ QString txt = d->control->text();
+ if (chr && pos < (int) txt.length())
+ *chr = txt.at(pos);
return pos;
}
@@ -1133,9 +980,9 @@ int QLineEdit::characterAt(int xpos, QChar *chr) const
bool QLineEdit::getSelection(int *start, int *end)
{
Q_D(QLineEdit);
- if (d->hasSelectedText() && start && end) {
- *start = d->selstart;
- *end = d->selend;
+ if (d->control->hasSelectedText() && start && end) {
+ *start = selectionStart();
+ *end = *start + selectedText().length();
return true;
}
return false;
@@ -1153,30 +1000,19 @@ bool QLineEdit::getSelection(int *start, int *end)
void QLineEdit::setSelection(int start, int length)
{
Q_D(QLineEdit);
- if (start < 0 || start > (int)d->text.length()) {
+ if (start < 0 || start > (int)d->control->text().length()) {
qWarning("QLineEdit::setSelection: Invalid start position (%d)", start);
return;
- } else {
- if (length > 0) {
- d->selstart = start;
- d->selend = qMin(start + length, (int)d->text.length());
- d->cursor = d->selend;
- } else {
- d->selstart = qMax(start + length, 0);
- d->selend = start;
- d->cursor = d->selstart;
- }
}
- if (d->hasSelectedText()){
+ d->control->setSelection(start, length);
+
+ if (d->control->hasSelectedText()){
QStyleOptionFrameV2 opt;
initStyleOption(&opt);
if (!style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
d->setCursorVisible(false);
}
-
- update();
- d->emitCursorPositionChanged();
}
@@ -1192,7 +1028,7 @@ void QLineEdit::setSelection(int start, int length)
bool QLineEdit::isUndoAvailable() const
{
Q_D(const QLineEdit);
- return d->isUndoAvailable();
+ return d->control->isUndoAvailable();
}
/*!
@@ -1208,7 +1044,7 @@ bool QLineEdit::isUndoAvailable() const
bool QLineEdit::isRedoAvailable() const
{
Q_D(const QLineEdit);
- return d->isRedoAvailable();
+ return d->control->isRedoAvailable();
}
/*!
@@ -1244,7 +1080,7 @@ void QLineEdit::setDragEnabled(bool b)
bool QLineEdit::hasAcceptableInput() const
{
Q_D(const QLineEdit);
- return d->hasAcceptableInput(d->text);
+ return d->control->hasAcceptableInput();
}
/*!
@@ -1350,15 +1186,13 @@ void QLineEdit::getTextMargins(int *left, int *top, int *right, int *bottom) con
QString QLineEdit::inputMask() const
{
Q_D(const QLineEdit);
- return (d->maskData ? d->inputMask + QLatin1Char(';') + d->blank : QString());
+ return d->control->inputMask();
}
void QLineEdit::setInputMask(const QString &inputMask)
{
Q_D(QLineEdit);
- d->parseInputMask(inputMask);
- if (d->maskData)
- d->moveCursor(d->nextMaskBlank(0));
+ d->control->setInputMask(inputMask);
}
/*!
@@ -1373,8 +1207,7 @@ void QLineEdit::setInputMask(const QString &inputMask)
void QLineEdit::selectAll()
{
Q_D(QLineEdit);
- d->selstart = d->selend = d->cursor = 0;
- d->moveCursor(d->text.length(), true);
+ d->control->selectAll();
}
/*!
@@ -1386,8 +1219,7 @@ void QLineEdit::selectAll()
void QLineEdit::deselect()
{
Q_D(QLineEdit);
- d->deselect();
- d->finishChange();
+ d->control->deselect();
}
@@ -1402,10 +1234,7 @@ void QLineEdit::insert(const QString &newText)
{
// q->resetInputContext(); //#### FIX ME IN QT
Q_D(QLineEdit);
- int priorState = d->undoState;
- d->removeSelectedText();
- d->insert(newText);
- d->finishChange(priorState);
+ d->control->insert(newText);
}
/*!
@@ -1416,13 +1245,8 @@ void QLineEdit::insert(const QString &newText)
void QLineEdit::clear()
{
Q_D(QLineEdit);
- int priorState = d->undoState;
resetInputContext();
- d->selstart = 0;
- d->selend = d->text.length();
- d->removeSelectedText();
- d->separate();
- d->finishChange(priorState, /*update*/false, /*edited*/false);
+ d->control->clear();
}
/*!
@@ -1435,8 +1259,7 @@ void QLineEdit::undo()
{
Q_D(QLineEdit);
resetInputContext();
- d->undo();
- d->finishChange(-1, true);
+ d->control->undo();
}
/*!
@@ -1447,8 +1270,7 @@ void QLineEdit::redo()
{
Q_D(QLineEdit);
resetInputContext();
- d->redo();
- d->finishChange();
+ d->control->redo();
}
@@ -1470,16 +1292,16 @@ void QLineEdit::redo()
bool QLineEdit::isReadOnly() const
{
Q_D(const QLineEdit);
- return d->readOnly;
+ return d->control->isReadOnly();
}
void QLineEdit::setReadOnly(bool enable)
{
Q_D(QLineEdit);
- if (d->readOnly != enable) {
- d->readOnly = enable;
- setAttribute(Qt::WA_MacShowFocusRect, !d->readOnly);
- setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
+ if (d->control->isReadOnly() != enable) {
+ d->control->setReadOnly(enable);
+ setAttribute(Qt::WA_MacShowFocusRect, !enable);
+ setAttribute(Qt::WA_InputMethodEnabled, d->shouldEnableInputMethod());
#ifndef QT_NO_CURSOR
setCursor(enable ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
@@ -1518,7 +1340,7 @@ void QLineEdit::cut()
void QLineEdit::copy() const
{
Q_D(const QLineEdit);
- d->copy();
+ d->control->copy();
}
/*!
@@ -1535,26 +1357,7 @@ void QLineEdit::copy() const
void QLineEdit::paste()
{
Q_D(QLineEdit);
- if (echoMode() == PasswordEchoOnEdit && !d->passwordEchoEditing) {
- // Clear the edit and reset to normal echo mode when pasting; the echo
- // mode switches back when the edit loses focus. ### changes a public
- // property, resets current content
- d->updatePasswordEchoEditing(true);
- clear();
- }
- insert(QApplication::clipboard()->text(QClipboard::Clipboard));
-}
-
-void QLineEditPrivate::copy(bool clipboard) const
-{
- Q_Q(const QLineEdit);
- QString t = q->selectedText();
- if (!t.isEmpty() && echoMode == QLineEdit::Normal) {
- q->disconnect(QApplication::clipboard(), SIGNAL(selectionChanged()), q, 0);
- QApplication::clipboard()->setText(t, clipboard ? QClipboard::Clipboard : QClipboard::Selection);
- q->connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
- q, SLOT(_q_clipboardChanged()));
- }
+ d->control->paste();
}
#endif // !QT_NO_CLIPBOARD
@@ -1564,57 +1367,10 @@ void QLineEditPrivate::copy(bool clipboard) const
bool QLineEdit::event(QEvent * e)
{
Q_D(QLineEdit);
-#ifndef QT_NO_SHORTCUT
- if (e->type() == QEvent::ShortcutOverride && !d->readOnly) {
- QKeyEvent* ke = (QKeyEvent*) e;
- if (ke == QKeySequence::Copy
- || ke == QKeySequence::Paste
- || ke == QKeySequence::Cut
- || ke == QKeySequence::Redo
- || ke == QKeySequence::Undo
- || ke == QKeySequence::MoveToNextWord
- || ke == QKeySequence::MoveToPreviousWord
- || ke == QKeySequence::MoveToStartOfDocument
- || ke == QKeySequence::MoveToEndOfDocument
- || ke == QKeySequence::SelectNextWord
- || ke == QKeySequence::SelectPreviousWord
- || ke == QKeySequence::SelectStartOfLine
- || ke == QKeySequence::SelectEndOfLine
- || ke == QKeySequence::SelectStartOfBlock
- || ke == QKeySequence::SelectEndOfBlock
- || ke == QKeySequence::SelectStartOfDocument
- || ke == QKeySequence::SelectAll
- || ke == QKeySequence::SelectEndOfDocument) {
- ke->accept();
- } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
- || ke->modifiers() == Qt::KeypadModifier) {
- if (ke->key() < Qt::Key_Escape) {
- ke->accept();
- } else {
- switch (ke->key()) {
- case Qt::Key_Delete:
- case Qt::Key_Home:
- case Qt::Key_End:
- case Qt::Key_Backspace:
- case Qt::Key_Left:
- case Qt::Key_Right:
- ke->accept();
- default:
- break;
- }
- }
- }
- } else
-#endif
- if (e->type() == QEvent::Timer) {
+ if (e->type() == QEvent::Timer) {
// should be timerEvent, is here for binary compatibility
int timerId = ((QTimerEvent*)e)->timerId();
- if (timerId == d->cursorTimer) {
- QStyleOptionFrameV2 opt;
- initStyleOption(&opt);
- if(!hasSelectedText()
- || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
- d->setCursorVisible(!d->cursorVisible);
+ if (false) {
#ifndef QT_NO_DRAGANDDROP
} else if (timerId == d->dndTimer.timerId()) {
d->drag();
@@ -1622,59 +1378,29 @@ bool QLineEdit::event(QEvent * e)
}
else if (timerId == d->tripleClickTimer.timerId())
d->tripleClickTimer.stop();
-#ifdef QT_KEYPAD_NAVIGATION
- else if (timerId == d->deleteAllTimer.timerId()) {
- d->deleteAllTimer.stop();
- clear();
- }
-#endif
} else if (e->type() == QEvent::ContextMenu) {
#ifndef QT_NO_IM
- if (d->composeMode())
+ if (d->control->composeMode())
return true;
#endif
- d->separate();
+ //d->separate();
} else if (e->type() == QEvent::WindowActivate) {
QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate()));
+ }else if(e->type() == QEvent::ShortcutOverride){
+ d->control->processEvent(e);
}
+
#ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled()) {
- if ((e->type() == QEvent::KeyPress) || (e->type() == QEvent::KeyRelease)) {
- QKeyEvent *ke = (QKeyEvent *)e;
- if (ke->key() == Qt::Key_Back) {
- if (ke->isAutoRepeat()) {
- // Swallow it. We don't want back keys running amok.
- ke->accept();
- return true;
- }
- if ((e->type() == QEvent::KeyRelease)
- && !isReadOnly()
- && d->deleteAllTimer.isActive()) {
- d->deleteAllTimer.stop();
- backspace();
- ke->accept();
- return true;
- }
- }
- } else if (e->type() == QEvent::EnterEditFocus) {
+ if (e->type() == QEvent::EnterEditFocus) {
end(false);
- if (!d->cursorTimer) {
- int cft = QApplication::cursorFlashTime();
- d->cursorTimer = cft ? startTimer(cft/2) : -1;
- }
+ d->setCursorVisible(true);
+ d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime());
} else if (e->type() == QEvent::LeaveEditFocus) {
d->setCursorVisible(false);
- if (d->cursorTimer > 0)
- killTimer(d->cursorTimer);
- d->cursorTimer = 0;
-
- if (!d->emitingEditingFinished) {
- if (hasAcceptableInput() || d->fixup()) {
- d->emitingEditingFinished = true;
- emit editingFinished();
- d->emitingEditingFinished = false;
- }
- }
+ d->control->setCursorBlinkPeriod(0);
+ if (d->control->hasAcceptableInput() || d->control->fixup())
+ emit editingFinished();
}
}
#endif
@@ -1687,15 +1413,15 @@ void QLineEdit::mousePressEvent(QMouseEvent* e)
{
Q_D(QLineEdit);
if (d->sendMouseEventToInputContext(e))
- return;
+ return;
if (e->button() == Qt::RightButton)
return;
#ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
setEditFocus(true);
// Get the completion list to pop up.
- if (d->completer)
- d->completer->complete();
+ if (d->control->completer())
+ d->control->completer()->complete();
}
#endif
if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() <
@@ -1706,18 +1432,16 @@ void QLineEdit::mousePressEvent(QMouseEvent* e)
bool mark = e->modifiers() & Qt::ShiftModifier;
int cursor = d->xToPos(e->pos().x());
#ifndef QT_NO_DRAGANDDROP
- if (!mark && d->dragEnabled && d->echoMode == Normal &&
- e->button() == Qt::LeftButton && d->inSelection(e->pos().x())) {
- d->cursor = cursor;
- update();
+ if (!mark && d->dragEnabled && d->control->echoMode() == Normal &&
+ e->button() == Qt::LeftButton && d->control->inSelection(e->pos().x())) {
+ d->control->moveCursor(cursor);
d->dndPos = e->pos();
if (!d->dndTimer.isActive())
d->dndTimer.start(QApplication::startDragTime(), this);
- d->emitCursorPositionChanged();
} else
#endif
{
- d->moveCursor(cursor, mark);
+ d->control->moveCursor(cursor, mark);
}
}
@@ -1727,7 +1451,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e)
{
Q_D(QLineEdit);
if (d->sendMouseEventToInputContext(e))
- return;
+ return;
if (e->buttons() & Qt::LeftButton) {
#ifndef QT_NO_DRAGANDDROP
@@ -1737,7 +1461,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e)
} else
#endif
{
- d->moveCursor(d->xToPos(e->pos().x()), true);
+ d->control->moveCursor(d->xToPos(e->pos().x()), true);
}
}
}
@@ -1748,7 +1472,7 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e)
{
Q_D(QLineEdit);
if (d->sendMouseEventToInputContext(e))
- return;
+ return;
#ifndef QT_NO_DRAGANDDROP
if (e->button() == Qt::LeftButton) {
if (d->dndTimer.isActive()) {
@@ -1761,13 +1485,16 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e)
#ifndef QT_NO_CLIPBOARD
if (QApplication::clipboard()->supportsSelection()) {
if (e->button() == Qt::LeftButton) {
- d->copy(false);
- } else if (!d->readOnly && e->button() == Qt::MidButton) {
- d->deselect();
+ d->control->copy(QClipboard::Selection);
+ } else if (!d->control->isReadOnly() && e->button() == Qt::MidButton) {
+ deselect();
insert(QApplication::clipboard()->text(QClipboard::Selection));
}
}
#endif
+
+ d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
+ d->clickCausedFocus = 0;
}
/*! \reimp
@@ -1776,16 +1503,9 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
{
Q_D(QLineEdit);
if (d->sendMouseEventToInputContext(e))
- return;
+ return;
if (e->button() == Qt::LeftButton) {
- deselect();
- d->cursor = d->xToPos(e->pos().x());
- d->cursor = d->textLayout.previousCursorPosition(d->cursor, QTextLayout::SkipWords);
- // ## text layout should support end of words.
- int end = d->textLayout.nextCursorPosition(d->cursor, QTextLayout::SkipWords);
- while (end > d->cursor && d->text[end-1].isSpace())
- --end;
- d->moveCursor(end, true);
+ d->control->selectWordAtPos(d->xToPos(e->pos().x()));
d->tripleClickTimer.start(QApplication::doubleClickInterval(), this);
d->tripleClick = e->pos();
}
@@ -1825,65 +1545,15 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
void QLineEdit::keyPressEvent(QKeyEvent *event)
{
Q_D(QLineEdit);
-
- bool inlineCompletionAccepted = false;
-
-#ifndef QT_NO_COMPLETER
- if (d->completer) {
- QCompleter::CompletionMode completionMode = d->completer->completionMode();
- if ((completionMode == QCompleter::PopupCompletion
- || completionMode == QCompleter::UnfilteredPopupCompletion)
- &&d->completer->popup()
- && d->completer->popup()->isVisible()) {
- // The following keys are forwarded by the completer to the widget
- // Ignoring the events lets the completer provide suitable default behavior
- switch (event->key()) {
- case Qt::Key_Escape:
- event->ignore();
- return;
- case Qt::Key_Enter:
- case Qt::Key_Return:
- case Qt::Key_F4:
-#ifdef QT_KEYPAD_NAVIGATION
- case Qt::Key_Select:
- if (!QApplication::keypadNavigationEnabled())
- break;
-#endif
- d->completer->popup()->hide(); // just hide. will end up propagating to parent
- default:
- break; // normal key processing
- }
- } else if (completionMode == QCompleter::InlineCompletion) {
- switch (event->key()) {
- case Qt::Key_Enter:
- case Qt::Key_Return:
- case Qt::Key_F4:
-#ifdef QT_KEYPAD_NAVIGATION
- case Qt::Key_Select:
- if (!QApplication::keypadNavigationEnabled())
- break;
-#endif
- if (!d->completer->currentCompletion().isEmpty() && d->selend > d->selstart
- && d->selend == d->text.length()) {
- setText(d->completer->currentCompletion());
- inlineCompletionAccepted = true;
- }
- default:
- break; // normal key processing
- }
- }
- }
-#endif // QT_NO_COMPLETER
-
-#ifdef QT_KEYPAD_NAVIGATION
+ #ifdef QT_KEYPAD_NAVIGATION
bool select = false;
switch (event->key()) {
case Qt::Key_Select:
if (QApplication::keypadNavigationEnabled()) {
if (hasEditFocus()) {
setEditFocus(false);
- if (d->completer && d->completer->popup()->isVisible())
- d->completer->popup()->hide();
+ if (d->control->completer() && d->control->completer()->popup()->isVisible())
+ d->control->completer()->popup()->hide();
select = true;
}
}
@@ -1919,273 +1589,7 @@ void QLineEdit::keyPressEvent(QKeyEvent *event)
return; // Just start. No action.
}
#endif
-
- if (echoMode() == PasswordEchoOnEdit
- && !d->passwordEchoEditing
- && !isReadOnly()
- && !event->text().isEmpty()
-#ifdef QT_KEYPAD_NAVIGATION
- && event->key() != Qt::Key_Select
- && event->key() != Qt::Key_Up
- && event->key() != Qt::Key_Down
- && event->key() != Qt::Key_Back
-#endif
- && !(event->modifiers() & Qt::ControlModifier)) {
- // Clear the edit and reset to normal echo mode while editing; the
- // echo mode switches back when the edit loses focus. ### changes a
- // public property, resets current content. dubious code; you can
- // navigate with keys up, down, back, and select(?), but if you press
- // "left" or "right" it clears?
- d->updatePasswordEchoEditing(true);
- clear();
- }
-
- d->setCursorVisible(true);
- if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
- if (hasAcceptableInput() || d->fixup()) {
- emit returnPressed();
- d->emitingEditingFinished = true;
- emit editingFinished();
- d->emitingEditingFinished = false;
- }
- if (inlineCompletionAccepted)
- event->accept();
- else
- event->ignore();
- return;
- }
- bool unknown = false;
-
- if (false) {
- }
-#ifndef QT_NO_SHORTCUT
- else if (event == QKeySequence::Undo) {
- if (!d->readOnly)
- undo();
- }
- else if (event == QKeySequence::Redo) {
- if (!d->readOnly)
- redo();
- }
- else if (event == QKeySequence::SelectAll) {
- selectAll();
- }
-#ifndef QT_NO_CLIPBOARD
- else if (event == QKeySequence::Copy) {
- copy();
- }
- else if (event == QKeySequence::Paste) {
- if (!d->readOnly)
- paste();
- }
- else if (event == QKeySequence::Cut) {
- if (!d->readOnly) {
- cut();
- }
- }
- else if (event == QKeySequence::DeleteEndOfLine) {
- if (!d->readOnly) {
- setSelection(d->cursor, d->text.size());
- copy();
- del();
- }
- }
-#endif //QT_NO_CLIPBOARD
- else if (event == QKeySequence::MoveToStartOfLine) {
- home(0);
- }
- else if (event == QKeySequence::MoveToEndOfLine) {
- end(0);
- }
- else if (event == QKeySequence::SelectStartOfLine) {
- home(1);
- }
- else if (event == QKeySequence::SelectEndOfLine) {
- end(1);
- }
- else if (event == QKeySequence::MoveToNextChar) {
-#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
- if (d->hasSelectedText()) {
-#else
- if (d->hasSelectedText() && d->completer
- && d->completer->completionMode() == QCompleter::InlineCompletion) {
-#endif
- d->moveCursor(d->selend, false);
- } else {
- cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
- }
- }
- else if (event == QKeySequence::SelectNextChar) {
- cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
- }
- else if (event == QKeySequence::MoveToPreviousChar) {
-#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
- if (d->hasSelectedText()) {
-#else
- if (d->hasSelectedText() && d->completer
- && d->completer->completionMode() == QCompleter::InlineCompletion) {
-#endif
- d->moveCursor(d->selstart, false);
- } else {
- cursorBackward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
- }
- }
- else if (event == QKeySequence::SelectPreviousChar) {
- cursorBackward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
- }
- else if (event == QKeySequence::MoveToNextWord) {
- if (echoMode() == Normal)
- layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
- else
- layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
- }
- else if (event == QKeySequence::MoveToPreviousWord) {
- if (echoMode() == Normal)
- layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0);
- else if (!d->readOnly) {
- layoutDirection() == Qt::LeftToRight ? home(0) : end(0);
- }
- }
- else if (event == QKeySequence::SelectNextWord) {
- if (echoMode() == Normal)
- layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
- else
- layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
- }
- else if (event == QKeySequence::SelectPreviousWord) {
- if (echoMode() == Normal)
- layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
- else
- layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
- }
- else if (event == QKeySequence::Delete) {
- if (!d->readOnly)
- del();
- }
- else if (event == QKeySequence::DeleteEndOfWord) {
- if (!d->readOnly) {
- cursorWordForward(true);
- del();
- }
- }
- else if (event == QKeySequence::DeleteStartOfWord) {
- if (!d->readOnly) {
- cursorWordBackward(true);
- del();
- }
- }
-#endif // QT_NO_SHORTCUT
- else {
-#ifdef Q_WS_MAC
- if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) {
- Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier);
- if (myModifiers & Qt::ShiftModifier) {
- if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier)
- || myModifiers == (Qt::AltModifier|Qt::ShiftModifier)
- || myModifiers == Qt::ShiftModifier) {
-
- event->key() == Qt::Key_Up ? home(1) : end(1);
- }
- } else {
- if ((myModifiers == Qt::ControlModifier
- || myModifiers == Qt::AltModifier
- || myModifiers == Qt::NoModifier)) {
- event->key() == Qt::Key_Up ? home(0) : end(0);
- }
- }
- }
-#endif
- if (event->modifiers() & Qt::ControlModifier) {
- switch (event->key()) {
- case Qt::Key_Backspace:
- if (!d->readOnly) {
- cursorWordBackward(true);
- del();
- }
- break;
-#ifndef QT_NO_COMPLETER
- case Qt::Key_Up:
- case Qt::Key_Down:
- d->complete(event->key());
- break;
-#endif
-#if defined(Q_WS_X11)
- case Qt::Key_E:
- end(0);
- break;
-
- case Qt::Key_U:
- if (!d->readOnly) {
- setSelection(0, d->text.size());
-#ifndef QT_NO_CLIPBOARD
- copy();
-#endif
- del();
- }
- break;
-#endif
- default:
- unknown = true;
- }
- } else { // ### check for *no* modifier
- switch (event->key()) {
- case Qt::Key_Backspace:
- if (!d->readOnly) {
- backspace();
-#ifndef QT_NO_COMPLETER
- d->complete(Qt::Key_Backspace);
-#endif
- }
- break;
-#ifdef QT_KEYPAD_NAVIGATION
- case Qt::Key_Back:
- if (QApplication::keypadNavigationEnabled() && !event->isAutoRepeat()
- && !isReadOnly()) {
- if (text().length() == 0) {
- setText(d->origText);
-
- if (d->passwordEchoEditing)
- d->updatePasswordEchoEditing(false);
-
- setEditFocus(false);
- } else if (!d->deleteAllTimer.isActive()) {
- d->deleteAllTimer.start(750, this);
- }
- } else {
- unknown = true;
- }
- break;
-#endif
-
- default:
- unknown = true;
- }
- }
- }
-
- if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
- setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
- d->updateTextLayout();
- update();
- unknown = false;
- }
-
- if (unknown && !d->readOnly) {
- QString t = event->text();
- if (!t.isEmpty() && t.at(0).isPrint()) {
- insert(t);
-#ifndef QT_NO_COMPLETER
- d->complete(event->key());
-#endif
- event->accept();
- return;
- }
- }
-
- if (unknown)
- event->ignore();
- else
- event->accept();
+ d->control->processKeyEvent(event);
}
/*!
@@ -2199,50 +1603,17 @@ QRect QLineEdit::cursorRect() const
return d->cursorRect();
}
-/*!
- This function is not intended as polymorphic usage. Just a shared code
- fragment that calls QInputContext::mouseHandler for this
- class.
-*/
-bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
-{
-#if !defined QT_NO_IM
- Q_Q(QLineEdit);
- if ( composeMode() ) {
- int tmp_cursor = xToPos(e->pos().x());
- int mousePos = tmp_cursor - cursor;
- if ( mousePos < 0 || mousePos > textLayout.preeditAreaText().length() ) {
- mousePos = -1;
- // don't send move events outside the preedit area
- if ( e->type() == QEvent::MouseMove )
- return true;
- }
-
- QInputContext *qic = q->inputContext();
- if ( qic )
- // may be causing reset() in some input methods
- qic->mouseHandler(mousePos, e);
- if (!textLayout.preeditAreaText().isEmpty())
- return true;
- }
-#else
- Q_UNUSED(e);
-#endif
-
- return false;
-}
-
/*! \reimp
*/
void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
{
Q_D(QLineEdit);
- if (d->readOnly) {
+ if (d->control->isReadOnly()) {
e->ignore();
return;
}
- if (echoMode() == PasswordEchoOnEdit && !d->passwordEchoEditing) {
+ if (echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing()) {
// Clear the edit and reset to normal echo mode while entering input
// method data; the echo mode switches back when the edit loses focus.
// ### changes a public property, resets current content.
@@ -2262,55 +1633,11 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
}
#endif
- int priorState = d->undoState;
- d->removeSelectedText();
-
- int c = d->cursor; // cursor position after insertion of commit string
- if (e->replacementStart() <= 0)
- c += e->commitString().length() + qMin(-e->replacementStart(), e->replacementLength());
-
- d->cursor += e->replacementStart();
+ d->control->processInputMethodEvent(e);
- // insert commit string
- if (e->replacementLength()) {
- d->selstart = d->cursor;
- d->selend = d->selstart + e->replacementLength();
- d->removeSelectedText();
- }
- if (!e->commitString().isEmpty())
- d->insert(e->commitString());
-
- d->cursor = qMin(c, d->text.length());
-
- d->textLayout.setPreeditArea(d->cursor, e->preeditString());
- d->preeditCursor = e->preeditString().length();
- d->hideCursor = false;
- QList<QTextLayout::FormatRange> formats;
- for (int i = 0; i < e->attributes().size(); ++i) {
- const QInputMethodEvent::Attribute &a = e->attributes().at(i);
- if (a.type == QInputMethodEvent::Cursor) {
- d->preeditCursor = a.start;
- d->hideCursor = !a.length;
- } else if (a.type == QInputMethodEvent::TextFormat) {
- QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
- if (f.isValid()) {
- QTextLayout::FormatRange o;
- o.start = a.start + d->cursor;
- o.length = a.length;
- o.format = f;
- formats.append(o);
- }
- }
- }
- d->textLayout.setAdditionalFormats(formats);
- d->updateTextLayout();
- update();
- if (!e->commitString().isEmpty())
- d->emitCursorPositionChanged();
- d->finishChange(priorState);
#ifndef QT_NO_COMPLETER
if (!e->commitString().isEmpty())
- d->complete(Qt::Key_unknown);
+ d->control->complete(Qt::Key_unknown);
#endif
}
@@ -2325,11 +1652,20 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
case Qt::ImFont:
return font();
case Qt::ImCursorPosition:
- return QVariant((d->selend - d->selstart == 0) ? d->cursor : d->selend);
+ return QVariant(d->control->cursor());
case Qt::ImSurroundingText:
- return QVariant(d->text);
+ return QVariant(text());
case Qt::ImCurrentSelection:
return QVariant(selectedText());
+ case Qt::ImMaximumTextLength:
+ return QVariant(maxLength());
+ case Qt::ImAnchorPosition:
+ if (d->control->selectionStart() == d->control->selectionEnd())
+ return QVariant(d->control->cursor());
+ else if (d->control->selectionStart() == d->control->cursor())
+ return QVariant(d->control->selectionEnd());
+ else
+ return QVariant(d->control->selectionStart());
default:
return QVariant();
}
@@ -2344,36 +1680,36 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
if (e->reason() == Qt::TabFocusReason ||
e->reason() == Qt::BacktabFocusReason ||
e->reason() == Qt::ShortcutFocusReason) {
- if (d->maskData)
- d->moveCursor(d->nextMaskBlank(0));
- else if (!d->hasSelectedText())
+ if (!d->control->inputMask().isEmpty())
+ d->control->moveCursor(d->control->nextMaskBlank(0));
+ else if (!d->control->hasSelectedText())
selectAll();
+ } else if (e->reason() == Qt::MouseFocusReason) {
+ d->clickCausedFocus = 1;
}
#ifdef QT_KEYPAD_NAVIGATION
- if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason))
+ if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason)){
#endif
- if (!d->cursorTimer) {
- int cft = QApplication::cursorFlashTime();
- d->cursorTimer = cft ? startTimer(cft/2) : -1;
- }
+ d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime());
QStyleOptionFrameV2 opt;
initStyleOption(&opt);
- if((!hasSelectedText() && d->textLayout.preeditAreaText().isEmpty())
+ if((!hasSelectedText() && d->control->preeditAreaText().isEmpty())
|| style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
d->setCursorVisible(true);
#ifdef Q_WS_MAC
- if (d->echoMode == Password || d->echoMode == NoEcho)
+ if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho)
qt_mac_secure_keyboard(true);
#endif
#ifdef QT_KEYPAD_NAVIGATION
- d->origText = d->text;
+ d->control->setCancelText(d->control->text());
+ }
#endif
#ifndef QT_NO_COMPLETER
- if (d->completer) {
- d->completer->setWidget(this);
- QObject::connect(d->completer, SIGNAL(activated(QString)),
+ if (d->control->completer()) {
+ d->control->completer()->setWidget(this);
+ QObject::connect(d->control->completer(), SIGNAL(activated(QString)),
this, SLOT(setText(QString)));
- QObject::connect(d->completer, SIGNAL(highlighted(QString)),
+ QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)),
this, SLOT(_q_completionHighlighted(QString)));
}
#endif
@@ -2386,7 +1722,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
void QLineEdit::focusOutEvent(QFocusEvent *e)
{
Q_D(QLineEdit);
- if (d->passwordEchoEditing) {
+ if (d->control->passwordEchoEditing()) {
// Reset the echomode back to PasswordEchoOnEdit when the widget loses
// focus.
d->updatePasswordEchoEditing(false);
@@ -2398,37 +1734,29 @@ void QLineEdit::focusOutEvent(QFocusEvent *e)
deselect();
d->setCursorVisible(false);
- if (d->cursorTimer > 0)
- killTimer(d->cursorTimer);
- d->cursorTimer = 0;
-
+ d->control->setCursorBlinkPeriod(0);
#ifdef QT_KEYPAD_NAVIGATION
// editingFinished() is already emitted on LeaveEditFocus
if (!QApplication::keypadNavigationEnabled())
#endif
if (reason != Qt::PopupFocusReason
|| !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) {
- if (!d->emitingEditingFinished) {
- if (hasAcceptableInput() || d->fixup()) {
- d->emitingEditingFinished = true;
+ if (hasAcceptableInput() || d->control->fixup())
emit editingFinished();
- d->emitingEditingFinished = false;
- }
- }
#ifdef QT3_SUPPORT
emit lostFocus();
#endif
}
#ifdef Q_WS_MAC
- if (d->echoMode == Password || d->echoMode == NoEcho)
+ if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho)
qt_mac_secure_keyboard(false);
#endif
#ifdef QT_KEYPAD_NAVIGATION
- d->origText = QString();
+ d->control->setCancelText(QString());
#endif
#ifndef QT_NO_COMPLETER
- if (d->completer) {
- QObject::disconnect(d->completer, 0, this, 0);
+ if (d->control->completer()) {
+ QObject::disconnect(d->control->completer(), 0, this, 0);
}
#endif
update();
@@ -2458,24 +1786,19 @@ void QLineEdit::paintEvent(QPaintEvent *)
Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment));
switch (va & Qt::AlignVertical_Mask) {
case Qt::AlignBottom:
- d->vscroll = r.y() + r.height() - fm.height() - verticalMargin;
+ d->vscroll = r.y() + r.height() - fm.height() - d->verticalMargin;
break;
case Qt::AlignTop:
- d->vscroll = r.y() + verticalMargin;
+ d->vscroll = r.y() + d->verticalMargin;
break;
default:
//center
d->vscroll = r.y() + (r.height() - fm.height() + 1) / 2;
break;
}
- QRect lineRect(r.x() + horizontalMargin, d->vscroll, r.width() - 2*horizontalMargin, fm.height());
- QTextLine line = d->textLayout.lineAt(0);
+ QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height());
- int cursor = d->cursor;
- if (d->preeditCursor != -1)
- cursor += d->preeditCursor;
- // locate cursor position
- int cix = qRound(line.cursorToX(cursor));
+ int cix = qRound(d->control->cursorToX());
// horizontal scrolling. d->hscroll is the left indent from the beginning
// of the text line to the left edge of lineRect. we update this value
@@ -2485,7 +1808,7 @@ void QLineEdit::paintEvent(QPaintEvent *)
// (cix).
int minLB = qMax(0, -fm.minLeftBearing());
int minRB = qMax(0, -fm.minRightBearing());
- int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
+ int widthUsed = d->control->width() + minRB;
if ((minLB + widthUsed) <= lineRect.width()) {
// text fits in lineRect; use hscroll for alignment
switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
@@ -2513,43 +1836,33 @@ void QLineEdit::paintEvent(QPaintEvent *)
d->hscroll = widthUsed - lineRect.width() + 1;
}
// the y offset is there to keep the baseline constant in case we have script changes in the text.
- QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->ascent - fm.ascent());
+ QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
// draw text, selections and cursors
#ifndef QT_NO_STYLE_STYLESHEET
if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style())) {
- cssStyle->focusPalette(this, &panel, &pal);
+ cssStyle->styleSheetPalette(this, &panel, &pal);
}
#endif
p.setPen(pal.text().color());
- QVector<QTextLayout::FormatRange> selections;
+ int flags = QLineControl::DrawText;
+
#ifdef QT_KEYPAD_NAVIGATION
if (!QApplication::keypadNavigationEnabled() || hasEditFocus())
#endif
- if (d->selstart < d->selend || (d->cursorVisible && d->maskData && !d->readOnly)) {
- QTextLayout::FormatRange o;
- if (d->selstart < d->selend) {
- o.start = d->selstart;
- o.length = d->selend - d->selstart;
- o.format.setBackground(pal.brush(QPalette::Highlight));
- o.format.setForeground(pal.brush(QPalette::HighlightedText));
- } else {
- // mask selection
- o.start = d->cursor;
- o.length = 1;
- o.format.setBackground(pal.brush(QPalette::Text));
- o.format.setForeground(pal.brush(QPalette::Window));
- }
- selections.append(o);
- }
+ if (d->control->hasSelectedText() || (d->cursorVisible && !d->control->inputMask().isEmpty() && !d->control->isReadOnly()))
+ flags |= QLineControl::DrawSelections;
// Asian users see an IM selection text as cursor on candidate
// selection phase of input method, so the ordinary cursor should be
// invisible if we have a preedit string.
- d->textLayout.draw(&p, topLeft, selections, r);
- if (d->cursorVisible && !d->readOnly && !d->hideCursor)
- d->textLayout.drawCursor(&p, topLeft, cursor, style()->pixelMetric(QStyle::PM_TextCursorWidth));
+ if (d->cursorVisible && !d->control->isReadOnly())
+ flags |= QLineControl::DrawCursor;
+
+ d->control->setCursorWidth(style()->pixelMetric(QStyle::PM_TextCursorWidth));
+ d->control->draw(&p, topLeft, r, flags);
+
}
@@ -2559,12 +1872,11 @@ void QLineEdit::paintEvent(QPaintEvent *)
void QLineEdit::dragMoveEvent(QDragMoveEvent *e)
{
Q_D(QLineEdit);
- if (!d->readOnly && e->mimeData()->hasFormat(QLatin1String("text/plain"))) {
+ if (!d->control->isReadOnly() && e->mimeData()->hasFormat(QLatin1String("text/plain"))) {
e->acceptProposedAction();
- d->cursor = d->xToPos(e->pos().x());
+ d->control->moveCursor(d->xToPos(e->pos().x()), false);
d->cursorVisible = true;
update();
- d->emitCursorPositionChanged();
}
}
@@ -2590,13 +1902,14 @@ void QLineEdit::dropEvent(QDropEvent* e)
Q_D(QLineEdit);
QString str = e->mimeData()->text();
- if (!str.isNull() && !d->readOnly) {
+ if (!str.isNull() && !d->control->isReadOnly()) {
if (e->source() == this && e->dropAction() == Qt::CopyAction)
deselect();
- d->cursor =d->xToPos(e->pos().x());
- int selStart = d->cursor;
- int oldSelStart = d->selstart;
- int oldSelEnd = d->selend;
+ int cursorPos = d->xToPos(e->pos().x());
+ int selStart = cursorPos;
+ int oldSelStart = d->control->selectionStart();
+ int oldSelEnd = d->control->selectionEnd();
+ d->control->moveCursor(cursorPos, false);
d->cursorVisible = false;
e->acceptProposedAction();
insert(str);
@@ -2618,22 +1931,6 @@ void QLineEdit::dropEvent(QDropEvent* e)
}
}
-void QLineEditPrivate::drag()
-{
- Q_Q(QLineEdit);
- dndTimer.stop();
- QMimeData *data = new QMimeData;
- data->setText(q->selectedText());
- QDrag *drag = new QDrag(q);
- drag->setMimeData(data);
- Qt::DropAction action = drag->start();
- if (action == Qt::MoveAction && !readOnly && drag->target() != q) {
- int priorState = undoState;
- removeSelectedText();
- finishChange(priorState);
- }
-}
-
#endif // QT_NO_DRAGANDDROP
#ifndef QT_NO_CONTEXTMENU
@@ -2678,37 +1975,39 @@ QMenu *QLineEdit::createStandardContextMenu()
popup->setObjectName(QLatin1String("qt_edit_menu"));
QAction *action = popup->addAction(QLineEdit::tr("&Undo") + ACCEL_KEY(QKeySequence::Undo));
- action->setEnabled(d->isUndoAvailable());
+ action->setEnabled(d->control->isUndoAvailable());
connect(action, SIGNAL(triggered()), SLOT(undo()));
action = popup->addAction(QLineEdit::tr("&Redo") + ACCEL_KEY(QKeySequence::Redo));
- action->setEnabled(d->isRedoAvailable());
+ action->setEnabled(d->control->isRedoAvailable());
connect(action, SIGNAL(triggered()), SLOT(redo()));
popup->addSeparator();
#ifndef QT_NO_CLIPBOARD
action = popup->addAction(QLineEdit::tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut));
- action->setEnabled(!d->readOnly && d->hasSelectedText());
+ action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText()
+ && d->control->echoMode() == QLineEdit::Normal);
connect(action, SIGNAL(triggered()), SLOT(cut()));
action = popup->addAction(QLineEdit::tr("&Copy") + ACCEL_KEY(QKeySequence::Copy));
- action->setEnabled(d->hasSelectedText());
+ action->setEnabled(d->control->hasSelectedText()
+ && d->control->echoMode() == QLineEdit::Normal);
connect(action, SIGNAL(triggered()), SLOT(copy()));
action = popup->addAction(QLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste));
- action->setEnabled(!d->readOnly && !QApplication::clipboard()->text().isEmpty());
+ action->setEnabled(!d->control->isReadOnly() && !QApplication::clipboard()->text().isEmpty());
connect(action, SIGNAL(triggered()), SLOT(paste()));
#endif
action = popup->addAction(QLineEdit::tr("Delete"));
- action->setEnabled(!d->readOnly && !d->text.isEmpty() && d->hasSelectedText());
- connect(action, SIGNAL(triggered()), SLOT(_q_deleteSelected()));
+ action->setEnabled(!d->control->isReadOnly() && !d->control->text().isEmpty() && d->control->hasSelectedText());
+ connect(action, SIGNAL(triggered()), d->control, SLOT(_q_deleteSelected()));
popup->addSeparator();
action = popup->addAction(QLineEdit::tr("Select All") + ACCEL_KEY(QKeySequence::SelectAll));
- action->setEnabled(!d->text.isEmpty() && !d->allSelected());
+ action->setEnabled(!d->control->text().isEmpty() && !d->control->allSelected());
d->selectAllAction = action;
connect(action, SIGNAL(triggered()), SLOT(selectAll()));
@@ -2722,9 +2021,9 @@ QMenu *QLineEdit::createStandardContextMenu()
#endif
#if defined(Q_WS_WIN)
- if (!d->readOnly && qt_use_rtl_extensions) {
+ if (!d->control->isReadOnly() && qt_use_rtl_extensions) {
#else
- if (!d->readOnly) {
+ if (!d->control->isReadOnly()) {
#endif
popup->addSeparator();
QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, popup);
@@ -2738,808 +2037,26 @@ QMenu *QLineEdit::createStandardContextMenu()
void QLineEdit::changeEvent(QEvent *ev)
{
Q_D(QLineEdit);
- if(ev->type() == QEvent::ActivationChange) {
+ switch(ev->type())
+ {
+ case QEvent::ActivationChange:
if (!palette().isEqual(QPalette::Active, QPalette::Inactive))
update();
- } else if (ev->type() == QEvent::FontChange
- || ev->type() == QEvent::StyleChange
- || ev->type() == QEvent::LayoutDirectionChange) {
- d->updateTextLayout();
- }
- QWidget::changeEvent(ev);
-}
-
-void QLineEditPrivate::_q_clipboardChanged()
-{
-}
-
-void QLineEditPrivate::_q_handleWindowActivate()
-{
- Q_Q(QLineEdit);
- if (!q->hasFocus() && q->hasSelectedText())
- q->deselect();
-}
-
-void QLineEditPrivate::_q_deleteSelected()
-{
- Q_Q(QLineEdit);
- if (!hasSelectedText())
- return;
-
- int priorState = undoState;
- q->resetInputContext();
- removeSelectedText();
- separate();
- finishChange(priorState);
-}
-
-void QLineEditPrivate::init(const QString& txt)
-{
- Q_Q(QLineEdit);
-#ifndef QT_NO_CURSOR
- q->setCursor(Qt::IBeamCursor);
-#endif
- q->setFocusPolicy(Qt::StrongFocus);
- q->setAttribute(Qt::WA_InputMethodEnabled);
- // Specifies that this widget can use more, but is able to survive on
- // less, horizontal space; and is fixed vertically.
- q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit));
- q->setBackgroundRole(QPalette::Base);
- q->setAttribute(Qt::WA_KeyCompression);
- q->setMouseTracking(true);
- q->setAcceptDrops(true);
- text = txt;
- updateTextLayout();
- cursor = text.length();
-
- q->setAttribute(Qt::WA_MacShowFocusRect);
-}
-
-void QLineEditPrivate::updatePasswordEchoEditing(bool editing)
-{
- Q_Q(QLineEdit);
- passwordEchoEditing = editing;
- q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(q));
- updateTextLayout();
- q->update();
-}
-
-void QLineEditPrivate::updateTextLayout()
-{
- // replace certain non-printable characters with spaces (to avoid
- // drawing boxes when using fonts that don't have glyphs for such
- // characters)
- Q_Q(QLineEdit);
- QString str = q->displayText();
- QChar* uc = str.data();
- for (int i = 0; i < (int)str.length(); ++i) {
- if ((uc[i] < 0x20 && uc[i] != 0x09)
- || uc[i] == QChar::LineSeparator
- || uc[i] == QChar::ParagraphSeparator
- || uc[i] == QChar::ObjectReplacementCharacter)
- uc[i] = QChar(0x0020);
- }
- textLayout.setFont(q->font());
- textLayout.setText(str);
- QTextOption option;
- option.setTextDirection(q->layoutDirection());
- option.setFlags(QTextOption::IncludeTrailingSpaces);
- textLayout.setTextOption(option);
-
- textLayout.beginLayout();
- QTextLine l = textLayout.createLine();
- textLayout.endLayout();
- ascent = qRound(l.ascent());
-}
-
-int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
-{
- QRect cr = adjustedContentsRect();
- x-= cr.x() - hscroll + horizontalMargin;
- QTextLine l = textLayout.lineAt(0);
- return l.xToCursor(x, betweenOrOn);
-}
-
-QRect QLineEditPrivate::cursorRect() const
-{
- Q_Q(const QLineEdit);
- QRect cr = adjustedContentsRect();
- int cix = cr.x() - hscroll + horizontalMargin;
- QTextLine l = textLayout.lineAt(0);
- int c = cursor;
- if (preeditCursor != -1)
- c += preeditCursor;
- cix += qRound(l.cursorToX(c));
- int ch = qMin(cr.height(), q->fontMetrics().height() + 1);
- int w = q->style()->pixelMetric(QStyle::PM_TextCursorWidth);
- return QRect(cix-5, vscroll, w + 9, ch);
-}
-
-QRect QLineEditPrivate::adjustedContentsRect() const
-{
- Q_Q(const QLineEdit);
- QStyleOptionFrameV2 opt;
- q->initStyleOption(&opt);
- QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q);
- r.setX(r.x() + leftTextMargin);
- r.setY(r.y() + topTextMargin);
- r.setRight(r.right() - rightTextMargin);
- r.setBottom(r.bottom() - bottomTextMargin);
- return r;
-}
-
-bool QLineEditPrivate::fixup() // this function assumes that validate currently returns != Acceptable
-{
-#ifndef QT_NO_VALIDATOR
- if (validator) {
- QString textCopy = text;
- int cursorCopy = cursor;
- validator->fixup(textCopy);
- if (validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
- if (textCopy != text || cursorCopy != cursor)
- setText(textCopy, cursorCopy);
- return true;
- }
- }
-#endif
- return false;
-}
-
-void QLineEditPrivate::moveCursor(int pos, bool mark)
-{
- Q_Q(QLineEdit);
- if (pos != cursor) {
- separate();
- if (maskData)
- pos = pos > cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
- }
- bool fullUpdate = mark || hasSelectedText();
- if (mark) {
- int anchor;
- if (selend > selstart && cursor == selstart)
- anchor = selend;
- else if (selend > selstart && cursor == selend)
- anchor = selstart;
- else
- anchor = cursor;
- selstart = qMin(anchor, pos);
- selend = qMax(anchor, pos);
- updateTextLayout();
- } else {
- deselect();
- }
- if (fullUpdate) {
- cursor = pos;
- q->update();
- } else {
- setCursorVisible(false);
- cursor = pos;
- setCursorVisible(true);
- if (!adjustedContentsRect().contains(cursorRect()))
- q->update();
- }
- QStyleOptionFrameV2 opt;
- q->initStyleOption(&opt);
- if (mark && !q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q))
- setCursorVisible(false);
- if (mark || selDirty) {
- selDirty = false;
- emit q->selectionChanged();
- }
- emitCursorPositionChanged();
-}
-
-void QLineEditPrivate::finishChange(int validateFromState, bool update, bool edited)
-{
- Q_Q(QLineEdit);
- bool lineDirty = selDirty;
- if (textDirty) {
- // do validation
- bool wasValidInput = validInput;
- validInput = true;
-#ifndef QT_NO_VALIDATOR
- if (validator) {
- validInput = false;
- QString textCopy = text;
- int cursorCopy = cursor;
- validInput = (validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
- if (validInput) {
- if (text != textCopy) {
- setText(textCopy, cursorCopy);
- return;
- }
- cursor = cursorCopy;
- }
- }
-#endif
- if (validateFromState >= 0 && wasValidInput && !validInput) {
- undo(validateFromState);
- history.resize(undoState);
- if (modifiedState > undoState)
- modifiedState = -1;
- validInput = true;
- textDirty = false;
- }
- updateTextLayout();
- lineDirty |= textDirty;
- if (textDirty) {
- textDirty = false;
- QString actualText = maskData ? stripString(text) : text;
- if (edited)
- emit q->textEdited(actualText);
- q->updateMicroFocus();
-#ifndef QT_NO_COMPLETER
- if (edited && completer && completer->completionMode() != QCompleter::InlineCompletion)
- complete(-1); // update the popup on cut/paste/del
-#endif
- emit q->textChanged(actualText);
- }
-#ifndef QT_NO_ACCESSIBILITY
- QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged);
-#endif
- }
- if (selDirty) {
- selDirty = false;
- emit q->selectionChanged();
- }
- if (lineDirty || update)
- q->update();
- emitCursorPositionChanged();
-}
-
-void QLineEditPrivate::emitCursorPositionChanged()
-{
- Q_Q(QLineEdit);
- if (cursor != lastCursorPos) {
- const int oldLast = lastCursorPos;
- lastCursorPos = cursor;
- emit q->cursorPositionChanged(oldLast, cursor);
- }
-}
-
-void QLineEditPrivate::setText(const QString& txt, int pos, bool edited)
-{
- Q_Q(QLineEdit);
- q->resetInputContext();
- deselect();
- QString oldText = text;
- if (maskData) {
- text = maskString(0, txt, true);
- text += clearString(text.length(), maxLength - text.length());
- } else {
- text = txt.isEmpty() ? txt : txt.left(maxLength);
- }
- history.clear();
- modifiedState = undoState = 0;
- cursor = (pos < 0 || pos > text.length()) ? text.length() : pos;
- textDirty = (oldText != text);
- finishChange(-1, true, edited);
-}
-
-
-void QLineEditPrivate::setCursorVisible(bool visible)
-{
- Q_Q(QLineEdit);
- if ((bool)cursorVisible == visible)
- return;
- if (cursorTimer)
- cursorVisible = visible;
- QRect r = cursorRect();
- if (maskData)
- q->update();
- else
- q->update(r);
-}
-
-void QLineEditPrivate::addCommand(const Command& cmd)
-{
- if (separator && undoState && history[undoState-1].type != Separator) {
- history.resize(undoState + 2);
- history[undoState++] = Command(Separator, cursor, 0, selstart, selend);
- } else {
- history.resize(undoState + 1);
- }
- separator = false;
- history[undoState++] = cmd;
-}
-
-void QLineEditPrivate::insert(const QString& s)
-{
- if (hasSelectedText())
- addCommand(Command(SetSelection, cursor, 0, selstart, selend));
- if (maskData) {
- QString ms = maskString(cursor, s);
- for (int i = 0; i < (int) ms.length(); ++i) {
- addCommand (Command(DeleteSelection, cursor+i, text.at(cursor+i), -1, -1));
- addCommand(Command(Insert, cursor+i, ms.at(i), -1, -1));
- }
- text.replace(cursor, ms.length(), ms);
- cursor += ms.length();
- cursor = nextMaskBlank(cursor);
- textDirty = true;
- } else {
- int remaining = maxLength - text.length();
- if (remaining != 0) {
- text.insert(cursor, s.left(remaining));
- for (int i = 0; i < (int) s.left(remaining).length(); ++i)
- addCommand(Command(Insert, cursor++, s.at(i), -1, -1));
- textDirty = true;
- }
- }
-}
-
-void QLineEditPrivate::del(bool wasBackspace)
-{
- if (cursor < (int) text.length()) {
- if (hasSelectedText())
- addCommand(Command(SetSelection, cursor, 0, selstart, selend));
- addCommand (Command((CommandType)((maskData?2:0)+(wasBackspace?Remove:Delete)), cursor, text.at(cursor), -1, -1));
- if (maskData) {
- text.replace(cursor, 1, clearString(cursor, 1));
- addCommand(Command(Insert, cursor, text.at(cursor), -1, -1));
- } else {
- text.remove(cursor, 1);
- }
- textDirty = true;
- }
-}
-
-void QLineEditPrivate::removeSelectedText()
-{
- if (selstart < selend && selend <= (int) text.length()) {
- separate();
- int i ;
- addCommand(Command(SetSelection, cursor, 0, selstart, selend));
- if (selstart <= cursor && cursor < selend) {
- // cursor is within the selection. Split up the commands
- // to be able to restore the correct cursor position
- for (i = cursor; i >= selstart; --i)
- addCommand (Command(DeleteSelection, i, text.at(i), -1, 1));
- for (i = selend - 1; i > cursor; --i)
- addCommand (Command(DeleteSelection, i - cursor + selstart - 1, text.at(i), -1, -1));
- } else {
- for (i = selend-1; i >= selstart; --i)
- addCommand (Command(RemoveSelection, i, text.at(i), -1, -1));
- }
- if (maskData) {
- text.replace(selstart, selend - selstart, clearString(selstart, selend - selstart));
- for (int i = 0; i < selend - selstart; ++i)
- addCommand(Command(Insert, selstart + i, text.at(selstart + i), -1, -1));
- } else {
- text.remove(selstart, selend - selstart);
- }
- if (cursor > selstart)
- cursor -= qMin(cursor, selend) - selstart;
- deselect();
- textDirty = true;
-
- // adjust hscroll to avoid gap
- const int minRB = qMax(0, -q_func()->fontMetrics().minRightBearing());
- updateTextLayout();
- const QTextLine line = textLayout.lineAt(0);
- const int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
- hscroll = qMin(hscroll, widthUsed);
- }
-}
-
-void QLineEditPrivate::parseInputMask(const QString &maskFields)
-{
- int delimiter = maskFields.indexOf(QLatin1Char(';'));
- if (maskFields.isEmpty() || delimiter == 0) {
- if (maskData) {
- delete [] maskData;
- maskData = 0;
- maxLength = 32767;
- setText(QString());
- }
- return;
- }
-
- if (delimiter == -1) {
- blank = QLatin1Char(' ');
- inputMask = maskFields;
- } else {
- inputMask = maskFields.left(delimiter);
- blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
- }
-
- // calculate maxLength / maskData length
- maxLength = 0;
- QChar c = 0;
- for (int i=0; i<inputMask.length(); i++) {
- c = inputMask.at(i);
- if (i > 0 && inputMask.at(i-1) == QLatin1Char('\\')) {
- maxLength++;
- continue;
- }
- if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
- c != QLatin1Char('<') && c != QLatin1Char('>') &&
- c != QLatin1Char('{') && c != QLatin1Char('}') &&
- c != QLatin1Char('[') && c != QLatin1Char(']'))
- maxLength++;
- }
-
- delete [] maskData;
- maskData = new MaskInputData[maxLength];
-
- MaskInputData::Casemode m = MaskInputData::NoCaseMode;
- c = 0;
- bool s;
- bool escape = false;
- int index = 0;
- for (int i = 0; i < inputMask.length(); i++) {
- c = inputMask.at(i);
- if (escape) {
- s = true;
- maskData[index].maskChar = c;
- maskData[index].separator = s;
- maskData[index].caseMode = m;
- index++;
- escape = false;
- } else if (c == QLatin1Char('<')) {
- m = MaskInputData::Lower;
- } else if (c == QLatin1Char('>')) {
- m = MaskInputData::Upper;
- } else if (c == QLatin1Char('!')) {
- m = MaskInputData::NoCaseMode;
- } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
- switch (c.unicode()) {
- case 'A':
- case 'a':
- case 'N':
- case 'n':
- case 'X':
- case 'x':
- case '9':
- case '0':
- case 'D':
- case 'd':
- case '#':
- case 'H':
- case 'h':
- case 'B':
- case 'b':
- s = false;
- break;
- case '\\':
- escape = true;
- default:
- s = true;
- break;
- }
-
- if (!escape) {
- maskData[index].maskChar = c;
- maskData[index].separator = s;
- maskData[index].caseMode = m;
- index++;
- }
- }
- }
- setText(text);
-}
-
-
-/* checks if the key is valid compared to the inputMask */
-bool QLineEditPrivate::isValidInput(QChar key, QChar mask) const
-{
- switch (mask.unicode()) {
- case 'A':
- if (key.isLetter())
- return true;
break;
- case 'a':
- if (key.isLetter() || key == blank)
- return true;
- break;
- case 'N':
- if (key.isLetterOrNumber())
- return true;
- break;
- case 'n':
- if (key.isLetterOrNumber() || key == blank)
- return true;
- break;
- case 'X':
- if (key.isPrint())
- return true;
- break;
- case 'x':
- if (key.isPrint() || key == blank)
- return true;
- break;
- case '9':
- if (key.isNumber())
- return true;
- break;
- case '0':
- if (key.isNumber() || key == blank)
- return true;
- break;
- case 'D':
- if (key.isNumber() && key.digitValue() > 0)
- return true;
+ case QEvent::FontChange:
+ d->control->setFont(font());
break;
- case 'd':
- if ((key.isNumber() && key.digitValue() > 0) || key == blank)
- return true;
- break;
- case '#':
- if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == blank)
- return true;
- break;
- case 'B':
- if (key == QLatin1Char('0') || key == QLatin1Char('1'))
- return true;
- break;
- case 'b':
- if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == blank)
- return true;
- break;
- case 'H':
- if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
- return true;
+ case QEvent::StyleChange:
+ d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter));
+ update();
break;
- case 'h':
- if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == blank)
- return true;
+ case QEvent::LayoutDirectionChange:
+ d->control->setLayoutDirection(layoutDirection());
break;
default:
break;
}
- return false;
-}
-
-bool QLineEditPrivate::hasAcceptableInput(const QString &str) const
-{
-#ifndef QT_NO_VALIDATOR
- QString textCopy = str;
- int cursorCopy = cursor;
- if (validator && validator->validate(textCopy, cursorCopy)
- != QValidator::Acceptable)
- return false;
-#endif
-
- if (!maskData)
- return true;
-
- if (str.length() != maxLength)
- return false;
-
- for (int i=0; i < maxLength; ++i) {
- if (maskData[i].separator) {
- if (str.at(i) != maskData[i].maskChar)
- return false;
- } else {
- if (!isValidInput(str.at(i), maskData[i].maskChar))
- return false;
- }
- }
- return true;
-}
-
-/*
- Applies the inputMask on \a str starting from position \a pos in the mask. \a clear
- specifies from where characters should be gotten when a separator is met in \a str - true means
- that blanks will be used, false that previous input is used.
- Calling this when no inputMask is set is undefined.
-*/
-QString QLineEditPrivate::maskString(uint pos, const QString &str, bool clear) const
-{
- if (pos >= (uint)maxLength)
- return QString::fromLatin1("");
-
- QString fill;
- fill = clear ? clearString(0, maxLength) : text;
-
- int strIndex = 0;
- QString s = QString::fromLatin1("");
- int i = pos;
- while (i < maxLength) {
- if (strIndex < str.length()) {
- if (maskData[i].separator) {
- s += maskData[i].maskChar;
- if (str[(int)strIndex] == maskData[i].maskChar)
- strIndex++;
- ++i;
- } else {
- if (isValidInput(str[(int)strIndex], maskData[i].maskChar)) {
- switch (maskData[i].caseMode) {
- case MaskInputData::Upper:
- s += str[(int)strIndex].toUpper();
- break;
- case MaskInputData::Lower:
- s += str[(int)strIndex].toLower();
- break;
- default:
- s += str[(int)strIndex];
- }
- ++i;
- } else {
- // search for separator first
- int n = findInMask(i, true, true, str[(int)strIndex]);
- if (n != -1) {
- if (str.length() != 1 || i == 0 || (i > 0 && (!maskData[i-1].separator || maskData[i-1].maskChar != str[(int)strIndex]))) {
- s += fill.mid(i, n-i+1);
- i = n + 1; // update i to find + 1
- }
- } else {
- // search for valid blank if not
- n = findInMask(i, true, false, str[(int)strIndex]);
- if (n != -1) {
- s += fill.mid(i, n-i);
- switch (maskData[n].caseMode) {
- case MaskInputData::Upper:
- s += str[(int)strIndex].toUpper();
- break;
- case MaskInputData::Lower:
- s += str[(int)strIndex].toLower();
- break;
- default:
- s += str[(int)strIndex];
- }
- i = n + 1; // updates i to find + 1
- }
- }
- }
- strIndex++;
- }
- } else
- break;
- }
-
- return s;
-}
-
-
-
-/*
- Returns a "cleared" string with only separators and blank chars.
- Calling this when no inputMask is set is undefined.
-*/
-QString QLineEditPrivate::clearString(uint pos, uint len) const
-{
- if (pos >= (uint)maxLength)
- return QString();
-
- QString s;
- int end = qMin((uint)maxLength, pos + len);
- for (int i=pos; i<end; i++)
- if (maskData[i].separator)
- s += maskData[i].maskChar;
- else
- s += blank;
-
- return s;
-}
-
-/*
- Strips blank parts of the input in a QLineEdit when an inputMask is set,
- separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1".
-*/
-QString QLineEditPrivate::stripString(const QString &str) const
-{
- if (!maskData)
- return str;
-
- QString s;
- int end = qMin(maxLength, (int)str.length());
- for (int i=0; i < end; i++)
- if (maskData[i].separator)
- s += maskData[i].maskChar;
- else
- if (str[i] != blank)
- s += str[i];
-
- return s;
-}
-
-/* searches forward/backward in maskData for either a separator or a blank */
-int QLineEditPrivate::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
-{
- if (pos >= maxLength || pos < 0)
- return -1;
-
- int end = forward ? maxLength : -1;
- int step = forward ? 1 : -1;
- int i = pos;
-
- while (i != end) {
- if (findSeparator) {
- if (maskData[i].separator && maskData[i].maskChar == searchChar)
- return i;
- } else {
- if (!maskData[i].separator) {
- if (searchChar.isNull())
- return i;
- else if (isValidInput(searchChar, maskData[i].maskChar))
- return i;
- }
- }
- i += step;
- }
- return -1;
-}
-
-void QLineEditPrivate::undo(int until)
-{
- if (!isUndoAvailable())
- return;
- deselect();
- while (undoState && undoState > until) {
- Command& cmd = history[--undoState];
- switch (cmd.type) {
- case Insert:
- text.remove(cmd.pos, 1);
- cursor = cmd.pos;
- break;
- case SetSelection:
- selstart = cmd.selStart;
- selend = cmd.selEnd;
- cursor = cmd.pos;
- break;
- case Remove:
- case RemoveSelection:
- text.insert(cmd.pos, cmd.uc);
- cursor = cmd.pos + 1;
- break;
- case Delete:
- case DeleteSelection:
- text.insert(cmd.pos, cmd.uc);
- cursor = cmd.pos;
- break;
- case Separator:
- continue;
- }
- if (until < 0 && undoState) {
- Command& next = history[undoState-1];
- if (next.type != cmd.type && next.type < RemoveSelection
- && (cmd.type < RemoveSelection || next.type == Separator))
- break;
- }
- }
- textDirty = true;
- emitCursorPositionChanged();
-}
-
-void QLineEditPrivate::redo() {
- if (!isRedoAvailable())
- return;
- deselect();
- while (undoState < (int)history.size()) {
- Command& cmd = history[undoState++];
- switch (cmd.type) {
- case Insert:
- text.insert(cmd.pos, cmd.uc);
- cursor = cmd.pos + 1;
- break;
- case SetSelection:
- selstart = cmd.selStart;
- selend = cmd.selEnd;
- cursor = cmd.pos;
- break;
- case Remove:
- case Delete:
- case RemoveSelection:
- case DeleteSelection:
- text.remove(cmd.pos, 1);
- cursor = cmd.pos;
- break;
- case Separator:
- selstart = cmd.selStart;
- selend = cmd.selEnd;
- cursor = cmd.pos;
- break;
- }
- if (undoState < (int)history.size()) {
- Command& next = history[undoState];
- if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator
- && (next.type < RemoveSelection || cmd.type == Separator))
- break;
- }
- }
- textDirty = true;
- emitCursorPositionChanged();
+ QWidget::changeEvent(ev);
}
/*!
diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h
index fab2a4e..97641c3 100644
--- a/src/gui/widgets/qlineedit.h
+++ b/src/gui/widgets/qlineedit.h
@@ -266,12 +266,15 @@ private:
#endif
Q_DISABLE_COPY(QLineEdit)
Q_DECLARE_PRIVATE(QLineEdit)
- Q_PRIVATE_SLOT(d_func(), void _q_clipboardChanged())
Q_PRIVATE_SLOT(d_func(), void _q_handleWindowActivate())
- Q_PRIVATE_SLOT(d_func(), void _q_deleteSelected())
+ Q_PRIVATE_SLOT(d_func(), void _q_textEdited(const QString &))
+ Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged(int, int))
#ifndef QT_NO_COMPLETER
Q_PRIVATE_SLOT(d_func(), void _q_completionHighlighted(QString))
#endif
+#ifdef QT_KEYPAD_NAVIGATION
+ Q_PRIVATE_SLOT(d_func(), void _q_editFocusChange(bool))
+#endif
};
#endif // QT_NO_LINEEDIT
diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp
new file mode 100644
index 0000000..4218630
--- /dev/null
+++ b/src/gui/widgets/qlineedit_p.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlineedit.h"
+#include "qlineedit_p.h"
+
+#ifndef QT_NO_LINEEDIT
+
+#include "qabstractitemview.h"
+#include "qclipboard.h"
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#ifndef QT_NO_IM
+#include "qinputcontext.h"
+#include "qlist.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+const int QLineEditPrivate::verticalMargin(1);
+const int QLineEditPrivate::horizontalMargin(2);
+
+int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
+{
+ QRect cr = adjustedContentsRect();
+ x-= cr.x() - hscroll + horizontalMargin;
+ return control->xToPos(x, betweenOrOn);
+}
+
+QRect QLineEditPrivate::cursorRect() const
+{
+ QRect cr = adjustedContentsRect();
+ int cix = cr.x() - hscroll + horizontalMargin;
+ QRect crect = control->cursorRect();
+ crect.moveTo(crect.topLeft() + QPoint(cix, vscroll));
+ return crect;
+}
+
+#ifndef QT_NO_COMPLETER
+
+void QLineEditPrivate::_q_completionHighlighted(QString newText)
+{
+ Q_Q(QLineEdit);
+ if (control->completer()->completionMode() != QCompleter::InlineCompletion) {
+ q->setText(newText);
+ } else {
+ int c = control->cursor();
+ QString text = control->text();
+ q->setText(text.left(c) + newText.mid(c));
+ control->moveCursor(control->end(), false);
+ control->moveCursor(c, true);
+ }
+}
+
+#endif // QT_NO_COMPLETER
+
+void QLineEditPrivate::_q_handleWindowActivate()
+{
+ Q_Q(QLineEdit);
+ if (!q->hasFocus() && control->hasSelectedText())
+ control->deselect();
+}
+
+void QLineEditPrivate::_q_textEdited(const QString &text)
+{
+ Q_Q(QLineEdit);
+#ifndef QT_NO_COMPLETER
+ if (control->completer() &&
+ control->completer()->completionMode() != QCompleter::InlineCompletion)
+ control->complete(-1); // update the popup on cut/paste/del
+#endif
+ emit q->textEdited(text);
+}
+
+void QLineEditPrivate::_q_cursorPositionChanged(int from, int to)
+{
+ Q_Q(QLineEdit);
+ q->update();
+ emit q->cursorPositionChanged(from, to);
+}
+
+#ifdef QT_KEYPAD_NAVIGATION
+void QLineEditPrivate::_q_editFocusChange(bool e)
+{
+ Q_Q(QLineEdit);
+ q->setEditFocus(e);
+}
+#endif
+
+void QLineEditPrivate::init(const QString& txt)
+{
+ Q_Q(QLineEdit);
+ control = new QLineControl(txt);
+ control->setFont(q->font());
+ QObject::connect(control, SIGNAL(textChanged(const QString &)),
+ q, SIGNAL(textChanged(const QString &)));
+ QObject::connect(control, SIGNAL(textEdited(const QString &)),
+ q, SLOT(_q_textEdited(const QString &)));
+ QObject::connect(control, SIGNAL(cursorPositionChanged(int, int)),
+ q, SLOT(_q_cursorPositionChanged(int, int)));
+ QObject::connect(control, SIGNAL(selectionChanged()),
+ q, SIGNAL(selectionChanged()));
+ QObject::connect(control, SIGNAL(accepted()),
+ q, SIGNAL(returnPressed()));
+ QObject::connect(control, SIGNAL(editingFinished()),
+ q, SIGNAL(editingFinished()));
+#ifdef QT_KEYPAD_NAVIGATION
+ QObject::connect(control, SIGNAL(editFocusChange(bool)),
+ q, SLOT(_q_editFocusChange(bool)));
+#endif
+ QObject::connect(control, SIGNAL(cursorPositionChanged(int, int)),
+ q, SLOT(updateMicroFocus()));
+
+ // for now, going completely overboard with updates.
+ QObject::connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(update()));
+
+ QObject::connect(control, SIGNAL(displayTextChanged(const QString &)),
+ q, SLOT(update()));
+
+ QObject::connect(control, SIGNAL(updateNeeded(const QRect &)),
+ q, SLOT(update()));
+ control->setPasswordCharacter(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter));
+#ifndef QT_NO_CURSOR
+ q->setCursor(Qt::IBeamCursor);
+#endif
+ q->setFocusPolicy(Qt::StrongFocus);
+ q->setAttribute(Qt::WA_InputMethodEnabled);
+ // Specifies that this widget can use more, but is able to survive on
+ // less, horizontal space; and is fixed vertically.
+ q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::LineEdit));
+ q->setBackgroundRole(QPalette::Base);
+ q->setAttribute(Qt::WA_KeyCompression);
+ q->setMouseTracking(true);
+ q->setAcceptDrops(true);
+
+ q->setAttribute(Qt::WA_MacShowFocusRect);
+}
+
+QRect QLineEditPrivate::adjustedContentsRect() const
+{
+ Q_Q(const QLineEdit);
+ QStyleOptionFrameV2 opt;
+ q->initStyleOption(&opt);
+ QRect r = q->style()->subElementRect(QStyle::SE_LineEditContents, &opt, q);
+ r.setX(r.x() + leftTextMargin);
+ r.setY(r.y() + topTextMargin);
+ r.setRight(r.right() - rightTextMargin);
+ r.setBottom(r.bottom() - bottomTextMargin);
+ return r;
+}
+
+void QLineEditPrivate::setCursorVisible(bool visible)
+{
+ Q_Q(QLineEdit);
+ if ((bool)cursorVisible == visible)
+ return;
+ cursorVisible = visible;
+ QRect r = cursorRect();
+ if (control->inputMask().isEmpty())
+ q->update(r);
+ else
+ q->update();
+}
+
+void QLineEditPrivate::updatePasswordEchoEditing(bool editing)
+{
+ Q_Q(QLineEdit);
+ control->updatePasswordEchoEditing(editing);
+ q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod());
+}
+
+/*!
+ This function is not intended as polymorphic usage. Just a shared code
+ fragment that calls QInputContext::mouseHandler for this
+ class.
+*/
+bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
+{
+#if !defined QT_NO_IM
+ Q_Q(QLineEdit);
+ if ( control->composeMode() ) {
+ int tmp_cursor = xToPos(e->pos().x());
+ int mousePos = tmp_cursor - control->cursor();
+ if ( mousePos < 0 || mousePos > control->preeditAreaText().length() ) {
+ mousePos = -1;
+ // don't send move events outside the preedit area
+ if ( e->type() == QEvent::MouseMove )
+ return true;
+ }
+
+ QInputContext *qic = q->inputContext();
+ if ( qic )
+ // may be causing reset() in some input methods
+ qic->mouseHandler(mousePos, e);
+ if (!control->preeditAreaText().isEmpty())
+ return true;
+ }
+#else
+ Q_UNUSED(e);
+#endif
+
+ return false;
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QLineEditPrivate::drag()
+{
+ Q_Q(QLineEdit);
+ dndTimer.stop();
+ QMimeData *data = new QMimeData;
+ data->setText(control->selectedText());
+ QDrag *drag = new QDrag(q);
+ drag->setMimeData(data);
+ Qt::DropAction action = drag->start();
+ if (action == Qt::MoveAction && !control->isReadOnly() && drag->target() != q)
+ control->removeSelection();
+}
+
+#endif // QT_NO_DRAGANDDROP
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h
index 4194cfd4..1df61fb 100644
--- a/src/gui/widgets/qlineedit_p.h
+++ b/src/gui/widgets/qlineedit_p.h
@@ -65,6 +65,8 @@
#include "QtCore/qpointer.h"
#include "QtGui/qlineedit.h"
+#include "private/qlinecontrol_p.h"
+
QT_BEGIN_NAMESPACE
class QLineEditPrivate : public QWidgetPrivate
@@ -73,168 +75,67 @@ class QLineEditPrivate : public QWidgetPrivate
public:
QLineEditPrivate()
- : cursor(0), preeditCursor(0), cursorTimer(0), frame(1),
- cursorVisible(0), hideCursor(false), separator(0), readOnly(0),
- dragEnabled(0), contextMenuEnabled(1), echoMode(0), textDirty(0),
- selDirty(0), validInput(1), alignment(Qt::AlignLeading | Qt::AlignVCenter), ascent(0),
- maxLength(32767), hscroll(0), vscroll(0), lastCursorPos(-1), maskData(0),
- modifiedState(0), undoState(0), selstart(0), selend(0), userInput(false),
- emitingEditingFinished(false), passwordEchoEditing(false)
-#ifndef QT_NO_COMPLETER
- , completer(0)
-#endif
- , leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0)
- {
- }
+ : control(0), frame(1), contextMenuEnabled(1), cursorVisible(0),
+ dragEnabled(0), clickCausedFocus(0), hscroll(0), vscroll(0),
+ alignment(Qt::AlignLeading | Qt::AlignVCenter),
+ leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0)
+ {
+ }
~QLineEditPrivate()
{
- delete [] maskData;
+ delete control;
}
+
+ QLineControl *control;
+
+#ifndef QT_NO_CONTEXTMENU
+ QPointer<QAction> selectAllAction;
+#endif
void init(const QString&);
- QString text;
- int cursor;
- int preeditCursor;
- int cursorTimer; // -1 for non blinking cursor.
+ int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
+ QRect cursorRect() const;
+ void setCursorVisible(bool visible);
+
+ void updatePasswordEchoEditing(bool);
+
+ inline bool shouldEnableInputMethod() const
+ {
+ return !control->isReadOnly();
+ }
+
QPoint tripleClick;
QBasicTimer tripleClickTimer;
uint frame : 1;
+ uint contextMenuEnabled : 1;
uint cursorVisible : 1;
- uint hideCursor : 1; // used to hide the cursor inside preedit areas
- uint separator : 1;
- uint readOnly : 1;
uint dragEnabled : 1;
- uint contextMenuEnabled : 1;
- uint echoMode : 2;
- uint textDirty : 1;
- uint selDirty : 1;
- uint validInput : 1;
- uint alignment;
- int ascent;
- int maxLength;
+ uint clickCausedFocus : 1;
int hscroll;
int vscroll;
- int lastCursorPos;
-
-#ifndef QT_NO_CONTEXTMENU
- QPointer<QAction> selectAllAction;
-#endif
+ uint alignment;
+ static const int verticalMargin;
+ static const int horizontalMargin;
- inline void emitCursorPositionChanged();
bool sendMouseEventToInputContext(QMouseEvent *e);
- void finishChange(int validateFromState = -1, bool update = false, bool edited = true);
-
- QPointer<QValidator> validator;
- struct MaskInputData {
- enum Casemode { NoCaseMode, Upper, Lower };
- QChar maskChar; // either the separator char or the inputmask
- bool separator;
- Casemode caseMode;
- };
- QString inputMask;
- QChar blank;
- MaskInputData *maskData;
- inline int nextMaskBlank(int pos) {
- int c = findInMask(pos, true, false);
- separator |= (c != pos);
- return (c != -1 ? c : maxLength);
- }
- inline int prevMaskBlank(int pos) {
- int c = findInMask(pos, false, false);
- separator |= (c != pos);
- return (c != -1 ? c : 0);
- }
-
- void setCursorVisible(bool visible);
-
-
- // undo/redo handling
- enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection };
- struct Command {
- inline Command() {}
- inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {}
- uint type : 4;
- QChar uc;
- int pos, selStart, selEnd;
- };
- int modifiedState;
- int undoState;
- QVector<Command> history;
- void addCommand(const Command& cmd);
- void insert(const QString& s);
- void del(bool wasBackspace = false);
- void remove(int pos);
-
- inline void separate() { separator = true; }
- void undo(int until = -1);
- void redo();
- inline bool isUndoAvailable() const { return !readOnly && undoState; }
- inline bool isRedoAvailable() const { return !readOnly && undoState < (int)history.size(); }
-
- // selection
- int selstart, selend;
- inline bool allSelected() const { return !text.isEmpty() && selstart == 0 && selend == (int)text.length(); }
- inline bool hasSelectedText() const { return !text.isEmpty() && selend > selstart; }
- inline void deselect() { selDirty |= (selend > selstart); selstart = selend = 0; }
- void removeSelectedText();
-#ifndef QT_NO_CLIPBOARD
- void copy(bool clipboard = true) const;
-#endif
- inline bool inSelection(int x) const
- { if (selstart >= selend) return false;
- int pos = xToPos(x, QTextLine::CursorOnCharacter); return pos >= selstart && pos < selend; }
-
- // masking
- void parseInputMask(const QString &maskFields);
- bool isValidInput(QChar key, QChar mask) const;
- bool hasAcceptableInput(const QString &text) const;
- QString maskString(uint pos, const QString &str, bool clear = false) const;
- QString clearString(uint pos, uint len) const;
- QString stripString(const QString &str) const;
- int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const;
-
- // input methods
- bool composeMode() const { return !textLayout.preeditAreaText().isEmpty(); }
-
- // complex text layout
- QTextLayout textLayout;
- void updateTextLayout();
- void moveCursor(int pos, bool mark = false);
- void setText(const QString& txt, int pos = -1, bool edited = true);
- int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
- QRect cursorRect() const;
- bool fixup();
-
QRect adjustedContentsRect() const;
-#ifndef QT_NO_DRAGANDDROP
- // drag and drop
- QPoint dndPos;
- QBasicTimer dndTimer;
- void drag();
-#endif
-
- void _q_clipboardChanged();
void _q_handleWindowActivate();
- void _q_deleteSelected();
- bool userInput;
- bool emitingEditingFinished;
-
+ void _q_textEdited(const QString &);
+ void _q_cursorPositionChanged(int, int);
#ifdef QT_KEYPAD_NAVIGATION
- QBasicTimer deleteAllTimer; // keypad navigation
- QString origText;
+ void _q_editFocusChange(bool);
#endif
- bool passwordEchoEditing;
- void updatePasswordEchoEditing(bool editing);
-
#ifndef QT_NO_COMPLETER
- QPointer<QCompleter> completer;
- void complete(int key = -1);
void _q_completionHighlighted(QString);
- bool advanceToEnabledItem(int n);
+#endif
+#ifndef QT_NO_DRAGANDDROP
+ QPoint dndPos;
+ QBasicTimer dndTimer;
+ void drag();
#endif
int leftTextMargin;
diff --git a/src/gui/widgets/qmacnativewidget_mac.h b/src/gui/widgets/qmacnativewidget_mac.h
index 0ea6a19..ccc3382 100644
--- a/src/gui/widgets/qmacnativewidget_mac.h
+++ b/src/gui/widgets/qmacnativewidget_mac.h
@@ -64,7 +64,7 @@ protected:
bool event(QEvent *ev);
private:
- Q_DECLARE_PRIVATE_D(QWidget::d_ptr, QMacNativeWidget)
+ Q_DECLARE_PRIVATE(QMacNativeWidget)
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp
index 1d3f9d0..8805fb8 100644
--- a/src/gui/widgets/qmainwindow.cpp
+++ b/src/gui/widgets/qmainwindow.cpp
@@ -73,7 +73,7 @@ class QMainWindowPrivate : public QWidgetPrivate
Q_DECLARE_PUBLIC(QMainWindow)
public:
inline QMainWindowPrivate()
- : layout(0), toolButtonStyle(Qt::ToolButtonIconOnly)
+ : layout(0), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly)
#ifdef Q_WS_MAC
, useHIToolBar(false)
#endif
@@ -107,8 +107,6 @@ void QMainWindowPrivate::init()
layout = new QMainWindowLayout(q);
const int metric = q->style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q);
iconSize = QSize(metric, metric);
- explicitIconSize = false;
-
q->setAttribute(Qt::WA_Hover);
}
@@ -148,8 +146,8 @@ void QMainWindowPrivate::init()
\class QMainWindow
\brief The QMainWindow class provides a main application
window.
- \ingroup application
- \mainclass
+ \ingroup mainwindow-classes
+
\tableofcontents
@@ -481,6 +479,11 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar)
oldMenuBar->deleteLater();
}
d->layout->setMenuBar(menuBar);
+ if (menuBar) {
+ QAction* menu = new QAction(QString::fromLatin1("Options"), this);
+ menu->setSoftKeyRole(QAction::MenuSoftKey);
+ setSoftKey(menu);
+ }
}
/*!
@@ -1029,6 +1032,8 @@ void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget
Restores the state of \a dockwidget if it is created after the call
to restoreState(). Returns true if the state was restored; otherwise
returns false.
+
+ \sa restoreState(), saveState()
*/
bool QMainWindow::restoreDockWidget(QDockWidget *dockwidget)
@@ -1160,6 +1165,11 @@ Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const
To restore the saved state, pass the return value and \a version
number to restoreState().
+ To save the geometry when the window closes, you can
+ implement a close event like this:
+
+ \snippet doc/src/snippets/code/src_gui_widgets_qmainwindow.cpp 0
+
\sa restoreState(), QWidget::saveGeometry(), QWidget::restoreGeometry()
*/
QByteArray QMainWindow::saveState(int version) const
@@ -1179,7 +1189,13 @@ QByteArray QMainWindow::saveState(int version) const
unchanged, and this function returns \c false; otherwise, the state
is restored, and this function returns \c true.
- \sa saveState(), QWidget::saveGeometry(), QWidget::restoreGeometry()
+ To restore geometry saved using QSettings, you can use code like
+ this:
+
+ \snippet doc/src/snippets/code/src_gui_widgets_qmainwindow.cpp 1
+
+ \sa saveState(), QWidget::saveGeometry(),
+ QWidget::restoreGeometry(), restoreDockWidget()
*/
bool QMainWindow::restoreState(const QByteArray &state, int version)
{
@@ -1369,20 +1385,25 @@ bool QMainWindow::event(QEvent *event)
#ifdef Q_WS_MAC
case QEvent::Show:
if (unifiedTitleAndToolBarOnMac())
- macWindowToolbarShow(this, true);
+ d->layout->syncUnifiedToolbarVisibility();
+ d->layout->blockVisiblityCheck = false;
break;
-# ifdef QT_MAC_USE_COCOA
case QEvent::WindowStateChange:
{
+ if (isHidden()) {
+ // We are coming out of a minimize, leave things as is.
+ d->layout->blockVisiblityCheck = true;
+ }
+# ifdef QT_MAC_USE_COCOA
// We need to update the HIToolbar status when we go out of or into fullscreen.
QWindowStateChangeEvent *wce = static_cast<QWindowStateChangeEvent *>(event);
if ((windowState() & Qt::WindowFullScreen) || (wce->oldState() & Qt::WindowFullScreen)) {
d->layout->updateHIToolBarStatus();
}
+# endif // Cocoa
}
break;
-# endif // Cocoa
-#endif
+#endif // Q_WS_MAC
#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
case QEvent::CursorChange:
if (d->cursorAdjusted) {
@@ -1391,7 +1412,16 @@ bool QMainWindow::event(QEvent *event)
}
break;
#endif
-
+#ifndef QT_NO_MENUBAR
+ case QEvent::WindowActivate:
+ if (d->layout->menuBar()) {
+ // ### TODO: This is evil, there is no need to create a new action every time
+ QAction* menu = new QAction(QString::fromLatin1("Options"), this);
+ menu->setSoftKeyRole(QAction::MenuSoftKey);
+ setSoftKey(menu);
+ }
+ break;
+#endif
default:
break;
}
diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp
index feccd0d..7785603 100644
--- a/src/gui/widgets/qmainwindowlayout.cpp
+++ b/src/gui/widgets/qmainwindowlayout.cpp
@@ -237,7 +237,7 @@ void QMainWindowLayoutState::apply(bool animated)
if (centralWidgetItem != 0) {
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
Q_ASSERT(layout != 0);
- layout->widgetAnimator->animate(centralWidgetItem->widget(), centralWidgetRect, animated);
+ layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated);
}
#endif
}
@@ -426,42 +426,42 @@ QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget,
return result;
}
-bool QMainWindowLayoutState::insertGap(QList<int> path, QLayoutItem *item)
+bool QMainWindowLayoutState::insertGap(const QList<int> &path, QLayoutItem *item)
{
if (path.isEmpty())
return false;
- int i = path.takeFirst();
+ int i = path.first();
#ifndef QT_NO_TOOLBAR
if (i == 0) {
Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != 0);
- return toolBarAreaLayout.insertGap(path, item);
+ return toolBarAreaLayout.insertGap(path.mid(1), item);
}
#endif
#ifndef QT_NO_DOCKWIDGET
if (i == 1) {
Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) != 0);
- return dockAreaLayout.insertGap(path, item);
+ return dockAreaLayout.insertGap(path.mid(1), item);
}
#endif //QT_NO_DOCKWIDGET
return false;
}
-void QMainWindowLayoutState::remove(QList<int> path)
+void QMainWindowLayoutState::remove(const QList<int> &path)
{
- int i = path.takeFirst();
+ int i = path.first();
#ifndef QT_NO_TOOLBAR
if (i == 0)
- toolBarAreaLayout.remove(path);
+ toolBarAreaLayout.remove(path.mid(1));
#endif
#ifndef QT_NO_DOCKWIDGET
if (i == 1)
- dockAreaLayout.remove(path);
+ dockAreaLayout.remove(path.mid(1));
#endif //QT_NO_DOCKWIDGET
}
@@ -490,10 +490,10 @@ void QMainWindowLayoutState::clear()
#ifndef QT_NO_DOCKWIDGET
dockAreaLayout.clear();
#else
- centralWidgetRect = QRect(0, 0, -1, -1);
+ centralWidgetRect = QRect();
#endif
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
}
bool QMainWindowLayoutState::isValid() const
@@ -501,88 +501,88 @@ bool QMainWindowLayoutState::isValid() const
return rect.isValid();
}
-QLayoutItem *QMainWindowLayoutState::item(QList<int> path)
+QLayoutItem *QMainWindowLayoutState::item(const QList<int> &path)
{
- int i = path.takeFirst();
+ int i = path.first();
#ifndef QT_NO_TOOLBAR
if (i == 0)
- return toolBarAreaLayout.item(path).widgetItem;
+ return toolBarAreaLayout.item(path.mid(1)).widgetItem;
#endif
#ifndef QT_NO_DOCKWIDGET
if (i == 1)
- return dockAreaLayout.item(path).widgetItem;
+ return dockAreaLayout.item(path.mid(1)).widgetItem;
#endif //QT_NO_DOCKWIDGET
return 0;
}
-QRect QMainWindowLayoutState::itemRect(QList<int> path) const
+QRect QMainWindowLayoutState::itemRect(const QList<int> &path) const
{
- int i = path.takeFirst();
+ int i = path.first();
#ifndef QT_NO_TOOLBAR
if (i == 0)
- return toolBarAreaLayout.itemRect(path);
+ return toolBarAreaLayout.itemRect(path.mid(1));
#endif
#ifndef QT_NO_DOCKWIDGET
if (i == 1)
- return dockAreaLayout.itemRect(path);
+ return dockAreaLayout.itemRect(path.mid(1));
#endif //QT_NO_DOCKWIDGET
return QRect();
}
-QRect QMainWindowLayoutState::gapRect(QList<int> path) const
+QRect QMainWindowLayoutState::gapRect(const QList<int> &path) const
{
- int i = path.takeFirst();
+ int i = path.first();
#ifndef QT_NO_TOOLBAR
if (i == 0)
- return toolBarAreaLayout.itemRect(path);
+ return toolBarAreaLayout.itemRect(path.mid(1));
#endif
#ifndef QT_NO_DOCKWIDGET
if (i == 1)
- return dockAreaLayout.gapRect(path);
+ return dockAreaLayout.gapRect(path.mid(1));
#endif //QT_NO_DOCKWIDGET
return QRect();
}
-QLayoutItem *QMainWindowLayoutState::plug(QList<int> path)
+QLayoutItem *QMainWindowLayoutState::plug(const QList<int> &path)
{
- int i = path.takeFirst();
+ int i = path.first();
#ifndef QT_NO_TOOLBAR
if (i == 0)
- return toolBarAreaLayout.plug(path);
+ return toolBarAreaLayout.plug(path.mid(1));
#endif
#ifndef QT_NO_DOCKWIDGET
if (i == 1)
- return dockAreaLayout.plug(path);
+ return dockAreaLayout.plug(path.mid(1));
#endif //QT_NO_DOCKWIDGET
return 0;
}
-QLayoutItem *QMainWindowLayoutState::unplug(QList<int> path, QMainWindowLayoutState *other)
+QLayoutItem *QMainWindowLayoutState::unplug(const QList<int> &path, QMainWindowLayoutState *other)
{
- int i = path.takeFirst();
+ int i = path.first();
#ifdef QT_NO_TOOLBAR
Q_UNUSED(other);
#else
if (i == 0)
- return toolBarAreaLayout.unplug(path, other ? &other->toolBarAreaLayout : 0);
+ return toolBarAreaLayout.unplug(path.mid(1), other ? &other->toolBarAreaLayout : 0);
#endif
#ifndef QT_NO_DOCKWIDGET
if (i == 1)
- return dockAreaLayout.unplug(path);
+ return dockAreaLayout.unplug(path.mid(1));
#endif //QT_NO_DOCKWIDGET
return 0;
@@ -939,16 +939,70 @@ void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar
void QMainWindowLayout::toggleToolBarsVisible()
{
- layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
- if (!layoutState.mainWindow->isMaximized()){
- QPoint topLeft = parentWidget()->geometry().topLeft();
- QRect r = parentWidget()->geometry();
- r = layoutState.toolBarAreaLayout.rectHint(r);
- r.moveTo(topLeft);
- parentWidget()->setGeometry(r);
-// widgetAnimator->animate(parentWidget(), r, true);
- } else{
- update();
+ bool updateNonUnifiedParts = true;
+#ifdef Q_WS_MAC
+ if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
+ // If we hit this case, someone has pressed the "toolbar button" which will
+ // toggle the unified toolbar visiblity, because that's what the user wants.
+ // We might be in a situation where someone has hidden all the toolbars
+ // beforehand (maybe in construction), but now they've hit this button and
+ // and are expecting the items to show. What do we do?
+ // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this
+ // preserves what people would expect (these toolbars were visible when I clicked last time).
+ // 2) If NONE are visible, then show them all. Again, this preserves the user expectation
+ // of, "I want to see the toolbars." The user may get more toolbars than expected, but this
+ // is better seeing nothing.
+ // Don't worry about any of this if we are going invisible. This does mean we may get
+ // into issues when switching into and out of fullscreen mode, but this is probably minor.
+ // If we ever need to do hiding, that would have to be taken care of after the unified toolbar
+ // has finished hiding.
+ // People can of course handle the QEvent::ToolBarChange event themselves and do
+ // WHATEVER they want if they don't like what we are doing (though the unified toolbar
+ // will fire regardless).
+
+ // Check if we REALLY need to update the geometry below. If we only have items in the
+ // unified toolbar, all the docks will be empty, so there's very little point
+ // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well).
+ // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar
+ // visibility can get out of sync. I really don't think it's a big issue. It is kept
+ // to a minimum because we only change the visibility if we absolutely must.
+ // update the "non unified parts."
+ updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty();
+
+ // We get this function before the unified toolbar does its thing.
+ // So, the value will be opposite of what we expect.
+ bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow));
+ if (goingVisible) {
+ const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size();
+ bool needAllVisible = true;
+ for (int i = 0; i < ToolBarCount; ++i) {
+ if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) {
+ needAllVisible = false;
+ break;
+ }
+ }
+ if (needAllVisible) {
+ QBoolBlocker blocker(blockVisiblityCheck); // Disable the visibilty check because
+ // the toggle has already happened.
+ for (int i = 0; i < ToolBarCount; ++i)
+ qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true);
+ }
+ }
+ if (!updateNonUnifiedParts)
+ layoutState.toolBarAreaLayout.visible = goingVisible;
+ }
+#endif
+ if (updateNonUnifiedParts) {
+ layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
+ if (!layoutState.mainWindow->isMaximized()) {
+ QPoint topLeft = parentWidget()->geometry().topLeft();
+ QRect r = parentWidget()->geometry();
+ r = layoutState.toolBarAreaLayout.rectHint(r);
+ r.moveTo(topLeft);
+ parentWidget()->setGeometry(r);
+ } else {
+ update();
+ }
}
}
@@ -1304,30 +1358,15 @@ bool QMainWindowLayout::separatorMove(const QPoint &pos)
if (movingSeparator.isEmpty())
return false;
movingSeparatorPos = pos;
- separatorMoveTimer->start();
+ separatorMoveTimer.start(0, this);
return true;
}
-void QMainWindowLayout::doSeparatorMove()
-{
- if (movingSeparator.isEmpty())
- return;
- if (movingSeparatorOrigin == movingSeparatorPos)
- return;
-
- layoutState = savedState;
- layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin,
- movingSeparatorPos,
- &separatorMoveCache);
- movingSeparatorPos = movingSeparatorOrigin;
-}
-
bool QMainWindowLayout::endSeparatorMove(const QPoint&)
{
bool result = !movingSeparator.isEmpty();
movingSeparator.clear();
savedState.clear();
- separatorMoveCache.clear();
return result;
}
@@ -1376,7 +1415,7 @@ QLayoutItem *QMainWindowLayout::takeAt(int index)
if (QLayoutItem *ret = layoutState.takeAt(index, &x)) {
// the widget might in fact have been destroyed by now
if (QWidget *w = ret->widget()) {
- widgetAnimator->abort(w);
+ widgetAnimator.abort(w);
if (w == pluggingWidget)
pluggingWidget = 0;
}
@@ -1424,7 +1463,7 @@ void QMainWindowLayout::setGeometry(const QRect &_r)
QSize(r.width(), statusbar->heightForWidth(r.width()))
.expandedTo(statusbar->minimumSize()));
sbr.moveBottom(r.bottom());
- QRect vr = QStyle::visualRect(QApplication::layoutDirection(), _r, sbr);
+ QRect vr = QStyle::visualRect(parentWidget()->layoutDirection(), _r, sbr);
statusbar->setGeometry(vr);
r.setBottom(sbr.top() - 1);
}
@@ -1543,75 +1582,28 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
layoutState.remove(previousPath);
pluggingWidget = widget;
- if (dockOptions & QMainWindow::AnimatedDocks) {
- QRect globalRect = currentGapRect;
- globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));
+ QRect globalRect = currentGapRect;
+ globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));
#ifndef QT_NO_DOCKWIDGET
- if (qobject_cast<QDockWidget*>(widget) != 0) {
- QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout());
- if (layout->nativeWindowDeco()) {
- globalRect.adjust(0, layout->titleHeight(), 0, 0);
- } else {
- int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, widget);
- globalRect.adjust(-fw, -fw, fw, fw);
- }
+ if (qobject_cast<QDockWidget*>(widget) != 0) {
+ QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout());
+ if (layout->nativeWindowDeco()) {
+ globalRect.adjust(0, layout->titleHeight(), 0, 0);
+ } else {
+ int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, widget);
+ globalRect.adjust(-fw, -fw, fw, fw);
}
-#endif
- widgetAnimator->animate(widget, globalRect,
- dockOptions & QMainWindow::AnimatedDocks);
- } else {
-#ifndef QT_NO_DOCKWIDGET
- if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
- dw->d_func()->plug(currentGapRect);
-#endif
-#ifndef QT_NO_TOOLBAR
- if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
- tb->d_func()->plug(currentGapRect);
-#endif
- applyState(layoutState);
- savedState.clear();
-#ifndef QT_NO_DOCKWIDGET
- parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
-#endif
- currentGapPos.clear();
- updateGapIndicator();
- pluggingWidget = 0;
}
+#endif
+ widgetAnimator.animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks);
return true;
}
-void QMainWindowLayout::allAnimationsFinished()
-{
-#ifndef QT_NO_DOCKWIDGET
- parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
-
-#ifndef QT_NO_TABBAR
- foreach (QTabBar *tab_bar, usedTabBars)
- tab_bar->show();
-#endif // QT_NO_TABBAR
-#endif // QT_NO_DOCKWIDGET
-
- updateGapIndicator();
-}
-
void QMainWindowLayout::animationFinished(QWidget *widget)
{
-
- /* This signal is delivered from QWidgetAnimator over a qeued connection. The problem is that
- the widget can be deleted. This is handled as follows:
-
- The animator only ever animates widgets that have been added to this layout. If a widget
- is deleted during animation, the widget's destructor removes the widget form this layout.
- This in turn aborts the animation (see takeAt()) and this signal will never be delivered.
-
- If the widget is deleted after the animation is finished but before this qeued signal
- is delivered, the widget is no longer in the layout and we catch it here. The key is that
- QMainWindowLayoutState::contains() never dereferences the pointer. */
-
- if (!layoutState.contains(widget))
- return;
-
+ //this function is called from within the Widget Animator whenever an animation is finished
+ //on a certain widget
#ifndef QT_NO_TOOLBAR
if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout());
@@ -1624,32 +1616,44 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
}
#endif
- if (widget != pluggingWidget)
- return;
+ if (widget == pluggingWidget) {
#ifndef QT_NO_DOCKWIDGET
- if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
- dw->d_func()->plug(currentGapRect);
+ if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
+ dw->d_func()->plug(currentGapRect);
#endif
#ifndef QT_NO_TOOLBAR
- if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
- tb->d_func()->plug(currentGapRect);
+ if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
+ tb->d_func()->plug(currentGapRect);
#endif
- applyState(layoutState, false);
#ifndef QT_NO_DOCKWIDGET
#ifndef QT_NO_TABBAR
- if (qobject_cast<QDockWidget*>(widget) != 0) {
- // info() might return null if the widget is destroyed while
- // animating but before the animationFinished signal is received.
- if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget))
- info->setCurrentTab(widget);
- }
+ if (qobject_cast<QDockWidget*>(widget) != 0) {
+ // info() might return null if the widget is destroyed while
+ // animating but before the animationFinished signal is received.
+ if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget))
+ info->setCurrentTab(widget);
+ }
#endif
#endif
- savedState.clear();
- currentGapPos.clear();
- pluggingWidget = 0;
+
+ savedState.clear();
+ currentGapPos.clear();
+ pluggingWidget = 0;
+ }
+
+ if (!widgetAnimator.animating()) {
+ //all animations are finished
+#ifndef QT_NO_DOCKWIDGET
+ parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
+#ifndef QT_NO_TABBAR
+ foreach (QTabBar *tab_bar, usedTabBars)
+ tab_bar->show();
+#endif // QT_NO_TABBAR
+#endif // QT_NO_DOCKWIDGET
+ }
+
updateGapIndicator();
}
@@ -1682,15 +1686,19 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow)
#endif
#endif
#endif // QT_NO_DOCKWIDGET
+ , widgetAnimator(this)
+ , pluggingWidget(0)
+#ifndef QT_NO_RUBBERBAND
+ , gapIndicator(new QRubberBand(QRubberBand::Rectangle, mainwindow))
+#endif //QT_NO_RUBBERBAND
+#ifdef Q_WS_MAC
+ , blockVisiblityCheck(false)
+#endif
{
#ifndef QT_NO_DOCKWIDGET
#ifndef QT_NO_TABBAR
sep = mainwindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainwindow);
#endif
- separatorMoveTimer = new QTimer(this);
- separatorMoveTimer->setSingleShot(true);
- separatorMoveTimer->setInterval(0);
- connect(separatorMoveTimer, SIGNAL(timeout()), this, SLOT(doSeparatorMove()));
#ifndef QT_NO_TABWIDGET
for (int i = 0; i < QInternal::DockCount; ++i)
@@ -1699,20 +1707,13 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow)
#endif // QT_NO_DOCKWIDGET
#ifndef QT_NO_RUBBERBAND
- gapIndicator = new QRubberBand(QRubberBand::Rectangle, mainwindow);
// For accessibility to identify this special widget.
gapIndicator->setObjectName(QLatin1String("qt_rubberband"));
-
gapIndicator->hide();
#endif
pluggingWidget = 0;
setObjectName(mainwindow->objectName() + QLatin1String("_layout"));
- widgetAnimator = new QWidgetAnimator(this);
- connect(widgetAnimator, SIGNAL(finished(QWidget*)),
- this, SLOT(animationFinished(QWidget*)), Qt::QueuedConnection);
- connect(widgetAnimator, SIGNAL(finishedAll()),
- this, SLOT(allAnimationsFinished()));
}
QMainWindowLayout::~QMainWindowLayout()
@@ -1814,14 +1815,8 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget)
void QMainWindowLayout::updateGapIndicator()
{
#ifndef QT_NO_RUBBERBAND
- if (widgetAnimator->animating() || currentGapPos.isEmpty()) {
- gapIndicator->hide();
- } else {
- if (gapIndicator->geometry() != currentGapRect)
- gapIndicator->setGeometry(currentGapRect);
- if (!gapIndicator->isVisible())
- gapIndicator->show();
- }
+ gapIndicator->setVisible(!widgetAnimator.animating() && !currentGapPos.isEmpty());
+ gapIndicator->setGeometry(currentGapRect);
#endif
}
@@ -1982,6 +1977,30 @@ bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const
#endif
}
+void QMainWindowLayout::timerEvent(QTimerEvent *e)
+{
+#ifndef QT_NO_DOCKWIDGET
+ if (e->timerId() == separatorMoveTimer.timerId()) {
+ //let's move the separators
+ separatorMoveTimer.stop();
+ if (movingSeparator.isEmpty())
+ return;
+ if (movingSeparatorOrigin == movingSeparatorPos)
+ return;
+
+ //when moving the separator, we need to update the previous position
+ parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
+
+ layoutState = savedState;
+ layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin,
+ movingSeparatorPos);
+ movingSeparatorPos = movingSeparatorOrigin;
+ }
+#endif
+ QLayout::timerEvent(e);
+}
+
+
QT_END_NAMESPACE
#endif // QT_NO_MAINWINDOW
diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm
index f093165..2ccd3e7 100644
--- a/src/gui/widgets/qmainwindowlayout_mac.mm
+++ b/src/gui/widgets/qmainwindowlayout_mac.mm
@@ -329,29 +329,25 @@ OSStatus QMainWindowLayout::qtmacToolbarDelegate(EventHandlerCallRef, EventRef e
void QMainWindowLayout::updateHIToolBarStatus()
{
bool useMacToolbar = layoutState.mainWindow->unifiedTitleAndToolBarOnMac();
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
#ifndef QT_MAC_USE_COCOA
- if (useMacToolbar) {
- ChangeWindowAttributes(qt_mac_window_for(layoutState.mainWindow),
- kWindowUnifiedTitleAndToolbarAttribute, 0);
- } else {
- ChangeWindowAttributes(qt_mac_window_for(layoutState.mainWindow),
- 0, kWindowUnifiedTitleAndToolbarAttribute);
- }
-#endif
- macWindowToolbarShow(layoutState.mainWindow, useMacToolbar);
+ if (useMacToolbar) {
+ ChangeWindowAttributes(qt_mac_window_for(layoutState.mainWindow),
+ kWindowUnifiedTitleAndToolbarAttribute, 0);
+ } else {
+ ChangeWindowAttributes(qt_mac_window_for(layoutState.mainWindow),
+ 0, kWindowUnifiedTitleAndToolbarAttribute);
}
+#endif
layoutState.mainWindow->setUpdatesEnabled(false); // reduces a little bit of flicker, not all though
if (!useMacToolbar) {
- OSWindowRef windowRef = qt_mac_window_for(parentWidget());
- macWindowToolbarShow(parentWidget(), false);
+ macWindowToolbarShow(layoutState.mainWindow, false);
// Move everything out of the HIToolbar into the main toolbar.
while (!qtoolbarsInUnifiedToolbarList.isEmpty()) {
// Should shrink the list by one every time.
layoutState.mainWindow->addToolBar(Qt::TopToolBarArea, qtoolbarsInUnifiedToolbarList.first());
}
- macWindowToolbarSet(windowRef, NULL);
+ macWindowToolbarSet(qt_mac_window_for(layoutState.mainWindow), 0);
} else {
QList<QToolBar *> toolbars = layoutState.mainWindow->findChildren<QToolBar *>();
for (int i = 0; i < toolbars.size(); ++i) {
@@ -361,6 +357,7 @@ void QMainWindowLayout::updateHIToolBarStatus()
layoutState.mainWindow->addToolBar(Qt::TopToolBarArea, toolbar);
}
}
+ syncUnifiedToolbarVisibility();
}
layoutState.mainWindow->setUpdatesEnabled(true);
}
@@ -441,7 +438,7 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar
#else
NSString *toolbarID = kQToolBarNSToolbarIdentifier;
toolbarID = [toolbarID stringByAppendingFormat:@"%p", toolbar];
- cocoaItemIDToToolbarHash.insert(QCFString::toQString(CFStringRef(toolbarID)), toolbar);
+ cocoaItemIDToToolbarHash.insert(qt_mac_NSStringToQString(toolbarID), toolbar);
[macToolbar insertItemWithItemIdentifier:toolbarID atIndex:beforeIndex];
#endif
}
@@ -489,6 +486,7 @@ void QMainWindowLayout::cleanUpMacToolbarItems()
void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const
{
+#ifdef QT_MAC_USE_COCOA
QHash<void *, QToolBar *>::const_iterator it = unifiedToolbarHash.constBegin();
NSToolbarItem *item = nil;
while (it != unifiedToolbarHash.constEnd()) {
@@ -502,12 +500,33 @@ void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const
QMacCocoaAutoReleasePool pool;
QWidgetItem layoutItem(tb);
QSize size = layoutItem.maximumSize();
- NSSize nssize = NSMakeSize(size.width(), size.height());
+ NSSize nssize = NSMakeSize(size.width(), size.height() - 2);
[item setMaxSize:nssize];
size = layoutItem.minimumSize();
nssize.width = size.width();
- nssize.height = size.height();
+ nssize.height = size.height() - 2;
[item setMinSize:nssize];
}
+#else
+ Q_UNUSED(tb);
+#endif
}
+
+void QMainWindowLayout::syncUnifiedToolbarVisibility()
+{
+ if (blockVisiblityCheck)
+ return;
+
+ Q_ASSERT(layoutState.mainWindow->unifiedTitleAndToolBarOnMac());
+ bool show = false;
+ const int ToolBarCount = qtoolbarsInUnifiedToolbarList.count();
+ for (int i = 0; i < ToolBarCount; ++i) {
+ if (qtoolbarsInUnifiedToolbarList.at(i)->isVisible()) {
+ show = true;
+ break;
+ }
+ }
+ macWindowToolbarShow(layoutState.mainWindow, show);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h
index ba241e3..f1f758c 100644
--- a/src/gui/widgets/qmainwindowlayout_p.h
+++ b/src/gui/widgets/qmainwindowlayout_p.h
@@ -61,7 +61,9 @@
#include "QtGui/qtabbar.h"
#include "QtCore/qvector.h"
#include "QtCore/qset.h"
+#include "QtCore/qbasictimer.h"
#include "private/qlayoutengine_p.h"
+#include "private/qwidgetanimator_p.h"
#include "qdockarealayout_p.h"
#include "qtoolbararealayout_p.h"
@@ -88,7 +90,6 @@ typedef const struct __CFString * CFStringRef;
QT_BEGIN_NAMESPACE
class QToolBar;
-class QWidgetAnimator;
class QRubberBand;
/* This data structure represents the state of all the tool-bars and dock-widgets. It's value based
@@ -127,9 +128,9 @@ public:
QLayoutItem *itemAt(int index, int *x) const;
QLayoutItem *takeAt(int index, int *x);
QList<int> indexOf(QWidget *widget) const;
- QLayoutItem *item(QList<int> path);
- QRect itemRect(QList<int> path) const;
- QRect gapRect(QList<int> path) const; // ### get rid of this, use itemRect() instead
+ QLayoutItem *item(const QList<int> &path);
+ QRect itemRect(const QList<int> &path) const;
+ QRect gapRect(const QList<int> &path) const; // ### get rid of this, use itemRect() instead
bool contains(QWidget *widget) const;
@@ -137,14 +138,14 @@ public:
QWidget *centralWidget() const;
QList<int> gapIndex(QWidget *widget, const QPoint &pos) const;
- bool insertGap(QList<int> path, QLayoutItem *item);
- void remove(QList<int> path);
+ bool insertGap(const QList<int> &path, QLayoutItem *item);
+ void remove(const QList<int> &path);
void remove(QLayoutItem *item);
void clear();
bool isValid() const;
- QLayoutItem *plug(QList<int> path);
- QLayoutItem *unplug(QList<int> path, QMainWindowLayoutState *savedState = 0);
+ QLayoutItem *plug(const QList<int> &path);
+ QLayoutItem *unplug(const QList<int> &path, QMainWindowLayoutState *savedState = 0);
void saveState(QDataStream &stream) const;
bool checkFormat(QDataStream &stream, bool pre43);
@@ -165,6 +166,8 @@ public:
void setDockOptions(QMainWindow::DockOptions opts);
bool usesHIToolBar(QToolBar *toolbar) const;
+ void timerEvent(QTimerEvent *e);
+
// status bar
QLayoutItem *statusbar;
@@ -243,8 +246,7 @@ public:
QList<int> movingSeparator;
QPoint movingSeparatorOrigin, movingSeparatorPos;
- QTimer *separatorMoveTimer;
- QVector<QLayoutStruct> separatorMoveCache;
+ QBasicTimer separatorMoveTimer;
bool startSeparatorMove(const QPoint &pos);
bool separatorMove(const QPoint &pos);
@@ -276,7 +278,7 @@ public:
// animations
- QWidgetAnimator *widgetAnimator;
+ QWidgetAnimator widgetAnimator;
QList<int> currentGapPos;
QRect currentGapRect;
QWidget *pluggingWidget;
@@ -293,12 +295,10 @@ public:
void applyState(QMainWindowLayoutState &newState, bool animate = true);
void restore(bool keepSavedState = false);
void updateHIToolBarStatus();
-
-private slots:
void animationFinished(QWidget *widget);
- void allAnimationsFinished();
+
+private Q_SLOTS:
#ifndef QT_NO_DOCKWIDGET
- void doSeparatorMove();
#ifndef QT_NO_TABBAR
void tabChanged();
#endif
@@ -335,40 +335,12 @@ public:
void cleanUpMacToolbarItems();
void fixSizeInUnifiedToolbar(QToolBar *tb) const;
bool useHIToolBar;
+ void syncUnifiedToolbarVisibility();
+ bool blockVisiblityCheck;
#endif
};
QT_END_NAMESPACE
#endif // QT_NO_MAINWINDOW
-QT_BEGIN_NAMESPACE
-static inline int pick(Qt::Orientation o, const QPoint &pos)
-{ return o == Qt::Horizontal ? pos.x() : pos.y(); }
-
-static inline int pick(Qt::Orientation o, const QSize &size)
-{ return o == Qt::Horizontal ? size.width() : size.height(); }
-
-static inline int &rpick(Qt::Orientation o, QPoint &pos)
-{ return o == Qt::Horizontal ? pos.rx() : pos.ry(); }
-
-static inline int &rpick(Qt::Orientation o, QSize &size)
-{ return o == Qt::Horizontal ? size.rwidth() : size.rheight(); }
-
-static inline QSizePolicy::Policy pick(Qt::Orientation o, const QSizePolicy &policy)
-{ return o == Qt::Horizontal ? policy.horizontalPolicy() : policy.verticalPolicy(); }
-
-static inline int perp(Qt::Orientation o, const QPoint &pos)
-{ return o == Qt::Vertical ? pos.x() : pos.y(); }
-
-static inline int perp(Qt::Orientation o, const QSize &size)
-{ return o == Qt::Vertical ? size.width() : size.height(); }
-
-static inline int &rperp(Qt::Orientation o, QPoint &pos)
-{ return o == Qt::Vertical ? pos.rx() : pos.ry(); }
-
-static inline int &rperp(Qt::Orientation o, QSize &size)
-{ return o == Qt::Vertical ? size.rwidth() : size.rheight(); }
-
-QT_END_NAMESPACE
-
#endif // QDYNAMICMAINWINDOWLAYOUT_P_H
diff --git a/src/gui/widgets/qmdiarea.cpp b/src/gui/widgets/qmdiarea.cpp
index aa0d7b0..6a17b71 100644
--- a/src/gui/widgets/qmdiarea.cpp
+++ b/src/gui/widgets/qmdiarea.cpp
@@ -43,8 +43,8 @@
\class QMdiArea
\brief The QMdiArea widget provides an area in which MDI windows are displayed.
\since 4.3
- \ingroup application
- \mainclass
+ \ingroup mainwindow-classes
+
QMdiArea functions, essentially, like a window manager for MDI
windows. For instance, it draws the windows it manages on itself
@@ -800,12 +800,12 @@ void QMdiAreaPrivate::appendChild(QMdiSubWindow *child)
Q_Q(QMdiArea);
Q_ASSERT(child && childWindows.indexOf(child) == -1);
- if (child->parent() != q->viewport())
- child->setParent(q->viewport(), child->windowFlags());
+ if (child->parent() != viewport)
+ child->setParent(viewport, child->windowFlags());
childWindows.append(QPointer<QMdiSubWindow>(child));
if (!child->testAttribute(Qt::WA_Resized) && q->isVisible()) {
- QSize newSize(child->sizeHint().boundedTo(q->viewport()->size()));
+ QSize newSize(child->sizeHint().boundedTo(viewport->size()));
child->resize(newSize.expandedTo(qSmartMinSize(child)));
}
@@ -931,7 +931,7 @@ void QMdiAreaPrivate::rearrange(Rearranger *rearranger)
widgets.move(indexToActive, 0);
}
- QRect domain = q->viewport()->rect();
+ QRect domain = viewport->rect();
if (rearranger->type() == Rearranger::RegularTiler && !widgets.isEmpty())
domain = resizeToMinimumTileSize(minSubWindowSize, widgets.count());
@@ -1212,7 +1212,7 @@ void QMdiAreaPrivate::internalRaise(QMdiSubWindow *mdiChild) const
QMdiSubWindow *stackUnderChild = 0;
if (!windowStaysOnTop(mdiChild)) {
- foreach (QObject *object, q_func()->viewport()->children()) {
+ foreach (QObject *object, viewport->children()) {
QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(object);
if (!child || !childWindows.contains(child))
continue;
@@ -1236,7 +1236,7 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
{
Q_Q(QMdiArea);
if (!minSubWindowSize.isValid() || subWindowCount <= 0)
- return q->viewport()->rect();
+ return viewport->rect();
// Calculate minimum size.
const int columns = qMax(qCeil(qSqrt(qreal(subWindowCount))), 1);
@@ -1255,10 +1255,10 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
// We don't want sub-subwindows to be placed at the edge, thus add 2 pixels.
int minAreaWidth = minWidth + left + right + 2;
int minAreaHeight = minHeight + top + bottom + 2;
- if (q->horizontalScrollBar()->isVisible())
- minAreaHeight += q->horizontalScrollBar()->height();
- if (q->verticalScrollBar()->isVisible())
- minAreaWidth += q->verticalScrollBar()->width();
+ if (hbar->isVisible())
+ minAreaHeight += hbar->height();
+ if (vbar->isVisible())
+ minAreaWidth += vbar->width();
if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, q)) {
const int frame = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, q);
minAreaWidth += 2 * frame;
@@ -1268,23 +1268,23 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
topLevel->resize(topLevel->size() + diff);
}
- QRect domain = q->viewport()->rect();
+ QRect domain = viewport->rect();
// Adjust domain width and provide horizontal scroll bar.
if (domain.width() < minWidth) {
domain.setWidth(minWidth);
- if (q->horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
+ if (hbarpolicy == Qt::ScrollBarAlwaysOff)
q->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- else if (q->horizontalScrollBar()->value() != 0)
- q->horizontalScrollBar()->setValue(0);
+ else
+ hbar->setValue(0);
}
// Adjust domain height and provide vertical scroll bar.
if (domain.height() < minHeight) {
domain.setHeight(minHeight);
- if (q->verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
+ if (vbarpolicy == Qt::ScrollBarAlwaysOff)
q->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- else if (q->verticalScrollBar()->value() != 0)
- q->verticalScrollBar()->setValue(0);
+ else
+ vbar->setValue(0);
}
return domain;
}
diff --git a/src/gui/widgets/qmdisubwindow.cpp b/src/gui/widgets/qmdisubwindow.cpp
index 2307015..a35ccdd 100644
--- a/src/gui/widgets/qmdisubwindow.cpp
+++ b/src/gui/widgets/qmdisubwindow.cpp
@@ -44,8 +44,8 @@
\brief The QMdiSubWindow class provides a subwindow class for
QMdiArea.
\since 4.3
- \ingroup application
- \mainclass
+ \ingroup mainwindow-classes
+
QMdiSubWindow represents a top-level window in a QMdiArea, and consists
of a title bar with window decorations, an internal widget, and
@@ -1006,7 +1006,7 @@ void QMdiSubWindowPrivate::removeBaseWidget()
Q_Q(QMdiSubWindow);
baseWidget->removeEventFilter(q);
- if (QLayout *layout = q->layout())
+ if (layout)
layout->removeWidget(baseWidget);
if (baseWidget->windowTitle() == q->windowTitle()) {
ignoreWindowTitleChange = true;
@@ -1066,7 +1066,7 @@ void QMdiSubWindowPrivate::createSystemMenu()
addToSystemMenu(CloseAction, QMdiSubWindow::tr("&Close"), SLOT(close()));
actions[CloseAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarCloseButton, 0, q));
#if !defined(QT_NO_SHORTCUT)
- actions[CloseAction]->setShortcut(QKeySequence::Close);
+ actions[CloseAction]->setShortcuts(QKeySequence::Close);
#endif
updateActions();
}
@@ -1102,7 +1102,7 @@ void QMdiSubWindowPrivate::updateCursor()
void QMdiSubWindowPrivate::updateDirtyRegions()
{
// No update necessary
- if (!q_func()->parent())
+ if (!parent)
return;
foreach (Operation operation, operationMap.keys())
@@ -1115,7 +1115,7 @@ void QMdiSubWindowPrivate::updateDirtyRegions()
void QMdiSubWindowPrivate::updateGeometryConstraints()
{
Q_Q(QMdiSubWindow);
- if (!q->parent())
+ if (!parent)
return;
internalMinimumSize = (!q->isMinimized() && !q->minimumSize().isNull())
@@ -1145,7 +1145,7 @@ void QMdiSubWindowPrivate::updateMask()
if (!q->mask().isEmpty())
q->clearMask();
- if (!q->parent())
+ if (!parent)
return;
if ((q->isMaximized() && !drawTitleBarWhenMaximized())
@@ -1168,7 +1168,7 @@ void QMdiSubWindowPrivate::setNewGeometry(const QPoint &pos)
{
Q_Q(QMdiSubWindow);
Q_ASSERT(currentOperation != None);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
uint cflags = operationMap.find(currentOperation).value().changeFlags;
int posX = pos.x();
@@ -1235,7 +1235,7 @@ void QMdiSubWindowPrivate::setNewGeometry(const QPoint &pos)
void QMdiSubWindowPrivate::setMinimizeMode()
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
ensureWindowState(Qt::WindowMinimized);
isShadeRequestFromMinimizeMode = true;
@@ -1263,7 +1263,7 @@ void QMdiSubWindowPrivate::setMinimizeMode()
void QMdiSubWindowPrivate::setNormalMode()
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
isShadeMode = false;
isMaximizeMode = false;
@@ -1334,7 +1334,7 @@ void QMdiSubWindowPrivate::setNormalMode()
void QMdiSubWindowPrivate::setMaximizeMode()
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
ensureWindowState(Qt::WindowMaximized);
isShadeMode = false;
@@ -1423,7 +1423,7 @@ void QMdiSubWindowPrivate::setMaximizeMode()
void QMdiSubWindowPrivate::setActive(bool activate, bool changeFocus)
{
Q_Q(QMdiSubWindow);
- if (!q->parent() || !activationEnabled)
+ if (!parent || !activationEnabled)
return;
if (activate && !isActive && q->isEnabled()) {
@@ -1711,7 +1711,7 @@ void QMdiSubWindowPrivate::ensureWindowState(Qt::WindowState state)
int QMdiSubWindowPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
{
Q_Q(const QMdiSubWindow);
- if (!q->parent() || q->windowFlags() & Qt::FramelessWindowHint
+ if (!parent || q->windowFlags() & Qt::FramelessWindowHint
|| (q->isMaximized() && !drawTitleBarWhenMaximized())) {
return 0;
}
@@ -1734,7 +1734,7 @@ void QMdiSubWindowPrivate::sizeParameters(int *margin, int *minWidth) const
{
Q_Q(const QMdiSubWindow);
Qt::WindowFlags flags = q->windowFlags();
- if (!q->parent() || flags & Qt::FramelessWindowHint) {
+ if (!parent || flags & Qt::FramelessWindowHint) {
*margin = 0;
*minWidth = 0;
return;
@@ -1772,7 +1772,7 @@ bool QMdiSubWindowPrivate::drawTitleBarWhenMaximized() const
if (isChildOfTabbedQMdiArea(q))
return false;
-#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) || defined(Q_OS_WINCE_WM)
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) || defined(Q_WS_WINCE_WM)
return true;
#else
if (q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q))
@@ -1893,7 +1893,7 @@ void QMdiSubWindowPrivate::enterRubberBandMode()
if (q->isMaximized())
return;
Q_ASSERT(oldGeometry.isValid());
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
if (!rubberBand) {
rubberBand = new QRubberBand(QRubberBand::Rectangle, q->parentWidget());
// For accessibility to identify this special widget.
@@ -1946,26 +1946,21 @@ QPalette QMdiSubWindowPrivate::desktopPalette() const
colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)));
newPalette.setColor(QPalette::Inactive, QPalette::HighlightedText,
colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)));
- if (QSysInfo::WindowsVersion != QSysInfo::WV_95
- && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
- colorsInitialized = true;
- BOOL hasGradient;
- QT_WA({
- SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &hasGradient, 0);
- } , {
- SystemParametersInfoA(SPI_GETGRADIENTCAPTIONS, 0, &hasGradient, 0);
- });
- if (hasGradient) {
- newPalette.setColor(QPalette::Active, QPalette::Base,
- colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)));
- newPalette.setColor(QPalette::Inactive, QPalette::Base,
- colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)));
- } else {
- newPalette.setColor(QPalette::Active, QPalette::Base,
- newPalette.color(QPalette::Active, QPalette::Highlight));
- newPalette.setColor(QPalette::Inactive, QPalette::Base,
- newPalette.color(QPalette::Inactive, QPalette::Highlight));
- }
+
+ colorsInitialized = true;
+ BOOL hasGradient = false;
+ SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &hasGradient, 0);
+
+ if (hasGradient) {
+ newPalette.setColor(QPalette::Active, QPalette::Base,
+ colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)));
+ newPalette.setColor(QPalette::Inactive, QPalette::Base,
+ colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)));
+ } else {
+ newPalette.setColor(QPalette::Active, QPalette::Base,
+ newPalette.color(QPalette::Active, QPalette::Highlight));
+ newPalette.setColor(QPalette::Inactive, QPalette::Base,
+ newPalette.color(QPalette::Inactive, QPalette::Highlight));
}
}
#endif // Q_WS_WIN
@@ -2079,7 +2074,7 @@ void QMdiSubWindowPrivate::restoreFocus()
void QMdiSubWindowPrivate::setWindowFlags(Qt::WindowFlags windowFlags)
{
Q_Q(QMdiSubWindow);
- if (!q->parent()) {
+ if (!parent) {
q->setWindowFlags(windowFlags);
return;
}
@@ -2164,7 +2159,7 @@ void QMdiSubWindowPrivate::addToSystemMenu(WindowStateAction action, const QStri
QSize QMdiSubWindowPrivate::iconSize() const
{
Q_Q(const QMdiSubWindow);
- if (!q->parent() || q->windowFlags() & Qt::FramelessWindowHint)
+ if (!parent || q->windowFlags() & Qt::FramelessWindowHint)
return QSize(-1, -1);
return QSize(q->style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth, 0, q), titleBarHeight());
}
@@ -2180,17 +2175,17 @@ void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip)
if (!newSizeGrip || sizeGrip || q->windowFlags() & Qt::FramelessWindowHint)
return;
- if (q->layout() && q->layout()->indexOf(newSizeGrip) != -1)
+ if (layout && layout->indexOf(newSizeGrip) != -1)
return;
newSizeGrip->setFixedSize(newSizeGrip->sizeHint());
- bool putSizeGripInLayout = q->layout() ? true : false;
+ bool putSizeGripInLayout = layout ? true : false;
#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
if (qobject_cast<QMacStyle *>(q->style()))
putSizeGripInLayout = false;
#endif
if (putSizeGripInLayout) {
- q->layout()->addWidget(newSizeGrip);
- q->layout()->setAlignment(newSizeGrip, Qt::AlignBottom | Qt::AlignRight);
+ layout->addWidget(newSizeGrip);
+ layout->setAlignment(newSizeGrip, Qt::AlignBottom | Qt::AlignRight);
} else {
newSizeGrip->setParent(q);
newSizeGrip->move(q->isLeftToRight() ? q->width() - newSizeGrip->width() : 0,
diff --git a/src/gui/widgets/qmdisubwindow_p.h b/src/gui/widgets/qmdisubwindow_p.h
index e8bbf02..6ee20d8 100644
--- a/src/gui/widgets/qmdisubwindow_p.h
+++ b/src/gui/widgets/qmdisubwindow_p.h
@@ -287,7 +287,7 @@ public:
inline int titleBarHeight() const
{
Q_Q(const QMdiSubWindow);
- if (!q->parent() || q->windowFlags() & Qt::FramelessWindowHint
+ if (!parent || q->windowFlags() & Qt::FramelessWindowHint
|| (q->isMaximized() && !drawTitleBarWhenMaximized())) {
return 0;
}
@@ -308,7 +308,7 @@ public:
inline void setNewGeometry(QRect *geometry)
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
geometry->setSize(geometry->size().expandedTo(internalMinimumSize));
#ifndef QT_NO_RUBBERBAND
if (isInRubberBandMode)
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 7e87ee1..ee1ec6f 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -60,6 +60,7 @@
#ifndef QT_NO_WHATSTHIS
# include <qwhatsthis.h>
#endif
+#include <private/qactiontokeyeventmapper_p.h>
#include "qmenu_p.h"
#include "qmenubar_p.h"
@@ -150,7 +151,6 @@ private:
void QMenuPrivate::init()
{
Q_Q(QMenu);
- activationRecursionGuard = false;
#ifndef QT_NO_WHATSTHIS
q->setAttribute(Qt::WA_CustomWhatsThis);
#endif
@@ -164,6 +164,12 @@ void QMenuPrivate::init()
}
}
+int QMenuPrivate::scrollerHeight() const
+{
+ Q_Q(const QMenu);
+ return qMax(QApplication::globalStrut().height(), q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q));
+}
+
//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't
QRect QMenuPrivate::popupGeometry(int screen) const
{
@@ -194,57 +200,85 @@ QList<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const
return ret;
}
-void QMenuPrivate::calcActionRects(QMap<QAction*, QRect> &actionRects, QList<QAction*> &actionList) const
+void QMenuPrivate::updateActionRects() const
{
Q_Q(const QMenu);
- if (!itemsDirty) {
- actionRects = this->actionRects;
- actionList = this->actionList;
+ if (!itemsDirty)
return;
+
+ q->ensurePolished();
+
+ //let's reinitialize the buffer
+ actionRects.resize(actions.count());
+ actionRects.fill(QRect());
+
+ //let's try to get the last visible action
+ int lastVisibleAction = actions.count() - 1;
+ for(;lastVisibleAction >= 0; --lastVisibleAction) {
+ const QAction *action = actions.at(lastVisibleAction);
+ if (action->isVisible()) {
+ //removing trailing separators
+ if (action->isSeparator() && collapsibleSeparators)
+ continue;
+ break;
+ }
}
- actionRects.clear();
- actionList.clear();
- QList<QAction*> items = filterActions(q->actions());
int max_column_width = 0,
dh = popupGeometry(QApplication::desktop()->screenNumber(q)).height(),
- ncols = 1,
y = 0;
- const int hmargin = q->style()->pixelMetric(QStyle::PM_MenuHMargin, 0, q),
- vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q),
- icone = q->style()->pixelMetric(QStyle::PM_SmallIconSize, 0, q);
+ QStyle *style = q->style();
+ QStyleOption opt;
+ opt.init(q);
+ const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q),
+ vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q),
+ icone = style->pixelMetric(QStyle::PM_SmallIconSize, &opt, q);
+ const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
+ const int deskFw = style->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, &opt, q);
+
+ const int sfcMargin = style->sizeFromContents(QStyle::CT_Menu, &opt, QApplication::globalStrut(), q).width() - QApplication::globalStrut().width();
+ const int min_column_width = q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin));
+ const int tearoffHeight = tearoff ? style->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, q) : 0;
//for compatability now - will have to refactor this away..
tabWidth = 0;
maxIconWidth = 0;
hasCheckableItems = false;
- for(int i = 0; i < items.count(); i++) {
- QAction *action = items.at(i);
- if (widgetItems.value(action))
+ ncols = 1;
+ sloppyAction = 0;
+
+ for (int i = 0; i < actions.count(); ++i) {
+ QAction *action = actions.at(i);
+ if (action->isSeparator() || !action->isVisible() || widgetItems.at(i))
continue;
+ //..and some members
hasCheckableItems |= action->isCheckable();
QIcon is = action->icon();
if (!is.isNull()) {
- uint miw = maxIconWidth;
- maxIconWidth = qMax<uint>(miw, icone + 4);
+ maxIconWidth = qMax<uint>(maxIconWidth, icone + 4);
}
}
//calculate size
QFontMetrics qfm = q->fontMetrics();
- for(int i = 0; i < items.count(); i++) {
- QAction *action = items.at(i);
+ bool previousWasSeparator = true; // this is true to allow removing the leading separators
+ for(int i = 0; i <= lastVisibleAction; i++) {
+ QAction *action = actions.at(i);
- QFontMetrics fm(action->font().resolve(q->font()));
- QSize sz;
+ if (!action->isVisible() ||
+ (collapsibleSeparators && previousWasSeparator && action->isSeparator()))
+ continue; // we continue, this action will get an empty QRect
+
+ previousWasSeparator = action->isSeparator();
//let the style modify the above size..
QStyleOptionMenuItem opt;
q->initStyleOption(&opt, action);
- opt.rect = q->rect();
+ const QFontMetrics &fm = opt.fontMetrics;
- if (QWidget *w = widgetItems.value(action)) {
- sz=w->sizeHint().expandedTo(w->minimumSize()).expandedTo(w->minimumSizeHint()).boundedTo(w->maximumSize());
+ QSize sz;
+ if (QWidget *w = widgetItems.at(i)) {
+ sz = w->sizeHint().expandedTo(w->minimumSize()).expandedTo(w->minimumSizeHint()).boundedTo(w->maximumSize());
} else {
//calc what I think the size is..
if (action->isSeparator()) {
@@ -262,10 +296,7 @@ void QMenuPrivate::calcActionRects(QMap<QAction*, QRect> &actionRects, QList<QAc
tabWidth = qMax(int(tabWidth), qfm.width(seq));
#endif
}
- int w = fm.boundingRect(QRect(), Qt::TextSingleLine, s).width();
- w -= s.count(QLatin1Char('&')) * fm.width(QLatin1Char('&'));
- w += s.count(QLatin1String("&&")) * fm.width(QLatin1Char('&'));
- sz.setWidth(w);
+ sz.setWidth(fm.boundingRect(QRect(), Qt::TextSingleLine | Qt::TextShowMnemonic, s).width());
sz.setHeight(qMax(fm.height(), qfm.height()));
QIcon is = action->icon();
@@ -275,132 +306,76 @@ void QMenuPrivate::calcActionRects(QMap<QAction*, QRect> &actionRects, QList<QAc
sz.setHeight(is_sz.height());
}
}
- sz = q->style()->sizeFromContents(QStyle::CT_MenuItem, &opt, sz, q);
+ sz = style->sizeFromContents(QStyle::CT_MenuItem, &opt, sz, q);
}
if (!sz.isEmpty()) {
- max_column_width = qMax(max_column_width, sz.width());
+ max_column_width = qMax(min_column_width, qMax(max_column_width, sz.width()));
//wrapping
if (!scroll &&
- y+sz.height()+vmargin > dh - (q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q) * 2)) {
+ y+sz.height()+vmargin > dh - (deskFw * 2)) {
ncols++;
y = vmargin;
}
y += sz.height();
- //append item
- actionRects.insert(action, QRect(0, 0, sz.width(), sz.height()));
- actionList.append(action);
+ //update the item
+ actionRects[i] = QRect(0, 0, sz.width(), sz.height());
}
}
- if (tabWidth)
- max_column_width += tabWidth; //finally add in the tab width
+ max_column_width += tabWidth; //finally add in the tab width
//calculate position
- int x = hmargin;
- y = vmargin;
-
- for(int i = 0; i < actionList.count(); i++) {
- QAction *action = actionList.at(i);
- QRect &rect = actionRects[action];
+ const int base_y = vmargin + fw + topmargin +
+ (scroll ? scroll->scrollOffset : 0) +
+ tearoffHeight;
+ int x = hmargin + fw + leftmargin;
+ y = base_y;
+
+ for(int i = 0; i < actions.count(); i++) {
+ QRect &rect = actionRects[i];
if (rect.isNull())
continue;
if (!scroll &&
- y+rect.height() > dh - (q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q) * 2)) {
- ncols--;
- if (ncols < 0)
- qWarning("QMenu: Column calculation mismatch (%d)", ncols);
+ y+rect.height() > dh - deskFw * 2) {
x += max_column_width + hmargin;
- y = vmargin;
+ y = base_y;
}
rect.translate(x, y); //move
rect.setWidth(max_column_width); //uniform width
- y += rect.height();
- }
-}
-void QMenuPrivate::updateActions()
-{
- Q_Q(const QMenu);
- if (!itemsDirty)
- return;
- sloppyAction = 0;
- calcActionRects(actionRects, actionList);
- for (QHash<QAction *, QWidget *>::ConstIterator item = widgetItems.constBegin(),
- end = widgetItems.constEnd(); item != end; ++item) {
- QAction *action = item.key();
- QWidget *widget = item.value();
- widget->setGeometry(actionRect(action));
- widget->setVisible(action->isVisible());
- }
- ncols = 1;
- int last_left = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q);
- if (!scroll) {
- for(int i = 0; i < actionList.count(); i++) {
- int left = actionRects.value(actionList.at(i)).left();
- if (left > last_left) {
- last_left = left;
- ncols++;
- }
+ //we need to update the widgets geometry
+ if (QWidget *widget = widgetItems.at(i)) {
+ widget->setGeometry(rect);
+ widget->setVisible(actions.at(i)->isVisible());
}
+
+ y += rect.height();
}
itemsDirty = 0;
}
-QList<QAction *> QMenuPrivate::filterActions(const QList<QAction *> &actions) const
+QRect QMenuPrivate::actionRect(QAction *act) const
{
- QList<QAction *> visibleActions;
- int i = 0;
- while (i < actions.count()) {
- QAction *action = actions.at(i);
- if (!action->isVisible()) {
- ++i;
- continue;
- }
- if (!action->isSeparator() || !collapsibleSeparators) {
- visibleActions.append(action);
- ++i;
- continue;
- }
+ int index = actions.indexOf(act);
+ if (index == -1)
+ return QRect();
- // no leading separators
- if (!visibleActions.isEmpty())
- visibleActions.append(action);
-
- // skip double/tripple/etc. separators
- while (i < actions.count()
- && (!actions.at(i)->isVisible() || actions.at(i)->isSeparator()))
- ++i;
- }
+ updateActionRects();
- if (collapsibleSeparators) {
- // remove trailing separators
- while (!visibleActions.isEmpty() && visibleActions.last()->isSeparator())
- visibleActions.removeLast();
- }
-
- return visibleActions;
+ //we found the action
+ return actionRects.at(index);
}
-QRect QMenuPrivate::actionRect(QAction *act) const
-{
- Q_Q(const QMenu);
- QRect ret = actionRects.value(act);
- if (ret.isNull())
- return ret;
- if (scroll)
- ret.translate(0, scroll->scrollOffset);
- if (tearoff)
- ret.translate(0, q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, q));
- const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q);
- ret.translate(fw+leftmargin, fw+topmargin);
- return ret;
-}
+#if defined(Q_WS_MAC)
+static const qreal MenuFadeTimeInSec = 0.150;
+#endif
void QMenuPrivate::hideUpToMenuBar()
{
Q_Q(QMenu);
+ bool fadeMenus = q->style()->styleHint(QStyle::SH_Menu_FadeOutOnHide);
if (!tornoff) {
QWidget *caused = causedPopup.widget;
hideMenu(q); //hide after getting causedPopup
@@ -415,8 +390,9 @@ void QMenuPrivate::hideUpToMenuBar()
if (QMenu *m = qobject_cast<QMenu*>(caused)) {
caused = m->d_func()->causedPopup.widget;
if (!m->d_func()->tornoff)
- hideMenu(m);
- m->d_func()->setCurrentAction(0);
+ hideMenu(m, fadeMenus);
+ if (!fadeMenus) // Mac doesn't clear the action until after hidden.
+ m->d_func()->setCurrentAction(0);
} else {
#ifndef QT_NO_TOOLBUTTON
if (qobject_cast<QToolButton*>(caused) == 0)
@@ -425,26 +401,32 @@ void QMenuPrivate::hideUpToMenuBar()
caused = 0;
}
}
+#if defined(Q_WS_MAC)
+ if (fadeMenus) {
+ QEventLoop eventLoop;
+ QTimer::singleShot(int(MenuFadeTimeInSec * 1000), &eventLoop, SLOT(quit()));
+ QMacWindowFader::currentFader()->performFade();
+ eventLoop.exec();
+ }
+#endif
}
setCurrentAction(0);
}
-void QMenuPrivate::hideMenu(QMenu *menu)
+void QMenuPrivate::hideMenu(QMenu *menu, bool justRegister)
{
if (!menu)
return;
-
#if !defined(QT_NO_EFFECTS)
menu->blockSignals(true);
aboutToHide = true;
// Flash item which is about to trigger (if any).
if (menu->style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)
- && currentAction && currentAction == actionAboutToTrigger) {
-
+ && currentAction && currentAction == actionAboutToTrigger
+ && menu->actions().contains(currentAction)) {
QEventLoop eventLoop;
QAction *activeAction = currentAction;
- // Deselect and wait 60 ms.
menu->setActiveAction(0);
QTimer::singleShot(60, &eventLoop, SLOT(quit()));
eventLoop.exec();
@@ -458,22 +440,24 @@ void QMenuPrivate::hideMenu(QMenu *menu)
// Fade out.
if (menu->style()->styleHint(QStyle::SH_Menu_FadeOutOnHide)) {
// ### Qt 4.4:
- // Should be something like: q->transitionWindow(Qt::FadeOutTransition, 150);
+ // Should be something like: q->transitionWindow(Qt::FadeOutTransition, MenuFadeTimeInSec);
// Hopefully we'll integrate qt/research/windowtransitions into main before 4.4.
// Talk to Richard, Trenton or Bjoern.
#if defined(Q_WS_MAC)
- macWindowFade(qt_mac_window_for(menu)); // FIXME - what is the default duration for view animations
+ if (justRegister) {
+ QMacWindowFader::currentFader()->setFadeDuration(MenuFadeTimeInSec);
+ QMacWindowFader::currentFader()->registerWindowToFade(menu);
+ } else {
+ macWindowFade(qt_mac_window_for(menu), MenuFadeTimeInSec);
+ }
- // Wait for the transition to complete.
- QEventLoop eventLoop;
- QTimer::singleShot(150, &eventLoop, SLOT(quit()));
- eventLoop.exec();
#endif // Q_WS_MAC
}
aboutToHide = false;
menu->blockSignals(false);
#endif // QT_NO_EFFECTS
- menu->hide();
+ if (!justRegister)
+ menu->hide();
}
void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst)
@@ -513,14 +497,17 @@ void QMenuPrivate::setSyncAction()
void QMenuPrivate::setFirstActionActive()
{
Q_Q(QMenu);
- const int scrollerHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q);
- for(int i = 0, saccum = 0; i < actionList.count(); i++) {
- QAction *act = actionList[i];
+ updateActionRects();
+ for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ const QRect &rect = actionRects.at(i);
+ if (rect.isNull())
+ continue;
if (scroll && scroll->scrollFlags & QMenuScroller::ScrollUp) {
- saccum -= actionRects.value(act).height();
- if (saccum > scroll->scrollOffset-scrollerHeight)
+ saccum -= rect.height();
+ if (saccum > scroll->scrollOffset - scrollerHeight())
continue;
}
+ QAction *act = actions.at(i);
if (!act->isSeparator() &&
(q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q)
|| act->isEnabled())) {
@@ -535,10 +522,12 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
{
Q_Q(QMenu);
tearoffHighlighted = 0;
- if (action == currentAction && !(action && action->menu() && action->menu() != activeMenu)) {
- if(QMenu *menu = qobject_cast<QMenu*>(causedPopup.widget)) {
- if(causedPopup.action && menu->d_func()->activeMenu == q)
- menu->d_func()->setCurrentAction(causedPopup.action, 0, reason, false);
+ if (action == currentAction) {
+ if (!action || !action->menu() || action->menu() == activeMenu) {
+ if(QMenu *menu = qobject_cast<QMenu*>(causedPopup.widget)) {
+ if(causedPopup.action && menu->d_func()->activeMenu == q)
+ menu->d_func()->setCurrentAction(causedPopup.action, 0, reason, false);
+ }
}
return;
}
@@ -553,7 +542,7 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
QAction *previousAction = currentAction;
#endif
#ifdef QT3_SUPPORT
- emitHighlighted = (action && action != currentAction);
+ emitHighlighted = action;
#endif
currentAction = action;
if (action) {
@@ -568,9 +557,10 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
popupAction(currentAction, popup, activateFirst);
}
q->update(actionRect(action));
- QWidget *widget = widgetItems.value(action);
if (reason == SelectedFromKeyboard) {
+ const int actionIndex = actions.indexOf(action);
+ QWidget *widget = widgetItems.at(actionIndex);
if (widget) {
if (widget->focusPolicy() != Qt::NoFocus)
widget->setFocus(Qt::TabFocusReason);
@@ -578,8 +568,14 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
//when the action has no QWidget, the QMenu itself should
// get the focus
// Since the menu is a pop-up, it uses the popup reason.
- if (!q->hasFocus())
+ if (!q->hasFocus()) {
q->setFocus(Qt::PopupFocusReason);
+#ifdef QT_KEYPAD_NAVIGATION
+ // TODO: aportale, remove KEYPAD_NAVIGATION_HACK when softkey stack
+ // handles focus related and user related actions separately...
+ QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, q);
+#endif
+ }
}
}
} else { //action is a separator
@@ -614,10 +610,9 @@ QAction *QMenuPrivate::actionAt(QPoint p) const
if (!q_func()->rect().contains(p)) //sanity check
return 0;
- for(int i = 0; i < actionList.count(); i++) {
- QAction *act = actionList[i];
- if (actionRect(act).contains(p))
- return act;
+ for(int i = 0; i < actionRects.count(); i++) {
+ if (actionRects.at(i).contains(p))
+ return actions.at(i);
}
return 0;
}
@@ -691,27 +686,25 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
Q_Q(QMenu);
if (!scroll || !scroll->scrollFlags)
return;
+ updateActionRects();
int newOffset = 0;
- const int scrollHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q);
- const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollHeight : 0;
- const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollHeight : 0;
+ const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0;
+ const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0;
const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q);
const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q);
if (location == QMenuScroller::ScrollTop) {
- for(int i = 0, saccum = 0; i < actionList.count(); i++) {
- QAction *act = actionList.at(i);
- if (act == action) {
+ for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ if (actions.at(i) == action) {
newOffset = topScroll - saccum;
break;
}
- saccum += actionRects.value(act).height();
+ saccum += actionRects.at(i).height();
}
} else {
- for(int i = 0, saccum = 0; i < actionList.count(); i++) {
- QAction *act = actionList.at(i);
- saccum += actionRects.value(act).height();
- if (act == action) {
+ for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ saccum += actionRects.at(i).height();
+ if (actions.at(i) == action) {
if (location == QMenuScroller::ScrollCenter)
newOffset = ((q->height() / 2) - botScroll) - (saccum - topScroll);
else
@@ -720,7 +713,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
}
}
if(newOffset)
- newOffset -= fw*2;
+ newOffset -= fw * 2;
}
//figure out which scroll flags
@@ -728,8 +721,8 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
if (newOffset < 0) //easy and cheap one
newScrollFlags |= QMenuScroller::ScrollUp;
int saccum = newOffset;
- for(int i = 0; i < actionList.count(); i++) {
- saccum += actionRects.value(actionList.at(i)).height();
+ for(int i = 0; i < actionRects.count(); i++) {
+ saccum += actionRects.at(i).height();
if (saccum > q->height()) {
newScrollFlags |= QMenuScroller::ScrollDown;
break;
@@ -780,9 +773,19 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
}
//actually update flags
- scroll->scrollOffset = newOffset;
- if (scroll->scrollOffset > 0)
- scroll->scrollOffset = 0;
+ const int delta = qMin(0, newOffset) - scroll->scrollOffset; //make sure the new offset is always negative
+ if (!itemsDirty && delta) {
+ //we've scrolled so we need to update the action rects
+ for (int i = 0; i < actionRects.count(); ++i) {
+ QRect &current = actionRects[i];
+ current.moveTop(current.top() + delta);
+
+ //we need to update the widgets geometry
+ if (QWidget *w = widgetItems.at(i))
+ w->setGeometry(current);
+ }
+ }
+ scroll->scrollOffset += delta;
scroll->scrollFlags = newScrollFlags;
if (active)
setCurrentAction(action);
@@ -793,9 +796,12 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
void QMenuPrivate::scrollMenu(QMenuScroller::ScrollLocation location, bool active)
{
Q_Q(QMenu);
+ updateActionRects();
if(location == QMenuScroller::ScrollBottom) {
- for(int i = actionList.size()-1; i >= 0; --i) {
- QAction *act = actionList.at(i);
+ for(int i = actions.size()-1; i >= 0; --i) {
+ QAction *act = actions.at(i);
+ if (actionRects.at(i).isNull())
+ continue;
if (!act->isSeparator() &&
(q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q)
|| act->isEnabled())) {
@@ -807,8 +813,10 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollLocation location, bool activ
}
}
} else if(location == QMenuScroller::ScrollTop) {
- for(int i = 0; i < actionList.size(); ++i) {
- QAction *act = actionList.at(i);
+ for(int i = 0; i < actions.size(); ++i) {
+ QAction *act = actions.at(i);
+ if (actionRects.at(i).isNull())
+ continue;
if (!act->isSeparator() &&
(q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q)
|| act->isEnabled())) {
@@ -828,38 +836,33 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollDirection direction, bool pag
Q_Q(QMenu);
if (!scroll || !(scroll->scrollFlags & direction)) //not really possible...
return;
- const int scrollHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q);
- const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollHeight : 0;
- const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollHeight : 0;
+ updateActionRects();
+ const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0;
+ const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0;
const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q);
const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q);
const int offset = topScroll ? topScroll-vmargin : 0;
if (direction == QMenuScroller::ScrollUp) {
- for(int i = 0, saccum = 0; i < actionList.count(); i++) {
- QAction *act = actionList.at(i);
- const int iHeight = actionRects.value(act).height();
- saccum -= iHeight;
+ for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ saccum -= actionRects.at(i).height();
if (saccum <= scroll->scrollOffset-offset) {
- scrollMenu(act, page ? QMenuScroller::ScrollBottom : QMenuScroller::ScrollTop, active);
+ scrollMenu(actions.at(i), page ? QMenuScroller::ScrollBottom : QMenuScroller::ScrollTop, active);
break;
}
}
} else if (direction == QMenuScroller::ScrollDown) {
bool scrolled = false;
- for(int i = 0, saccum = 0; i < actionList.count(); i++) {
- QAction *act = actionList.at(i);
- const int iHeight = actionRects.value(act).height();
+ for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ const int iHeight = actionRects.at(i).height();
saccum -= iHeight;
if (saccum <= scroll->scrollOffset-offset) {
const int scrollerArea = q->height() - botScroll - fw*2;
int visible = (scroll->scrollOffset-offset) - saccum;
- for(i++ ; i < actionList.count(); i++) {
- act = actionList.at(i);
- const int iHeight = actionRects.value(act).height();
- visible += iHeight;
+ for(i++ ; i < actions.count(); i++) {
+ visible += actionRects.at(i).height();
if (visible > scrollerArea - topScroll) {
scrolled = true;
- scrollMenu(act, page ? QMenuScroller::ScrollTop : QMenuScroller::ScrollBottom, active);
+ scrollMenu(actions.at(i), page ? QMenuScroller::ScrollTop : QMenuScroller::ScrollBottom, active);
break;
}
}
@@ -882,13 +885,12 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
if (scroll && !activeMenu) { //let the scroller "steal" the event
bool isScroll = false;
if (pos.x() >= 0 && pos.x() < q->width()) {
- const int scrollerHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q);
for(int dir = QMenuScroller::ScrollUp; dir <= QMenuScroller::ScrollDown; dir = dir << 1) {
if (scroll->scrollFlags & dir) {
if (dir == QMenuScroller::ScrollUp)
- isScroll = (pos.y() <= scrollerHeight);
+ isScroll = (pos.y() <= scrollerHeight());
else if (dir == QMenuScroller::ScrollDown)
- isScroll = (pos.y() >= q->height()-scrollerHeight);
+ isScroll = (pos.y() >= q->height() - scrollerHeight());
if (isScroll) {
scroll->scrollDirection = dir;
break;
@@ -897,19 +899,17 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
}
}
if (isScroll) {
- if (!scroll->scrollTimer)
- scroll->scrollTimer = new QBasicTimer;
- scroll->scrollTimer->start(50, q);
+ scroll->scrollTimer.start(50, q);
return true;
- } else if (scroll->scrollTimer && scroll->scrollTimer->isActive()) {
- scroll->scrollTimer->stop();
+ } else {
+ scroll->scrollTimer.stop();
}
}
if (tearoff) { //let the tear off thingie "steal" the event..
QRect tearRect(0, 0, q->width(), q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, q));
if (scroll && scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
- tearRect.translate(0, q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q));
+ tearRect.translate(0, scrollerHeight());
q->update(tearRect);
if (tearRect.contains(pos) && hasMouseMoved(e->globalPos())) {
setCurrentAction(0);
@@ -1034,7 +1034,7 @@ void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
hideUpToMenuBar();
} else {
- for(QWidget *widget = qApp->activePopupWidget(); widget; ) {
+ for(QWidget *widget = QApplication::activePopupWidget(); widget; ) {
if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) {
if(qmenu == q)
hideUpToMenuBar();
@@ -1164,7 +1164,8 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
else
option->palette.setCurrentColorGroup(QPalette::Disabled);
- option->font = action->font();
+ option->font = action->font().resolve(font());
+ option->fontMetrics = QFontMetrics(option->font);
if (d->currentAction && d->currentAction == action && !d->currentAction->isSeparator()) {
option->state |= QStyle::State_Selected
@@ -1208,9 +1209,9 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
\brief The QMenu class provides a menu widget for use in menu
bars, context menus, and other popup menus.
- \ingroup application
+ \ingroup mainwindow-classes
\ingroup basicwidgets
- \mainclass
+
A menu widget is a selection menu. It can be either a pull-down
menu in a menu bar or a standalone context menu. Pull-down menus
@@ -1359,19 +1360,17 @@ QMenu::QMenu(QMenuPrivate &dd, QWidget *parent)
QMenu::~QMenu()
{
Q_D(QMenu);
- for (QHash<QAction *, QWidget *>::ConstIterator item = d->widgetItems.constBegin(),
- end = d->widgetItems.constEnd(); item != end; ++item) {
- QWidgetAction *action = static_cast<QWidgetAction *>(item.key());
- QWidget *widget = item.value();
- if (action && widget)
+ for (int i = 0; i < d->widgetItems.count(); ++i) {
+ if (QWidget *widget = d->widgetItems.at(i)) {
+ QWidgetAction *action = static_cast<QWidgetAction *>(d->actions.at(i));
action->releaseWidget(widget);
+ d->widgetItems[i] = 0;
+ }
}
- d->widgetItems.clear();
if (d->eventLoop)
d->eventLoop->exit();
- if (d->tornPopup)
- d->tornPopup->close();
+ hideTearOffMenu();
}
/*!
@@ -1582,8 +1581,8 @@ void QMenu::setTearOffEnabled(bool b)
Q_D(QMenu);
if (d->tearoff == b)
return;
- if (!b && d->tornPopup)
- d->tornPopup->close();
+ if (!b)
+ hideTearOffMenu();
d->tearoff = b;
d->itemsDirty = true;
@@ -1618,8 +1617,8 @@ bool QMenu::isTearOffMenuVisible() const
*/
void QMenu::hideTearOffMenu()
{
- if (d_func()->tornPopup)
- d_func()->tornPopup->close();
+ if (QWidget *w = d_func()->tornPopup)
+ w->close();
}
@@ -1717,36 +1716,26 @@ QRect QMenu::actionGeometry(QAction *act) const
QSize QMenu::sizeHint() const
{
Q_D(const QMenu);
- ensurePolished();
- QMap<QAction*, QRect> actionRects;
- QList<QAction*> actionList;
- d->calcActionRects(actionRects, actionList);
+ d->updateActionRects();
QSize s;
- QStyleOption opt(0);
- opt.rect = rect();
- opt.palette = palette();
- opt.state = QStyle::State_None;
- for (QMap<QAction*, QRect>::const_iterator i = actionRects.constBegin();
- i != actionRects.constEnd(); ++i) {
- if (i.value().bottom() > s.height())
- s.setHeight(i.value().y()+i.value().height());
- if (i.value().right() > s.width())
- s.setWidth(i.value().right());
- }
- if (d->tearoff)
- s.rheight() += style()->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, this);
- if (const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, this)) {
- s.rwidth() += fw*2;
- s.rheight() += fw*2;
+ for (int i = 0; i < d->actionRects.count(); ++i) {
+ const QRect &rect = d->actionRects.at(i);
+ if (rect.isNull())
+ continue;
+ if (rect.bottom() >= s.height())
+ s.setHeight(rect.y() + rect.height());
+ if (rect.right() >= s.width())
+ s.setWidth(rect.x() + rect.width());
}
// Note that the action rects calculated above already include
// the top and left margins, so we only need to add margins for
// the bottom and right.
- s.rwidth() += style()->pixelMetric(QStyle::PM_MenuHMargin, &opt, this);
- s.rheight() += style()->pixelMetric(QStyle::PM_MenuVMargin, &opt, this);
-
- s += QSize(d->leftmargin + d->rightmargin, d->topmargin + d->bottommargin);
+ QStyleOption opt(0);
+ opt.init(this);
+ const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, this);
+ s.rwidth() += style()->pixelMetric(QStyle::PM_MenuHMargin, &opt, this) + fw + d->rightmargin;
+ s.rheight() += style()->pixelMetric(QStyle::PM_MenuVMargin, &opt, this) + fw + d->bottommargin;
return style()->sizeFromContents(QStyle::CT_Menu, &opt,
s.expandedTo(QApplication::globalStrut()), this);
@@ -1788,19 +1777,35 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
ensurePolished(); // Get the right font
emit aboutToShow();
- d->updateActions();
+ d->updateActionRects();
QPoint pos = p;
QSize size = sizeHint();
QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(p));
const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this);
bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen);
+#ifdef QT_KEYPAD_NAVIGATION
+ if (!atAction && QApplication::keypadNavigationEnabled()) {
+ // Try to have one item activated
+ if (d->defaultAction && d->defaultAction->isEnabled()) {
+ atAction = d->defaultAction;
+ // TODO: This works for first level menus, not yet sub menus
+ } else {
+ foreach (QAction *action, d->actions)
+ if (action->isEnabled()) {
+ atAction = action;
+ break;
+ }
+ }
+ d->currentAction = atAction;
+ }
+#endif
if (d->ncols > 1) {
pos.setY(screen.top()+desktopFrame);
} else if (atAction) {
- for(int i=0, above_height=0; i<(int)d->actionList.count(); i++) {
- QAction *action = d->actionList.at(i);
+ for(int i = 0, above_height = 0; i < d->actions.count(); i++) {
+ QAction *action = d->actions.at(i);
if (action == atAction) {
- int newY = pos.y()-above_height;
+ int newY = pos.y() - above_height;
if (d->scroll && newY < desktopFrame) {
d->scroll->scrollFlags = d->scroll->scrollFlags
| QMenuPrivate::QMenuScroller::ScrollUp;
@@ -1812,13 +1817,13 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
if (d->scroll && d->scroll->scrollFlags != QMenuPrivate::QMenuScroller::ScrollNone
&& !style()->styleHint(QStyle::SH_Menu_FillScreenWithScroll, 0, this)) {
int below_height = above_height + d->scroll->scrollOffset;
- for(int i2 = i; i2 < (int)d->actionList.count(); i2++)
- below_height += d->actionRects.value(d->actionList.at(i2)).height();
+ for(int i2 = i; i2 < d->actionRects.count(); i2++)
+ below_height += d->actionRects.at(i2).height();
size.setHeight(below_height);
}
break;
} else {
- above_height += d->actionRects.value(action).height();
+ above_height += d->actionRects.at(i).height();
}
}
}
@@ -1829,7 +1834,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
if (adjustToDesktop) {
//handle popup falling "off screen"
- if (qApp->layoutDirection() == Qt::RightToLeft) {
+ if (isRightToLeft()) {
if(snapToMouse) //position flowing left from the mouse
pos.setX(mouse.x()-size.width());
@@ -1867,9 +1872,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
}
setGeometry(QRect(pos, size));
#ifndef QT_NO_EFFECTS
- int hGuess = qApp->layoutDirection() == Qt::RightToLeft ? QEffects::LeftScroll : QEffects::RightScroll;
+ int hGuess = isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
int vGuess = QEffects::DownScroll;
- if (qApp->layoutDirection() == Qt::RightToLeft) {
+ if (isRightToLeft()) {
if ((snapToMouse && (pos.x() + size.width()/2 > mouse.x())) ||
(qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width()/2 > d->causedPopup.widget->x()))
hGuess = QEffects::RightScroll;
@@ -1921,6 +1926,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
#ifndef QT_NO_ACCESSIBILITY
QAccessible::updateAccessibility(this, 0, QAccessible::PopupMenuStart);
#endif
+#ifdef QT_KEYPAD_NAVIGATION
+ QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, this);
+#endif
}
/*!
@@ -2025,8 +2033,7 @@ QAction *QMenu::exec(const QPoint &p, QAction *action)
QAction *QMenu::exec(QList<QAction*> actions, const QPoint &pos, QAction *at, QWidget *parent)
{
QMenu menu(parent);
- for(QList<QAction*>::ConstIterator it = actions.constBegin(); it != actions.constEnd(); ++it)
- menu.addAction((*it));
+ menu.addActions(actions);
return menu.exec(pos, at);
}
@@ -2076,6 +2083,8 @@ void QMenu::hideEvent(QHideEvent *)
d->hasHadMouse = false;
d->causedPopup.widget = 0;
d->causedPopup.action = 0;
+ if (d->scroll)
+ d->scroll->scrollTimer.stop(); //make sure the timer stops
}
/*!
@@ -2084,6 +2093,7 @@ void QMenu::hideEvent(QHideEvent *)
void QMenu::paintEvent(QPaintEvent *e)
{
Q_D(QMenu);
+ d->updateActionRects();
QPainter p(this);
QRegion emptyArea = QRegion(rect());
@@ -2096,11 +2106,11 @@ void QMenu::paintEvent(QPaintEvent *e)
style()->drawPrimitive(QStyle::PE_PanelMenu, &menuOpt, &p, this);
//draw the items that need updating..
- for (int i = 0; i < d->actionList.count(); ++i) {
- QAction *action = d->actionList.at(i);
- QRect adjustedActionRect = d->actionRect(action);
+ for (int i = 0; i < d->actions.count(); ++i) {
+ QAction *action = d->actions.at(i);
+ QRect adjustedActionRect = d->actionRects.at(i);
if (!e->rect().intersects(adjustedActionRect)
- || d->widgetItems.value(action))
+ || d->widgetItems.at(i))
continue;
//set the clip region to be extra safe (and adjust for the scrollers)
QRegion adjustedActionReg(adjustedActionRect);
@@ -2116,18 +2126,17 @@ void QMenu::paintEvent(QPaintEvent *e)
const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this);
//draw the scroller regions..
if (d->scroll) {
- const int scrollerHeight = style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, this);
menuOpt.menuItemType = QStyleOptionMenuItem::Scroller;
menuOpt.state |= QStyle::State_Enabled;
if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) {
- menuOpt.rect.setRect(fw, fw, width() - (fw * 2), scrollerHeight);
+ menuOpt.rect.setRect(fw, fw, width() - (fw * 2), d->scrollerHeight());
emptyArea -= QRegion(menuOpt.rect);
p.setClipRect(menuOpt.rect);
style()->drawControl(QStyle::CE_MenuScroller, &menuOpt, &p, this);
}
if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown) {
- menuOpt.rect.setRect(fw, height() - scrollerHeight - fw, width() - (fw * 2),
- scrollerHeight);
+ menuOpt.rect.setRect(fw, height() - d->scrollerHeight() - fw, width() - (fw * 2),
+ d->scrollerHeight());
emptyArea -= QRegion(menuOpt.rect);
menuOpt.state |= QStyle::State_DownArrow;
p.setClipRect(menuOpt.rect);
@@ -2140,7 +2149,7 @@ void QMenu::paintEvent(QPaintEvent *e)
menuOpt.rect.setRect(fw, fw, width() - (fw * 2),
style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this));
if (d->scroll && d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
- menuOpt.rect.translate(0, style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, this));
+ menuOpt.rect.translate(0, d->scrollerHeight());
emptyArea -= QRegion(menuOpt.rect);
p.setClipRect(menuOpt.rect);
menuOpt.state = QStyle::State_None;
@@ -2249,7 +2258,7 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e)
break;
}
}
- if (e->button() == Qt::LeftButton || (e->button() == Qt::RightButton && isContextMenu))
+ if (e->button() == Qt::LeftButton || isContextMenu)
#endif
d->activateAction(action, QAction::Trigger);
}
@@ -2330,11 +2339,11 @@ QMenu::event(QEvent *e)
setMask(menuMask.region);
}
d->itemsDirty = 1;
- d->updateActions();
+ d->updateActionRects();
break; }
case QEvent::Show:
d->mouseDown = 0;
- d->updateActions();
+ d->updateActionRects();
if (d->currentAction)
d->popupAction(d->currentAction, 0, false);
break;
@@ -2370,6 +2379,7 @@ bool QMenu::focusNextPrevChild(bool next)
void QMenu::keyPressEvent(QKeyEvent *e)
{
Q_D(QMenu);
+ d->updateActionRects();
int key = e->key();
if (isRightToLeft()) { // in reverse mode open/close key for submenues are reversed
if (key == Qt::Key_Left)
@@ -2421,8 +2431,10 @@ void QMenu::keyPressEvent(QKeyEvent *e)
QMenuPrivate::QMenuScroller::ScrollLocation scroll_loc = QMenuPrivate::QMenuScroller::ScrollStay;
if (!d->currentAction) {
if(key == Qt::Key_Down) {
- for(int i = 0; i < d->actionList.size(); ++i) {
- QAction *act = d->actionList.at(i);
+ for(int i = 0; i < d->actions.count(); ++i) {
+ QAction *act = d->actions.at(i);
+ if (d->actionRects.at(i).isNull())
+ continue;
if (!act->isSeparator() &&
(style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)
|| act->isEnabled())) {
@@ -2431,8 +2443,10 @@ void QMenu::keyPressEvent(QKeyEvent *e)
}
}
} else {
- for(int i = d->actionList.size()-1; i >= 0; --i) {
- QAction *act = d->actionList.at(i);
+ for(int i = d->actions.count()-1; i >= 0; --i) {
+ QAction *act = d->actions.at(i);
+ if (d->actionRects.at(i).isNull())
+ continue;
if (!act->isSeparator() &&
(style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)
|| act->isEnabled())) {
@@ -2442,8 +2456,8 @@ void QMenu::keyPressEvent(QKeyEvent *e)
}
}
} else {
- for(int i=0, y=0; !nextAction && i < (int)d->actionList.count(); i++) {
- QAction *act = d->actionList.at(i);
+ for(int i = 0, y = 0; !nextAction && i < d->actions.count(); i++) {
+ QAction *act = d->actions.at(i);
if (act == d->currentAction) {
if (key == Qt::Key_Up) {
for(int next_i = i-1; true; next_i--) {
@@ -2452,21 +2466,23 @@ void QMenu::keyPressEvent(QKeyEvent *e)
break;
if (d->scroll)
scroll_loc = QMenuPrivate::QMenuScroller::ScrollBottom;
- next_i = d->actionList.count()-1;
+ next_i = d->actionRects.count()-1;
}
- QAction *next = d->actionList.at(next_i);
+ QAction *next = d->actions.at(next_i);
if (next == d->currentAction)
break;
+ if (d->actionRects.at(next_i).isNull())
+ continue;
if (next->isSeparator() ||
(!next->isEnabled() &&
!style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)))
continue;
nextAction = next;
if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)) {
- int topVisible = style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, this);
+ int topVisible = d->scrollerHeight();
if (d->tearoff)
topVisible += style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this);
- if (((y + d->scroll->scrollOffset) - topVisible) <= d->actionRects.value(nextAction).height())
+ if (((y + d->scroll->scrollOffset) - topVisible) <= d->actionRects.at(next_i).height())
scroll_loc = QMenuPrivate::QMenuScroller::ScrollTop;
}
break;
@@ -2474,31 +2490,32 @@ void QMenu::keyPressEvent(QKeyEvent *e)
if (!nextAction && d->tearoff)
d->tearoffHighlighted = 1;
} else {
- y += d->actionRects.value(act).height();
+ y += d->actionRects.at(i).height();
for(int next_i = i+1; true; next_i++) {
- if (next_i == d->actionList.count()) {
+ if (next_i == d->actionRects.count()) {
if(!style()->styleHint(QStyle::SH_Menu_SelectionWrap, 0, this))
break;
if (d->scroll)
scroll_loc = QMenuPrivate::QMenuScroller::ScrollTop;
next_i = 0;
}
- QAction *next = d->actionList.at(next_i);
+ QAction *next = d->actions.at(next_i);
if (next == d->currentAction)
break;
+ if (d->actionRects.at(next_i).isNull())
+ continue;
if (next->isSeparator() ||
(!next->isEnabled() &&
!style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this)))
continue;
nextAction = next;
if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)) {
- const int scrollerHeight = style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, this);
- int bottomVisible = height()-scrollerHeight;
+ int bottomVisible = height() - d->scrollerHeight();
if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
- bottomVisible -= scrollerHeight;
+ bottomVisible -= d->scrollerHeight();
if (d->tearoff)
bottomVisible -= style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this);
- if ((y + d->scroll->scrollOffset + d->actionRects.value(nextAction).height()) > bottomVisible)
+ if ((y + d->scroll->scrollOffset + d->actionRects.at(next_i).height()) > bottomVisible)
scroll_loc = QMenuPrivate::QMenuScroller::ScrollBottom;
}
break;
@@ -2506,13 +2523,12 @@ void QMenu::keyPressEvent(QKeyEvent *e)
}
break;
}
- y += d->actionRects.value(act).height();
+ y += d->actionRects.at(i).height();
}
}
if (nextAction) {
if (d->scroll && scroll_loc != QMenuPrivate::QMenuScroller::ScrollStay) {
- if (d->scroll->scrollTimer)
- d->scroll->scrollTimer->stop();
+ d->scroll->scrollTimer.stop();
d->scrollMenu(nextAction, scroll_loc);
}
d->setCurrentAction(nextAction, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard);
@@ -2561,7 +2577,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
{
d->hideMenu(this);
#ifndef QT_NO_MENUBAR
- if (QMenuBar *mb = qobject_cast<QMenuBar*>(qApp->focusWidget())) {
+ if (QMenuBar *mb = qobject_cast<QMenuBar*>(QApplication::focusWidget())) {
mb->d_func()->setKeyboardMode(false);
}
#endif
@@ -2571,6 +2587,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
case Qt::Key_Escape:
#ifdef QT_KEYPAD_NAVIGATION
case Qt::Key_Back:
+ QActionToKeyEventMapper::removeSoftkey(this);
#endif
key_consumed = true;
if (d->tornoff) {
@@ -2634,9 +2651,11 @@ void QMenu::keyPressEvent(QKeyEvent *e)
int best_match_count = 0;
d->searchBufferTimer.start(2000, this);
d->searchBuffer += e->text();
- for(int i = 0; i < d->actionList.size(); ++i) {
+ for(int i = 0; i < d->actions.size(); ++i) {
int match_count = 0;
- register QAction *act = d->actionList.at(i);
+ if (d->actionRects.at(i).isNull())
+ continue;
+ QAction *act = d->actions.at(i);
const QString act_text = act->text();
for(int c = 0; c < d->searchBuffer.size(); ++c) {
if(act_text.indexOf(d->searchBuffer.at(c), 0, Qt::CaseInsensitive) != -1)
@@ -2653,8 +2672,10 @@ void QMenu::keyPressEvent(QKeyEvent *e)
int clashCount = 0;
QAction *first = 0, *currentSelected = 0, *firstAfterCurrent = 0;
QChar c = e->text().at(0).toUpper();
- for(int i = 0; i < d->actionList.size(); ++i) {
- register QAction *act = d->actionList.at(i);
+ for(int i = 0; i < d->actions.size(); ++i) {
+ if (d->actionRects.at(i).isNull())
+ continue;
+ QAction *act = d->actions.at(i);
QKeySequence sequence = QKeySequence::mnemonic(act->text());
int key = sequence[0] & 0xffff;
if (key == c.unicode()) {
@@ -2705,7 +2726,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
#ifdef Q_OS_WIN32
if (key_consumed && (e->key() == Qt::Key_Control || e->key() == Qt::Key_Shift || e->key() == Qt::Key_Meta))
- qApp->beep();
+ QApplication::beep();
#endif // Q_OS_WIN32
}
if (key_consumed)
@@ -2725,14 +2746,14 @@ void QMenu::mouseMoveEvent(QMouseEvent *e)
d->motions++;
if (d->motions == 0) // ignore first mouse move event (see enterEvent())
return;
- d->hasHadMouse |= rect().contains(e->pos());
+ d->hasHadMouse = d->hasHadMouse || rect().contains(e->pos());
QAction *action = d->actionAt(e->pos());
if (!action) {
- if (d->hasHadMouse && !rect().contains(e->pos()))
+ if (d->hasHadMouse)
d->setCurrentAction(0);
return;
- } else if(e->buttons() & (Qt::LeftButton | Qt::RightButton)) {
+ } else if(e->buttons()) {
d->mouseDown = this;
}
if (d->sloppyRegion.contains(e->pos())) {
@@ -2760,6 +2781,8 @@ void QMenu::leaveEvent(QEvent *)
d->sloppyAction = 0;
if (!d->sloppyRegion.isEmpty())
d->sloppyRegion = QRegion();
+ if (!d->activeMenu && d->currentAction)
+ setActiveAction(0);
}
/*!
@@ -2769,10 +2792,10 @@ void
QMenu::timerEvent(QTimerEvent *e)
{
Q_D(QMenu);
- if (d->scroll && d->scroll->scrollTimer && d->scroll->scrollTimer->timerId() == e->timerId()) {
+ if (d->scroll && d->scroll->scrollTimer.timerId() == e->timerId()) {
d->scrollMenu((QMenuPrivate::QMenuScroller::ScrollDirection)d->scroll->scrollDirection);
if (d->scroll->scrollFlags == QMenuPrivate::QMenuScroller::ScrollNone)
- d->scroll->scrollTimer->stop();
+ d->scroll->scrollTimer.stop();
} else if(QMenuPrivate::menuDelayTimer.timerId() == e->timerId()) {
QMenuPrivate::menuDelayTimer.stop();
internalDelayedPopup();
@@ -2799,31 +2822,25 @@ void QMenu::actionEvent(QActionEvent *e)
connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
}
+ QWidget *widget = 0;
+ if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action()))
+ widget = wa->requestWidget(this);
+
+ int index = d->actions.indexOf(e->action());
+ Q_ASSERT(index != -1);
+ d->widgetItems.insert(index, widget);
- if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
- QWidget *widget = wa->requestWidget(this);
- if (widget)
- d->widgetItems.insert(wa, widget);
- }
} else if (e->type() == QEvent::ActionRemoved) {
- d->actionRects.clear();
- d->actionList.clear();
e->action()->disconnect(this);
if (e->action() == d->currentAction)
d->currentAction = 0;
+ int index = d->actions.indexOf(e->before()) + 1;
if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
- QWidget *widget = d->widgetItems.take(wa);
- if (widget)
+ if (QWidget *widget = d->widgetItems.at(index))
wa->releaseWidget(widget);
- } else {
- // If this is called from the QAction destructor, the
- // previous call to qobject_cast will fail because the
- // QWidgetAction has been destroyed already. We need to
- // remove it from the hash anyway or it might crash later
- // the widget itself has been already destroyed in
- // ~QWidgetAction
- d->widgetItems.remove(e->action());
}
+ Q_ASSERT(index != -1);
+ d->widgetItems.removeAt(index);
}
#ifdef Q_WS_MAC
@@ -2837,7 +2854,7 @@ void QMenu::actionEvent(QActionEvent *e)
}
#endif
-#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR)
+#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
if (!d->wce_menu)
d->wce_menu = new QMenuPrivate::QWceMenuPrivate;
if (e->type() == QEvent::ActionAdded)
@@ -2848,8 +2865,18 @@ void QMenu::actionEvent(QActionEvent *e)
d->wce_menu->syncAction(e->action());
#endif
+#ifdef Q_WS_S60
+ if (!d->symbian_menu)
+ d->symbian_menu = new QMenuPrivate::QSymbianMenuPrivate;
+ if (e->type() == QEvent::ActionAdded)
+ d->symbian_menu->addAction(e->action(), d->symbian_menu->findAction(e->before()));
+ else if (e->type() == QEvent::ActionRemoved)
+ d->symbian_menu->removeAction(e->action());
+ else if (e->type() == QEvent::ActionChanged)
+ d->symbian_menu->syncAction(e->action());
+#endif
if (isVisible()) {
- d->updateActions();
+ d->updateActionRects();
resize(sizeHint());
update();
}
@@ -3027,12 +3054,19 @@ bool QMenu::separatorsCollapsible() const
void QMenu::setSeparatorsCollapsible(bool collapse)
{
Q_D(QMenu);
+ if (d->collapsibleSeparators == collapse)
+ return;
+
d->collapsibleSeparators = collapse;
d->itemsDirty = 1;
if (isVisible()) {
- d->updateActions();
+ d->updateActionRects();
update();
}
+#ifdef Q_WS_MAC
+ if (d->mac_menu)
+ d->syncSeparatorsCollapsible(collapse);
+#endif
}
#ifdef QT3_SUPPORT
@@ -3089,9 +3123,9 @@ int QMenu::insertSeparator(int index)
QAction *QMenu::findActionForId(int id) const
{
- QList<QAction *> list = actions();
- for (int i = 0; i < list.size(); ++i) {
- QAction *act = list.at(i);
+ Q_D(const QMenu);
+ for (int i = 0; i < d->actions.size(); ++i) {
+ QAction *act = d->actions.at(i);
if (findIdForAction(act)== id)
return act;
}
diff --git a/src/gui/widgets/qmenu.h b/src/gui/widgets/qmenu.h
index e290018..370e39b 100644
--- a/src/gui/widgets/qmenu.h
+++ b/src/gui/widgets/qmenu.h
@@ -52,11 +52,19 @@
#endif
QT_BEGIN_HEADER
+#ifdef Q_WS_S60
+ class CEikMenuPane;
+#endif
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
+#ifdef Q_WS_S60
+ IMPORT_C void qt_symbian_show_toplevel(CEikMenuPane* menuPane);
+ IMPORT_C void qt_symbian_show_submenu(CEikMenuPane* menuPane, int id);
+#endif // Q_WS_S60
+
#ifndef QT_NO_MENU
class QMenuPrivate;
@@ -141,11 +149,10 @@ public:
OSMenuRef macMenu(OSMenuRef merge=0);
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
HMENU wceMenu(bool create = false);
#endif
-
bool separatorsCollapsible() const;
void setSeparatorsCollapsible(bool collapse);
@@ -174,7 +181,7 @@ protected:
bool focusNextPrevChild(bool next);
void initStyleOption(QStyleOptionMenuItem *option, const QAction *action) const;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
QAction* wceCommands(uint command);
#endif
diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm
index 165b7ec..73c8270 100644
--- a/src/gui/widgets/qmenu_mac.mm
+++ b/src/gui/widgets/qmenu_mac.mm
@@ -71,7 +71,6 @@ QT_BEGIN_NAMESPACE
/*****************************************************************************
QMenu globals
*****************************************************************************/
-bool qt_mac_no_native_menubar = false;
bool qt_mac_no_menubar_merge = false;
bool qt_mac_quit_menu_item_enabled = true;
int qt_mac_menus_open_count = 0;
@@ -143,6 +142,39 @@ static int qt_mac_CountMenuItems(OSMenuRef menu)
return 0;
}
+static quint32 constructModifierMask(quint32 accel_key)
+{
+ quint32 ret = 0;
+ const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
+#ifndef QT_MAC_USE_COCOA
+ if ((accel_key & Qt::ALT) == Qt::ALT)
+ ret |= kMenuOptionModifier;
+ if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
+ ret |= kMenuShiftModifier;
+ if (dontSwap) {
+ if ((accel_key & Qt::META) != Qt::META)
+ ret |= kMenuNoCommandModifier;
+ if ((accel_key & Qt::CTRL) == Qt::CTRL)
+ ret |= kMenuControlModifier;
+ } else {
+ if ((accel_key & Qt::CTRL) != Qt::CTRL)
+ ret |= kMenuNoCommandModifier;
+ if ((accel_key & Qt::META) == Qt::META)
+ ret |= kMenuControlModifier;
+ }
+#else
+ if ((accel_key & Qt::CTRL) == Qt::CTRL)
+ ret |= (dontSwap ? NSControlKeyMask : NSCommandKeyMask);
+ if ((accel_key & Qt::META) == Qt::META)
+ ret |= (dontSwap ? NSCommandKeyMask : NSControlKeyMask);
+ if ((accel_key & Qt::ALT) == Qt::ALT)
+ ret |= NSAlternateKeyMask;
+ if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
+ ret |= NSShiftKeyMask;
+#endif
+ return ret;
+}
+
static bool actualMenuItemVisibility(const QMenuBarPrivate::QMacMenuBarPrivate *mbp,
const QMacMenuAction *action)
{
@@ -166,7 +198,7 @@ bool qt_mac_activate_action(MenuRef menu, uint command, QAction::ActionEvent act
QMenuMergeList *list = 0;
GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyMergeList,
sizeof(list), 0, &list);
- if (!list && qt_mac_current_menubar.qmenubar) {
+ if (!list && qt_mac_current_menubar.qmenubar && qt_mac_current_menubar.qmenubar->isNativeMenuBar()) {
MenuRef apple_menu = qt_mac_current_menubar.qmenubar->d_func()->mac_menubar->apple_menu;
GetMenuItemProperty(apple_menu, 0, kMenuCreatorQt, kMenuPropertyMergeList, sizeof(list), 0, &list);
if (list)
@@ -426,7 +458,8 @@ OSStatus qt_mac_menu_event(EventHandlerCallRef er, EventRef event, void *)
int merged = 0;
const QMenuPrivate::QMacMenuPrivate *mac_menu = qmenu->d_func()->mac_menu;
- for(int i = 0; i < mac_menu->actionItems.size(); ++i) {
+ const int ActionItemsCount = mac_menu->actionItems.size();
+ for(int i = 0; i < ActionItemsCount; ++i) {
QMacMenuAction *action = mac_menu->actionItems.at(i);
if (action->action->isSeparator()) {
bool hide = false;
@@ -526,15 +559,7 @@ static bool qt_mac_auto_apple_menu(MenuCommand cmd)
static void qt_mac_get_accel(quint32 accel_key, quint32 *modif, quint32 *key) {
if (modif) {
- *modif = 0;
- if ((accel_key & Qt::CTRL) != Qt::CTRL)
- *modif |= kMenuNoCommandModifier;
- if ((accel_key & Qt::META) == Qt::META)
- *modif |= kMenuControlModifier;
- if ((accel_key & Qt::ALT) == Qt::ALT)
- *modif |= kMenuOptionModifier;
- if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
- *modif |= kMenuShiftModifier;
+ *modif = constructModifierMask(accel_key);
}
accel_key &= ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL);
@@ -582,6 +607,13 @@ static inline void syncNSMenuItemVisiblity(NSMenuItem *menuItem, bool actionVisi
[menuItem setHidden:!actionVisibility];
}
+static inline void syncNSMenuItemEnabled(NSMenuItem *menuItem, bool enabled)
+{
+ [menuItem setEnabled:NO];
+ [menuItem setEnabled:YES];
+ [menuItem setEnabled:enabled];
+}
+
static inline void syncMenuBarItemsVisiblity(const QMenuBarPrivate::QMacMenuBarPrivate *mac_menubar)
{
const QList<QMacMenuAction *> &menubarActions = mac_menubar->actionItems;
@@ -599,7 +631,7 @@ static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader()
static NSMenuItem *createNSMenuItem(const QString &title)
{
NSMenuItem *item = [[NSMenuItem alloc]
- initWithTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(title)))
+ initWithTitle:qt_mac_QStringToNSString(title)
action:@selector(qtDispatcherToQAction:) keyEquivalent:@""];
[item setTarget:getMenuLoader()];
return item;
@@ -634,12 +666,12 @@ void qt_mac_set_modal_state_helper_recursive(OSMenuRef menu, OSMenuRef merge, bo
// The item should follow what the QAction has.
if ([item tag]) {
QAction *action = reinterpret_cast<QAction *>([item tag]);
- [item setEnabled:action->isEnabled()];
+ syncNSMenuItemEnabled(item, action->isEnabled());
} else {
- [item setEnabled:YES];
+ syncNSMenuItemEnabled(item, YES);
}
} else {
- [item setEnabled:NO];
+ syncNSMenuItemEnabled(item, NO);
}
}
}
@@ -703,6 +735,9 @@ bool qt_mac_menubar_is_open()
void qt_mac_clear_menubar()
{
+ if (QApplication::testAttribute(Qt::AA_MacPluginApplication))
+ return;
+
#ifndef QT_MAC_USE_COCOA
MenuRef clear_menu = 0;
if (CreateNewMenu(0, 0, &clear_menu) == noErr) {
@@ -728,6 +763,18 @@ QMacMenuAction::~QMacMenuAction()
{
#ifdef QT_MAC_USE_COCOA
[menu release];
+ if (action) {
+ QAction::MenuRole role = action->menuRole();
+ // Check if the item is owned by Qt, and should be hidden to keep it from causing
+ // problems. Do it for everything but the quit menu item since that should always
+ // be visible.
+ if (role > QAction::ApplicationSpecificRole && role < QAction::QuitRole) {
+ [menuItem setHidden:YES];
+ } else if (role == QAction::TextHeuristicRole
+ && menuItem != [getMenuLoader() quitMenuItem]) {
+ [menuItem setHidden:YES];
+ }
+ }
[menuItem setTag:nil];
[menuItem release];
#endif
@@ -915,21 +962,22 @@ static QKeySequence qt_mac_menu_merge_accel(QMacMenuAction *action)
ret = action->action->shortcut();
#ifndef QT_MAC_USE_COCOA
else if (action->command == kHICommandPreferences)
- ret = QKeySequence(Qt::CTRL+Qt::Key_Comma);
+ ret = QKeySequence(QKeySequence::Preferences);
else if (action->command == kHICommandQuit)
- ret = QKeySequence(Qt::CTRL+Qt::Key_Q);
+ ret = QKeySequence(QKeySequence::Quit);
#else
else if (action->menuItem == [loader preferencesMenuItem])
- ret = QKeySequence(Qt::CTRL+Qt::Key_Comma);
+ ret = QKeySequence(QKeySequence::Preferences);
else if (action->menuItem == [loader quitMenuItem])
- ret = QKeySequence(Qt::CTRL+Qt::Key_Q);
+ ret = QKeySequence(QKeySequence::Quit);
#endif
return ret;
}
void Q_GUI_EXPORT qt_mac_set_menubar_icons(bool b)
{ QApplication::instance()->setAttribute(Qt::AA_DontShowIconsInMenus, !b); }
-void Q_GUI_EXPORT qt_mac_set_native_menubar(bool b) { qt_mac_no_native_menubar = !b; }
+void Q_GUI_EXPORT qt_mac_set_native_menubar(bool b)
+{ QApplication::instance()->setAttribute(Qt::AA_DontUseNativeMenuBar, !b); }
void Q_GUI_EXPORT qt_mac_set_menubar_merge(bool b) { qt_mac_no_menubar_merge = !b; }
/*****************************************************************************
@@ -1143,7 +1191,7 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction
#endif
}
- QWidget *widget = qmenu ? qmenu->widgetItems.value(action->action) : 0;
+ QWidget *widget = qmenu ? qmenu->widgetItems.value(qmenu->actions.indexOf(action->action)) : 0;
if (widget) {
#ifndef QT_MAC_USE_COCOA
ChangeMenuAttributes(action->menu, kMenuAttrDoNotCacheImage, 0);
@@ -1206,58 +1254,21 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction
NSString *keySequenceToKeyEqivalent(const QKeySequence &accel)
{
quint32 accel_key = (accel[0] & ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL));
- unichar keyEquiv[1] = { 0 };
- if (accel_key == Qt::Key_Return)
- keyEquiv[0] = kReturnCharCode;
- else if (accel_key == Qt::Key_Enter)
- keyEquiv[0] = kEnterCharCode;
- else if (accel_key == Qt::Key_Tab)
- keyEquiv[0] = kTabCharCode;
- else if (accel_key == Qt::Key_Backspace)
- keyEquiv[0] = kBackspaceCharCode;
- else if (accel_key == Qt::Key_Delete)
- keyEquiv[0] = NSDeleteFunctionKey;
- else if (accel_key == Qt::Key_Escape)
- keyEquiv[0] = kEscapeCharCode;
- else if (accel_key == Qt::Key_PageUp)
- keyEquiv[0] = NSPageUpFunctionKey;
- else if (accel_key == Qt::Key_PageDown)
- keyEquiv[0] = NSPageDownFunctionKey;
- else if (accel_key == Qt::Key_Up)
- keyEquiv[0] = NSUpArrowFunctionKey;
- else if (accel_key == Qt::Key_Down)
- keyEquiv[0] = NSDownArrowFunctionKey;
- else if (accel_key == Qt::Key_Left)
- keyEquiv[0] = NSLeftArrowFunctionKey;
- else if (accel_key == Qt::Key_Right)
- keyEquiv[0] = NSRightArrowFunctionKey;
- else if (accel_key == Qt::Key_CapsLock)
- keyEquiv[0] = kMenuCapsLockGlyph; // ### Cocoa has no equivalent
- else if (accel_key >= Qt::Key_F1 && accel_key <= Qt::Key_F15)
- keyEquiv[0] = (accel_key - Qt::Key_F1) + NSF1FunctionKey;
- else if (accel_key == Qt::Key_Home)
- keyEquiv[0] = NSHomeFunctionKey;
- else if (accel_key == Qt::Key_End)
- keyEquiv[0] = NSEndFunctionKey;
- else
- keyEquiv[0] = unichar(QChar(accel_key).toLower().unicode());
- return [NSString stringWithCharacters:keyEquiv length:1];
+ extern QChar qt_macSymbolForQtKey(int key); // qkeysequence.cpp
+ QChar keyEquiv = qt_macSymbolForQtKey(accel_key);
+ if (keyEquiv.isNull()) {
+ if (accel_key >= Qt::Key_F1 && accel_key <= Qt::Key_F15)
+ keyEquiv = (accel_key - Qt::Key_F1) + NSF1FunctionKey;
+ else
+ keyEquiv = unichar(QChar(accel_key).toLower().unicode());
+ }
+ return [NSString stringWithCharacters:&keyEquiv.unicode() length:1];
}
// return the cocoa modifier mask for the QKeySequence (currently only looks at the first one).
NSUInteger keySequenceModifierMask(const QKeySequence &accel)
{
- NSUInteger ret = 0;
- quint32 accel_key = accel[0];
- if ((accel_key & Qt::CTRL) == Qt::CTRL)
- ret |= NSCommandKeyMask;
- if ((accel_key & Qt::META) == Qt::META)
- ret |= NSControlKeyMask;
- if ((accel_key & Qt::ALT) == Qt::ALT)
- ret |= NSAlternateKeyMask;
- if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
- ret |= NSShiftKeyMask;
- return ret;
+ return constructModifierMask(accel[0]);
}
void
@@ -1337,8 +1348,9 @@ QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action)
accel = qt_mac_menu_merge_accel(action);
}
}
+ // Show multiple key sequences as part of the menu text.
if (accel.count() > 1)
- text += QLatin1String(" (****)"); //just to denote a multi stroke shortcut
+ text += QLatin1String(" (") + accel.toString(QKeySequence::NativeText) + QLatin1String(")");
QString finalString = qt_mac_removeMnemonics(text);
@@ -1379,18 +1391,18 @@ QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action)
// Cocoa Font and title
if (action->action->font().resolve()) {
const QFont &actionFont = action->action->font();
- NSFont *customMenuFont = [NSFont fontWithName:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(actionFont.family())))
+ NSFont *customMenuFont = [NSFont fontWithName:qt_mac_QStringToNSString(actionFont.family())
size:actionFont.pointSize()];
NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil];
NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil];
NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
- NSAttributedString *str = [[[NSAttributedString alloc] initWithString:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(finalString)))
+ NSAttributedString *str = [[[NSAttributedString alloc] initWithString:qt_mac_QStringToNSString(finalString)
attributes:attributes] autorelease];
[item setAttributedTitle: str];
} else {
- [item setTitle: reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(finalString)))];
+ [item setTitle: qt_mac_QStringToNSString(finalString)];
}
- [item setTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(qt_mac_removeMnemonics(text))))];
+ [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))];
// Cocoa Enabled
[item setEnabled: action->action->isEnabled()];
@@ -1420,14 +1432,15 @@ QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action)
data.whichData |= kMenuItemDataCmdKey;
data.whichData |= kMenuItemDataCmdKeyModifiers;
data.whichData |= kMenuItemDataCmdKeyGlyph;
- if (!accel.isEmpty()) {
+ if (accel.count() == 1) {
qt_mac_get_accel(accel[0], (quint32*)&data.cmdKeyModifiers, (quint32*)&data.cmdKeyGlyph);
if (data.cmdKeyGlyph == 0)
data.cmdKey = (UniChar)accel[0];
}
#else
[item setSubmenu:0];
- if (!accel.isEmpty()) {
+ // No key equivalent set for multiple key QKeySequence.
+ if (accel.count() == 1) {
[item setKeyEquivalent:keySequenceToKeyEqivalent(accel)];
[item setKeyEquivalentModifierMask:keySequenceModifierMask(accel)];
} else {
@@ -1511,12 +1524,31 @@ QMenuPrivate::macMenu(OSMenuRef merge)
QList<QAction*> items = q->actions();
for(int i = 0; i < items.count(); i++)
mac_menu->addAction(items[i], 0, this);
+ syncSeparatorsCollapsible(collapsibleSeparators);
return mac_menu->menu;
}
/*!
\internal
*/
+void
+QMenuPrivate::syncSeparatorsCollapsible(bool collapse)
+{
+#ifndef QT_MAC_USE_COCOA
+ if (collapse)
+ ChangeMenuAttributes(mac_menu->menu, kMenuAttrCondenseSeparators, 0);
+ else
+ ChangeMenuAttributes(mac_menu->menu, 0, kMenuAttrCondenseSeparators);
+#else
+ qt_mac_menu_collapseSeparators(mac_menu->menu, collapse);
+#endif
+}
+
+
+
+/*!
+ \internal
+*/
void QMenuPrivate::setMacMenuEnabled(bool enable)
{
if (!macMenu(0))
@@ -1699,7 +1731,7 @@ QMenuBarPrivate::QMacMenuBarPrivate::syncAction(QMacMenuAction *action)
ChangeMenuAttributes(submenu, kMenuAttrHidden, 0);
#else
[item setSubmenu: submenu];
- [submenu setTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(qt_mac_removeMnemonics(action->action->text()))))];
+ [submenu setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(action->action->text()))];
syncNSMenuItemVisiblity(item, visible);
#endif
if (release_submenu) { //no pointers to it
@@ -1732,10 +1764,17 @@ void
QMenuBarPrivate::macCreateMenuBar(QWidget *parent)
{
Q_Q(QMenuBar);
- static int checkEnv = -1;
- if (qt_mac_no_native_menubar == false && checkEnv < 0) {
- checkEnv = !qgetenv("QT_MAC_NO_NATIVE_MENUBAR").isEmpty();
- qt_mac_no_native_menubar = checkEnv;
+ static int dontUseNativeMenuBar = -1;
+ // We call the isNativeMenuBar function here
+ // because that will make sure that local overrides
+ // are dealt with correctly.
+ bool qt_mac_no_native_menubar = !q->isNativeMenuBar();
+ if (qt_mac_no_native_menubar == false && dontUseNativeMenuBar < 0) {
+ bool isPlugin = QApplication::testAttribute(Qt::AA_MacPluginApplication);
+ bool environmentSaysNo = !qgetenv("QT_MAC_NO_NATIVE_MENUBAR").isEmpty();
+ dontUseNativeMenuBar = isPlugin || environmentSaysNo;
+ QApplication::instance()->setAttribute(Qt::AA_DontUseNativeMenuBar, dontUseNativeMenuBar);
+ qt_mac_no_native_menubar = !q->isNativeMenuBar();
}
if (!qt_mac_no_native_menubar) {
extern void qt_event_request_menubarupdate(); //qapplication_mac.cpp
@@ -1770,7 +1809,7 @@ void QMenuBarPrivate::macDestroyMenuBar()
OSMenuRef QMenuBarPrivate::macMenu()
{
Q_Q(QMenuBar);
- if (!mac_menubar) {
+ if (!q->isNativeMenuBar() || !mac_menubar) {
return 0;
} else if (!mac_menubar->menu) {
mac_menubar->menu = qt_mac_create_menu(q);
@@ -1786,7 +1825,7 @@ OSMenuRef QMenuBarPrivate::macMenu()
SetMenuItemHierarchicalMenu(mac_menubar->menu, index, mac_menubar->apple_menu);
SetMenuItemProperty(mac_menubar->apple_menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(q), &q);
#else
- [mac_menubar->apple_menu setTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(QString(QChar(0x14)))))];
+ [mac_menubar->apple_menu setTitle:qt_mac_QStringToNSString(QString(QChar(0x14)))];
NSMenuItem *apple_menuItem = [[NSMenuItem alloc] init];
[apple_menuItem setSubmenu:mac_menubar->menu];
[mac_menubar->apple_menu addItem:apple_menuItem];
@@ -1829,6 +1868,9 @@ OSMenuRef QMenuBar::macMenu() { return d_func()->macMenu(); }
*/
static bool qt_mac_is_ancestor(QWidget* possibleAncestor, QWidget *child)
{
+ if (!possibleAncestor)
+ return false;
+
QWidget * current = child->parentWidget();
while (current != 0) {
if (current == possibleAncestor)
@@ -1847,22 +1889,19 @@ static bool qt_mac_should_disable_menu(QMenuBar *menuBar, QWidget *modalWidget)
{
if (modalWidget == 0 || menuBar == 0)
return false;
- const Qt::WindowModality modality = modalWidget->windowModality();
- if (modality == Qt::ApplicationModal) {
- return true;
- } else if (modality == Qt::WindowModal) {
- QWidget * parent = menuBar->parentWidget();
-
- // Special case for the global menu bar: It's not associated
- // with a window so don't disable it.
- if (parent == 0)
- return false;
- // Disable menu entries in menu bars that belong to ancestors of
- // the modal widget, leave entries in unrelated menu bars enabled.
- return qt_mac_is_ancestor(parent, modalWidget);
+ // If there is an application modal window on
+ // screen, the entries of the menubar should be disabled:
+ QWidget *w = modalWidget;
+ while (w) {
+ if (w->isVisible() && w->windowModality() == Qt::ApplicationModal)
+ return true;
+ w = w->parentWidget();
}
- return false; // modality == NonModal
+
+ // INVARIANT: modalWidget is window modal. Disable menu entries
+ // if the menu bar belongs to an ancestor of modalWidget:
+ return qt_mac_is_ancestor(menuBar->parentWidget(), modalWidget);
}
static void cancelAllMenuTracking()
@@ -1891,9 +1930,6 @@ static void cancelAllMenuTracking()
*/
bool QMenuBar::macUpdateMenuBar()
{
- if (qt_mac_no_native_menubar) //nothing to be done..
- return true;
-
cancelAllMenuTracking();
QMenuBar *mb = 0;
//find a menu bar
@@ -1927,7 +1963,7 @@ bool QMenuBar::macUpdateMenuBar()
mb = fallback;
//now set it
bool ret = false;
- if (mb) {
+ if (mb && mb->isNativeMenuBar()) {
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
#endif
@@ -1965,7 +2001,7 @@ bool QMenuBar::macUpdateMenuBar()
qt_mac_current_menubar.qmenubar = mb;
qt_mac_current_menubar.modal = QApplicationPrivate::modalState();
ret = true;
- } else if (qt_mac_current_menubar.qmenubar) {
+ } else if (qt_mac_current_menubar.qmenubar && qt_mac_current_menubar.qmenubar->isNativeMenuBar()) {
const bool modal = QApplicationPrivate::modalState();
if (modal != qt_mac_current_menubar.modal) {
ret = true;
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h
index 4d7ec47..3f3018f 100644
--- a/src/gui/widgets/qmenu_p.h
+++ b/src/gui/widgets/qmenu_p.h
@@ -61,6 +61,9 @@
#include "QtCore/qbasictimer.h"
#include "private/qwidget_p.h"
+#ifdef Q_WS_S60
+class CEikMenuPane;
+#endif
QT_BEGIN_NAMESPACE
#ifndef QT_NO_MENU
@@ -112,7 +115,7 @@ struct QMenuMergeItem
typedef QList<QMenuMergeItem> QMenuMergeList;
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
struct QWceMenuAction {
uint command;
QPointer<QAction> action;
@@ -120,21 +123,33 @@ struct QWceMenuAction {
QWceMenuAction() : menuHandle(0), command(0) {}
};
#endif
+#ifdef Q_WS_S60
+struct QSymbianMenuAction {
+ uint command;
+ int parent;
+ CEikMenuPane* menuPane;
+ QPointer<QAction> action;
+ QSymbianMenuAction() : command(0) {}
+};
+#endif
class QMenuPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QMenu)
public:
QMenuPrivate() : itemsDirty(0), maxIconWidth(0), tabWidth(0), ncols(0),
- collapsibleSeparators(true), hasHadMouse(0), aboutToHide(0), motions(0),
+ collapsibleSeparators(true), activationRecursionGuard(false), hasHadMouse(0), aboutToHide(0), motions(0),
currentAction(0), scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0),
- hasCheckableItems(0), sloppyAction(0)
+ hasCheckableItems(0), sloppyAction(0), doChildEffects(false)
#ifdef Q_WS_MAC
,mac_menu(0)
#endif
-#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR)
+#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
,wce_menu(0)
#endif
+#ifdef Q_WS_S60
+ ,symbian_menu(0)
+#endif
#ifdef QT3_SUPPORT
,emitHighlighted(false)
#endif
@@ -145,24 +160,28 @@ public:
#ifdef Q_WS_MAC
delete mac_menu;
#endif
-#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR)
+#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
delete wce_menu;
#endif
+#ifdef Q_WS_S60
+ delete symbian_menu;
+#endif
+
}
void init();
+ int scrollerHeight() const;
+
//item calculations
mutable uint itemsDirty : 1;
mutable uint maxIconWidth, tabWidth;
QRect actionRect(QAction *) const;
- mutable QMap<QAction*, QRect> actionRects;
- mutable QList<QAction*> actionList;
- mutable QHash<QAction *, QWidget *> widgetItems;
- void calcActionRects(QMap<QAction*, QRect> &actionRects, QList<QAction*> &actionList) const;
- void updateActions();
+
+ mutable QVector<QRect> actionRects;
+ mutable QWidgetList widgetItems;
+ void updateActionRects() const;
QRect popupGeometry(int screen=-1) const;
- QList<QAction *> filterActions(const QList<QAction *> &actions) const;
- uint ncols : 4; //4 bits is probably plenty
+ mutable uint ncols : 4; //4 bits is probably plenty
uint collapsibleSeparators : 1;
uint activationRecursionGuard : 1;
@@ -191,10 +210,10 @@ public:
enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 };
uint scrollFlags : 2, scrollDirection : 2;
int scrollOffset;
- QBasicTimer *scrollTimer;
+ QBasicTimer scrollTimer;
- QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0), scrollTimer(0) { }
- ~QMenuScroller() { delete scrollTimer; }
+ QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0) { }
+ ~QMenuScroller() { }
} *scroll;
void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false);
void scrollMenu(QMenuScroller::ScrollDirection direction, bool page=false, bool active=false);
@@ -220,7 +239,7 @@ public:
virtual QList<QPointer<QWidget> > calcCausedStack() const;
QMenuCaused causedPopup;
void hideUpToMenuBar();
- void hideMenu(QMenu *menu);
+ void hideMenu(QMenu *menu, bool justRegister = false);
//index mappings
inline QAction *actionAt(int i) const { return q_func()->actions().at(i); }
@@ -234,7 +253,7 @@ public:
//sloppy selection
static QBasicTimer sloppyDelayTimer;
- QAction *sloppyAction;
+ mutable QAction *sloppyAction;
QRegion sloppyRegion;
//default action
@@ -284,6 +303,7 @@ public:
} *mac_menu;
OSMenuRef macMenu(OSMenuRef merge);
void setMacMenuEnabled(bool enable = true);
+ void syncSeparatorsCollapsible(bool collapsible);
static QHash<OSMenuRef, OSMenuRef> mergeMenuHash;
static QHash<OSMenuRef, QMenuMergeList*> mergeMenuItemsHash;
#endif
@@ -293,7 +313,7 @@ public:
bool emitHighlighted;
#endif
-#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR)
+#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
struct QWceMenuPrivate {
QList<QWceMenuAction*> actionItems;
HMENU menuHandle;
@@ -318,7 +338,28 @@ public:
HMENU wceMenu(bool create = false);
QAction* wceCommands(uint command);
#endif
-
+#if defined(Q_WS_S60)
+ struct QSymbianMenuPrivate {
+ QList<QSymbianMenuAction*> actionItems;
+ QSymbianMenuPrivate();
+ ~QSymbianMenuPrivate();
+ void addAction(QAction *, QSymbianMenuAction* =0);
+ void addAction(QSymbianMenuAction *, QSymbianMenuAction* =0);
+ void syncAction(QSymbianMenuAction *);
+ inline void syncAction(QAction *a) { syncAction(findAction(a)); }
+ void removeAction(QSymbianMenuAction *);
+ void rebuild(bool reCreate = false);
+ inline void removeAction(QAction *a) { removeAction(findAction(a)); }
+ inline QSymbianMenuAction *findAction(QAction *a) {
+ for(int i = 0; i < actionItems.size(); i++) {
+ QSymbianMenuAction *act = actionItems[i];
+ if(a == act->action)
+ return act;
+ }
+ return 0;
+ }
+ } *symbian_menu;
+#endif
QPointer<QWidget> noReplayFor;
};
diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp
new file mode 100644
index 0000000..dc92b07
--- /dev/null
+++ b/src/gui/widgets/qmenu_symbian.cpp
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmenu.h"
+#include "qapplication.h"
+#include "qevent.h"
+#include "qstyle.h"
+#include "qdebug.h"
+#include "qwidgetaction.h"
+#include <private/qapplication_p.h>
+#include <private/qmenu_p.h>
+#include <private/qmenubar_p.h>
+#include <qt_s60_p.h>
+#include <QtCore/qlibrary.h>
+
+#ifdef Q_WS_S60
+#include <eikmenub.h>
+#include <eikmenup.h>
+#include <eikaufty.h>
+#include <eikbtgpc.h>
+#include <avkon.rsg>
+#endif
+
+#if !defined(QT_NO_MENUBAR) && defined(Q_WS_S60)
+
+QT_BEGIN_NAMESPACE
+
+typedef QMultiHash<QWidget *, QMenuBarPrivate *> MenuBarHash;
+Q_GLOBAL_STATIC(MenuBarHash, menubars)
+
+#define QT_FIRST_MENU_ITEM 32000
+
+struct SymbianMenuItem
+{
+ int id;
+ CEikMenuPaneItem::SData menuItemData;
+ QList<SymbianMenuItem*> children;
+ QAction* action;
+};
+
+static QList<SymbianMenuItem*> symbianMenus;
+static QList<QMenuBar*> nativeMenuBars;
+static uint qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM;
+static QPointer<QWidget> widgetWithContextMenu;
+static QList<QAction*> contextMenuActionList;
+static QAction contextAction(0);
+static int contexMenuCommand=0;
+
+bool menuExists()
+{
+ QWidget *w = qApp->activeWindow();
+ QMenuBarPrivate *mb = menubars()->value(w);
+ if ((!mb) && !menubars()->count())
+ return false;
+ return true;
+}
+
+static bool hasContextMenu(QWidget* widget)
+{
+ if (!widget)
+ return false;
+ const Qt::ContextMenuPolicy policy = widget->contextMenuPolicy();
+ if (policy != Qt::NoContextMenu && policy != Qt::PreventContextMenu ) {
+ return true;
+ }
+ return false;
+}
+// ### FIX THIS, copy/paste of original (faulty) stripped text implementation.
+// Implementation should be removed from QAction implementation to some generic place
+static QString qt_strippedText_copy_from_qaction(QString s)
+{
+ s.remove(QString::fromLatin1("..."));
+ int i = 0;
+ while (i < s.size()) {
+ ++i;
+ if (s.at(i-1) != QLatin1Char('&'))
+ continue;
+ if (i < s.size() && s.at(i) == QLatin1Char('&'))
+ ++i;
+ s.remove(i-1,1);
+ }
+ return s.trimmed();
+};
+
+static SymbianMenuItem* qt_symbian_find_menu(int id, const QList<SymbianMenuItem*> &parent)
+{
+ int index=0;
+ while (index < parent.count()) {
+ SymbianMenuItem* temp = parent[index];
+ if (temp->menuItemData.iCascadeId == id)
+ return temp;
+ else if (temp->menuItemData.iCascadeId != 0) {
+ SymbianMenuItem* result = qt_symbian_find_menu( id, temp->children);
+ if (result)
+ return result;
+ }
+ index++;
+ }
+ return 0;
+}
+
+static SymbianMenuItem* qt_symbian_find_menu_item(int id, const QList<SymbianMenuItem*> &parent)
+{
+ int index=0;
+ while (index < parent.count()) {
+ SymbianMenuItem* temp = parent[index];
+ if (temp->menuItemData.iCascadeId != 0) {
+ SymbianMenuItem* result = qt_symbian_find_menu_item( id, temp->children);
+ if (result)
+ return result;
+ }
+ else if (temp->menuItemData.iCommandId == id)
+ return temp;
+ index++;
+
+ }
+ return 0;
+}
+
+static void qt_symbian_insert_action(QSymbianMenuAction* action, QList<SymbianMenuItem*>* parent)
+{
+ if (action->action->isVisible()) {
+ if (action->action->isSeparator())
+ return;
+
+// ### FIX THIS, the qt_strippedText2 doesn't work perfectly for stripping & marks. Same bug is in QAction
+// New really working method is needed in a place where the implementation isn't copy/pasted
+ QString text = qt_strippedText_copy_from_qaction(action->action->text());
+ TPtrC menuItemText(qt_QString2TPtrC(text));
+
+ if (action->action->menu()) {
+ SymbianMenuItem* menuItem = new SymbianMenuItem();
+ menuItem->menuItemData.iCascadeId = action->command;
+ menuItem->menuItemData.iCommandId = action->command;
+ menuItem->menuItemData.iFlags = 0;
+ menuItem->menuItemData.iText = menuItemText;
+ menuItem->action = action->action;
+ if (action->action->menu()->actions().size() == 0 || !action->action->isEnabled() )
+ menuItem->menuItemData.iFlags |= EEikMenuItemDimmed;
+ parent->append(menuItem);
+
+ if (action->action->menu()->actions().size() > 0) {
+ for (int c2= 0; c2 < action->action->menu()->actions().size(); ++c2) {
+ QSymbianMenuAction *symbianAction2 = new QSymbianMenuAction;
+ symbianAction2->action = action->action->menu()->actions().at(c2);
+ QMenu * menu = symbianAction2->action->menu();
+ symbianAction2->command = qt_symbian_menu_static_cmd_id++;
+ qt_symbian_insert_action(symbianAction2, &(menuItem->children));
+ }
+ }
+
+ } else {
+ SymbianMenuItem* menuItem = new SymbianMenuItem();
+ menuItem->menuItemData.iCascadeId = 0;
+ menuItem->menuItemData.iCommandId = action->command;
+ menuItem->menuItemData.iFlags = 0;
+ menuItem->menuItemData.iText = menuItemText;
+ menuItem->action = action->action;
+ if (!action->action->isEnabled()){
+ menuItem->menuItemData.iFlags += EEikMenuItemDimmed;
+ }
+
+ if (action->action->isCheckable()) {
+ if (action->action->isChecked())
+ menuItem->menuItemData.iFlags += EEikMenuItemCheckBox | EEikMenuItemSymbolOn;
+ else
+ menuItem->menuItemData.iFlags += EEikMenuItemCheckBox;
+ }
+ parent->append(menuItem);
+ }
+ }
+}
+
+void deleteAll(QList<SymbianMenuItem*> *items)
+{
+ while (!items->isEmpty()) {
+ SymbianMenuItem* temp = items->takeFirst();
+ deleteAll(&temp->children);
+ delete temp;
+ }
+}
+
+static void rebuildMenu()
+{
+ widgetWithContextMenu = 0;
+ QMenuBarPrivate *mb = 0;
+ QWidget *w = qApp->activeWindow();
+ QWidget* focusWidget = QApplication::focusWidget();
+ if (focusWidget) {
+ if (hasContextMenu(focusWidget))
+ widgetWithContextMenu = focusWidget;
+ }
+
+ if (w) {
+ mb = menubars()->value(w);
+ qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM;
+ deleteAll( &symbianMenus );
+ if (!mb)
+ return;
+ mb->symbian_menubar->rebuild();
+ }
+}
+
+#ifdef Q_WS_S60
+Q_GUI_EXPORT void qt_symbian_show_toplevel( CEikMenuPane* menuPane)
+{
+ if (!menuExists())
+ return;
+ rebuildMenu();
+ for (int i = 0; i < symbianMenus.count(); ++i)
+ QT_TRAP_THROWING(menuPane->AddMenuItemL(symbianMenus.at(i)->menuItemData));
+}
+
+Q_GUI_EXPORT void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id)
+{
+ SymbianMenuItem* menu = qt_symbian_find_menu(id, symbianMenus);
+ if (menu) {
+ for (int i = 0; i < menu->children.count(); ++i)
+ QT_TRAP_THROWING(menuPane->AddMenuItemL(menu->children.at(i)->menuItemData));
+ }
+}
+#endif // Q_WS_S60
+
+void QMenuBarPrivate::symbianCommands(int command)
+{
+ if (command == contexMenuCommand && !widgetWithContextMenu.isNull()) {
+ QContextMenuEvent* event = new QContextMenuEvent(QContextMenuEvent::Keyboard, QPoint(0,0));
+ QCoreApplication::postEvent(widgetWithContextMenu, event);
+ }
+
+ int size = nativeMenuBars.size();
+ for (int i = 0; i < nativeMenuBars.size(); ++i) {
+ SymbianMenuItem* menu = qt_symbian_find_menu_item(command, symbianMenus);
+ if (!menu)
+ continue;
+
+ emit nativeMenuBars.at(i)->triggered(menu->action);
+ menu->action->activate(QAction::Trigger);
+ break;
+ }
+}
+
+void QMenuBarPrivate::symbianCreateMenuBar(QWidget *parent)
+{
+ Q_Q(QMenuBar);
+ if (parent && parent->isWindow()){
+ menubars()->insert(q->window(), this);
+ symbian_menubar = new QSymbianMenuBarPrivate(this);
+ nativeMenuBars.append(q);
+ }
+}
+
+void QMenuBarPrivate::symbianDestroyMenuBar()
+{
+ Q_Q(QMenuBar);
+ int index = nativeMenuBars.indexOf(q);
+ nativeMenuBars.removeAt(index);
+ menubars()->remove(q->window(), this);
+ rebuildMenu();
+ if (symbian_menubar)
+ delete symbian_menubar;
+ symbian_menubar = 0;
+}
+
+QMenuBarPrivate::QSymbianMenuBarPrivate::QSymbianMenuBarPrivate(QMenuBarPrivate *menubar)
+{
+ d = menubar;
+}
+
+QMenuBarPrivate::QSymbianMenuBarPrivate::~QSymbianMenuBarPrivate()
+{
+ deleteAll( &symbianMenus );
+ symbianMenus.clear();
+ d = 0;
+ rebuild();
+}
+
+QMenuPrivate::QSymbianMenuPrivate::QSymbianMenuPrivate()
+{
+}
+
+QMenuPrivate::QSymbianMenuPrivate::~QSymbianMenuPrivate()
+{
+
+}
+
+void QMenuPrivate::QSymbianMenuPrivate::addAction(QAction *a, QSymbianMenuAction *before)
+{
+ QSymbianMenuAction *action = new QSymbianMenuAction;
+ action->action = a;
+ action->command = qt_symbian_menu_static_cmd_id++;
+ addAction(action, before);
+}
+
+void QMenuPrivate::QSymbianMenuPrivate::addAction(QSymbianMenuAction *action, QSymbianMenuAction *before)
+{
+ if (!action)
+ return;
+ int before_index = actionItems.indexOf(before);
+ if (before_index < 0) {
+ before = 0;
+ before_index = actionItems.size();
+ }
+ actionItems.insert(before_index, action);
+}
+
+
+void QMenuPrivate::QSymbianMenuPrivate::syncAction(QSymbianMenuAction *)
+{
+ rebuild();
+}
+
+void QMenuPrivate::QSymbianMenuPrivate::removeAction(QSymbianMenuAction *action)
+{
+ actionItems.removeAll(action);
+ delete action;
+ action = 0;
+ rebuild();
+}
+
+void QMenuPrivate::QSymbianMenuPrivate::rebuild(bool)
+{
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::addAction(QAction *a, QSymbianMenuAction *before)
+{
+ QSymbianMenuAction *action = new QSymbianMenuAction;
+ action->action = a;
+ action->command = qt_symbian_menu_static_cmd_id++;
+ addAction(action, before);
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::addAction(QSymbianMenuAction *action, QSymbianMenuAction *before)
+{
+ if (!action)
+ return;
+ int before_index = actionItems.indexOf(before);
+ if (before_index < 0) {
+ before = 0;
+ before_index = actionItems.size();
+ }
+ actionItems.insert(before_index, action);
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::syncAction(QSymbianMenuAction*)
+{
+ rebuild();
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::removeAction(QSymbianMenuAction *action)
+{
+ actionItems.removeAll(action);
+ delete action;
+ rebuild();
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::insertNativeMenuItems(const QList<QAction*> &actions)
+{
+ for (int i = 0; i <actions.size(); ++i) {
+ QSymbianMenuAction *symbianActionTopLevel = new QSymbianMenuAction;
+ symbianActionTopLevel->action = actions.at(i);
+ symbianActionTopLevel->parent = 0;
+ symbianActionTopLevel->command = qt_symbian_menu_static_cmd_id++;
+ qt_symbian_insert_action(symbianActionTopLevel, &symbianMenus);
+ }
+}
+
+
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::rebuild()
+{
+ contexMenuCommand = 0;
+ qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM;
+ deleteAll( &symbianMenus );
+ if (d)
+ insertNativeMenuItems(d->actions);
+
+ contextMenuActionList.clear();
+ if (widgetWithContextMenu) {
+ contexMenuCommand = qt_symbian_menu_static_cmd_id;
+ contextAction.setText(QMenuBar::tr("Actions"));
+ contextMenuActionList.append(&contextAction);
+ insertNativeMenuItems(contextMenuActionList);
+ }
+}
+QT_END_NAMESPACE
+
+#endif //QT_NO_MENUBAR
diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp
index c3f4871..1c9c02e 100644
--- a/src/gui/widgets/qmenu_wince.cpp
+++ b/src/gui/widgets/qmenu_wince.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
//Native menubars are only supported for Windows Mobile not the standard SDK/generic WinCE
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qmenu.h"
#include "qt_windows.h"
#include "qapplication.h"
@@ -621,4 +621,4 @@ void QMenuBarPrivate::QWceMenuBarPrivate::rebuild() {
QT_END_NAMESPACE
#endif //QT_NO_MENUBAR
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp
index 280fac2..37e172b 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -67,7 +67,7 @@
#include "qmenubar_p.h"
#include "qdebug.h"
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp
#endif
@@ -116,11 +116,9 @@ QSize QMenuBarExtension::sizeHint() const
*/
QAction *QMenuBarPrivate::actionAt(QPoint p) const
{
- Q_Q(const QMenuBar);
- QList<QAction*> items = q->actions();
- for(int i = 0; i < items.size(); ++i) {
- if(actionRect(items.at(i)).contains(p))
- return items.at(i);
+ for(int i = 0; i < actions.size(); ++i) {
+ if(actionRect(actions.at(i)).contains(p))
+ return actions.at(i);
}
return 0;
}
@@ -134,7 +132,7 @@ QRect QMenuBarPrivate::menuRect(bool extVisible) const
result.adjust(hmargin, 0, -hmargin, 0);
if (extVisible) {
- if (q->layoutDirection() == Qt::RightToLeft)
+ if (q->isRightToLeft())
result.setLeft(result.left() + extension->sizeHint().width());
else
result.setWidth(result.width() - extension->sizeHint().width());
@@ -142,7 +140,7 @@ QRect QMenuBarPrivate::menuRect(bool extVisible) const
if (leftWidget && leftWidget->isVisible()) {
QSize sz = leftWidget->sizeHint();
- if (q->layoutDirection() == Qt::RightToLeft)
+ if (q->isRightToLeft())
result.setRight(result.right() - sz.width());
else
result.setLeft(result.left() + sz.width());
@@ -150,7 +148,7 @@ QRect QMenuBarPrivate::menuRect(bool extVisible) const
if (rightWidget && rightWidget->isVisible()) {
QSize sz = rightWidget->sizeHint();
- if (q->layoutDirection() == Qt::RightToLeft)
+ if (q->isRightToLeft())
result.setLeft(result.left() + sz.width());
else
result.setRight(result.right() - sz.width());
@@ -194,22 +192,20 @@ void QMenuBarPrivate::updateGeometries()
}
#ifdef Q_WS_MAC
- if(mac_menubar) {//nothing to see here folks, move along..
+ if(q->isNativeMenuBar()) {//nothing to see here folks, move along..
itemsDirty = false;
return;
}
#endif
- calcActionRects(q_width, q_start, actionRects, actionList);
- itemsWidth = q_width;
- itemsStart = q_start;
+ calcActionRects(q_width, q_start);
currentAction = 0;
#ifndef QT_NO_SHORTCUT
if(itemsDirty) {
for(int j = 0; j < shortcutIndexMap.size(); ++j)
q->releaseShortcut(shortcutIndexMap.value(j));
shortcutIndexMap.resize(0); // faster than clear
- for(int i = 0; i < actionList.count(); i++)
- shortcutIndexMap.append(q->grabShortcut(QKeySequence::mnemonic(actionList.at(i)->text())));
+ for(int i = 0; i < actions.count(); i++)
+ shortcutIndexMap.append(q->grabShortcut(QKeySequence::mnemonic(actions.at(i)->text())));
}
#endif
itemsDirty = false;
@@ -220,8 +216,9 @@ void QMenuBarPrivate::updateGeometries()
//we try to see if the actions will fit there
bool hasHiddenActions = false;
- foreach(QAction *action, actionList) {
- if (!menuRect.contains(actionRect(action))) {
+ for (int i = 0; i < actions.count(); ++i) {
+ const QRect &rect = actionRects.at(i);
+ if (rect.isValid() && !menuRect.contains(rect)) {
hasHiddenActions = true;
break;
}
@@ -230,9 +227,10 @@ void QMenuBarPrivate::updateGeometries()
//...and if not, determine the ones that fit on the menu with the extension visible
if (hasHiddenActions) {
menuRect = this->menuRect(true);
- foreach(QAction *action, actionList) {
- if (!menuRect.contains(actionRect(action))) {
- hiddenActions.append(action);
+ for (int i = 0; i < actions.count(); ++i) {
+ const QRect &rect = actionRects.at(i);
+ if (rect.isValid() && !menuRect.contains(rect)) {
+ hiddenActions.append(actions.at(i));
}
}
}
@@ -247,7 +245,7 @@ void QMenuBarPrivate::updateGeometries()
pop->addActions(hiddenActions);
int vmargin = q->style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q);
- int x = q->layoutDirection() == Qt::RightToLeft
+ int x = q->isRightToLeft()
? menuRect.left() - extension->sizeHint().width() + 1
: menuRect.right();
extension->setGeometry(x, vmargin, extension->sizeHint().width(), menuRect.height() - vmargin*2);
@@ -257,9 +255,9 @@ void QMenuBarPrivate::updateGeometries()
}
q->updateGeometry();
#ifdef QT3_SUPPORT
- if (q->parentWidget() != 0) {
+ if (parent) {
QMenubarUpdatedEvent menubarUpdated(q);
- QApplication::sendEvent(q->parentWidget(), &menubarUpdated);
+ QApplication::sendEvent(parent, &menubarUpdated);
}
#endif
}
@@ -267,12 +265,31 @@ void QMenuBarPrivate::updateGeometries()
QRect QMenuBarPrivate::actionRect(QAction *act) const
{
Q_Q(const QMenuBar);
- QRect ret = actionRects.value(act);
- const int fw = q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, q);
- ret.translate(fw, fw);
+ const int index = actions.indexOf(act);
+ if (index == -1)
+ return QRect();
+
+ //makes sure the geometries are up-to-date
+ const_cast<QMenuBarPrivate*>(this)->updateGeometries();
+
+ if (index >= actionRects.count())
+ return QRect(); // that can happen in case of native menubar
+
+ QRect ret = actionRects.at(index);
return QStyle::visualRect(q->layoutDirection(), q->rect(), ret);
}
+void QMenuBarPrivate::focusFirstAction()
+{
+ if(!currentAction) {
+ updateGeometries();
+ int index = 0;
+ while (index < actions.count() && actionRects.at(index).isNull()) ++index;
+ if (index < actions.count())
+ setCurrentAction(actions.at(index));
+ }
+}
+
void QMenuBarPrivate::setKeyboardMode(bool b)
{
Q_Q(QMenuBar);
@@ -282,17 +299,16 @@ void QMenuBarPrivate::setKeyboardMode(bool b)
}
keyboardState = b;
if(b) {
- QWidget *fw = qApp->focusWidget();
+ QWidget *fw = QApplication::focusWidget();
if (fw != q)
keyboardFocusWidget = fw;
- if(!currentAction && !actionList.isEmpty())
- setCurrentAction(actionList.first());
+ focusFirstAction();
q->setFocus(Qt::MenuBarFocusReason);
} else {
if(!popupState)
setCurrentAction(0);
if(keyboardFocusWidget) {
- if (qApp->focusWidget() == q)
+ if (QApplication::focusWidget() == q)
keyboardFocusWidget->setFocus(Qt::MenuBarFocusReason);
keyboardFocusWidget = 0;
}
@@ -398,28 +414,29 @@ void QMenuBarPrivate::setCurrentAction(QAction *action, bool popup, bool activat
fw->setFocus(Qt::NoFocusReason);
}
-void QMenuBarPrivate::calcActionRects(int max_width, int start, QMap<QAction*, QRect> &actionRects, QList<QAction*> &actionList) const
+void QMenuBarPrivate::calcActionRects(int max_width, int start) const
{
Q_Q(const QMenuBar);
- if(!itemsDirty && itemsWidth == max_width && itemsStart == start) {
- actionRects = actionRects;
- actionList = actionList;
+ if(!itemsDirty)
return;
- }
- actionRects.clear();
- actionList.clear();
- const int itemSpacing = q->style()->pixelMetric(QStyle::PM_MenuBarItemSpacing, 0, q);
+
+ //let's reinitialize the buffer
+ actionRects.resize(actions.count());
+ actionRects.fill(QRect());
+
+ const QStyle *style = q->style();
+
+ const int itemSpacing = style->pixelMetric(QStyle::PM_MenuBarItemSpacing, 0, q);
int max_item_height = 0, separator = -1, separator_start = 0, separator_len = 0;
- QList<QAction*> items = q->actions();
//calculate size
const QFontMetrics fm = q->fontMetrics();
- const int hmargin = q->style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, q),
- vmargin = q->style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q),
- icone = q->style()->pixelMetric(QStyle::PM_SmallIconSize, 0, q);
- for(int i = 0; i < items.count(); i++) {
- QAction *action = items.at(i);
+ const int hmargin = style->pixelMetric(QStyle::PM_MenuBarHMargin, 0, q),
+ vmargin = style->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q),
+ icone = style->pixelMetric(QStyle::PM_SmallIconSize, 0, q);
+ for(int i = 0; i < actions.count(); i++) {
+ QAction *action = actions.at(i);
if(!action->isVisible())
continue;
@@ -427,26 +444,17 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start, QMap<QAction*, Q
//calc what I think the size is..
if(action->isSeparator()) {
- if (q->style()->styleHint(QStyle::SH_DrawMenuBarSeparator, 0, q))
- separator = actionRects.count();
+ if (style->styleHint(QStyle::SH_DrawMenuBarSeparator, 0, q))
+ separator = i;
continue; //we don't really position these!
} else {
- QString s = action->text();
- if(!s.isEmpty()) {
- int w = fm.width(s);
- w -= s.count(QLatin1Char('&')) * fm.width(QLatin1Char('&'));
- w += s.count(QLatin1String("&&")) * fm.width(QLatin1Char('&'));
- sz = QSize(w, fm.height());
- }
-
+ const QString s = action->text();
QIcon is = action->icon();
- if (!is.isNull()) {
- QSize is_sz = QSize(icone, icone);
- if (is_sz.height() > sz.height())
- sz.setHeight(is_sz.height());
- if (is_sz.width() > sz.width())
- sz.setWidth(is_sz.width());
- }
+ // If an icon is set, only the icon is visible
+ if (!is.isNull())
+ sz = sz.expandedTo(QSize(icone, icone));
+ else if (!s.isEmpty())
+ sz = fm.size(Qt::TextShowMnemonic, s);
}
//let the style modify the above size..
@@ -456,8 +464,7 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start, QMap<QAction*, Q
if(!sz.isEmpty()) {
{ //update the separator state
- int iWidth = sz.width();
- iWidth += itemSpacing;
+ int iWidth = sz.width() + itemSpacing;
if(separator == -1)
separator_start += iWidth;
else
@@ -466,17 +473,19 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start, QMap<QAction*, Q
//maximum height
max_item_height = qMax(max_item_height, sz.height());
//append
- actionRects.insert(action, QRect(0, 0, sz.width(), sz.height()));
- actionList.append(action);
+ actionRects[i] = QRect(0, 0, sz.width(), sz.height());
}
}
//calculate position
- int x = ((start == -1) ? hmargin : start) + itemSpacing;
- int y = vmargin;
- for(int i = 0; i < actionList.count(); i++) {
- QAction *action = actionList.at(i);
- QRect &rect = actionRects[action];
+ const int fw = q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, q);
+ int x = fw + ((start == -1) ? hmargin : start) + itemSpacing;
+ int y = fw + vmargin;
+ for(int i = 0; i < actions.count(); i++) {
+ QRect &rect = actionRects[i];
+ if (rect.isNull())
+ continue;
+
//resize
rect.setHeight(max_item_height);
@@ -532,7 +541,6 @@ void QMenuBarPrivate::_q_actionHovered()
emit q->hovered(action);
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
- QList<QAction*> actions = q->actions();
int actionIndex = actions.indexOf(action);
++actionIndex;
QAccessible::updateAccessibility(q, actionIndex, QAccessible::Focus);
@@ -582,8 +590,7 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti
\class QMenuBar
\brief The QMenuBar class provides a horizontal menu bar.
- \ingroup application
- \mainclass
+ \ingroup mainwindow-classes
A menu bar consists of a list of pull-down menu items. You add
menu items with addMenu(). For example, asuming that \c menubar
@@ -707,11 +714,11 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti
\section1 Examples
The \l{mainwindows/menus}{Menus} example shows how to use QMenuBar
- and QMenu. The other \l{Qt Examples#Main Windows}{main window
+ and QMenu. The other \l{Main Window Examples}{main window
application examples} also provide menus using these classes.
\sa QMenu, QShortcut, QAction,
- {http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/index.html}{Introduction to Apple Human Interface Guidelines},
+ {http://developer.apple.com/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGIntro/XHIGIntro.html}{Introduction to Apple Human Interface Guidelines},
{fowler}{GUI Design Handbook: Menu Bar}, {Menus Example}
*/
@@ -726,13 +733,19 @@ void QMenuBarPrivate::init()
if(mac_menubar)
q->hide();
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile()) {
wceCreateMenuBar(q->parentWidget());
if(wce_menubar)
q->hide();
}
#endif
+#ifdef Q_WS_S60
+ symbianCreateMenuBar(q->parentWidget());
+ if(symbian_menubar)
+ q->hide();
+#endif
+
q->setBackgroundRole(QPalette::Button);
oldWindow = oldParent = 0;
#ifdef QT3_SUPPORT
@@ -746,6 +759,28 @@ void QMenuBarPrivate::init()
extension->hide();
}
+//Gets the next action for keyboard navigation
+QAction *QMenuBarPrivate::getNextAction(const int _start, const int increment) const
+{
+ Q_Q(const QMenuBar);
+ const_cast<QMenuBarPrivate*>(this)->updateGeometries();
+ bool allowActiveAndDisabled = q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q);
+ const int start = (_start == -1 && increment == -1) ? actions.count() : _start;
+ const int end = increment == -1 ? 0 : actions.count() - 1;
+
+ for (int i = start; start != end;) {
+ i += increment;
+ QAction *current = actions.at(i);
+ if (!actionRects.at(i).isNull() && (allowActiveAndDisabled || current->isEnabled()))
+ return current;
+ }
+
+ if (_start != -1) //let's try from the beginning or the end
+ return getNextAction(-1, increment);
+
+ return 0;
+}
+
/*!
Constructs a menu bar with parent \a parent.
*/
@@ -777,11 +812,15 @@ QMenuBar::~QMenuBar()
Q_D(QMenuBar);
d->macDestroyMenuBar();
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
Q_D(QMenuBar);
if (qt_wince_is_mobile())
d->wceDestroyMenuBar();
#endif
+#ifdef Q_WS_S60
+ Q_D(QMenuBar);
+ d->symbianDestroyMenuBar();
+#endif
}
/*!
@@ -925,6 +964,13 @@ void QMenuBar::setActiveAction(QAction *act)
/*!
Removes all the actions from the menu bar.
+ \note On Mac OS X, menu items that have been merged to the system
+ menu bar are not removed by this function. One way to handle this
+ would be to remove the extra actions yourself. You can set the
+ \l{QAction::MenuRole}{menu role} on the different menus, so that
+ you know ahead of time which menu items get merged and which do
+ not. Then decide what to recreate or remove yourself.
+
\sa removeAction()
*/
void QMenuBar::clear()
@@ -978,8 +1024,8 @@ void QMenuBar::paintEvent(QPaintEvent *e)
QRegion emptyArea(rect());
//draw the items
- for (int i = 0; i < d->actionList.count(); ++i) {
- QAction *action = d->actionList.at(i);
+ for (int i = 0; i < d->actions.count(); ++i) {
+ QAction *action = d->actions.at(i);
QRect adjustedActionRect = d->actionRect(action);
if (adjustedActionRect.isEmpty() || !d->isVisible(action))
continue;
@@ -1026,16 +1072,16 @@ void QMenuBar::paintEvent(QPaintEvent *e)
*/
void QMenuBar::setVisible(bool visible)
{
-#ifdef Q_WS_MAC
- Q_D(QMenuBar);
- if(d->mac_menubar)
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+ if (isNativeMenuBar())
return;
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_S60
Q_D(QMenuBar);
- if(d->wce_menubar)
+ if(d->symbian_menubar)
return;
#endif
+
QWidget::setVisible(visible);
}
@@ -1101,6 +1147,7 @@ void QMenuBar::mouseReleaseEvent(QMouseEvent *e)
void QMenuBar::keyPressEvent(QKeyEvent *e)
{
Q_D(QMenuBar);
+ d->updateGeometries();
int key = e->key();
if(isRightToLeft()) { // in reverse mode open/close key for submenues are reversed
if(key == Qt::Key_Left)
@@ -1135,54 +1182,8 @@ void QMenuBar::keyPressEvent(QKeyEvent *e)
case Qt::Key_Right:
case Qt::Key_Left: {
if(d->currentAction) {
- QAction *nextAction = 0;
- bool allowActiveAndDisabled =
- style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, this);
-
- for(int i=0; i<(int)d->actionList.count(); i++) {
- if(d->actionList.at(i) == (QAction*)d->currentAction) {
- if (key == Qt::Key_Left) {
- while (i > 0) {
- i--;
- if (allowActiveAndDisabled || d->actionList[i]->isEnabled()) {
- nextAction = d->actionList.at(i);
- break;
- }
- }
- } else {
- while (i < d->actionList.count()-1) {
- i++;
- if (allowActiveAndDisabled || d->actionList[i]->isEnabled()) {
- nextAction = d->actionList.at(i);
- break;
- }
- }
- }
- break;
-
- }
- }
-
- if(!nextAction) {
- if (key == Qt::Key_Left) {
- for (int i = d->actionList.size() - 1 ; i >= 0 ; --i) {
- if (allowActiveAndDisabled || d->actionList[i]->isEnabled()) {
- nextAction = d->actionList.at(i);
- i--;
- break;
- }
- }
- } else {
- for (int i = 0 ; i < d->actionList.count() ; ++i) {
- if (allowActiveAndDisabled || d->actionList[i]->isEnabled()) {
- nextAction = d->actionList.at(i);
- i++;
- break;
- }
- }
- }
- }
- if(nextAction) {
+ int index = d->actions.indexOf(d->currentAction);
+ if (QAction *nextAction = d->getNextAction(index, key == Qt::Key_Left ? -1 : +1)) {
d->setCurrentAction(nextAction, d->popupState, true);
key_consumed = true;
}
@@ -1206,8 +1207,10 @@ void QMenuBar::keyPressEvent(QKeyEvent *e)
QAction *first = 0, *currentSelected = 0, *firstAfterCurrent = 0;
{
QChar c = e->text()[0].toUpper();
- for(int i = 0; i < d->actionList.size(); ++i) {
- register QAction *act = d->actionList.at(i);
+ for(int i = 0; i < d->actions.size(); ++i) {
+ if (d->actionRects.at(i).isNull())
+ continue;
+ QAction *act = d->actions.at(i);
QString s = act->text();
if(!s.isEmpty()) {
int ampersand = s.indexOf(QLatin1Char('&'));
@@ -1262,7 +1265,8 @@ void QMenuBar::mouseMoveEvent(QMouseEvent *e)
void QMenuBar::leaveEvent(QEvent *)
{
Q_D(QMenuBar);
- if(!hasFocus() && !d->popupState)
+ if((!hasFocus() && !d->popupState) ||
+ (d->currentAction && d->currentAction->menu() == 0))
d->setCurrentAction(0);
}
@@ -1273,26 +1277,34 @@ void QMenuBar::actionEvent(QActionEvent *e)
{
Q_D(QMenuBar);
d->itemsDirty = true;
+#if defined (Q_WS_MAC) || defined(Q_OS_WINCE)
+ if (isNativeMenuBar()) {
#ifdef Q_WS_MAC
- if(d->mac_menubar) {
+ QMenuBarPrivate::QMacMenuBarPrivate *nativeMenuBar = d->mac_menubar;
+#else
+ QMenuBarPrivate::QWceMenuBarPrivate *nativeMenuBar = d->wce_menubar;
+#endif
+ if (!nativeMenuBar)
+ return;
if(e->type() == QEvent::ActionAdded)
- d->mac_menubar->addAction(e->action(), d->mac_menubar->findAction(e->before()));
+ nativeMenuBar->addAction(e->action(), nativeMenuBar->findAction(e->before()));
else if(e->type() == QEvent::ActionRemoved)
- d->mac_menubar->removeAction(e->action());
+ nativeMenuBar->removeAction(e->action());
else if(e->type() == QEvent::ActionChanged)
- d->mac_menubar->syncAction(e->action());
+ nativeMenuBar->syncAction(e->action());
}
#endif
-#ifdef Q_OS_WINCE
- if(d->wce_menubar) {
+#ifdef Q_WS_S60
+ if(d->symbian_menubar) {
if(e->type() == QEvent::ActionAdded)
- d->wce_menubar->addAction(e->action(), d->wce_menubar->findAction(e->before()));
+ d->symbian_menubar->addAction(e->action(), d->symbian_menubar->findAction(e->before()));
else if(e->type() == QEvent::ActionRemoved)
- d->wce_menubar->removeAction(e->action());
+ d->symbian_menubar->removeAction(e->action());
else if(e->type() == QEvent::ActionChanged)
- d->wce_menubar->syncAction(e->action());
+ d->symbian_menubar->syncAction(e->action());
}
#endif
+
if(e->type() == QEvent::ActionAdded) {
connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
@@ -1311,8 +1323,8 @@ void QMenuBar::actionEvent(QActionEvent *e)
void QMenuBar::focusInEvent(QFocusEvent *)
{
Q_D(QMenuBar);
- if(d->keyboardState && !d->currentAction && !d->actionList.isEmpty())
- d->setCurrentAction(d->actionList.first());
+ if(d->keyboardState)
+ d->focusFirstAction();
}
/*!
@@ -1375,10 +1387,15 @@ void QMenuBarPrivate::handleReparent()
macCreateMenuBar(newParent);
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile() && wce_menubar)
wce_menubar->rebuild();
#endif
+#ifdef Q_WS_S60
+ if (symbian_menubar)
+ symbian_menubar->rebuild();
+#endif
+
}
#ifdef QT3_SUPPORT
@@ -1613,30 +1630,26 @@ QRect QMenuBar::actionGeometry(QAction *act) const
QSize QMenuBar::minimumSizeHint() const
{
Q_D(const QMenuBar);
-#ifdef Q_WS_MAC
- const bool as_gui_menubar = !d->mac_menubar;
-#elif defined (Q_OS_WINCE)
- const bool as_gui_menubar = !d->wce_menubar;
+#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_WS_S60)
+ const bool as_gui_menubar = !isNativeMenuBar();
#else
const bool as_gui_menubar = true;
#endif
ensurePolished();
QSize ret(0, 0);
+ const_cast<QMenuBarPrivate*>(d)->updateGeometries();
const int hmargin = style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, this);
const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, this);
int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this);
int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this);
if(as_gui_menubar) {
- QMap<QAction*, QRect> actionRects;
- QList<QAction*> actionList;
int w = parentWidget() ? parentWidget()->width() : QApplication::desktop()->width();
- d->calcActionRects(w - (2 * fw), 0, actionRects, actionList);
- if (d->actionList.count() > 0) {
- ret = d->actionRect(d->actionList.at(0)).size();
- if (!d->extension->isHidden())
- ret += QSize(d->extension->sizeHint().width(), 0);
- }
+ d->calcActionRects(w - (2 * fw), 0);
+ for (int i = 0; ret.isNull() && i < d->actions.count(); ++i)
+ ret = d->actionRects.at(i).size();
+ if (!d->extension->isHidden())
+ ret += QSize(d->extension->sizeHint().width(), 0);
ret += QSize(2*fw + hmargin, 2*fw + vmargin);
}
int margin = 2*vmargin + 2*fw + spaceBelowMenuBar;
@@ -1673,34 +1686,30 @@ QSize QMenuBar::minimumSizeHint() const
QSize QMenuBar::sizeHint() const
{
Q_D(const QMenuBar);
-#ifdef Q_WS_MAC
- const bool as_gui_menubar = !d->mac_menubar;
-#elif defined (Q_OS_WINCE)
- const bool as_gui_menubar = !d->wce_menubar;
+#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_WS_S60)
+ const bool as_gui_menubar = !isNativeMenuBar();
#else
const bool as_gui_menubar = true;
#endif
+
ensurePolished();
QSize ret(0, 0);
+ const_cast<QMenuBarPrivate*>(d)->updateGeometries();
const int hmargin = style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, this);
const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, this);
int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this);
int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this);
if(as_gui_menubar) {
- QMap<QAction*, QRect> actionRects;
- QList<QAction*> actionList;
const int w = parentWidget() ? parentWidget()->width() : QApplication::desktop()->width();
- d->calcActionRects(w - (2 * fw), 0, actionRects, actionList);
- for (QMap<QAction*, QRect>::const_iterator i = actionRects.constBegin();
- i != actionRects.constEnd(); ++i) {
- QRect actionRect(i.value());
- if(actionRect.x() + actionRect.width() > ret.width())
- ret.setWidth(actionRect.x() + actionRect.width());
- if(actionRect.y() + actionRect.height() > ret.height())
- ret.setHeight(actionRect.y() + actionRect.height());
+ d->calcActionRects(w - (2 * fw), 0);
+ for (int i = 0; i < d->actionRects.count(); ++i) {
+ const QRect &actionRect = d->actionRects.at(i);
+ ret = ret.expandedTo(QSize(actionRect.x() + actionRect.width(), actionRect.y() + actionRect.height()));
}
- ret += QSize(2*fw + 2*hmargin, 2*fw + 2*vmargin);
+ //the action geometries already contain the top and left
+ //margins. So we only need to add those from right and bottom.
+ ret += QSize(fw + hmargin, fw + vmargin);
}
int margin = 2*vmargin + 2*fw + spaceBelowMenuBar;
if(d->leftWidget) {
@@ -1736,23 +1745,22 @@ QSize QMenuBar::sizeHint() const
int QMenuBar::heightForWidth(int) const
{
Q_D(const QMenuBar);
-#ifdef Q_WS_MAC
- const bool as_gui_menubar = !d->mac_menubar;
-#elif defined (Q_OS_WINCE)
- const bool as_gui_menubar = !d->wce_menubar;
+#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_WS_S60)
+ const bool as_gui_menubar = !isNativeMenuBar();
#else
const bool as_gui_menubar = true;
#endif
+
+ const_cast<QMenuBarPrivate*>(d)->updateGeometries();
int height = 0;
const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, this);
int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this);
int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this);
if(as_gui_menubar) {
- if (d->actionList.count()) {
- // assume all actionrects have the same height
- height = d->actionRect(d->actionList.first()).height();
+ for (int i = 0; i < d->actionRects.count(); ++i)
+ height = qMax(height, d->actionRects.at(i).height());
+ if (height) //there is at least one non-null item
height += spaceBelowMenuBar;
- }
height += 2*fw;
height += 2*vmargin;
}
@@ -1779,12 +1787,15 @@ int QMenuBar::heightForWidth(int) const
void QMenuBarPrivate::_q_internalShortcutActivated(int id)
{
Q_Q(QMenuBar);
- QAction *act = actionList.at(id);
+ QAction *act = actions.at(id);
setCurrentAction(act, true, true);
if (act && !act->menu()) {
activateAction(act, QAction::Trigger);
//100 is the same as the default value in QPushButton::animateClick
autoReleaseTimer.start(100, q);
+ } else if (act && q->style()->styleHint(QStyle::SH_MenuBar_AltKeyNavigation, 0, q)) {
+ // When we open a menu using a shortcut, we should end up in keyboard state
+ setKeyboardMode(true);
}
}
@@ -1857,6 +1868,60 @@ QWidget *QMenuBar::cornerWidget(Qt::Corner corner) const
}
/*!
+ \property QMenuBar::nativeMenuBar
+ \brief Whether or not a menubar will be used as a native menubar on platforms that support it
+ \since 4.6
+
+ This property specifies whether or not the menubar should be used as a native menubar on platforms
+ that support it. The currently supported platforms are Mac OS X and Windows CE. On these platforms
+ if this property is true, the menubar is used in the native menubar and is not in the window of
+ its parent, if false the menubar remains in the window. On other platforms the value of this
+ attribute has no effect.
+
+ The default is to follow whether the Qt::AA_DontUseNativeMenuBar attribute
+ is set for the application. Explicitly settings this property overrides
+ the presence (or abscence) of the attribute.
+*/
+
+void QMenuBar::setNativeMenuBar(bool nativeMenuBar)
+{
+ Q_D(QMenuBar);
+ if (d->nativeMenuBar == -1 || (nativeMenuBar != bool(d->nativeMenuBar))) {
+ d->nativeMenuBar = nativeMenuBar;
+#ifdef Q_WS_MAC
+ if (!d->nativeMenuBar) {
+ extern void qt_mac_clear_menubar();
+ qt_mac_clear_menubar();
+ d->macDestroyMenuBar();
+ const QList<QAction *> &menubarActions = actions();
+ for (int i = 0; i < menubarActions.size(); ++i) {
+ const QAction *action = menubarActions.at(i);
+ if (QMenu *menu = action->menu()) {
+ delete menu->d_func()->mac_menu;
+ menu->d_func()->mac_menu = 0;
+ }
+ }
+ } else {
+ d->macCreateMenuBar(parentWidget());
+ }
+ macUpdateMenuBar();
+ updateGeometry();
+ setVisible(false);
+ setVisible(true);
+#endif
+ }
+}
+
+bool QMenuBar::isNativeMenuBar() const
+{
+ Q_D(const QMenuBar);
+ if (d->nativeMenuBar == -1) {
+ return !QApplication::instance()->testAttribute(Qt::AA_DontUseNativeMenuBar);
+ }
+ return d->nativeMenuBar;
+}
+
+/*!
\since 4.4
Sets the default action to \a act.
@@ -1870,13 +1935,13 @@ QWidget *QMenuBar::cornerWidget(Qt::Corner corner) const
\sa defaultAction()
*/
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void QMenuBar::setDefaultAction(QAction *act)
{
Q_D(QMenuBar);
if (d->defaultAction == act)
return;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile())
if (d->defaultAction) {
disconnect(d->defaultAction, SIGNAL(changed()), this, SLOT(_q_updateDefaultAction()));
@@ -1884,7 +1949,7 @@ void QMenuBar::setDefaultAction(QAction *act)
}
#endif
d->defaultAction = act;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile())
if (d->defaultAction) {
connect(d->defaultAction, SIGNAL(changed()), this, SLOT(_q_updateDefaultAction()));
diff --git a/src/gui/widgets/qmenubar.h b/src/gui/widgets/qmenubar.h
index 5bfa561..bdff409 100644
--- a/src/gui/widgets/qmenubar.h
+++ b/src/gui/widgets/qmenubar.h
@@ -64,6 +64,7 @@ class Q_GUI_EXPORT QMenuBar : public QWidget
Q_OBJECT
Q_PROPERTY(bool defaultUp READ isDefaultUp WRITE setDefaultUp)
+ Q_PROPERTY(bool nativeMenuBar READ isNativeMenuBar WRITE setNativeMenuBar)
public:
explicit QMenuBar(QWidget *parent = 0);
@@ -110,7 +111,7 @@ public:
static bool macUpdateMenuBar();
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void setDefaultAction(QAction *);
QAction *defaultAction() const;
@@ -118,6 +119,9 @@ public:
static void wceRefresh();
#endif
+ bool isNativeMenuBar() const;
+ void setNativeMenuBar(bool nativeMenuBar);
+
public Q_SLOTS:
virtual void setVisible(bool visible);
@@ -339,7 +343,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_internalShortcutActivated(int))
Q_PRIVATE_SLOT(d_func(), void _q_updateLayout())
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
Q_PRIVATE_SLOT(d_func(), void _q_updateDefaultAction())
#endif
diff --git a/src/gui/widgets/qmenubar_p.h b/src/gui/widgets/qmenubar_p.h
index 04ba352..71205ae 100644
--- a/src/gui/widgets/qmenubar_p.h
+++ b/src/gui/widgets/qmenubar_p.h
@@ -57,10 +57,17 @@
#include "QtGui/qstyleoption.h"
#include <private/qmenu_p.h> // Mac needs what in this file!
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qguifunctions_wince.h"
#endif
+#ifndef QT_NO_MENUBAR
+#ifdef Q_WS_S60
+class CCoeControl;
+class CEikMenuBar;
+#endif
+#endif
+
QT_BEGIN_NAMESPACE
#ifndef QT_NO_MENUBAR
@@ -69,37 +76,46 @@ class QMenuBarPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QMenuBar)
public:
- QMenuBarPrivate() : itemsDirty(0), itemsWidth(0), itemsStart(-1), currentAction(0), mouseDown(0),
- closePopupMode(0), defaultPopDown(1), popupState(0), keyboardState(0), altPressed(0)
+ QMenuBarPrivate() : itemsDirty(0), currentAction(0), mouseDown(0),
+ closePopupMode(0), defaultPopDown(1), popupState(0), keyboardState(0), altPressed(0),
+ nativeMenuBar(-1), doChildEffects(false)
+#ifdef QT3_SUPPORT
+ , doAutoResize(false)
+#endif
#ifdef Q_WS_MAC
, mac_menubar(0)
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
, wce_menubar(0), wceClassicMenu(false)
#endif
- { }
+#ifdef Q_WS_S60
+ , symbian_menubar(0)
+#endif
+
+ { }
~QMenuBarPrivate()
{
#ifdef Q_WS_MAC
delete mac_menubar;
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
delete wce_menubar;
#endif
+#ifdef Q_WS_S60
+ delete symbian_menubar;
+#endif
}
void init();
- QStyleOptionMenuItem getStyleOption(const QAction *action) const;
+ QAction *getNextAction(const int start, const int increment) const;
//item calculations
uint itemsDirty : 1;
- int itemsWidth, itemsStart;
QVector<int> shortcutIndexMap;
- mutable QMap<QAction*, QRect> actionRects;
- mutable QList<QAction*> actionList;
- void calcActionRects(int max_width, int start, QMap<QAction*, QRect> &actionRects, QList<QAction*> &actionList) const;
+ mutable QVector<QRect> actionRects;
+ void calcActionRects(int max_width, int start) const;
QRect actionRect(QAction *) const;
void updateGeometries();
@@ -115,10 +131,13 @@ public:
QPointer<QMenu> activeMenu;
//keyboard mode for keyboard navigation
+ void focusFirstAction();
void setKeyboardMode(bool);
uint keyboardState : 1, altPressed : 1;
QPointer<QWidget> keyboardFocusWidget;
+
+ int nativeMenuBar : 3; // Only has values -1, 0, and 1
//firing of events
void activateAction(QAction *, QAction::ActionEvent);
@@ -127,7 +146,7 @@ public:
void _q_internalShortcutActivated(int);
void _q_updateLayout();
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void _q_updateDefaultAction();
#endif
@@ -181,7 +200,7 @@ public:
void macDestroyMenuBar();
OSMenuRef macMenu();
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void wceCreateMenuBar(QWidget *);
void wceDestroyMenuBar();
struct QWceMenuBarPrivate {
@@ -220,6 +239,35 @@ public:
void wceRefresh();
bool wceEmitSignals(QList<QWceMenuAction*> actions, uint command);
#endif
+#ifdef Q_WS_S60
+ void symbianCreateMenuBar(QWidget *);
+ void symbianDestroyMenuBar();
+ struct QSymbianMenuBarPrivate {
+ QList<QSymbianMenuAction*> actionItems;
+ QMenuBarPrivate *d;
+ QSymbianMenuBarPrivate(QMenuBarPrivate *menubar);
+ ~QSymbianMenuBarPrivate();
+ void addAction(QAction *, QSymbianMenuAction* =0);
+ void addAction(QSymbianMenuAction *, QSymbianMenuAction* =0);
+ void syncAction(QSymbianMenuAction *);
+ inline void syncAction(QAction *a) { syncAction(findAction(a)); }
+ void removeAction(QSymbianMenuAction *);
+ void rebuild();
+ inline void removeAction(QAction *a) { removeAction(findAction(a)); }
+ inline QSymbianMenuAction *findAction(QAction *a) {
+ for(int i = 0; i < actionItems.size(); i++) {
+ QSymbianMenuAction *act = actionItems[i];
+ if(a == act->action)
+ return act;
+ }
+ return 0;
+ }
+ void insertNativeMenuItems(const QList<QAction*> &actions);
+
+ } *symbian_menubar;
+ static void symbianCommands(int command);
+
+#endif
};
#endif
diff --git a/src/gui/widgets/qmenudata.h b/src/gui/widgets/qmenudata.h
index ad4e7bb..8d48238 100644
--- a/src/gui/widgets/qmenudata.h
+++ b/src/gui/widgets/qmenudata.h
@@ -67,6 +67,8 @@ private:
friend class QMenuBar;
void setId(int);
void setSignalValue(int);
+
+ Q_DISABLE_COPY(QMenuItem);
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp
index 050a7fd..c79e482 100644
--- a/src/gui/widgets/qplaintextedit.cpp
+++ b/src/gui/widgets/qplaintextedit.cpp
@@ -66,12 +66,21 @@
#include <qtexttable.h>
#include <qvariant.h>
+#ifdef Q_WS_WIN
+#include <qstandardgestures.h>
+#endif
+
#include <qinputcontext.h>
#ifndef QT_NO_TEXTEDIT
QT_BEGIN_NAMESPACE
+static inline bool shouldEnableInputMethod(QPlainTextEdit *plaintextedit)
+{
+ return !plaintextedit->isReadOnly();
+}
+
class QPlainTextDocumentLayoutPrivate : public QAbstractTextDocumentLayoutPrivate
{
Q_DECLARE_PUBLIC(QPlainTextDocumentLayout)
@@ -109,8 +118,7 @@ public:
\since 4.4
\brief The QPlainTextDocumentLayout class implements a plain text layout for QTextDocument
- \ingroup text
-
+ \ingroup richtext-processing
A QPlainTextDocumentLayout is required for text documents that can
be display or edited in a QPlainTextEdit. See
@@ -250,7 +258,7 @@ QPlainTextDocumentLayoutPrivate *QPlainTextDocumentLayout::priv() const
*/
void QPlainTextDocumentLayout::requestUpdate()
{
- emit update(QRectF(0., -4., 1000000000., 1000000000.));
+ emit update(QRectF(0., -document()->documentMargin(), 1000000000., 1000000000.));
}
@@ -345,8 +353,7 @@ void QPlainTextDocumentLayout::documentChanged(int from, int /*charsRemoved*/, i
}
if (!d->blockUpdate)
- emit update(); // optimization potential
-
+ emit update(QRectF(0., -doc->documentMargin(), 1000000000., 1000000000.)); // optimization potential
}
@@ -370,11 +377,16 @@ void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block)
extraMargin += fm.width(QChar(0x21B5));
}
tl->beginLayout();
+ qreal availableWidth = d->width;
+ if (availableWidth <= 0) {
+ availableWidth = qreal(INT_MAX); // similar to text edit with pageSize.width == 0
+ }
+ availableWidth -= 2*margin + extraMargin;
while (1) {
QTextLine line = tl->createLine();
if (!line.isValid())
break;
- line.setLineWidth(d->width - 2*margin - extraMargin);
+ line.setLineWidth(availableWidth);
height += leading;
line.setPosition(QPointF(margin, height));
@@ -439,7 +451,7 @@ QPlainTextEditControl::QPlainTextEditControl(QPlainTextEdit *parent)
void QPlainTextEditPrivate::_q_cursorPositionChanged()
{
pageUpDownLastCursorYIsValid = false;
-};
+}
void QPlainTextEditPrivate::_q_verticalScrollbarActionTriggered(int action) {
if (action == QAbstractSlider::SliderPageStepAdd) {
@@ -555,7 +567,8 @@ QRectF QPlainTextEditControl::blockBoundingRect(const QTextBlock &block) const {
if (!currentBlock.isValid())
return QRectF();
Q_ASSERT(currentBlock.blockNumber() == currentBlockNumber);
- QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
+ QTextDocument *doc = document();
+ QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
Q_ASSERT(documentLayout);
QPointF offset;
@@ -567,13 +580,22 @@ QRectF QPlainTextEditControl::blockBoundingRect(const QTextBlock &block) const {
offset.ry() += r.height();
currentBlock = currentBlock.next();
++currentBlockNumber;
+ if (!currentBlock.isVisible()) {
+ currentBlock = doc->findBlockByLineNumber(currentBlock.firstLineNumber());
+ currentBlockNumber = currentBlock.blockNumber();
+ }
r = documentLayout->blockBoundingRect(currentBlock);
}
while (currentBlockNumber > blockNumber && offset.y() + maxVerticalOffset >= -textEdit->viewport()->height()) {
currentBlock = currentBlock.previous();
+ --currentBlockNumber;
+ while (!currentBlock.isVisible()) {
+ currentBlock = currentBlock.previous();
+ --currentBlockNumber;
+ }
if (!currentBlock.isValid())
break;
- --currentBlockNumber;
+
r = documentLayout->blockBoundingRect(currentBlock);
offset.ry() -= r.height();
}
@@ -706,12 +728,16 @@ QPlainTextEditPrivate::QPlainTextEditPrivate()
tabChangesFocus(false),
lineWrap(QPlainTextEdit::WidgetWidth),
wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere),
- topLine(0), pageUpDownLastCursorYIsValid(false)
+ clickCausedFocus(0),topLine(0),
+ pageUpDownLastCursorYIsValid(false)
{
showCursorOnInitialShow = true;
backgroundVisible = false;
centerOnScroll = false;
inDrag = false;
+#ifdef Q_WS_WIN
+ singleFingerPanEnabled = true;
+#endif
}
@@ -747,7 +773,7 @@ void QPlainTextEditPrivate::init(const QString &txt)
// set a null page size initially to avoid any relayouting until the textedit
// is shown. relayoutDocument() will take care of setting the page size to the
// viewport dimensions later.
- doc->setTextWidth(0);
+ doc->setTextWidth(-1);
doc->documentLayout()->setPaintDevice(viewport);
doc->setDefaultFont(q->font());
@@ -767,6 +793,11 @@ void QPlainTextEditPrivate::init(const QString &txt)
#ifndef QT_NO_CURSOR
viewport->setCursor(Qt::IBeamCursor);
#endif
+ originalOffsetY = 0;
+#ifdef Q_WS_WIN
+ panGesture = new QPanGesture(q);
+ QObject::connect(panGesture, SIGNAL(triggered()), q, SLOT(_q_gestureTriggered()));
+#endif
}
void QPlainTextEditPrivate::_q_repaintContents(const QRectF &contentsRect)
@@ -986,8 +1017,8 @@ void QPlainTextEditPrivate::ensureViewportLayouted()
\brief The QPlainTextEdit class provides a widget that is used to edit and display
plain text.
- \ingroup text
- \mainclass
+ \ingroup richtext-processing
+
\tableofcontents
@@ -1014,15 +1045,14 @@ void QPlainTextEditPrivate::ensureViewportLayouted()
\section1 Using QPlainTextEdit as a Display Widget
- The text is set or replaced using setPlainText() which deletes any
- existing text and replaces it with the text passed in the
- setPlainText() call.
+ The text is set or replaced using setPlainText() which deletes the
+ existing text and replaces it with the text passed to setPlainText().
- Text itself can be inserted using the QTextCursor class or using
- the convenience functins insertPlainText(), appendPlainText() or
+ Text can be inserted using the QTextCursor class or using the
+ convenience functions insertPlainText(), appendPlainText() or
paste().
- By default the text edit wraps words at whitespace to fit within
+ By default, the text edit wraps words at whitespace to fit within
the text edit widget. The setLineWrapMode() function is used to
specify the kind of line wrap you want, \l WidgetWidth or \l
NoWrap if you don't want any wrapping. If you use word wrap to
@@ -1711,8 +1741,7 @@ static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, QRectF
p->save();
if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) {
if (!gradientRect.isNull()) {
- QTransform m;
- m.translate(gradientRect.left(), gradientRect.top());
+ QTransform m = QTransform::fromTranslate(gradientRect.left(), gradientRect.top());
m.scale(gradientRect.width(), gradientRect.height());
brush.setTransform(m);
const_cast<QGradient *>(brush.gradient())->setCoordinateMode(QGradient::LogicalMode);
@@ -1742,7 +1771,7 @@ void QPlainTextEdit::paintEvent(QPaintEvent *e)
QTextBlock block = firstVisibleBlock();
qreal maximumWidth = document()->documentLayout()->documentSize().width();
-
+
// keep right margin clean from full-width selection
int maxX = offset.x() + qMax((qreal)viewportRect.width(), maximumWidth)
- document()->documentMargin();
@@ -1906,6 +1935,9 @@ void QPlainTextEdit::mouseReleaseEvent(QMouseEvent *e)
d->autoScrollTimer.stop();
d->ensureCursorVisible();
}
+
+ d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
+ d->clickCausedFocus = 0;
}
/*! \reimp
@@ -2006,6 +2038,7 @@ void QPlainTextEdit::inputMethodEvent(QInputMethodEvent *e)
}
#endif
d->sendControlEvent(e);
+ ensureCursorVisible();
}
/*!\reimp
@@ -2039,6 +2072,9 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
void QPlainTextEdit::focusInEvent(QFocusEvent *e)
{
Q_D(QPlainTextEdit);
+ if (e->reason() == Qt::MouseFocusReason) {
+ d->clickCausedFocus = 1;
+ }
QAbstractScrollArea::focusInEvent(e);
d->sendControlEvent(e);
}
@@ -2305,7 +2341,7 @@ void QPlainTextEdit::setReadOnly(bool ro)
} else {
flags = Qt::TextEditorInteraction;
}
- setAttribute(Qt::WA_InputMethodEnabled, !ro);
+ setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
d->control->setTextInteractionFlags(flags);
}
@@ -2886,6 +2922,34 @@ QAbstractTextDocumentLayout::PaintContext QPlainTextEdit::getPaintContext() cons
(\a available is true) or unavailable (\a available is false).
*/
+#ifdef Q_WS_WIN
+
+void QPlainTextEditPrivate::_q_gestureTriggered()
+{
+ Q_Q(QPlainTextEdit);
+ QPanGesture *g = qobject_cast<QPanGesture*>(q->sender());
+ if (!g)
+ return;
+ QScrollBar *hBar = q->horizontalScrollBar();
+ QScrollBar *vBar = q->verticalScrollBar();
+ if (g->state() == Qt::GestureStarted)
+ originalOffsetY = vBar->value();
+ QSizeF totalOffset = g->totalOffset();
+ if (!totalOffset.isNull()) {
+ if (QApplication::isRightToLeft())
+ totalOffset.rwidth() *= -1;
+ // QPlainTextEdit scrolls by lines only in vertical direction
+ QFontMetrics fm(q->document()->defaultFont());
+ int lineHeight = fm.height();
+ int newX = hBar->value() - g->lastOffset().width();
+ int newY = originalOffsetY - totalOffset.height()/lineHeight;
+ hbar->setValue(newX);
+ vbar->setValue(newY);
+ }
+}
+
+#endif
+
QT_END_NAMESPACE
#include "moc_qplaintextedit.cpp"
diff --git a/src/gui/widgets/qplaintextedit.h b/src/gui/widgets/qplaintextedit.h
index 3750c17..8ad6175 100644
--- a/src/gui/widgets/qplaintextedit.h
+++ b/src/gui/widgets/qplaintextedit.h
@@ -269,6 +269,11 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_adjustScrollbars())
Q_PRIVATE_SLOT(d_func(), void _q_verticalScrollbarActionTriggered(int))
Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged())
+
+#ifdef Q_WS_WIN
+ Q_PRIVATE_SLOT(d_func(), void _q_gestureTriggered())
+#endif
+
friend class QPlainTextEditControl;
};
diff --git a/src/gui/widgets/qplaintextedit_p.h b/src/gui/widgets/qplaintextedit_p.h
index e2208c1..7ff0c03 100644
--- a/src/gui/widgets/qplaintextedit_p.h
+++ b/src/gui/widgets/qplaintextedit_p.h
@@ -72,6 +72,7 @@ class QMimeData;
class QPlainTextEdit;
class ExtraArea;
+class QPanGesture;
class QPlainTextEditControl : public QTextControl
{
@@ -91,7 +92,10 @@ public:
return r;
}
inline QRectF cursorRect() { return cursorRect(textCursor()); }
- void ensureCursorVisible() { textEdit->ensureCursorVisible(); }
+ void ensureCursorVisible() {
+ textEdit->ensureCursorVisible();
+ emit microFocusChanged();
+ }
QPlainTextEdit *textEdit;
@@ -148,6 +152,7 @@ public:
uint backgroundVisible : 1;
uint centerOnScroll : 1;
uint inDrag : 1;
+ uint clickCausedFocus : 1;
int topLine;
@@ -171,8 +176,14 @@ public:
#endif
void _q_cursorPositionChanged();
-
void _q_modificationChanged(bool);
+
+ int originalOffsetY;
+
+#ifdef Q_WS_WIN
+ void _q_gestureTriggered();
+ QPanGesture *panGesture;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qprintpreviewwidget.cpp b/src/gui/widgets/qprintpreviewwidget.cpp
index bd0ba71..fdb087c 100644
--- a/src/gui/widgets/qprintpreviewwidget.cpp
+++ b/src/gui/widgets/qprintpreviewwidget.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qprintpreviewwidget.h"
+#include "private/qwidget_p.h"
#include <private/qprinter_p.h>
#include <QtCore/qmath.h>
@@ -98,29 +99,8 @@ void PageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QRectF paperRect(0,0, paperSize.width(), paperSize.height());
- painter->setClipRect(paperRect & option->exposedRect);
- painter->fillRect(paperRect, Qt::white);
- if (!pagePicture)
- return;
- painter->drawPicture(pageRect.topLeft(), *pagePicture);
-
- // Effect: make anything drawn in the margins look washed out.
- QPainterPath path;
- path.addRect(paperRect);
- path.addRect(pageRect);
- painter->setPen(QPen(Qt::NoPen));
- painter->setBrush(QColor(255, 255, 255, 180));
- painter->drawPath(path);
-
- painter->setClipRect(option->exposedRect);
-#if 0
- // Draw frame around paper.
- painter->setPen(QPen(Qt::black, 0));
- painter->setBrush(Qt::NoBrush);
- painter->drawRect(paperRect);
-#endif
-
// Draw shadow
+ painter->setClipRect(option->exposedRect);
qreal shWidth = paperRect.width()/100;
QRectF rshadow(paperRect.topRight() + QPointF(0, shWidth),
paperRect.bottomRight() + QPointF(shWidth, 0));
@@ -141,6 +121,27 @@ void PageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
cgrad.setColorAt(1.0, QColor(0,0,0,0));
painter->fillRect(cshadow, QBrush(cgrad));
+ painter->setClipRect(paperRect & option->exposedRect);
+ painter->fillRect(paperRect, Qt::white);
+ if (!pagePicture)
+ return;
+ painter->drawPicture(pageRect.topLeft(), *pagePicture);
+
+ // Effect: make anything drawn in the margins look washed out.
+ QPainterPath path;
+ path.addRect(paperRect);
+ path.addRect(pageRect);
+ painter->setPen(QPen(Qt::NoPen));
+ painter->setBrush(QColor(255, 255, 255, 180));
+ painter->drawPath(path);
+
+#if 0
+ // Draw frame around paper.
+ painter->setPen(QPen(Qt::black, 0));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawRect(paperRect);
+#endif
+
// todo: drawtext "Page N" below paper
}
@@ -170,12 +171,12 @@ protected:
} // anonymous namespace
-class QPrintPreviewWidgetPrivate
+class QPrintPreviewWidgetPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QPrintPreviewWidget)
public:
- QPrintPreviewWidgetPrivate(QPrintPreviewWidget *q)
- : q_ptr(q), scene(0), curPage(1),
+ QPrintPreviewWidgetPrivate()
+ : scene(0), curPage(1),
viewMode(QPrintPreviewWidget::SinglePageView),
zoomMode(QPrintPreviewWidget::FitInView),
zoomFactor(1), initialized(false), fitting(true)
@@ -194,7 +195,6 @@ public:
void setZoomFactor(qreal zoomFactor);
int calcCurrentPage();
- QPrintPreviewWidget *q_ptr;
GraphicsView *graphicsView;
QGraphicsScene *scene;
@@ -452,7 +452,7 @@ void QPrintPreviewWidgetPrivate::setZoomFactor(qreal _zoomFactor)
\brief The QPrintPreviewWidget class provides a widget for
previewing page layouts for printer output.
- \ingroup multimedia
+ \ingroup printing
QPrintPreviewDialog uses a QPrintPreviewWidget internally, and the
purpose of QPrintPreviewWidget is to make it possible to embed the
@@ -518,7 +518,7 @@ void QPrintPreviewWidgetPrivate::setZoomFactor(qreal _zoomFactor)
\sa QWidget::setWindowFlags()
*/
QPrintPreviewWidget::QPrintPreviewWidget(QPrinter *printer, QWidget *parent, Qt::WindowFlags flags)
- : QWidget(parent, flags), d_ptr(new QPrintPreviewWidgetPrivate(this))
+ : QWidget(*new QPrintPreviewWidgetPrivate, parent, flags)
{
Q_D(QPrintPreviewWidget);
d->printer = printer;
@@ -534,7 +534,7 @@ QPrintPreviewWidget::QPrintPreviewWidget(QPrinter *printer, QWidget *parent, Qt:
preview.
*/
QPrintPreviewWidget::QPrintPreviewWidget(QWidget *parent, Qt::WindowFlags flags)
- : QWidget(parent, flags), d_ptr(new QPrintPreviewWidgetPrivate(this))
+ : QWidget(*new QPrintPreviewWidgetPrivate, parent, flags)
{
Q_D(QPrintPreviewWidget);
d->printer = new QPrinter;
@@ -551,7 +551,6 @@ QPrintPreviewWidget::~QPrintPreviewWidget()
Q_D(QPrintPreviewWidget);
if (d->ownPrinter)
delete d->printer;
- delete d_ptr;
}
/*!
diff --git a/src/gui/widgets/qprintpreviewwidget.h b/src/gui/widgets/qprintpreviewwidget.h
index af2b578..a3ecc07 100644
--- a/src/gui/widgets/qprintpreviewwidget.h
+++ b/src/gui/widgets/qprintpreviewwidget.h
@@ -111,7 +111,7 @@ Q_SIGNALS:
void previewChanged();
private:
- QPrintPreviewWidgetPrivate *d_ptr;
+ void *dummy; // ### remove in Qt 5.0
Q_PRIVATE_SLOT(d_func(), void _q_fit())
Q_PRIVATE_SLOT(d_func(), void _q_updateCurrentPage())
};
diff --git a/src/gui/widgets/qprogressbar.cpp b/src/gui/widgets/qprogressbar.cpp
index 9a3f5b3..046fb5d 100644
--- a/src/gui/widgets/qprogressbar.cpp
+++ b/src/gui/widgets/qprogressbar.cpp
@@ -172,7 +172,7 @@ bool QProgressBarPrivate::repaintRequired() const
\brief The QProgressBar widget provides a horizontal or vertical progress bar.
\ingroup basicwidgets
- \mainclass
+
A progress bar is used to give the user an indication of the
progress of an operation and to reassure them that the application
@@ -190,10 +190,11 @@ bool QProgressBarPrivate::repaintRequired() const
with setValue(). The progress bar can be rewound to the
beginning with reset().
- If minimum and maximum both are set to 0, the bar shows a busy indicator
- instead of a percentage of steps. This is useful, for example, when using
- QFtp or QHttp to download items when they are unable to determine the
- size of the item being downloaded.
+ If minimum and maximum both are set to 0, the bar shows a busy
+ indicator instead of a percentage of steps. This is useful, for
+ example, when using QFtp or QNetworkAccessManager to download
+ items when they are unable to determine the size of the item being
+ downloaded.
\table
\row \o \inlineimage macintosh-progressbar.png Screenshot of a Macintosh style progress bar
@@ -204,7 +205,7 @@ bool QProgressBarPrivate::repaintRequired() const
\o A progress bar shown in the Plastique widget style.
\endtable
- \sa QTimeLine, QProgressDialog, {fowler}{GUI Design Handbook: Progress Indicator}
+ \sa QProgressDialog, {fowler}{GUI Design Handbook: Progress Indicator}
*/
/*!
@@ -443,26 +444,26 @@ QSize QProgressBar::minimumSizeHint() const
QString QProgressBar::text() const
{
Q_D(const QProgressBar);
- if (d->maximum == 0 || d->value < d->minimum
+ if ((d->maximum == 0 && d->minimum == 0) || d->value < d->minimum
|| (d->value == INT_MIN && d->minimum == INT_MIN))
return QString();
- qint64 totalSteps = qint64(d->maximum) - qint64(d->minimum);
+ qint64 totalSteps = qint64(d->maximum) - d->minimum;
QString result = d->format;
- result.replace(QLatin1String("%m"), QString::fromLatin1("%1").arg(totalSteps));
- result.replace(QLatin1String("%v"), QString::fromLatin1("%1").arg(d->value));
+ result.replace(QLatin1String("%m"), QString::number(totalSteps));
+ result.replace(QLatin1String("%v"), QString::number(d->value));
// If max and min are equal and we get this far, it means that the
// progress bar has one step and that we are on that step. Return
// 100% here in order to avoid division by zero further down.
if (totalSteps == 0) {
- result.replace(QLatin1String("%p"), QString::fromLatin1("%1").arg(100));
+ result.replace(QLatin1String("%p"), QString::number(100));
return result;
}
- int progress = int(((qreal(d->value) - qreal(d->minimum)) * 100.0) / totalSteps);
- result.replace(QLatin1String("%p"), QString::fromLatin1("%1").arg(progress));
+ int progress = (qreal(d->value) - d->minimum) * 100.0 / totalSteps;
+ result.replace(QLatin1String("%p"), QString::number(progress));
return result;
}
diff --git a/src/gui/widgets/qpushbutton.cpp b/src/gui/widgets/qpushbutton.cpp
index b49d5b3..ceb9a43 100644
--- a/src/gui/widgets/qpushbutton.cpp
+++ b/src/gui/widgets/qpushbutton.cpp
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
\brief The QPushButton widget provides a command button.
\ingroup basicwidgets
- \mainclass
+
The push button, or command button, is perhaps the most commonly
used widget in any graphical user interface. Push (click) a button
@@ -387,8 +387,9 @@ bool QPushButton::isDefault() const
QSize QPushButton::sizeHint() const
{
Q_D(const QPushButton);
- if (d->sizeHint.isValid())
+ if (d->sizeHint.isValid() && d->lastAutoDefault == autoDefault())
return d->sizeHint;
+ d->lastAutoDefault = autoDefault();
ensurePolished();
int w = 0, h = 0;
@@ -527,8 +528,7 @@ void QPushButton::setMenu(QMenu* menu)
return;
if (menu && !d->menu) {
- disconnect(this, SIGNAL(pressed()), this, SLOT(_q_popupPressed()));
- connect(this, SIGNAL(pressed()), this, SLOT(_q_popupPressed()));
+ connect(this, SIGNAL(pressed()), this, SLOT(_q_popupPressed()), Qt::UniqueConnection);
}
if (d->menu)
removeAction(d->menu->menuAction());
@@ -577,7 +577,7 @@ void QPushButtonPrivate::_q_popupPressed()
menu->setNoReplayFor(q);
bool horizontal = true;
#if !defined(QT_NO_TOOLBAR)
- QToolBar *tb = qobject_cast<QToolBar*>(q->parentWidget());
+ QToolBar *tb = qobject_cast<QToolBar*>(parent);
if (tb && tb->orientation() == Qt::Vertical)
horizontal = false;
#endif
@@ -590,7 +590,7 @@ void QPushButtonPrivate::_q_popupPressed()
int x = globalPos.x();
int y = globalPos.y();
if (horizontal) {
- if (globalPos.y() + rect.height() + menuSize.height() <= qApp->desktop()->height()) {
+ if (globalPos.y() + rect.height() + menuSize.height() <= QApplication::desktop()->height()) {
y += rect.height();
} else {
y -= menuSize.height();
@@ -598,7 +598,7 @@ void QPushButtonPrivate::_q_popupPressed()
if (q->layoutDirection() == Qt::RightToLeft)
x += rect.width() - menuSize.width();
} else {
- if (globalPos.x() + rect.width() + menu->sizeHint().width() <= qApp->desktop()->width())
+ if (globalPos.x() + rect.width() + menu->sizeHint().width() <= QApplication::desktop()->width())
x += rect.width();
else
x -= menuSize.width();
@@ -658,6 +658,8 @@ bool QPushButton::event(QEvent *e)
) {
d->resetLayoutItemMargins();
updateGeometry();
+ } else if (e->type() == QEvent::PolishRequest) {
+ updateGeometry();
}
return QAbstractButton::event(e);
}
diff --git a/src/gui/widgets/qpushbutton_p.h b/src/gui/widgets/qpushbutton_p.h
index 9459ccd..0f61ea7 100644
--- a/src/gui/widgets/qpushbutton_p.h
+++ b/src/gui/widgets/qpushbutton_p.h
@@ -65,7 +65,7 @@ public:
QPushButtonPrivate()
: QAbstractButtonPrivate(QSizePolicy::PushButton), autoDefault(Auto),
- defaultButton(false), flat(false), menuOpen(false) {}
+ defaultButton(false), flat(false), menuOpen(false), lastAutoDefault(false) {}
inline void init() { resetLayoutItemMargins(); }
void resetLayoutItemMargins();
@@ -77,6 +77,7 @@ public:
uint defaultButton : 1;
uint flat : 1;
uint menuOpen : 1;
+ mutable uint lastAutoDefault : 1;
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qradiobutton.cpp b/src/gui/widgets/qradiobutton.cpp
index aa96c38..db7e73f 100644
--- a/src/gui/widgets/qradiobutton.cpp
+++ b/src/gui/widgets/qradiobutton.cpp
@@ -80,7 +80,7 @@ void QRadioButtonPrivate::init()
\brief The QRadioButton widget provides a radio button with a text label.
\ingroup basicwidgets
- \mainclass
+
A QRadioButton is an option button that can be switched on (checked) or
off (unchecked). Radio buttons typically present the user with a "one
diff --git a/src/gui/widgets/qrubberband.cpp b/src/gui/widgets/qrubberband.cpp
index 558c20b..d343dd0 100644
--- a/src/gui/widgets/qrubberband.cpp
+++ b/src/gui/widgets/qrubberband.cpp
@@ -98,9 +98,6 @@ void QRubberBand::initStyleOption(QStyleOptionRubberBand *option) const
\brief The QRubberBand class provides a rectangle or line that can
indicate a selection or a boundary.
- \ingroup misc
- \mainclass
-
A rubber band is often used to show a new bounding area (as in a
QSplitter or a QDockWidget that is undocking). Historically this has
been implemented using a QPainter and XOR, but this approach
diff --git a/src/gui/widgets/qscrollarea.cpp b/src/gui/widgets/qscrollarea.cpp
index 1205a79..aee3563 100644
--- a/src/gui/widgets/qscrollarea.cpp
+++ b/src/gui/widgets/qscrollarea.cpp
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
another widget.
\ingroup basicwidgets
- \mainclass
+
A scroll area is used to display the contents of a child widget
within a frame. If the widget exceeds the size of the frame, the
diff --git a/src/gui/widgets/qscrollbar.cpp b/src/gui/widgets/qscrollbar.cpp
index a5c3099..3c4f9f8 100644
--- a/src/gui/widgets/qscrollbar.cpp
+++ b/src/gui/widgets/qscrollbar.cpp
@@ -431,6 +431,12 @@ void QScrollBarPrivate::init()
q->setSizePolicy(sp);
q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
q->setAttribute(Qt::WA_OpaquePaintEvent);
+
+#if !defined(QT_NO_CONTEXTMENU) && defined(Q_WS_WINCE)
+ if (!q->style()->styleHint(QStyle::SH_ScrollBar_ContextMenu, 0, q)) {
+ q->setContextMenuPolicy(Qt::PreventContextMenu);
+ }
+#endif
}
#ifndef QT_NO_CONTEXTMENU
diff --git a/src/gui/widgets/qsizegrip.cpp b/src/gui/widgets/qsizegrip.cpp
index 39a8375..bc9abde 100644
--- a/src/gui/widgets/qsizegrip.cpp
+++ b/src/gui/widgets/qsizegrip.cpp
@@ -139,7 +139,7 @@ public:
void QSizeGripPrivate::updateMacSizer(bool hide) const
{
Q_Q(const QSizeGrip);
- if (QApplication::closingDown() || !q->parentWidget())
+ if (QApplication::closingDown() || !parent)
return;
QWidget *topLevelWindow = qt_sizegrip_topLevelWidget(const_cast<QSizeGrip *>(q));
if(topLevelWindow && topLevelWindow->isWindow())
@@ -165,9 +165,8 @@ Qt::Corner QSizeGripPrivate::corner() const
\brief The QSizeGrip class provides a resize handle for resizing top-level windows.
- \ingroup application
+ \ingroup mainwindow-classes
\ingroup basicwidgets
- \ingroup appearance
This widget works like the standard Windows resize handle. In the
X11 version this resize handle generally works differently from
@@ -335,8 +334,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
orientation = d->atLeft() ? SZ_SIZETOPLEFT : SZ_SIZETOPRIGHT;
ReleaseCapture();
- QT_WA_INLINE(PostMessageW(tlw->winId(), WM_SYSCOMMAND, orientation, 0),
- PostMessageA(tlw->winId(), WM_SYSCOMMAND, orientation, 0));
+ PostMessage(tlw->winId(), WM_SYSCOMMAND, orientation, 0);
return;
}
#endif // Q_WS_WIN
diff --git a/src/gui/widgets/qslider.cpp b/src/gui/widgets/qslider.cpp
index 1e02808..5193a1f 100644
--- a/src/gui/widgets/qslider.cpp
+++ b/src/gui/widgets/qslider.cpp
@@ -62,7 +62,6 @@ public:
int tickInterval;
QSlider::TickPosition tickPosition;
int clickOffset;
- int snapBackPosition;
void init();
void resetLayoutItemMargins();
int pixelPosToRangeValue(int pos) const;
@@ -204,7 +203,7 @@ QStyle::SubControl QSliderPrivate::newHoverControl(const QPoint &pos)
\brief The QSlider widget provides a vertical or horizontal slider.
\ingroup basicwidgets
- \mainclass
+
The slider is the classic widget for controlling a bounded value.
It lets the user move a slider handle along a horizontal or vertical
@@ -493,7 +492,6 @@ void QSlider::mousePressEvent(QMouseEvent *ev)
setRepeatAction(SliderNoAction);
QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
d->clickOffset = d->pick(ev->pos() - sr.topLeft());
- d->snapBackPosition = d->position;
update(sr);
setSliderDown(true);
}
@@ -513,14 +511,6 @@ void QSlider::mouseMoveEvent(QMouseEvent *ev)
int newPosition = d->pixelPosToRangeValue(d->pick(ev->pos()) - d->clickOffset);
QStyleOptionSlider opt;
initStyleOption(&opt);
- int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &opt, this);
- if (m >= 0) {
- QRect r = rect();
- r.adjust(-m, -m, m, m);
- if (!r.contains(ev->pos())) {
- newPosition = d->snapBackPosition;
- }
- }
setSliderPosition(newPosition);
}
diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp
index 5510e60..3ce64be 100644
--- a/src/gui/widgets/qspinbox.cpp
+++ b/src/gui/widgets/qspinbox.cpp
@@ -50,6 +50,7 @@
#include <qdebug.h>
#include <math.h>
+#include <float.h>
QT_BEGIN_NAMESPACE
@@ -77,6 +78,8 @@ public:
QChar thousand;
inline void init() {
+ Q_Q(QSpinBox);
+ q->setInputMethodHints(Qt::ImhDigitsOnly);
setLayoutItemMargins(QStyle::SE_SpinBoxLayoutItem);
}
};
@@ -97,6 +100,11 @@ public:
// variables
int decimals;
QChar delimiter, thousand;
+
+ inline void init() {
+ Q_Q(QDoubleSpinBox);
+ q->setInputMethodHints(Qt::ImhFormattedNumbersOnly);
+ }
};
@@ -105,7 +113,7 @@ public:
\brief The QSpinBox class provides a spin box widget.
\ingroup basicwidgets
- \mainclass
+
QSpinBox is designed to handle integers and discrete sets of
values (e.g., month names); use QDoubleSpinBox for floating point
@@ -284,6 +292,9 @@ void QSpinBox::setPrefix(const QString &prefix)
d->prefix = prefix;
d->updateEdit();
+
+ d->cachedSizeHint = QSize();
+ updateGeometry();
}
/*!
@@ -318,6 +329,9 @@ void QSpinBox::setSuffix(const QString &suffix)
d->suffix = suffix;
d->updateEdit();
+
+ d->cachedSizeHint = QSize();
+ updateGeometry();
}
/*!
@@ -520,7 +534,7 @@ void QSpinBox::fixup(QString &input) const
takes doubles.
\ingroup basicwidgets
- \mainclass
+
QDoubleSpinBox allows the user to choose a value by clicking the
up and down buttons or by pressing Up or Down on the keyboard to
@@ -592,6 +606,8 @@ void QSpinBox::fixup(QString &input) const
QDoubleSpinBox::QDoubleSpinBox(QWidget *parent)
: QAbstractSpinBox(*new QDoubleSpinBoxPrivate(parent), parent)
{
+ Q_D(QDoubleSpinBox);
+ d->init();
}
/*!
@@ -817,8 +833,8 @@ void QDoubleSpinBox::setRange(double minimum, double maximum)
Sets how many decimals the spinbox will use for displaying and
interpreting doubles.
- \warning The results might not be reliable with very high values
- for \a decimals.
+ \warning The maximum value for \a decimals is DBL_MAX_10_EXP +
+ DBL_DIG (ie. 323) because of the limitations of the double type.
Note: The maximum, minimum and value might change as a result of
changing this property.
@@ -834,7 +850,7 @@ int QDoubleSpinBox::decimals() const
void QDoubleSpinBox::setDecimals(int decimals)
{
Q_D(QDoubleSpinBox);
- d->decimals = qMax(0, decimals);
+ d->decimals = qBound(0, decimals, DBL_MAX_10_EXP + DBL_DIG);
setRange(minimum(), maximum()); // make sure values are rounded
setValue(value());
@@ -983,7 +999,7 @@ QVariant QSpinBoxPrivate::valueFromText(const QString &text) const
bool QSpinBoxPrivate::isIntermediateValue(const QString &str) const
{
- const int num = q_func()->locale().toInt(str, 0, 10);
+ const int num = locale.toInt(str, 0, 10);
const int min = minimum.toInt();
const int max = maximum.toInt();
@@ -1030,7 +1046,7 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
{
if (cachedText == input && !input.isEmpty()) {
state = cachedState;
- QSBDEBUG() << "cachedText was" << "'" << cachedText << "'" << "state was "
+ QSBDEBUG() << "cachedText was '" << cachedText << "' state was "
<< state << " and value was " << cachedValue;
return cachedValue;
@@ -1048,18 +1064,18 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
|| (min >= 0 && copy == QLatin1String("+")))) {
state = QValidator::Intermediate;
QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
- } else if (copy.startsWith(QLatin1String("-")) && min >= 0) {
+ } else if (copy.startsWith(QLatin1Char('-')) && min >= 0) {
state = QValidator::Invalid; // special-case -0 will be interpreted as 0 and thus not be invalid with a range from 0-100
} else {
bool ok = false;
bool removedThousand = false;
- num = q_func()->locale().toInt(copy, &ok, 10);
+ num = locale.toInt(copy, &ok, 10);
if (!ok && copy.contains(thousand) && (max >= 1000 || min <= -1000)) {
const int s = copy.size();
copy.remove(thousand);
pos = qMax(0, pos - (s - copy.size()));
removedThousand = true;
- num = q_func()->locale().toInt(copy, &ok, 10);
+ num = locale.toInt(copy, &ok, 10);
}
QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
if (!ok) {
@@ -1199,7 +1215,7 @@ bool QDoubleSpinBoxPrivate::isIntermediateValue(const QString &str) const
return false;
}
if (doright) {
- QSBDEBUG("match %lld min_left %lld max_left %lld", match, min_left, max_left);
+ QSBDEBUG() << "match" << match << "min_left" << min_left << "max_left" << max_left;
if (!doleft) {
if (min_left == max_left) {
const bool ret = isIntermediateValueHelper(qAbs(left),
@@ -1254,9 +1270,7 @@ QVariant QDoubleSpinBoxPrivate::valueFromText(const QString &f) const
double QDoubleSpinBoxPrivate::round(double value) const
{
- Q_Q(const QDoubleSpinBox);
- const QString strDbl = q->locale().toString(value, 'f', decimals);
- return q->locale().toDouble(strDbl);
+ return QString::number(value, 'f', decimals).toDouble();
}
@@ -1271,7 +1285,7 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
{
if (cachedText == input && !input.isEmpty()) {
state = cachedState;
- QSBDEBUG() << "cachedText was" << "'" << cachedText << "'" << "state was "
+ QSBDEBUG() << "cachedText was '" << cachedText << "' state was "
<< state << " and value was " << cachedValue;
return cachedValue;
}
@@ -1348,9 +1362,8 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
{
bool ok = false;
- QLocale loc(q_func()->locale());
- num = loc.toDouble(copy, &ok);
- QSBDEBUG() << __FILE__ << __LINE__ << loc << copy << num << ok;
+ num = locale.toDouble(copy, &ok);
+ QSBDEBUG() << __FILE__ << __LINE__ << locale << copy << num << ok;
bool notAcceptable = false;
if (!ok) {
@@ -1375,7 +1388,7 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
pos = qMax(0, pos - (s - copy.size()));
- num = loc.toDouble(copy, &ok);
+ num = locale.toDouble(copy, &ok);
QSBDEBUG() << thousand << num << copy << ok;
if (!ok) {
@@ -1469,7 +1482,7 @@ QString QDoubleSpinBoxPrivate::textFromValue(const QVariant &f) const
static bool isIntermediateValueHelper(qint64 num, qint64 min, qint64 max, qint64 *match)
{
- QSBDEBUG("%lld %lld %lld", num, min, max);
+ QSBDEBUG() << num << min << max;
if (num >= min && num <= max) {
if (match)
diff --git a/src/gui/widgets/qsplashscreen.cpp b/src/gui/widgets/qsplashscreen.cpp
index fc56d70..32b286c 100644
--- a/src/gui/widgets/qsplashscreen.cpp
+++ b/src/gui/widgets/qsplashscreen.cpp
@@ -72,9 +72,6 @@ public:
\brief The QSplashScreen widget provides a splash screen that can
be shown during application startup.
- \ingroup misc
- \mainclass
-
A splash screen is a widget that is usually displayed when an
application is being started. Splash screens are often used for
applications that have long start up times (e.g. database or
diff --git a/src/gui/widgets/qsplitter.cpp b/src/gui/widgets/qsplitter.cpp
index 6525b5d..57ee7fe 100644
--- a/src/gui/widgets/qsplitter.cpp
+++ b/src/gui/widgets/qsplitter.cpp
@@ -119,7 +119,6 @@ QSplitterHandle::QSplitterHandle(Qt::Orientation orientation, QSplitter *parent)
{
Q_D(QSplitterHandle);
d->s = parent;
- d->hover = false;
setOrientation(orientation);
}
@@ -269,8 +268,11 @@ void QSplitterHandle::mouseMoveEvent(QMouseEvent *e)
void QSplitterHandle::mousePressEvent(QMouseEvent *e)
{
Q_D(QSplitterHandle);
- if (e->button() == Qt::LeftButton)
+ if (e->button() == Qt::LeftButton) {
d->mouseOffset = d->pick(e->pos());
+ d->pressed = true;
+ update();
+ }
}
/*!
@@ -285,6 +287,10 @@ void QSplitterHandle::mouseReleaseEvent(QMouseEvent *e)
d->s->setRubberBand(-1);
moveSplitter(pos);
}
+ if (e->button() == Qt::LeftButton) {
+ d->pressed = false;
+ update();
+ }
}
/*!
@@ -303,6 +309,8 @@ void QSplitterHandle::paintEvent(QPaintEvent *)
opt.state = QStyle::State_None;
if (d->hover)
opt.state |= QStyle::State_MouseOver;
+ if (d->pressed)
+ opt.state |= QStyle::State_Sunken;
if (isEnabled())
opt.state |= QStyle::State_Enabled;
parentWidget()->style()->drawControl(QStyle::CE_Splitter, &opt, &p, d->s);
@@ -389,7 +397,7 @@ void QSplitterPrivate::recalc(bool update)
}
if (empty) {
- if (qobject_cast<QSplitter *>(q->parentWidget())) {
+ if (qobject_cast<QSplitter *>(parent)) {
// nested splitters; be nice
maxl = maxt = 0;
} else {
@@ -923,7 +931,7 @@ QSplitterLayoutStruct *QSplitterPrivate::insertWidget(int index, QWidget *w)
\brief The QSplitter class implements a splitter widget.
\ingroup organizers
- \mainclass
+
A splitter lets the user control the size of child widgets by dragging the
boundary between the children. Any number of widgets may be controlled by a
diff --git a/src/gui/widgets/qsplitter_p.h b/src/gui/widgets/qsplitter_p.h
index d41e2e3..74328bb 100644
--- a/src/gui/widgets/qsplitter_p.h
+++ b/src/gui/widgets/qsplitter_p.h
@@ -131,16 +131,17 @@ class QSplitterHandlePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QSplitterHandle)
public:
- QSplitterHandlePrivate() : orient(Qt::Horizontal), opaq(false), s(0), mouseOffset(0) {}
+ QSplitterHandlePrivate() : s(0), orient(Qt::Horizontal), mouseOffset(0), opaq(false), hover(false), pressed(false) {}
inline int pick(const QPoint &pos) const
{ return orient == Qt::Horizontal ? pos.x() : pos.y(); }
- Qt::Orientation orient;
- bool opaq;
QSplitter *s;
- bool hover;
+ Qt::Orientation orient;
int mouseOffset;
+ bool opaq : 1;
+ bool hover : 1;
+ bool pressed : 1;
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qstackedwidget.cpp b/src/gui/widgets/qstackedwidget.cpp
index 396cb30..25d725e 100644
--- a/src/gui/widgets/qstackedwidget.cpp
+++ b/src/gui/widgets/qstackedwidget.cpp
@@ -65,8 +65,7 @@ public:
\ingroup organizers
\ingroup geomanagement
- \ingroup appearance
- \mainclass
+
QStackedWidget can be used to create a user interface similar to
the one provided by QTabWidget. It is a convenience layout widget
diff --git a/src/gui/widgets/qstatusbar.cpp b/src/gui/widgets/qstatusbar.cpp
index c8fe1f5..56d56c0 100644
--- a/src/gui/widgets/qstatusbar.cpp
+++ b/src/gui/widgets/qstatusbar.cpp
@@ -144,7 +144,7 @@ QRect QStatusBarPrivate::messageRect() const
if (rtl)
left = qMax(left, item->w->x() + item->w->width() + 2);
else
- right = qMin(right, item->w->x()-1);
+ right = qMin(right, item->w->x() - 2);
}
break;
}
@@ -158,9 +158,9 @@ QRect QStatusBarPrivate::messageRect() const
\brief The QStatusBar class provides a horizontal bar suitable for
presenting status information.
- \ingroup application
+ \ingroup mainwindow-classes
\ingroup helpsystem
- \mainclass
+
Each status indicator falls into one of three categories:
@@ -728,7 +728,7 @@ void QStatusBar::paintEvent(QPaintEvent *event)
QStatusBarPrivate::SBItem* item = d->items.at(i);
if (item && item->w->isVisible() && (!haveMessage || item->p)) {
QRect ir = item->w->geometry().adjusted(-2, -1, 2, 1);
- if (event->rect().contains(ir)) {
+ if (event->rect().intersects(ir)) {
QStyleOption opt(0);
opt.rect = ir;
opt.palette = palette();
diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp
index bf2c0bb..64e383f 100644
--- a/src/gui/widgets/qtabbar.cpp
+++ b/src/gui/widgets/qtabbar.cpp
@@ -87,13 +87,17 @@ void QTabBarPrivate::updateMacBorderMetrics()
// TODO: get metrics to preserve the bottom value
// TODO: test tab bar position
- // push the black line at the bottom of the menu bar down to the client are so we can paint over it
+ OSWindowRef window = qt_mac_window_for(q);
+
+ // push base line separator down to the client are so we can paint over it (Carbon)
metrics.top = (documentMode && q->isVisible()) ? 1 : 0;
metrics.bottom = 0;
metrics.left = 0;
metrics.right = 0;
-
- qt_mac_updateContentBorderMetricts(qt_mac_window_for(q), metrics);
+ qt_mac_updateContentBorderMetricts(window, metrics);
+
+ // hide the base line separator if the tabs have docuemnt mode enabled (Cocoa)
+ qt_mac_showBaseLineSeparator(window, !documentMode);
}
#endif
}
@@ -176,12 +180,11 @@ void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const
if (tw->cornerWidget(Qt::TopRightCorner) || tw->cornerWidget(Qt::BottomRightCorner))
option->cornerWidgets |= QStyleOptionTab::RightCornerWidget;
}
+#endif
QRect textRect = style()->subElementRect(QStyle::SE_TabBarTabText, option, this);
-
option->text = fontMetrics().elidedText(option->text, d->elideMode, textRect.width(),
Qt::TextShowMnemonic);
-#endif
}
/*!
@@ -189,7 +192,7 @@ void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const
\brief The QTabBar class provides a tab bar, e.g. for use in tabbed dialogs.
\ingroup basicwidgets
- \mainclass
+
QTabBar is straightforward to use; it draws the tabs using one of
the predefined \link QTabBar::Shape shapes\endlink, and emits a
@@ -664,7 +667,7 @@ void QTabBarPrivate::refresh()
if (pressedIndex != -1
&& movable
&& QApplication::mouseButtons() == Qt::NoButton) {
- _q_moveTabFinished(pressedIndex);
+ moveTabFinished(pressedIndex);
if (!validIndex(pressedIndex))
pressedIndex = -1;
}
@@ -1290,6 +1293,7 @@ QSize QTabBarPrivate::minimumTabSizeHint(int index)
*/
QSize QTabBar::tabSizeHint(int index) const
{
+ //Note: this must match with the computations in QCommonStylePrivate::tabLayout
Q_D(const QTabBar);
if (const QTabBarPrivate::Tab *tab = d->at(index)) {
QStyleOptionTabV3 opt;
@@ -1306,18 +1310,18 @@ QSize QTabBar::tabSizeHint(int index) const
int widgetWidth = 0;
int widgetHeight = 0;
int padding = 0;
- if (opt.leftButtonSize.isValid()) {
- padding += 6 + 2;
+ if (!opt.leftButtonSize.isEmpty()) {
+ padding += 4;
widgetWidth += opt.leftButtonSize.width();
widgetHeight += opt.leftButtonSize.height();
}
- if (opt.rightButtonSize.isValid()) {
- padding += 6 + 2;
+ if (!opt.rightButtonSize.isEmpty()) {
+ padding += 4;
widgetWidth += opt.rightButtonSize.width();
widgetHeight += opt.rightButtonSize.height();
}
- if (opt.iconSize.isValid())
- padding += 2;
+ if (!opt.icon.isNull())
+ padding += 4;
QSize csz;
if (verticalTabs(d->shape)) {
@@ -1663,26 +1667,17 @@ void QTabBarPrivate::slide(int from, int to)
q->setUpdatesEnabled(true);
int postLocation = vertical ? q->tabRect(to).y() : q->tabRect(to).x();
int length = postLocation - preLocation;
- tabList[to].makeTimeLine(q);
- tabList[to].dragOffset += -1 * length;
- tabList[to].timeLine->setFrameRange(tabList[to].dragOffset, 0);
- animations[tabList[to].timeLine] = to;
- tabList[to].timeLine->setDuration(ANIMATION_DURATION);
- if (tabList[to].timeLine->state() != QTimeLine::Running)
- tabList[to].timeLine->start();
+ tabList[to].dragOffset -= length;
+ tabList[to].startAnimation(this, ANIMATION_DURATION);
}
-void QTabBarPrivate::_q_moveTab(int offset)
+void QTabBarPrivate::moveTab(int index, int offset)
{
- Q_Q(QTabBar);
- if (QTimeLine *timeLine = qobject_cast<QTimeLine *>(q->sender())) {
- int index = animations[timeLine];
- if (!validIndex(index))
- return;
- tabList[index].dragOffset = offset;
- layoutTab(index); // Make buttons follow tab
- q->update();
- }
+ if (!validIndex(index))
+ return;
+ tabList[index].dragOffset = offset;
+ layoutTab(index); // Make buttons follow tab
+ q_func()->update();
}
/*!\reimp
@@ -1696,7 +1691,7 @@ void QTabBar::mousePressEvent(QMouseEvent *event)
}
// Be safe!
if (d->pressedIndex != -1 && d->movable)
- d->_q_moveTabFinished(d->pressedIndex);
+ d->moveTabFinished(d->pressedIndex);
d->pressedIndex = d->indexAtPos(event->pos());
if (d->validIndex(d->pressedIndex)) {
@@ -1722,7 +1717,7 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event)
// Be safe!
if (d->pressedIndex != -1
&& event->buttons() == Qt::NoButton)
- d->_q_moveTabFinished(d->pressedIndex);
+ d->moveTabFinished(d->pressedIndex);
// Start drag
if (!d->dragInProgress && d->pressedIndex != -1) {
@@ -1790,16 +1785,6 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event)
optTabBase.documentMode = d->documentMode;
}
-void QTabBarPrivate::_q_moveTabFinished()
-{
- Q_Q(QTabBar);
- if (QTimeLine *timeLine = qobject_cast<QTimeLine *>(q->sender())) {
- int index = animations[timeLine];
- animations.remove(timeLine);
- _q_moveTabFinished(index);
- }
-}
-
void QTabBarPrivate::setupMovableTab()
{
Q_Q(QTabBar);
@@ -1839,12 +1824,20 @@ void QTabBarPrivate::setupMovableTab()
movingTab->setVisible(true);
}
-void QTabBarPrivate::_q_moveTabFinished(int index)
+void QTabBarPrivate::moveTabFinished(int index)
{
Q_Q(QTabBar);
bool cleanup = (pressedIndex == index) || (pressedIndex == -1) || !validIndex(index);
- if (animations.isEmpty() && cleanup) {
- if (movingTab)
+ bool allAnimationsFinished = true;
+#ifndef QT_NO_ANIMATION
+ for(int i = 0; allAnimationsFinished && i < tabList.count(); ++i) {
+ const Tab &t = tabList.at(i);
+ if (t.animation && t.animation->state() == QAbstractAnimation::Running)
+ allAnimationsFinished = false;
+ }
+#endif //QT_NO_ANIMATION
+ if (allAnimationsFinished && cleanup) {
+ if(movingTab)
movingTab->setVisible(false); // We might not get a mouse release
for (int i = 0; i < tabList.count(); ++i) {
tabList[i].dragOffset = 0;
@@ -1879,17 +1872,8 @@ void QTabBar::mouseReleaseEvent(QMouseEvent *event)
? tabRect(d->pressedIndex).height()
: tabRect(d->pressedIndex).width();
int duration = qMin(ANIMATION_DURATION,
- ((length < 0 ? (-1 * length) : length) * ANIMATION_DURATION) / width);
- if (duration > 0) {
- d->tabList[d->pressedIndex].makeTimeLine(this);
- d->tabList[d->pressedIndex].timeLine->setFrameRange(length, 0);
- d->animations[d->tabList[d->pressedIndex].timeLine] = d->pressedIndex;
- d->tabList[d->pressedIndex].timeLine->setDuration(duration);
- if (d->tabList[d->pressedIndex].timeLine->state() != QTimeLine::Running)
- d->tabList[d->pressedIndex].timeLine->start();
- } else {
- d->_q_moveTabFinished(d->pressedIndex);
- }
+ (qAbs(length) * ANIMATION_DURATION) / width);
+ d->tabList[d->pressedIndex].startAnimation(d, duration);
d->dragInProgress = false;
d->movingTab->setVisible(false);
d->dragStartPosition = QPoint();
@@ -1945,8 +1929,10 @@ void QTabBar::changeEvent(QEvent *event)
if (event->type() == QEvent::StyleChange) {
d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, 0, this));
d->useScrollButtons = !style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, 0, this);
+ d->refresh();
+ } else if (event->type() == QEvent::FontChange) {
+ d->refresh();
}
- d->refresh();
QWidget::changeEvent(event);
}
diff --git a/src/gui/widgets/qtabbar.h b/src/gui/widgets/qtabbar.h
index 65d79c2..a756ca4 100644
--- a/src/gui/widgets/qtabbar.h
+++ b/src/gui/widgets/qtabbar.h
@@ -215,8 +215,6 @@ private:
Q_DECLARE_PRIVATE(QTabBar)
Q_PRIVATE_SLOT(d_func(), void _q_scrollTabs())
Q_PRIVATE_SLOT(d_func(), void _q_closeTab())
- Q_PRIVATE_SLOT(d_func(), void _q_moveTab(int))
- Q_PRIVATE_SLOT(d_func(), void _q_moveTabFinished())
};
#endif // QT_NO_TABBAR
diff --git a/src/gui/widgets/qtabbar_p.h b/src/gui/widgets/qtabbar_p.h
index d632753..150909e 100644
--- a/src/gui/widgets/qtabbar_p.h
+++ b/src/gui/widgets/qtabbar_p.h
@@ -58,9 +58,8 @@
#include <qicon.h>
#include <qtoolbutton.h>
-#include <qtimeline.h>
-#include <qhash.h>
#include <qdebug.h>
+#include <qvariantanimation.h>
#ifndef QT_NO_TABBAR
@@ -75,9 +74,10 @@ class QTabBarPrivate : public QWidgetPrivate
Q_DECLARE_PUBLIC(QTabBar)
public:
QTabBarPrivate()
- :currentIndex(-1), pressedIndex(-1),
- shape(QTabBar::RoundedNorth),
- layoutDirty(false), drawBase(true), scrollOffset(0), expanding(true), closeButtonOnTabs(false), selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false), dragInProgress(false), documentMode(false), movingTab(0) {}
+ :currentIndex(-1), pressedIndex(-1), shape(QTabBar::RoundedNorth), layoutDirty(false),
+ drawBase(true), scrollOffset(0), expanding(true), closeButtonOnTabs(false),
+ selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false),
+ dragInProgress(false), documentMode(false), movingTab(0) {}
int currentIndex;
int pressedIndex;
@@ -88,16 +88,13 @@ public:
struct Tab {
inline Tab(const QIcon &ico, const QString &txt)
- : enabled(true)
- , shortcutId(0)
- , text(txt)
- , icon(ico)
- , leftWidget(0)
- , rightWidget(0)
- , lastTab(-1)
- , timeLine(0)
- , dragOffset(0)
+ : enabled(true) , shortcutId(0), text(txt), icon(ico),
+ leftWidget(0), rightWidget(0), lastTab(-1), dragOffset(0)
+#ifndef QT_NO_ANIMATION
+ , animation(0)
+#endif //QT_NO_ANIMATION
{}
+ bool operator==(const Tab &other) const { return &other == this; }
bool enabled;
int shortcutId;
QString text;
@@ -117,21 +114,39 @@ public:
QWidget *leftWidget;
QWidget *rightWidget;
int lastTab;
-
- QTimeLine *timeLine;
int dragOffset;
- void makeTimeLine(QWidget *q) {
- if (timeLine)
- return;
- timeLine = new QTimeLine(ANIMATION_DURATION, q);
- q->connect(timeLine, SIGNAL(frameChanged(int)), q, SLOT(_q_moveTab(int)));
- q->connect(timeLine, SIGNAL(finished()), q, SLOT(_q_moveTabFinished()));
+#ifndef QT_NO_ANIMATION
+ ~Tab() { delete animation; }
+ struct TabBarAnimation : public QVariantAnimation {
+ TabBarAnimation(Tab *t, QTabBarPrivate *_priv) : tab(t), priv(_priv)
+ { setEasingCurve(QEasingCurve::InOutQuad); }
+
+ void updateCurrentValue(const QVariant &current)
+ { priv->moveTab(priv->tabList.indexOf(*tab), current.toInt()); }
+
+ void updateState(State, State newState)
+ { if (newState == Stopped) priv->moveTabFinished(priv->tabList.indexOf(*tab)); }
+ private:
+ //these are needed for the callbacks
+ Tab *tab;
+ QTabBarPrivate *priv;
+ } *animation;
+
+ void startAnimation(QTabBarPrivate *priv, int duration) {
+ if (!animation)
+ animation = new TabBarAnimation(this, priv);
+ animation->setStartValue(dragOffset);
+ animation->setEndValue(0);
+ animation->setDuration(duration);
+ animation->start();
}
-
+#else
+ void startAnimation(QTabBarPrivate *priv, int duration)
+ { Q_UNUSED(duration); priv->moveTabFinished(priv->tabList.indexOf(*this)); }
+#endif //QT_NO_ANIMATION
};
QList<Tab> tabList;
- QHash<QTimeLine*, int> animations;
int calculateNewPosition(int from, int to, int index) const;
void slide(int from, int to);
@@ -152,9 +167,8 @@ public:
void _q_scrollTabs();
void _q_closeTab();
- void _q_moveTab(int);
- void _q_moveTabFinished();
- void _q_moveTabFinished(int offset);
+ void moveTab(int index, int offset);
+ void moveTabFinished(int index);
QRect hoverRect;
void refresh();
diff --git a/src/gui/widgets/qtabwidget.cpp b/src/gui/widgets/qtabwidget.cpp
index 53f9bb5..a555def 100644
--- a/src/gui/widgets/qtabwidget.cpp
+++ b/src/gui/widgets/qtabwidget.cpp
@@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE
\ingroup organizers
\ingroup basicwidgets
- \mainclass
+
A tab widget provides a tab bar (see QTabBar) and a "page area"
that is used to display pages related to each tab. By default, the
@@ -1057,7 +1057,7 @@ void QTabWidget::keyPressEvent(QKeyEvent *e)
break;
}
}
- if (!qApp->focusWidget())
+ if (!QApplication::focusWidget())
d->tabs->setFocus();
} else {
e->ignore();
diff --git a/src/gui/widgets/qtextbrowser.cpp b/src/gui/widgets/qtextbrowser.cpp
index ee94406..438d8de 100644
--- a/src/gui/widgets/qtextbrowser.cpp
+++ b/src/gui/widgets/qtextbrowser.cpp
@@ -263,7 +263,7 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
Q_Q(QTextBrowser);
#ifndef QT_NO_CURSOR
if (q->isVisible())
- qApp->setOverrideCursor(Qt::WaitCursor);
+ QApplication::setOverrideCursor(Qt::WaitCursor);
#endif
textOrSourceChanged = true;
@@ -295,9 +295,9 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
if (q->isVisible()) {
QString firstTag = txt.left(txt.indexOf(QLatin1Char('>')) + 1);
- if (firstTag.left(3) == QLatin1String("<qt") && firstTag.contains(QLatin1String("type")) && firstTag.contains(QLatin1String("detail"))) {
+ if (firstTag.startsWith(QLatin1String("<qt")) && firstTag.contains(QLatin1String("type")) && firstTag.contains(QLatin1String("detail"))) {
#ifndef QT_NO_CURSOR
- qApp->restoreOverrideCursor();
+ QApplication::restoreOverrideCursor();
#endif
#ifndef QT_NO_WHATSTHIS
QWhatsThis::showText(QCursor::pos(), txt, q);
@@ -342,7 +342,7 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
#ifndef QT_NO_CURSOR
if (q->isVisible())
- qApp->restoreOverrideCursor();
+ QApplication::restoreOverrideCursor();
#endif
emit q->sourceChanged(url);
}
@@ -580,7 +580,7 @@ void QTextBrowserPrivate::restoreHistoryEntry(const HistoryEntry entry)
\class QTextBrowser
\brief The QTextBrowser class provides a rich text browser with hypertext navigation.
- \ingroup text
+ \ingroup richtext-processing
This class extends QTextEdit (in read-only mode), adding some navigation
functionality so that users can follow links in hypertext documents.
diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp
index 05004a2..547a4fb 100644
--- a/src/gui/widgets/qtextedit.cpp
+++ b/src/gui/widgets/qtextedit.cpp
@@ -67,6 +67,8 @@
#include <qtexttable.h>
#include <qvariant.h>
+#include <qstandardgestures.h>
+
#include <qinputcontext.h>
#endif
@@ -74,6 +76,10 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_TEXTEDIT
+static inline bool shouldEnableInputMethod(QTextEdit *textedit)
+{
+ return !textedit->isReadOnly();
+}
class QTextEditControl : public QTextControl
{
@@ -105,12 +111,16 @@ QTextEditPrivate::QTextEditPrivate()
: control(0),
autoFormatting(QTextEdit::AutoNone), tabChangesFocus(false),
lineWrap(QTextEdit::WidgetWidth), lineWrapColumnOrWidth(0),
- wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), textFormat(Qt::AutoText)
+ wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), clickCausedFocus(0),
+ textFormat(Qt::AutoText)
{
ignoreAutomaticScrollbarAdjustment = false;
preferRichText = false;
showCursorOnInitialShow = true;
inDrag = false;
+#ifdef Q_WS_WIN
+ setSingleFingerPanEnabled(true);
+#endif
}
void QTextEditPrivate::createAutoBulletList()
@@ -328,8 +338,8 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
\brief The QTextEdit class provides a widget that is used to edit and display
both plain and rich text.
- \ingroup text
- \mainclass
+ \ingroup richtext-processing
+
\tableofcontents
@@ -1559,6 +1569,8 @@ void QTextEdit::mouseReleaseEvent(QMouseEvent *e)
d->autoScrollTimer.stop();
ensureCursorVisible();
}
+ d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
+ d->clickCausedFocus = 0;
}
/*! \reimp
@@ -1659,6 +1671,7 @@ void QTextEdit::inputMethodEvent(QInputMethodEvent *e)
}
#endif
d->sendControlEvent(e);
+ ensureCursorVisible();
}
/*!\reimp
@@ -1694,6 +1707,9 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
void QTextEdit::focusInEvent(QFocusEvent *e)
{
Q_D(QTextEdit);
+ if (e->reason() == Qt::MouseFocusReason) {
+ d->clickCausedFocus = 1;
+ }
QAbstractScrollArea::focusInEvent(e);
d->sendControlEvent(e);
}
@@ -2058,7 +2074,7 @@ void QTextEdit::setReadOnly(bool ro)
} else {
flags = Qt::TextEditorInteraction;
}
- setAttribute(Qt::WA_InputMethodEnabled, !ro);
+ setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
d->control->setTextInteractionFlags(flags);
}
@@ -2609,7 +2625,6 @@ void QTextEdit::ensureCursorVisible()
d->control->ensureCursorVisible();
}
-
/*!
\enum QTextEdit::KeyboardAction
diff --git a/src/gui/widgets/qtextedit_p.h b/src/gui/widgets/qtextedit_p.h
index 9db1a09..fb1611d 100644
--- a/src/gui/widgets/qtextedit_p.h
+++ b/src/gui/widgets/qtextedit_p.h
@@ -70,7 +70,6 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_TEXTEDIT
class QMimeData;
-
class QTextEditPrivate : public QAbstractScrollAreaPrivate
{
Q_DECLARE_PUBLIC(QTextEdit)
@@ -123,6 +122,7 @@ public:
uint preferRichText : 1;
uint showCursorOnInitialShow : 1;
uint inDrag : 1;
+ uint clickCausedFocus : 1;
// Qt3 COMPAT only, for setText
Qt::TextFormat textFormat;
diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp
index e02fdd5..7270954 100644
--- a/src/gui/widgets/qtoolbar.cpp
+++ b/src/gui/widgets/qtoolbar.cpp
@@ -70,6 +70,8 @@
#include "qdebug.h"
+#define POPUP_TIMER_INTERVAL 500
+
QT_BEGIN_NAMESPACE
#ifdef Q_WS_MAC
@@ -87,14 +89,6 @@ static void qt_mac_updateToolBarButtonHint(QWidget *parentWidget)
void QToolBarPrivate::init()
{
Q_Q(QToolBar);
-
- waitForPopupTimer = new QTimer(q);
- waitForPopupTimer->setSingleShot(false);
- waitForPopupTimer->setInterval(500);
- QObject::connect(waitForPopupTimer, SIGNAL(timeout()), q, SLOT(_q_waitForPopup()));
-
- floatable = true;
- movable = true;
q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
q->setBackgroundRole(QPalette::Button);
q->setAttribute(Qt::WA_Hover);
@@ -198,7 +192,7 @@ void QToolBarPrivate::initDrag(const QPoint &pos)
if (state != 0)
return;
- QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *win = qobject_cast<QMainWindow*>(parent);
Q_ASSERT(win != 0);
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
Q_ASSERT(layout != 0);
@@ -211,7 +205,7 @@ void QToolBarPrivate::initDrag(const QPoint &pos)
state->moving = false;
state->widgetItem = 0;
- if (q->layoutDirection() == Qt::RightToLeft)
+ if (q->isRightToLeft())
state->pressPos = QPoint(q->width() - state->pressPos.x(), state->pressPos.y());
}
@@ -224,7 +218,7 @@ void QToolBarPrivate::startDrag(bool moving)
if ((moving && state->moving) || state->dragging)
return;
- QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *win = qobject_cast<QMainWindow*>(parent);
Q_ASSERT(win != 0);
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
Q_ASSERT(layout != 0);
@@ -274,14 +268,16 @@ void QToolBarPrivate::endDrag()
bool QToolBarPrivate::mousePressEvent(QMouseEvent *event)
{
- if (layout->handleRect().contains(event->pos()) == false) {
+ Q_Q(QToolBar);
+ QStyleOptionToolBar opt;
+ q->initStyleOption(&opt);
+ if (q->style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, q).contains(event->pos()) == false) {
#ifdef Q_WS_MAC
- Q_Q(QToolBar);
// When using the unified toolbar on Mac OS X the user can can click and
// drag between toolbar contents to move the window. Make this work by
// implementing the standard mouse-dragging code and then call
// window->move() in mouseMoveEvent below.
- if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q->parentWidget())) {
+ if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parent)) {
if (mainWindow->toolBarArea(q) == Qt::TopToolBarArea
&& mainWindow->unifiedTitleAndToolBarOnMac()
&& q->childAt(event->pos()) == 0) {
@@ -335,7 +331,7 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
return false;
}
- QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *win = qobject_cast<QMainWindow*>(parent);
if (win == 0)
return true;
@@ -363,7 +359,7 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
QPoint pos = event->globalPos();
// if we are right-to-left, we move so as to keep the right edge the same distance
// from the mouse
- if (q->layoutDirection() == Qt::LeftToRight)
+ if (q->isLeftToRight())
pos -= state->pressPos;
else
pos += QPoint(state->pressPos.x() - q->width(), -state->pressPos.y());
@@ -373,14 +369,14 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
} else if (state->moving) {
const QPoint rtl(q->width() - state->pressPos.x(), state->pressPos.y()); //for RTL
- const QPoint globalPressPos = q->mapToGlobal(q->layoutDirection() == Qt::RightToLeft ? rtl : state->pressPos);
+ const QPoint globalPressPos = q->mapToGlobal(q->isRightToLeft() ? rtl : state->pressPos);
int pos = 0;
QPoint delta = event->globalPos() - globalPressPos;
if (orientation == Qt::Vertical) {
pos = q->y() + delta.y();
} else {
- if (q->layoutDirection() == Qt::RightToLeft) {
+ if (q->isRightToLeft()) {
pos = win->width() - q->width() - q->x() - delta.x();
} else {
pos = q->x() + delta.x();
@@ -395,7 +391,7 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
void QToolBarPrivate::unplug(const QRect &_r)
{
Q_Q(QToolBar);
-
+ layout->setExpanded(false, false);
QRect r = _r;
r.moveTopLeft(q->mapToGlobal(QPoint(0, 0)));
setWindowState(true, true, r);
@@ -416,8 +412,8 @@ void QToolBarPrivate::plug(const QRect &r)
\brief The QToolBar class provides a movable panel that contains a
set of controls.
- \ingroup application
- \mainclass
+ \ingroup mainwindow-classes
+
Toolbar buttons are added by adding \e actions, using addAction()
or insertAction(). Groups of buttons can be separated using
@@ -878,7 +874,7 @@ QAction *QToolBar::insertSeparator(QAction *before)
If you add a QToolButton with this method, the tools bar's
Qt::ToolButtonStyle will not be respected.
- Note: You should use QAction::setVisible() to change the
+ \note You should use QAction::setVisible() to change the
visibility of the widget. Using QWidget::setVisible(),
QWidget::show() and QWidget::hide() does not work.
@@ -1041,7 +1037,7 @@ void QToolBar::paintEvent(QPaintEvent *)
style->drawControl(QStyle::CE_ToolBar, &opt, &p, this);
}
- opt.rect = d->layout->handleRect();
+ opt.rect = style->subElementRect(QStyle::SE_ToolBarHandle, &opt, this);
if (opt.rect.isValid())
style->drawPrimitive(QStyle::PE_IndicatorToolBarHandle, &opt, &p, this);
}
@@ -1078,19 +1074,46 @@ static bool waitForPopup(QToolBar *tb, QWidget *popup)
return false;
}
+#if defined(Q_WS_MAC)
+static bool toolbarInUnifiedToolBar(QToolBar *toolbar)
+{
+ const QMainWindow *mainWindow = qobject_cast<const QMainWindow *>(toolbar->parentWidget());
+ return mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()
+ && mainWindow->toolBarArea(toolbar) == Qt::TopToolBarArea;
+}
+#endif
+
/*! \reimp */
bool QToolBar::event(QEvent *event)
{
Q_D(QToolBar);
switch (event->type()) {
+ case QEvent::Timer:
+ if (d->waitForPopupTimer.timerId() == static_cast<QTimerEvent*>(event)->timerId()) {
+ QWidget *w = QApplication::activePopupWidget();
+ if (!waitForPopup(this, w)) {
+ d->waitForPopupTimer.stop();
+ if (!this->underMouse())
+ d->layout->setExpanded(false);
+ }
+ }
+ break;
case QEvent::Hide:
if (!isHidden())
break;
// fallthrough intended
case QEvent::Show:
d->toggleViewAction->setChecked(event->type() == QEvent::Show);
-#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
+#if defined(Q_WS_MAC)
+ if (toolbarInUnifiedToolBar(this)) {
+ // I can static_cast because I did the qobject_cast in the if above, therefore
+ // we must have a QMainWindowLayout here.
+ QMainWindowLayout *mwLayout = static_cast<QMainWindowLayout *>(parentWidget()->layout());
+ mwLayout->fixSizeInUnifiedToolbar(this);
+ mwLayout->syncUnifiedToolbarVisibility();
+ }
+# if !defined(QT_MAC_USE_COCOA)
// Fall through
case QEvent::LayoutRequest: {
// There's currently no way to invalidate the size and let
@@ -1105,10 +1128,9 @@ bool QToolBar::event(QEvent *event)
}
if (needUpdate) {
- OSWindowRef windowRef = qt_mac_window_for(this);
- if (mainWindow->unifiedTitleAndToolBarOnMac()
- && mainWindow->toolBarArea(this) == Qt::TopToolBarArea
- && macWindowToolbarVisible(windowRef)) {
+ OSWindowRef windowRef = qt_mac_window_for(mainWindow);
+ if (toolbarInUnifiedToolBar(this)
+ && macWindowToolbarIsVisible(windowRef)) {
DisableScreenUpdates();
macWindowToolbarShow(this, false);
macWindowToolbarShow(this, true);
@@ -1120,7 +1142,8 @@ bool QToolBar::event(QEvent *event)
return earlyResult;
}
}
-#endif
+# endif // !QT_MAC_USE_COCOA
+#endif // Q_WS_MAC
break;
case QEvent::ParentChange:
d->layout->checkUsePopupMenu();
@@ -1139,10 +1162,16 @@ bool QToolBar::event(QEvent *event)
if (d->mouseReleaseEvent(static_cast<QMouseEvent*>(event)))
return true;
break;
+ case QEvent::HoverEnter:
+ case QEvent::HoverLeave:
+ // there's nothing special to do here and we don't want to update the whole widget
+ return true;
case QEvent::HoverMove: {
#ifndef QT_NO_CURSOR
QHoverEvent *e = static_cast<QHoverEvent*>(event);
- if (d->layout->handleRect().contains(e->pos()))
+ QStyleOptionToolBar opt;
+ initStyleOption(&opt);
+ if (style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, this).contains(e->pos()))
setCursor(Qt::SizeAllCursor);
else
unsetCursor();
@@ -1153,7 +1182,7 @@ bool QToolBar::event(QEvent *event)
if (d->mouseMoveEvent(static_cast<QMouseEvent*>(event)))
return true;
break;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
case QEvent::ContextMenu:
{
QContextMenuEvent* contextMenuEvent = static_cast<QContextMenuEvent*>(event);
@@ -1177,13 +1206,13 @@ bool QToolBar::event(QEvent *event)
if (!d->layout->expanded)
break;
- QWidget *w = qApp->activePopupWidget();
+ QWidget *w = QApplication::activePopupWidget();
if (waitForPopup(this, w)) {
- d->waitForPopupTimer->start();
+ d->waitForPopupTimer.start(POPUP_TIMER_INTERVAL, this);
break;
}
- d->waitForPopupTimer->stop();
+ d->waitForPopupTimer.stop();
d->layout->setExpanded(false);
break;
}
@@ -1193,18 +1222,6 @@ bool QToolBar::event(QEvent *event)
return QWidget::event(event);
}
-void QToolBarPrivate::_q_waitForPopup()
-{
- Q_Q(QToolBar);
-
- QWidget *w = qApp->activePopupWidget();
- if (!waitForPopup(q, w)) {
- waitForPopupTimer->stop();
- if (!q->underMouse())
- layout->setExpanded(false);
- }
-}
-
/*!
Returns a checkable action that can be used to show or hide this
toolbar.
diff --git a/src/gui/widgets/qtoolbar.h b/src/gui/widgets/qtoolbar.h
index 0e89e59..9635868 100644
--- a/src/gui/widgets/qtoolbar.h
+++ b/src/gui/widgets/qtoolbar.h
@@ -167,7 +167,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_toggleView(bool))
Q_PRIVATE_SLOT(d_func(), void _q_updateIconSize(const QSize &))
Q_PRIVATE_SLOT(d_func(), void _q_updateToolButtonStyle(Qt::ToolButtonStyle))
- Q_PRIVATE_SLOT(d_func(), void _q_waitForPopup())
friend class QMainWindow;
friend class QMainWindowLayout;
diff --git a/src/gui/widgets/qtoolbar_p.h b/src/gui/widgets/qtoolbar_p.h
index ce17b24..513427c 100644
--- a/src/gui/widgets/qtoolbar_p.h
+++ b/src/gui/widgets/qtoolbar_p.h
@@ -56,6 +56,7 @@
#include "qtoolbar.h"
#include "QtGui/qaction.h"
#include "private/qwidget_p.h"
+#include <QtCore/qbasictimer.h>
QT_BEGIN_NAMESPACE
@@ -70,7 +71,7 @@ class QToolBarPrivate : public QWidgetPrivate
public:
inline QToolBarPrivate()
- : explicitIconSize(false), explicitToolButtonStyle(false), movable(false),
+ : explicitIconSize(false), explicitToolButtonStyle(false), movable(true), floatable(true),
allowedAreas(Qt::AllToolBarAreas), orientation(Qt::Horizontal),
toolButtonStyle(Qt::ToolButtonIconOnly),
layout(0), state(0)
@@ -84,16 +85,15 @@ public:
void _q_toggleView(bool b);
void _q_updateIconSize(const QSize &sz);
void _q_updateToolButtonStyle(Qt::ToolButtonStyle style);
- void _q_waitForPopup();
bool explicitIconSize;
bool explicitToolButtonStyle;
bool movable;
+ bool floatable;
Qt::ToolBarAreas allowedAreas;
Qt::Orientation orientation;
Qt::ToolButtonStyle toolButtonStyle;
QSize iconSize;
- bool floatable;
QAction *toggleViewAction;
@@ -125,7 +125,7 @@ public:
void unplug(const QRect &r);
void plug(const QRect &r);
- QTimer *waitForPopupTimer;
+ QBasicTimer waitForPopupTimer;
};
#endif // QT_NO_TOOLBAR
diff --git a/src/gui/widgets/qtoolbararealayout.cpp b/src/gui/widgets/qtoolbararealayout.cpp
index dd5522e..5c6b6b0 100644
--- a/src/gui/widgets/qtoolbararealayout.cpp
+++ b/src/gui/widgets/qtoolbararealayout.cpp
@@ -113,7 +113,7 @@ QSize QToolBarAreaLayoutLine::sizeHint() const
continue;
QSize sh = item.sizeHint();
- a += pick(o, sh) + item.extraSpace;
+ a += item.preferredSize > 0 ? item.preferredSize : pick(o, sh);
b = qMax(b, perp(o, sh));
}
@@ -156,19 +156,18 @@ void QToolBarAreaLayoutLine::fitLayout()
if (item.skip())
continue;
- QToolBarLayout *tblayout = qobject_cast<QToolBarLayout*>(item.widgetItem->widget()->layout());
- if (tblayout)
+ if (QToolBarLayout *tblayout = qobject_cast<QToolBarLayout*>(item.widgetItem->widget()->layout()))
tblayout->checkUsePopupMenu();
- int itemMin = pick(o, item.minimumSize());
- int itemHint = pick(o, item.sizeHint());
- //we ensure the extraspace is not too low
- item.extraSpace = qMax(itemMin - itemHint, item.extraSpace);
- itemHint += item.extraSpace;
- int itemExtra = qMin(itemHint - itemMin, extra);
+ const int itemMin = pick(o, item.minimumSize());
+ //preferredSize is the default if it is set, otherwise, we take the sizehint
+ item.size = item.preferredSize > 0 ? item.preferredSize : pick(o, item.sizeHint());
- item.size = itemMin + itemExtra;
- extra -= itemExtra;
+ //the extraspace is the space above the item minimum sizehint
+ const int extraSpace = qMin(item.size - itemMin, extra);
+ item.size = itemMin + extraSpace; //that is the real size
+
+ extra -= extraSpace;
last = i;
}
@@ -395,17 +394,15 @@ void QToolBarAreaLayoutInfo::removeToolBarBreak(QToolBar *before)
void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
{
- if (dirty) {
+ if (dirty)
fitLayout();
- }
dirty = true;
- if (o == Qt::Vertical) {
+ if (o == Qt::Vertical)
pos -= rect.top();
- }
- //here we actually update the extraSpace for the line containing the toolbar so that we move it
+ //here we actually update the preferredSize for the line containing the toolbar so that we move it
for (int j = 0; j < lines.count(); ++j) {
QToolBarAreaLayoutLine &line = lines[j];
@@ -432,22 +429,22 @@ void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
newPos = qMin(pos, maxPos);
}
- //let's update the previous extra space
+ //extra is the number of pixels to add to the previous toolbar
int extra = newPos - current.pos;
- if (qAbs(previous.extraSpace + extra) < QApplication::startDragDistance()) {
- //we stick to the default space
- extra = 0;
+ //we check if the previous is near its size hint
+ //in which case we try to stick to it
+ const int diff = pick(o, previous.sizeHint()) - (previous.size + extra);
+ if (qAbs(diff) < QApplication::startDragDistance()) {
+ //we stick to the default place and size
+ extra += diff;
}
//update for the current item
- current.extraSpace -= extra;
- //this ensures the toolbars to be pushed to the right when necessary
- current.extraSpace = qMax(pick(o,current.minimumSize())- pick(o,current.sizeHint()), current.extraSpace);
-
- if (extra >= 0) {
- previous.extraSpace += extra;
+ current.extendSize(line.o, -extra);
+ if (extra >= 0) {
+ previous.extendSize(line.o, extra);
} else {
//we need to push the toolbars on the left starting with previous
extra = -extra; // we just need to know the number of pixels
@@ -455,13 +452,13 @@ void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
for(int l = previousIndex; l >=0; --l) {
QToolBarAreaLayoutItem &item = line.toolBarItems[l];
if (!item.skip()) {
- const int minExtraSpace = pick(o, item.minimumSize()) - pick(o, item.sizeHint());
- const int margin = item.extraSpace - minExtraSpace;
+ const int minPreferredSize = pick(o, item.minimumSize());
+ const int margin = item.size - minPreferredSize;
if (margin < extra) {
- item.extraSpace = minExtraSpace;
+ item.resize(line.o, minPreferredSize);
extra -= margin;
} else {
- item.extraSpace -= extra;
+ item.extendSize(line.o, -extra);
extra = 0;
}
}
@@ -523,9 +520,10 @@ QList<int> QToolBarAreaLayoutInfo::gapIndex(const QPoint &pos) const
return QList<int>();
}
-bool QToolBarAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *item)
+bool QToolBarAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *item)
{
- int j = path.at(0);
+ Q_ASSERT(path.count() == 2);
+ int j = path.first();
if (j == lines.count())
lines.append(QToolBarAreaLayoutLine(o));
@@ -536,13 +534,22 @@ bool QToolBarAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *item)
gap_item.gap = true;
gap_item.widgetItem = item;
- //update the previous item's extra space
+ //update the previous item's preferred size
for(int p = k - 1 ; p >= 0; --p) {
QToolBarAreaLayoutItem &previous = line.toolBarItems[p];
if (!previous.skip()) {
//we found the previous one
- gap_item.extraSpace = qMax(0, previous.extraSpace - pick(o, gap_item.sizeHint()));
- previous.extraSpace = qMin(previous.extraSpace, 0);
+ int previousSizeHint = pick(line.o, previous.sizeHint());
+ int previousExtraSpace = previous.size - previousSizeHint;
+
+ if (previousExtraSpace > 0) {
+ //in this case we reset the space
+ previous.preferredSize = -1;
+ previous.size = previousSizeHint;
+
+ gap_item.resize(o, previousExtraSpace);
+ }
+
break;
}
}
@@ -555,11 +562,12 @@ bool QToolBarAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *item)
void QToolBarAreaLayoutInfo::clear()
{
lines.clear();
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
}
-QRect QToolBarAreaLayoutInfo::itemRect(QList<int> path) const
+QRect QToolBarAreaLayoutInfo::itemRect(const QList<int> &path) const
{
+ Q_ASSERT(path.count() == 2);
int j = path.at(0);
int k = path.at(1);
@@ -611,10 +619,8 @@ QRect QToolBarAreaLayoutInfo::appendLineDropRect() const
** QToolBarAreaLayout
*/
-QToolBarAreaLayout::QToolBarAreaLayout(QMainWindow *win)
+QToolBarAreaLayout::QToolBarAreaLayout(const QMainWindow *win) : mainWindow(win), visible(true)
{
- visible = true;
- mainWindow = win;
for (int i = 0; i < QInternal::DockCount; ++i) {
QInternal::DockPosition pos = static_cast<QInternal::DockPosition>(i);
docks[i] = QToolBarAreaLayoutInfo(pos);
@@ -920,7 +926,7 @@ void QToolBarAreaLayout::apply(bool animate)
if (visible && dock.o == Qt::Horizontal)
geo = QStyle::visualRect(dir, line.rect, geo);
- layout->widgetAnimator->animate(widget, geo, animate);
+ layout->widgetAnimator.animate(widget, geo, animate);
}
}
}
@@ -1052,16 +1058,17 @@ QList<int> QToolBarAreaLayout::currentGapIndex() const
return QList<int>();
}
-bool QToolBarAreaLayout::insertGap(QList<int> path, QLayoutItem *item)
+bool QToolBarAreaLayout::insertGap(const QList<int> &path, QLayoutItem *item)
{
- Q_ASSERT(!path.isEmpty());
- int i = path.takeFirst();
+ Q_ASSERT(path.count() == 3);
+ const int i = path.first();
Q_ASSERT(i >= 0 && i < QInternal::DockCount);
- return docks[i].insertGap(path, item);
+ return docks[i].insertGap(path.mid(1), item);
}
-void QToolBarAreaLayout::remove(QList<int> path)
+void QToolBarAreaLayout::remove(const QList<int> &path)
{
+ Q_ASSERT(path.count() == 3);
docks[path.at(0)].lines[path.at(1)].toolBarItems.removeAt(path.at(2));
}
@@ -1089,10 +1096,10 @@ void QToolBarAreaLayout::clear()
{
for (int i = 0; i < QInternal::DockCount; ++i)
docks[i].clear();
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
}
-QToolBarAreaLayoutItem &QToolBarAreaLayout::item(QList<int> path)
+QToolBarAreaLayoutItem &QToolBarAreaLayout::item(const QList<int> &path)
{
Q_ASSERT(path.count() == 3);
@@ -1104,18 +1111,18 @@ QToolBarAreaLayoutItem &QToolBarAreaLayout::item(QList<int> path)
return line.toolBarItems[path.at(2)];
}
-QRect QToolBarAreaLayout::itemRect(QList<int> path) const
+QRect QToolBarAreaLayout::itemRect(const QList<int> &path) const
{
- int i = path.takeFirst();
+ const int i = path.first();
- QRect r = docks[i].itemRect(path);
+ QRect r = docks[i].itemRect(path.mid(1));
if (docks[i].o == Qt::Horizontal)
r = QStyle::visualRect(mainWindow->layoutDirection(),
docks[i].rect, r);
return r;
}
-QLayoutItem *QToolBarAreaLayout::plug(QList<int> path)
+QLayoutItem *QToolBarAreaLayout::plug(const QList<int> &path)
{
QToolBarAreaLayoutItem &item = this->item(path);
Q_ASSERT(item.gap);
@@ -1124,25 +1131,33 @@ QLayoutItem *QToolBarAreaLayout::plug(QList<int> path)
return item.widgetItem;
}
-QLayoutItem *QToolBarAreaLayout::unplug(QList<int> path, QToolBarAreaLayout *other)
+QLayoutItem *QToolBarAreaLayout::unplug(const QList<int> &path, QToolBarAreaLayout *other)
{
//other needs to be update as well
+ Q_ASSERT(path.count() == 3);
QToolBarAreaLayoutItem &item = this->item(path);
//update the leading space here
QToolBarAreaLayoutInfo &info = docks[path.at(0)];
QToolBarAreaLayoutLine &line = info.lines[path.at(1)];
- if (item.extraSpace != 0) {
+ if (item.size != pick(line.o, item.realSizeHint())) {
+ //the item doesn't have its default size
+ //so we'll give this to the next item
int newExtraSpace = 0;
+ //let's iterate over the siblings of the current item that pare placed before it
+ //we need to find just the one before
for (int i = path.at(2) - 1; i >= 0; --i) {
QToolBarAreaLayoutItem &previous = line.toolBarItems[i];
if (!previous.skip()) {
+ //we need to check if it has a previous element and a next one
+ //the previous will get its size changed
for (int j = path.at(2) + 1; j < line.toolBarItems.count(); ++j) {
const QToolBarAreaLayoutItem &next = line.toolBarItems.at(j);
if (!next.skip()) {
- newExtraSpace = previous.extraSpace = next.pos - previous.pos - pick(line.o, previous.sizeHint());
+ newExtraSpace = next.pos - previous.pos - pick(line.o, previous.sizeHint());
+ previous.resize(line.o, next.pos - previous.pos);
+ break;
}
- break;
}
break;
}
@@ -1154,7 +1169,7 @@ QLayoutItem *QToolBarAreaLayout::unplug(QList<int> path, QToolBarAreaLayout *oth
for (int i = path.at(2) - 1; i >= 0; --i) {
QToolBarAreaLayoutItem &previous = line.toolBarItems[i];
if (!previous.skip()) {
- previous.extraSpace = newExtraSpace;
+ previous.resize(line.o, pick(line.o, previous.sizeHint()) + newExtraSpace);
break;
}
}
@@ -1162,7 +1177,6 @@ QLayoutItem *QToolBarAreaLayout::unplug(QList<int> path, QToolBarAreaLayout *oth
}
}
-
Q_ASSERT(!item.gap);
item.gap = true;
return item.widgetItem;
@@ -1253,8 +1267,8 @@ void QToolBarAreaLayout::saveState(QDataStream &stream) const
}
stream << shownOrientation;
stream << item.pos;
- //if extraSpace is 0 the item has its "normal" size, so no need to store the size (we store -1)
- stream << (item.extraSpace == 0 ? -1 : (pick(line.o, item.realSizeHint()) + item.extraSpace));
+ //we store the preferred size. If the use rdidn't resize the toolbars it will be -1
+ stream << item.preferredSize;
uint geom0, geom1;
packRect(&geom0, &geom1, widget->geometry(), widget->isWindow());
@@ -1339,10 +1353,7 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList<QToolBar*
toolBar->setVisible(shown & 1);
toolBar->d_func()->setWindowState(floating, true, rect);
- //if it is -1, it means we should use the default size
- item.extraSpace = (item.size == -1) ? 0 : item.size - pick(line.o, item.realSizeHint());
-
-
+ item.preferredSize = item.size;
line.toolBarItems.append(item);
}
}
diff --git a/src/gui/widgets/qtoolbararealayout_p.h b/src/gui/widgets/qtoolbararealayout_p.h
index 5cde78d..f1c2e27 100644
--- a/src/gui/widgets/qtoolbararealayout_p.h
+++ b/src/gui/widgets/qtoolbararealayout_p.h
@@ -59,6 +59,33 @@
QT_BEGIN_NAMESPACE
+static inline int pick(Qt::Orientation o, const QPoint &pos)
+{ return o == Qt::Horizontal ? pos.x() : pos.y(); }
+
+static inline int pick(Qt::Orientation o, const QSize &size)
+{ return o == Qt::Horizontal ? size.width() : size.height(); }
+
+static inline int &rpick(Qt::Orientation o, QPoint &pos)
+{ return o == Qt::Horizontal ? pos.rx() : pos.ry(); }
+
+static inline int &rpick(Qt::Orientation o, QSize &size)
+{ return o == Qt::Horizontal ? size.rwidth() : size.rheight(); }
+
+static inline QSizePolicy::Policy pick(Qt::Orientation o, const QSizePolicy &policy)
+{ return o == Qt::Horizontal ? policy.horizontalPolicy() : policy.verticalPolicy(); }
+
+static inline int perp(Qt::Orientation o, const QPoint &pos)
+{ return o == Qt::Vertical ? pos.x() : pos.y(); }
+
+static inline int perp(Qt::Orientation o, const QSize &size)
+{ return o == Qt::Vertical ? size.width() : size.height(); }
+
+static inline int &rperp(Qt::Orientation o, QPoint &pos)
+{ return o == Qt::Vertical ? pos.rx() : pos.ry(); }
+
+static inline int &rperp(Qt::Orientation o, QSize &size)
+{ return o == Qt::Vertical ? size.rwidth() : size.rheight(); }
+
#ifndef QT_NO_TOOLBAR
class QToolBar;
@@ -70,17 +97,41 @@ class QToolBarAreaLayoutItem
{
public:
QToolBarAreaLayoutItem(QLayoutItem *item = 0)
- : widgetItem(item), pos(0), size(-1), extraSpace(0), gap(false) {}
+ : widgetItem(item), pos(0), size(-1), preferredSize(-1), gap(false) {}
bool skip() const;
QSize minimumSize() const;
QSize sizeHint() const;
- QSize realSizeHint() const;
+ QSize realSizeHint() const;
+
+ void resize(Qt::Orientation o, int newSize)
+ {
+ newSize = qMax(pick(o, minimumSize()), newSize);
+ int sizeh = pick(o, sizeHint());
+ if (newSize == sizeh) {
+ preferredSize = -1;
+ size = sizeh;
+ } else {
+ preferredSize = newSize;
+ }
+ }
+
+ void extendSize(Qt::Orientation o, int extent)
+ {
+ int newSize = qMax(pick(o, minimumSize()), (preferredSize > 0 ? preferredSize : size) + extent);
+ int sizeh = pick(o, sizeHint());
+ if (newSize == sizeh) {
+ preferredSize = -1;
+ size = sizeh;
+ } else {
+ preferredSize = newSize;
+ }
+ }
QLayoutItem *widgetItem;
int pos;
int size;
- int extraSpace;
+ int preferredSize;
bool gap;
};
@@ -123,9 +174,9 @@ public:
void moveToolBar(QToolBar *toolbar, int pos);
QList<int> gapIndex(const QPoint &pos) const;
- bool insertGap(QList<int> path, QLayoutItem *item);
+ bool insertGap(const QList<int> &path, QLayoutItem *item);
void clear();
- QRect itemRect(QList<int> path) const;
+ QRect itemRect(const QList<int> &path) const;
QRect appendLineDropRect() const;
QRect rect;
@@ -143,11 +194,11 @@ public:
};
QRect rect;
- QMainWindow *mainWindow;
+ const QMainWindow *mainWindow;
QToolBarAreaLayoutInfo docks[4];
bool visible;
- QToolBarAreaLayout(QMainWindow *win);
+ QToolBarAreaLayout(const QMainWindow *win);
QRect fitLayout();
@@ -179,14 +230,14 @@ public:
QList<int> indexOf(QWidget *toolBar) const;
QList<int> gapIndex(const QPoint &pos) const;
QList<int> currentGapIndex() const;
- bool insertGap(QList<int> path, QLayoutItem *item);
- void remove(QList<int> path);
+ bool insertGap(const QList<int> &path, QLayoutItem *item);
+ void remove(const QList<int> &path);
void remove(QLayoutItem *item);
void clear();
- QToolBarAreaLayoutItem &item(QList<int> path);
- QRect itemRect(QList<int> path) const;
- QLayoutItem *plug(QList<int> path);
- QLayoutItem *unplug(QList<int> path, QToolBarAreaLayout *other);
+ QToolBarAreaLayoutItem &item(const QList<int> &path);
+ QRect itemRect(const QList<int> &path) const;
+ QLayoutItem *plug(const QList<int> &path);
+ QLayoutItem *unplug(const QList<int> &path, QToolBarAreaLayout *other);
void saveState(QDataStream &stream) const;
bool restoreState(QDataStream &stream, const QList<QToolBar*> &toolBars, uchar tmarker, bool pre43, bool testing = false);
diff --git a/src/gui/widgets/qtoolbarextension.cpp b/src/gui/widgets/qtoolbarextension.cpp
index 2fd592a..09b0e85 100644
--- a/src/gui/widgets/qtoolbarextension.cpp
+++ b/src/gui/widgets/qtoolbarextension.cpp
@@ -61,10 +61,12 @@ QToolBarExtension::QToolBarExtension(QWidget *parent)
void QToolBarExtension::setOrientation(Qt::Orientation o)
{
+ QStyleOption opt;
+ opt.init(this);
if (o == Qt::Horizontal) {
- setIcon(style()->standardIcon(QStyle::SP_ToolBarHorizontalExtensionButton));
+ setIcon(style()->standardIcon(QStyle::SP_ToolBarHorizontalExtensionButton, &opt));
} else {
- setIcon(style()->standardIcon(QStyle::SP_ToolBarVerticalExtensionButton));
+ setIcon(style()->standardIcon(QStyle::SP_ToolBarVerticalExtensionButton, &opt));
}
}
diff --git a/src/gui/widgets/qtoolbarlayout.cpp b/src/gui/widgets/qtoolbarlayout.cpp
index 9b59431..a6f0a93 100644
--- a/src/gui/widgets/qtoolbarlayout.cpp
+++ b/src/gui/widgets/qtoolbarlayout.cpp
@@ -127,10 +127,8 @@ void QToolBarLayout::setUsePopupMenu(bool set)
if (!dirty && ((popupMenu == 0) == set))
invalidate();
if (!set) {
- QObject::disconnect(extension, SIGNAL(clicked(bool)),
- this, SLOT(setExpanded(bool)));
QObject::connect(extension, SIGNAL(clicked(bool)),
- this, SLOT(setExpanded(bool)));
+ this, SLOT(setExpanded(bool)), Qt::UniqueConnection);
extension->setPopupMode(QToolButton::DelayedPopup);
extension->setMenu(0);
delete popupMenu;
@@ -336,7 +334,7 @@ void QToolBarLayout::updateGeomArray() const
if (QMainWindow *mw = qobject_cast<QMainWindow *>(parentWidget()->parentWidget())) {
if (mw->unifiedTitleAndToolBarOnMac()
&& mw->toolBarArea(static_cast<QToolBar *>(parentWidget())) == Qt::TopToolBarArea) {
- if (that->expandFlag) {
+ if (expandFlag) {
tb->setMaximumSize(0xFFFFFF, 0xFFFFFF);
} else {
tb->setMaximumSize(hint);
@@ -362,23 +360,11 @@ void QToolBarLayout::setGeometry(const QRect &rect)
QStyle *style = tb->style();
QStyleOptionToolBar opt;
tb->initStyleOption(&opt);
- const int handleExtent = movable()
- ? style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb) : 0;
const int margin = this->margin();
const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
Qt::Orientation o = tb->orientation();
QLayout::setGeometry(rect);
- if (movable()) {
- if (o == Qt::Horizontal) {
- handRect = QRect(margin, margin, handleExtent, rect.height() - 2*margin);
- handRect = QStyle::visualRect(parentWidget()->layoutDirection(), rect, handRect);
- } else {
- handRect = QRect(margin, margin, rect.width() - 2*margin, handleExtent);
- }
- } else {
- handRect = QRect();
- }
bool ranOutOfSpace = false;
if (!animating)
@@ -656,7 +642,7 @@ QSize QToolBarLayout::expandedSize(const QSize &size) const
return result;
}
-void QToolBarLayout::setExpanded(bool exp)
+void QToolBarLayout::setExpanded(bool exp, bool animated)
{
if (exp == expanded)
return;
@@ -679,7 +665,7 @@ void QToolBarLayout::setExpanded(bool exp)
layoutActions(rect.size());
}
}
- layout->layoutState.toolBarAreaLayout.apply(true);
+ layout->layoutState.toolBarAreaLayout.apply(animated);
}
}
@@ -744,11 +730,6 @@ QToolBarItem *QToolBarLayout::createItem(QAction *action)
return result;
}
-QRect QToolBarLayout::handleRect() const
-{
- return handRect;
-}
-
QT_END_NAMESPACE
#endif // QT_NO_TOOLBAR
diff --git a/src/gui/widgets/qtoolbarlayout_p.h b/src/gui/widgets/qtoolbarlayout_p.h
index aec8f20..cc4210f 100644
--- a/src/gui/widgets/qtoolbarlayout_p.h
+++ b/src/gui/widgets/qtoolbarlayout_p.h
@@ -65,7 +65,7 @@ class QAction;
class QToolBarExtension;
class QMenu;
-class Q_GUI_EXPORT QToolBarItem : public QWidgetItem
+class QToolBarItem : public QWidgetItem
{
public:
QToolBarItem(QWidget *widget);
@@ -75,7 +75,7 @@ public:
bool customWidget;
};
-class Q_GUI_EXPORT QToolBarLayout : public QLayout
+class QToolBarLayout : public QLayout
{
Q_OBJECT
@@ -100,8 +100,6 @@ public:
int indexOf(QAction *action) const;
int indexOf(QWidget *widget) const { return QLayout::indexOf(widget); }
- QRect handleRect() const;
-
bool layoutActions(const QSize &size);
QSize expandedSize(const QSize &size) const;
bool expanded, animating;
@@ -113,8 +111,8 @@ public:
void updateMarginAndSpacing();
bool hasExpandFlag() const;
-public slots:
- void setExpanded(bool b);
+public Q_SLOTS:
+ void setExpanded(bool b, bool animated = true);
private:
QList<QToolBarItem*> items;
diff --git a/src/gui/widgets/qtoolbox.cpp b/src/gui/widgets/qtoolbox.cpp
index a0e087b..95febcc 100644
--- a/src/gui/widgets/qtoolbox.cpp
+++ b/src/gui/widgets/qtoolbox.cpp
@@ -252,7 +252,7 @@ void QToolBoxButton::paintEvent(QPaintEvent *)
\brief The QToolBox class provides a column of tabbed widget items.
- \mainclass
+
\ingroup basicwidgets
A toolbox is a widget that displays a column of tabs one above the
diff --git a/src/gui/widgets/qtoolbutton.cpp b/src/gui/widgets/qtoolbutton.cpp
index de971bc..75e8fb9 100644
--- a/src/gui/widgets/qtoolbutton.cpp
+++ b/src/gui/widgets/qtoolbutton.cpp
@@ -104,10 +104,9 @@ public:
#ifndef QT_NO_MENU
bool QToolButtonPrivate::hasMenu() const
{
- Q_Q(const QToolButton);
return ((defaultAction && defaultAction->menu())
|| (menuAction && menuAction->menu())
- || q->actions().size() > (defaultAction ? 1 : 0));
+ || actions.size() > (defaultAction ? 1 : 0));
}
#endif
@@ -117,7 +116,7 @@ bool QToolButtonPrivate::hasMenu() const
commands or options, usually used inside a QToolBar.
\ingroup basicwidgets
- \mainclass
+
A tool button is a special button that provides quick-access to
specific commands or options. As opposed to a normal command
@@ -278,7 +277,7 @@ void QToolButtonPrivate::init()
#endif
defaultAction = 0;
#ifndef QT_NO_TOOLBAR
- if (qobject_cast<QToolBar*>(q->parentWidget()))
+ if (qobject_cast<QToolBar*>(parent))
autoRaise = true;
else
#endif
@@ -379,7 +378,17 @@ void QToolButton::initStyleOption(QStyleOptionToolButton *option) const
if (d->hasMenu())
option->features |= QStyleOptionToolButton::HasMenu;
#endif
- option->toolButtonStyle = d->toolButtonStyle;
+ if (d->toolButtonStyle == Qt::ToolButtonFollowStyle) {
+ option->toolButtonStyle = Qt::ToolButtonStyle(style()->styleHint(QStyle::SH_ToolButtonStyle, option, this));
+ } else
+ option->toolButtonStyle = d->toolButtonStyle;
+
+ if (option->toolButtonStyle == Qt::ToolButtonTextBesideIcon) {
+ // If the action is not prioritized, remove the text label to save space
+ if (d->defaultAction && d->defaultAction->priority() < QAction::NormalPriority)
+ option->toolButtonStyle = Qt::ToolButtonIconOnly;
+ }
+
if (d->icon.isNull() && d->arrowType == Qt::NoArrow && !forceNoText) {
if (!d->text.isEmpty())
option->toolButtonStyle = Qt::ToolButtonTextOnly;
@@ -477,6 +486,9 @@ QSize QToolButton::minimumSizeHint() const
The default is Qt::ToolButtonIconOnly.
+ To have the style of toolbuttons follow the system settings (as available
+ in GNOME and KDE desktop environments), set this property to Qt::ToolButtonFollowStyle.
+
QToolButton automatically connects this slot to the relevant
signal in the QMainWindow in which is resides.
*/
@@ -859,8 +871,7 @@ void QToolButtonPrivate::_q_buttonPressed()
Q_Q(QToolButton);
if (!hasMenu())
return; // no menu to show
-
- if (delay > 0 && popupMode == QToolButton::DelayedPopup)
+ if (delay > 0 && !popupTimer.isActive() && popupMode == QToolButton::DelayedPopup)
popupTimer.start(delay, q);
else if (delay == 0 || popupMode == QToolButton::InstantPopup)
q->showMenu();
@@ -883,7 +894,6 @@ void QToolButtonPrivate::popupTimerDone()
} else {
actualMenu = new QMenu(q);
mustDeleteActualMenu = true;
- QList<QAction*> actions = q->actions();
for(int i = 0; i < actions.size(); i++)
actualMenu->addAction(actions.at(i));
}
@@ -891,12 +901,12 @@ void QToolButtonPrivate::popupTimerDone()
q->setAutoRepeat(false);
bool horizontal = true;
#if !defined(QT_NO_TOOLBAR)
- QToolBar *tb = qobject_cast<QToolBar*>(q->parentWidget());
+ QToolBar *tb = qobject_cast<QToolBar*>(parent);
if (tb && tb->orientation() == Qt::Vertical)
horizontal = false;
#endif
QPoint p;
- QRect screen = qApp->desktop()->availableGeometry(q);
+ QRect screen = QApplication::desktop()->availableGeometry(q);
QSize sh = ((QToolButton*)(QMenu*)actualMenu)->receivers(SIGNAL(aboutToShow()))? QSize() : actualMenu->sizeHint();
QRect rect = q->rect();
if (horizontal) {
diff --git a/src/gui/widgets/qvalidator.cpp b/src/gui/widgets/qvalidator.cpp
index 8813c17..48168c4 100644
--- a/src/gui/widgets/qvalidator.cpp
+++ b/src/gui/widgets/qvalidator.cpp
@@ -55,9 +55,6 @@ QT_BEGIN_NAMESPACE
\class QValidator
\brief The QValidator class provides validation of input text.
- \ingroup misc
- \mainclass
-
The class itself is abstract. Two subclasses, \l QIntValidator and
\l QDoubleValidator, provide basic numeric-range checking, and \l
QRegExpValidator provides general checking using a custom regular
@@ -246,8 +243,6 @@ void QValidator::fixup(QString &) const
\brief The QIntValidator class provides a validator that ensures
a string contains a valid integer within a specified range.
- \ingroup misc
-
Example of use:
\snippet doc/src/snippets/code/src_gui_widgets_qvalidator.cpp 0
@@ -370,7 +365,7 @@ static int numDigits(qlonglong n)
if (n == 0)
return 1;
return (int)log10(double(n)) + 1;
-};
+}
static qlonglong pow10(int exp)
{
@@ -497,8 +492,6 @@ public:
\brief The QDoubleValidator class provides range checking of
floating-point numbers.
- \ingroup misc
-
QDoubleValidator provides an upper bound, a lower bound, and a
limit on the number of digits after the decimal point. It does not
provide a fixup() function.
@@ -767,8 +760,6 @@ QDoubleValidator::Notation QDoubleValidator::notation() const
\brief The QRegExpValidator class is used to check a string
against a regular expression.
- \ingroup misc
-
QRegExpValidator uses a regular expression (regexp) to
determine whether an input string is \l Acceptable, \l
Intermediate, or \l Invalid. The regexp can either be supplied
diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h
index 1213300..c656820 100644
--- a/src/gui/widgets/qvalidator.h
+++ b/src/gui/widgets/qvalidator.h
@@ -61,7 +61,7 @@ class Q_GUI_EXPORT QValidator : public QObject
{
Q_OBJECT
public:
- explicit QValidator(QObject * parent);
+ explicit QValidator(QObject * parent=0);
~QValidator();
enum State {
@@ -100,7 +100,7 @@ class Q_GUI_EXPORT QIntValidator : public QValidator
Q_PROPERTY(int top READ top WRITE setTop)
public:
- explicit QIntValidator(QObject * parent);
+ explicit QIntValidator(QObject * parent=0);
QIntValidator(int bottom, int top, QObject * parent);
~QIntValidator();
diff --git a/src/gui/widgets/qwidgetanimator.cpp b/src/gui/widgets/qwidgetanimator.cpp
index 5b278f6..6e76e79 100644
--- a/src/gui/widgets/qwidgetanimator.cpp
+++ b/src/gui/widgets/qwidgetanimator.cpp
@@ -39,158 +39,80 @@
**
****************************************************************************/
-#include <QtCore/qtimer.h>
-#include <QtCore/qdatetime.h>
+#include <QtCore/qpropertyanimation.h>
#include <QtGui/qwidget.h>
-#include <QtGui/qtextedit.h>
-#include <QtGui/private/qwidget_p.h>
-#include <qdebug.h>
+#include <QtGui/private/qmainwindowlayout_p.h>
#include "qwidgetanimator_p.h"
QT_BEGIN_NAMESPACE
-static const int g_animation_steps = 12;
-static const int g_animation_interval = 16;
-
-// 1000 * (x/(1 + x*x) + 0.5) on interval [-1, 1]
-static const int g_animate_function[] =
-{
- 0, 1, 5, 12, 23, 38, 58, 84, 116, 155, 199, 251, 307, 368,
- 433, 500, 566, 631, 692, 748, 799, 844, 883, 915, 941, 961,
- 976, 987, 994, 998, 1000
-};
-static const int g_animate_function_points = sizeof(g_animate_function)/sizeof(int);
-
-static inline int animateHelper(int start, int stop, int step, int steps)
-{
- if (start == stop)
- return start;
- if (step == 0)
- return start;
- if (step == steps)
- return stop;
-
- int x = g_animate_function_points*step/(steps + 1);
- return start + g_animate_function[x]*(stop - start)/1000;
-}
-
-QWidgetAnimator::QWidgetAnimator(QObject *parent)
- : QObject(parent)
+QWidgetAnimator::QWidgetAnimator(QMainWindowLayout *layout) : m_mainWindowLayout(layout)
{
- m_time = new QTime();
- m_timer = new QTimer(this);
- m_timer->setInterval(g_animation_interval);
- connect(m_timer, SIGNAL(timeout()), this, SLOT(animationStep()));
}
-QWidgetAnimator::~QWidgetAnimator()
+void QWidgetAnimator::abort(QWidget *w)
{
- delete m_time;
+#ifndef QT_NO_ANIMATION
+ AnimationMap::iterator it = m_animation_map.find(w);
+ if (it == m_animation_map.end())
+ return;
+ QPropertyAnimation *anim = *it;
+ m_animation_map.erase(it);
+ anim->stop();
+ m_mainWindowLayout->animationFinished(w);
+#else
+ Q_UNUSED(w); //there is no animation to abort
+#endif //QT_NO_ANIMATION
}
-void QWidgetAnimator::abort(QWidget *w)
+#ifndef QT_NO_ANIMATION
+void QWidgetAnimator::animationFinished()
{
- if (m_animation_map.remove(w) == 0)
- return;
- if (m_animation_map.isEmpty()) {
- m_timer->stop();
- emit finishedAll();
- }
+ QPropertyAnimation *anim = qobject_cast<QPropertyAnimation*>(sender());
+ abort(static_cast<QWidget*>(anim->targetObject()));
}
+#endif //QT_NO_ANIMATION
void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, bool animate)
{
- QRect final_geometry = _final_geometry;
-
QRect r = widget->geometry();
if (r.right() < 0 || r.bottom() < 0)
r = QRect();
- if (r.isNull() || final_geometry.isNull())
- animate = false;
+ animate = animate && !r.isNull() && !_final_geometry.isNull();
- AnimationMap::const_iterator it = m_animation_map.constFind(widget);
- if (it == m_animation_map.constEnd()) {
- if (r == final_geometry) {
- emit finished(widget);
- return;
- }
- } else {
- if ((*it).r2 == final_geometry)
- return;
- }
-
- if (animate) {
- AnimationItem item(widget, r, final_geometry);
- m_animation_map[widget] = item;
- if (!m_timer->isActive()) {
- m_timer->start();
- m_time->start();
- }
- } else {
- m_animation_map.remove(widget);
- if (m_animation_map.isEmpty())
- m_timer->stop();
-
- if (!final_geometry.isValid() && !widget->isWindow()) {
- // Make the wigdet go away by sending it to negative space
- QSize s = widget->size();
- final_geometry = QRect(-500 - s.width(), -500 - s.height(), s.width(), s.height());
- }
- widget->setGeometry(final_geometry);
-
- emit finished(widget);
-
- if (m_animation_map.isEmpty())
- emit finishedAll();
+ // might make the wigdet go away by sending it to negative space
+ const QRect final_geometry = _final_geometry.isValid() || widget->isWindow() ? _final_geometry :
+ QRect(QPoint(-500 - widget->width(), -500 - widget->height()), widget->size());
+ if (r == final_geometry)
+ return; //the widget is already where it should be
+#ifndef QT_NO_ANIMATION
+ AnimationMap::const_iterator it = m_animation_map.constFind(widget);
+ if (it != m_animation_map.constEnd() && (*it)->endValue().toRect() == final_geometry)
return;
- }
-}
-
-void QWidgetAnimator::animationStep()
-{
- int steps = (1 + m_time->restart())/g_animation_interval;
- AnimationMap::iterator it = m_animation_map.begin();
- while (it != m_animation_map.end()) {
- AnimationItem &item = *it;
-
- item.step = qMin(item.step + steps, g_animation_steps);
-
- int x = animateHelper(item.r1.left(), item.r2.left(),
- item.step, g_animation_steps);
- int y = animateHelper(item.r1.top(), item.r2.top(),
- item.step, g_animation_steps);
- int w = animateHelper(item.r1.width(), item.r2.width(),
- item.step, g_animation_steps);
- int h = animateHelper(item.r1.height(), item.r2.height(),
- item.step, g_animation_steps);
-
- item.widget->setGeometry(x, y, w, h);
-
- if (item.step == g_animation_steps) {
- emit finished(item.widget);
- AnimationMap::iterator tmp = it;
- ++it;
- m_animation_map.erase(tmp);
- } else {
- ++it;
- }
- }
- if (m_animation_map.isEmpty()) {
- m_timer->stop();
- emit finishedAll();
- }
+ QPropertyAnimation *anim = new QPropertyAnimation(widget, "geometry", widget);
+ anim->setDuration(animate ? 200 : 0);
+ anim->setEasingCurve(QEasingCurve::InOutQuad);
+ anim->setEndValue(final_geometry);
+ m_animation_map[widget] = anim;
+ connect(anim, SIGNAL(finished()), SLOT(animationFinished()));
+ anim->start(QPropertyAnimation::DeleteWhenStopped);
+#else
+ //we do it in one shot
+ widget->setGeometry(final_geometry);
+ m_mainWindowLayout->animationFinished(widget);
+#endif //QT_NO_ANIMATION
}
bool QWidgetAnimator::animating() const
{
- return m_timer->isActive();
+ return !m_animation_map.isEmpty();
}
-bool QWidgetAnimator::animating(QWidget *widget)
+bool QWidgetAnimator::animating(QWidget *widget) const
{
return m_animation_map.contains(widget);
}
diff --git a/src/gui/widgets/qwidgetanimator_p.h b/src/gui/widgets/qwidgetanimator_p.h
index a6a2d22..1d71b8e 100644
--- a/src/gui/widgets/qwidgetanimator_p.h
+++ b/src/gui/widgets/qwidgetanimator_p.h
@@ -54,47 +54,35 @@
//
#include <qobject.h>
-#include <qrect.h>
#include <qmap.h>
QT_BEGIN_NAMESPACE
class QWidget;
-class QTimer;
-class QTime;
+class QMainWindowLayout;
+class QPropertyAnimation;
+class QRect;
class QWidgetAnimator : public QObject
{
Q_OBJECT
public:
- QWidgetAnimator(QObject *parent = 0);
- ~QWidgetAnimator();
+ QWidgetAnimator(QMainWindowLayout *layout);
void animate(QWidget *widget, const QRect &final_geometry, bool animate);
bool animating() const;
- bool animating(QWidget *widget);
+ bool animating(QWidget *widget) const;
void abort(QWidget *widget);
-signals:
- void finished(QWidget *widget);
- void finishedAll();
-
-private slots:
- void animationStep();
+#ifndef QT_NO_ANIMATION
+private Q_SLOTS:
+ void animationFinished();
+#endif
private:
- struct AnimationItem {
- AnimationItem(QWidget *_widget = 0, const QRect &_r1 = QRect(),
- const QRect &_r2 = QRect())
- : widget(_widget), r1(_r1), r2(_r2), step(0) {}
- QWidget *widget;
- QRect r1, r2;
- int step;
- };
- typedef QMap<QWidget*, AnimationItem> AnimationMap;
+ typedef QMap<QWidget*, QPropertyAnimation*> AnimationMap;
AnimationMap m_animation_map;
- QTimer *m_timer;
- QTime *m_time;
+ QMainWindowLayout *m_mainWindowLayout;
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qwidgetresizehandler.cpp b/src/gui/widgets/qwidgetresizehandler.cpp
index 07055ac..634a693 100644
--- a/src/gui/widgets/qwidgetresizehandler.cpp
+++ b/src/gui/widgets/qwidgetresizehandler.cpp
@@ -258,7 +258,7 @@ void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
#ifdef Q_WS_X11
// Workaround for window managers which refuse to move a tool window partially offscreen.
- QRect desktop = qApp->desktop()->availableGeometry(widget);
+ QRect desktop = QApplication::desktop()->availableGeometry(widget);
pp.rx() = qMax(pp.x(), desktop.left());
pp.ry() = qMax(pp.y(), desktop.top());
p.rx() = qMin(p.x(), desktop.right());
diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp
index c001431..05d5463 100644
--- a/src/gui/widgets/qworkspace.cpp
+++ b/src/gui/widgets/qworkspace.cpp
@@ -110,11 +110,11 @@ bool QMDIControl::event(QEvent *event)
QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt,
helpEvent->pos(), this);
if (ctrl == QStyle::SC_MdiCloseButton)
- QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Close"));
+ QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Close"), this);
else if (ctrl == QStyle::SC_MdiMinButton)
- QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Minimize"));
+ QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Minimize"), this);
else if (ctrl == QStyle::SC_MdiNormalButton)
- QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Restore Down"));
+ QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Restore Down"), this);
else
QToolTip::hideText();
#endif // QT_NO_TOOLTIP
@@ -397,21 +397,17 @@ void QWorkspaceTitleBarPrivate::readColors()
pal.setColor(QPalette::Inactive, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)));
pal.setColor(QPalette::Active, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)));
pal.setColor(QPalette::Inactive, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)));
- if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
- colorsInitialized = true;
- BOOL gradient;
- QT_WA({
- SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
- } , {
- SystemParametersInfoA(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
- });
- if (gradient) {
- pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)));
- pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)));
- } else {
- pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight));
- pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight));
- }
+
+ colorsInitialized = true;
+ BOOL gradient = false;
+ SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
+
+ if (gradient) {
+ pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)));
+ pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)));
+ } else {
+ pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight));
+ pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight));
}
}
#endif // Q_WS_WIN
@@ -838,7 +834,6 @@ QSize QWorkspaceTitleBar::sizeHint() const
\obsolete
\brief The QWorkspace widget provides a workspace window that can be
used in an MDI application.
- \ingroup application
This class is deprecated. Use QMdiArea instead.
diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri
index 86dc453..4567902 100644
--- a/src/gui/widgets/widgets.pri
+++ b/src/gui/widgets/widgets.pri
@@ -30,6 +30,7 @@ HEADERS += \
widgets/qlcdnumber.h \
widgets/qlineedit.h \
widgets/qlineedit_p.h \
+ widgets/qlinecontrol_p.h \
widgets/qmainwindow.h \
widgets/qmainwindowlayout_p.h \
widgets/qmdiarea.h \
@@ -37,7 +38,9 @@ HEADERS += \
widgets/qmdisubwindow.h \
widgets/qmdisubwindow_p.h \
widgets/qmenu.h \
+ widgets/qmenu_p.h \
widgets/qmenubar.h \
+ widgets/qmenubar_p.h \
widgets/qmenudata.h \
widgets/qprogressbar.h \
widgets/qpushbutton.h \
@@ -78,8 +81,8 @@ HEADERS += \
widgets/qtoolbararealayout_p.h \
widgets/qplaintextedit.h \
widgets/qplaintextedit_p.h \
- widgets/qprintpreviewwidget.h
-
+ widgets/qprintpreviewwidget.h \
+ widgets/qactiontokeyeventmapper_p.h
SOURCES += \
widgets/qabstractbutton.cpp \
widgets/qabstractslider.cpp \
@@ -99,7 +102,9 @@ SOURCES += \
widgets/qgroupbox.cpp \
widgets/qlabel.cpp \
widgets/qlcdnumber.cpp \
+ widgets/qlineedit_p.cpp \
widgets/qlineedit.cpp \
+ widgets/qlinecontrol.cpp \
widgets/qmainwindow.cpp \
widgets/qmainwindowlayout.cpp \
widgets/qmdiarea.cpp \
@@ -138,8 +143,8 @@ SOURCES += \
widgets/qwidgetanimator.cpp \
widgets/qtoolbararealayout.cpp \
widgets/qplaintextedit.cpp \
- widgets/qprintpreviewwidget.cpp
-
+ widgets/qprintpreviewwidget.cpp \
+ widgets/qactiontokeyeventmapper.cpp
!embedded:mac {
HEADERS += widgets/qmacnativewidget_mac.h \
@@ -160,3 +165,7 @@ wince*: {
RC_FILE = widgets/qmenu_wince.rc
!static: QMAKE_WRITE_DEFAULT_RC = 1
}
+
+symbian*: {
+ SOURCES += widgets/qmenu_symbian.cpp
+}