summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/animation/qguivariantanimation.cpp5
-rw-r--r--src/gui/dialogs/dialogs.pri3
-rw-r--r--src/gui/dialogs/qabstractprintdialog.cpp7
-rw-r--r--src/gui/dialogs/qabstractprintdialog.h6
-rw-r--r--src/gui/dialogs/qdialog.cpp11
-rw-r--r--src/gui/dialogs/qerrormessage.cpp2
-rw-r--r--src/gui/dialogs/qfiledialog.cpp13
-rw-r--r--src/gui/dialogs/qfiledialog_mac.mm29
-rw-r--r--src/gui/dialogs/qfiledialog_win.cpp141
-rw-r--r--src/gui/dialogs/qfiledialog_win_p.h243
-rw-r--r--src/gui/dialogs/qfileinfogatherer.cpp40
-rw-r--r--src/gui/dialogs/qfileinfogatherer_p.h14
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp129
-rw-r--r--src/gui/dialogs/qfilesystemmodel.h1
-rw-r--r--src/gui/dialogs/qfilesystemmodel_p.h4
-rw-r--r--src/gui/dialogs/qfontdialog.cpp27
-rw-r--r--src/gui/dialogs/qfontdialog_mac.mm395
-rw-r--r--src/gui/dialogs/qfontdialog_p.h12
-rw-r--r--src/gui/dialogs/qmessagebox.cpp53
-rw-r--r--src/gui/dialogs/qpagesetupdialog_mac.mm5
-rw-r--r--src/gui/dialogs/qprintdialog_qws.cpp17
-rw-r--r--src/gui/dialogs/qprintdialog_unix.cpp23
-rw-r--r--src/gui/dialogs/qprintdialog_win.cpp20
-rw-r--r--src/gui/dialogs/qprintsettingsoutput.ui246
-rw-r--r--src/gui/dialogs/qprogressdialog.cpp4
-rw-r--r--src/gui/dialogs/qwizard.cpp205
-rw-r--r--src/gui/dialogs/qwizard.h5
-rw-r--r--src/gui/dialogs/qwizard_win_p.h1
-rw-r--r--src/gui/egl/egl.pri1
-rw-r--r--src/gui/egl/qegl.cpp395
-rw-r--r--src/gui/egl/qegl_p.h193
-rw-r--r--src/gui/egl/qegl_qws.cpp30
-rw-r--r--src/gui/egl/qegl_stub.cpp90
-rw-r--r--src/gui/egl/qegl_symbian.cpp48
-rw-r--r--src/gui/egl/qegl_wince.cpp54
-rw-r--r--src/gui/egl/qegl_x11.cpp388
-rw-r--r--src/gui/egl/qeglcontext_p.h113
-rw-r--r--src/gui/egl/qeglproperties.cpp71
-rw-r--r--src/gui/egl/qeglproperties_p.h72
-rw-r--r--src/gui/egl/qeglproperties_stub.cpp20
-rw-r--r--src/gui/embedded/directfb.pri2
-rw-r--r--src/gui/embedded/qscreen_qws.cpp21
-rw-r--r--src/gui/embedded/qscreenlinuxfb_qws.cpp72
-rw-r--r--src/gui/embedded/qscreenlinuxfb_qws.h4
-rw-r--r--src/gui/embedded/qwsmanager_qws.cpp6
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp353
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h30
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h90
-rw-r--r--src/gui/graphicsview/qgraphicslinearlayout.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp13
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp429
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h19
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp34
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h2
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp51
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h14
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp51
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h11
-rw-r--r--src/gui/gui.pro14
-rw-r--r--src/gui/image/image.pri4
-rw-r--r--src/gui/image/qicon.cpp19
-rw-r--r--src/gui/image/qicon.h2
-rw-r--r--src/gui/image/qiconengine.cpp20
-rw-r--r--src/gui/image/qiconengine.h5
-rw-r--r--src/gui/image/qiconloader.cpp6
-rw-r--r--src/gui/image/qimage.cpp109
-rw-r--r--src/gui/image/qimage.h3
-rw-r--r--src/gui/image/qimagereader.cpp2
-rw-r--r--src/gui/image/qpaintengine_pic.cpp5
-rw-r--r--src/gui/image/qpicture.cpp52
-rw-r--r--src/gui/image/qpixmap.cpp28
-rw-r--r--src/gui/image/qpixmap.h4
-rw-r--r--src/gui/image/qpixmap_raster.cpp4
-rw-r--r--src/gui/image/qpixmap_x11.cpp30
-rw-r--r--src/gui/image/qpixmap_x11_p.h12
-rw-r--r--src/gui/image/qpixmapfilter.cpp4
-rw-r--r--src/gui/image/qpnghandler.cpp137
-rw-r--r--src/gui/inputmethod/qwininputcontext_p.h2
-rw-r--r--src/gui/inputmethod/qximinputcontext_x11.cpp54
-rw-r--r--src/gui/itemviews/qabstractitemview.cpp22
-rw-r--r--src/gui/itemviews/qabstractitemview_p.h5
-rw-r--r--src/gui/itemviews/qdirmodel.cpp10
-rw-r--r--src/gui/itemviews/qfileiconprovider.cpp2
-rw-r--r--src/gui/itemviews/qheaderview.cpp60
-rw-r--r--src/gui/itemviews/qitemdelegate.cpp6
-rw-r--r--src/gui/itemviews/qitemselectionmodel.cpp109
-rw-r--r--src/gui/itemviews/qitemselectionmodel.h2
-rw-r--r--src/gui/itemviews/qitemselectionmodel_p.h2
-rw-r--r--src/gui/itemviews/qlistview.cpp28
-rw-r--r--src/gui/itemviews/qproxymodel.h25
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp79
-rw-r--r--src/gui/itemviews/qtableview.cpp49
-rw-r--r--src/gui/itemviews/qtreeview.cpp480
-rw-r--r--src/gui/itemviews/qtreeview_p.h22
-rw-r--r--src/gui/itemviews/qtreewidget.cpp6
-rw-r--r--src/gui/kernel/kernel.pri1
-rw-r--r--src/gui/kernel/qaction.cpp1
-rw-r--r--src/gui/kernel/qaction.h3
-rw-r--r--src/gui/kernel/qaction_p.h17
-rw-r--r--src/gui/kernel/qapplication.cpp289
-rw-r--r--src/gui/kernel/qapplication.h1
-rw-r--r--src/gui/kernel/qapplication_mac.mm134
-rw-r--r--src/gui/kernel/qapplication_p.h17
-rw-r--r--src/gui/kernel/qapplication_s60.cpp2
-rw-r--r--src/gui/kernel/qapplication_win.cpp52
-rw-r--r--src/gui/kernel/qapplication_x11.cpp205
-rw-r--r--src/gui/kernel/qclipboard.cpp6
-rw-r--r--src/gui/kernel/qclipboard_x11.cpp15
-rw-r--r--src/gui/kernel/qcocoaapplication_mac.mm46
-rw-r--r--src/gui/kernel/qcocoaapplication_mac_p.h8
-rw-r--r--src/gui/kernel/qcocoaapplicationdelegate_mac.mm20
-rw-r--r--src/gui/kernel/qcocoamenuloader_mac.mm34
-rw-r--r--src/gui/kernel/qcocoamenuloader_mac_p.h5
-rw-r--r--src/gui/kernel/qcocoapanel_mac.mm1
-rw-r--r--src/gui/kernel/qcocoapanel_mac_p.h6
-rw-r--r--src/gui/kernel/qcocoasharedwindowmethods_mac_p.h250
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm293
-rw-r--r--src/gui/kernel/qcocoaview_mac_p.h3
-rw-r--r--src/gui/kernel/qcocoawindow_mac.mm1
-rw-r--r--src/gui/kernel/qcocoawindow_mac_p.h3
-rw-r--r--src/gui/kernel/qcocoawindowdelegate_mac.mm7
-rw-r--r--src/gui/kernel/qcursor.cpp6
-rw-r--r--src/gui/kernel/qcursor_mac.mm67
-rw-r--r--src/gui/kernel/qcursor_s60.cpp2
-rw-r--r--src/gui/kernel/qcursor_win.cpp7
-rw-r--r--src/gui/kernel/qcursor_x11.cpp118
-rw-r--r--src/gui/kernel/qdesktopwidget_win.cpp4
-rw-r--r--src/gui/kernel/qdnd.cpp218
-rw-r--r--src/gui/kernel/qdnd_p.h2
-rw-r--r--src/gui/kernel/qdnd_win.cpp16
-rw-r--r--src/gui/kernel/qdnd_x11.cpp18
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm401
-rw-r--r--src/gui/kernel/qeventdispatcher_mac_p.h11
-rw-r--r--src/gui/kernel/qgesture_p.h6
-rw-r--r--src/gui/kernel/qgesturerecognizer.cpp3
-rw-r--r--src/gui/kernel/qguieventdispatcher_glib.cpp5
-rw-r--r--src/gui/kernel/qguieventdispatcher_glib_p.h1
-rw-r--r--src/gui/kernel/qkeymapper_mac.cpp67
-rw-r--r--src/gui/kernel/qkeymapper_p.h2
-rw-r--r--src/gui/kernel/qkeymapper_s60.cpp4
-rw-r--r--src/gui/kernel/qkeymapper_win.cpp4
-rw-r--r--src/gui/kernel/qkeymapper_x11.cpp41
-rw-r--r--src/gui/kernel/qkeysequence.cpp75
-rw-r--r--src/gui/kernel/qkeysequence.h12
-rw-r--r--src/gui/kernel/qmime_mac.cpp57
-rw-r--r--src/gui/kernel/qmime_win.cpp2
-rw-r--r--src/gui/kernel/qnsthemeframe_mac_p.h2
-rw-r--r--src/gui/kernel/qsoftkeymanager.cpp12
-rw-r--r--src/gui/kernel/qsoftkeymanager_p.h3
-rw-r--r--src/gui/kernel/qsoftkeymanager_s60.cpp5
-rw-r--r--src/gui/kernel/qstandardgestures.cpp7
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm253
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac_p.h32
-rw-r--r--src/gui/kernel/qt_mac_p.h1
-rw-r--r--src/gui/kernel/qt_x11_p.h15
-rw-r--r--src/gui/kernel/qwidget.cpp337
-rw-r--r--src/gui/kernel/qwidget.h1
-rw-r--r--src/gui/kernel/qwidget_mac.mm306
-rw-r--r--src/gui/kernel/qwidget_p.h16
-rw-r--r--src/gui/kernel/qwidget_win.cpp25
-rw-r--r--src/gui/kernel/qwidget_wince.cpp4
-rw-r--r--src/gui/kernel/qwidget_x11.cpp52
-rw-r--r--src/gui/kernel/qx11embed_x11.cpp4
-rw-r--r--src/gui/mac/qt_menu.nib/classes.nib16
-rw-r--r--src/gui/mac/qt_menu.nib/info.nib4
-rw-r--r--src/gui/mac/qt_menu.nib/keyedobjects.nibbin5567 -> 5560 bytes
-rw-r--r--src/gui/math3d/qmatrix4x4.h2
-rw-r--r--src/gui/math3d/qquaternion.h2
-rw-r--r--src/gui/math3d/qvector2d.h2
-rw-r--r--src/gui/math3d/qvector3d.h2
-rw-r--r--src/gui/math3d/qvector4d.h2
-rw-r--r--src/gui/painting/painting.pri16
-rw-r--r--src/gui/painting/qbackingstore.cpp70
-rw-r--r--src/gui/painting/qbackingstore_p.h4
-rw-r--r--src/gui/painting/qbezier.cpp345
-rw-r--r--src/gui/painting/qbezier_p.h13
-rw-r--r--src/gui/painting/qblendfunctions.cpp446
-rw-r--r--src/gui/painting/qblendfunctions_p.h497
-rw-r--r--src/gui/painting/qbrush.cpp36
-rw-r--r--src/gui/painting/qcolor.cpp39
-rw-r--r--src/gui/painting/qcolor.h3
-rw-r--r--src/gui/painting/qcolormap.qdoc10
-rw-r--r--src/gui/painting/qcups.cpp3
-rw-r--r--src/gui/painting/qdatabuffer_p.h7
-rw-r--r--src/gui/painting/qdrawhelper.cpp747
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp409
-rw-r--r--src/gui/painting/qdrawhelper_neon_asm.S192
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h58
-rw-r--r--src/gui/painting/qdrawhelper_p.h14
-rw-r--r--src/gui/painting/qdrawutil.cpp217
-rw-r--r--src/gui/painting/qdrawutil.h25
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp35
-rw-r--r--src/gui/painting/qemulationpaintengine_p.h1
-rw-r--r--src/gui/painting/qmemrotate_p.h3
-rw-r--r--src/gui/painting/qpaintbuffer.cpp451
-rw-r--r--src/gui/painting/qpaintbuffer_p.h15
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp59
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h5
-rw-r--r--src/gui/painting/qpaintengineex.cpp43
-rw-r--r--src/gui/painting/qpaintengineex_p.h6
-rw-r--r--src/gui/painting/qpainter.cpp374
-rw-r--r--src/gui/painting/qpainter.h41
-rw-r--r--src/gui/painting/qpainter_p.h8
-rw-r--r--src/gui/painting/qpainterpath.cpp13
-rw-r--r--src/gui/painting/qpainterpath.h2
-rw-r--r--src/gui/painting/qpathclipper.cpp1069
-rw-r--r--src/gui/painting/qpathclipper_p.h31
-rw-r--r--src/gui/painting/qpdf.cpp12
-rw-r--r--src/gui/painting/qpdf_p.h2
-rw-r--r--src/gui/painting/qprintengine.h2
-rw-r--r--src/gui/painting/qprintengine_mac.mm15
-rw-r--r--src/gui/painting/qprintengine_qws.cpp5
-rw-r--r--src/gui/painting/qprintengine_win.cpp12
-rw-r--r--src/gui/painting/qprintengine_win_p.h1
-rw-r--r--src/gui/painting/qprinter.cpp102
-rw-r--r--src/gui/painting/qprinter.h6
-rw-r--r--src/gui/painting/qregion.cpp36
-rw-r--r--src/gui/painting/qstroker.cpp116
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp76
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h13
-rw-r--r--src/gui/painting/qtransform.cpp58
-rw-r--r--src/gui/painting/qwindowsurface.cpp28
-rw-r--r--src/gui/painting/qwindowsurface_p.h10
-rw-r--r--src/gui/painting/qwindowsurface_s60.cpp4
-rw-r--r--src/gui/s60framework/s60framework.pri2
-rw-r--r--src/gui/statemachine/qguistatemachine.cpp6
-rw-r--r--src/gui/styles/qcommonstyle.cpp202
-rw-r--r--src/gui/styles/qgtkpainter.cpp2
-rw-r--r--src/gui/styles/qgtkstyle.cpp205
-rw-r--r--src/gui/styles/qgtkstyle_p.cpp103
-rw-r--r--src/gui/styles/qgtkstyle_p.h83
-rw-r--r--src/gui/styles/qmacstyle_mac.mm43
-rw-r--r--src/gui/styles/qplastiquestyle.cpp5
-rw-r--r--src/gui/styles/qs60style_s60.cpp6
-rw-r--r--src/gui/styles/qs60style_simulated.cpp12
-rw-r--r--src/gui/styles/qstylehelper.cpp65
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp29
-rw-r--r--src/gui/styles/qwindowsstyle.cpp10
-rw-r--r--src/gui/styles/qwindowsstyle_p.h4
-rw-r--r--src/gui/styles/qwindowsvistastyle_p.h1
-rw-r--r--src/gui/text/qfont.cpp12
-rw-r--r--src/gui/text/qfont.h24
-rw-r--r--src/gui/text/qfont_s60.cpp4
-rw-r--r--src/gui/text/qfontdatabase_qws.cpp7
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp4
-rw-r--r--src/gui/text/qfontdatabase_win.cpp1
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp17
-rw-r--r--src/gui/text/qfontengine.cpp10
-rw-r--r--src/gui/text/qfontengine_ft.cpp74
-rw-r--r--src/gui/text/qfontengine_ft_p.h16
-rw-r--r--src/gui/text/qfontengine_mac.mm102
-rw-r--r--src/gui/text/qfontengine_qpf.cpp14
-rw-r--r--src/gui/text/qfontengine_win.cpp6
-rw-r--r--src/gui/text/qfontmetrics.cpp18
-rw-r--r--src/gui/text/qstatictext.cpp660
-rw-r--r--src/gui/text/qstatictext.h106
-rw-r--r--src/gui/text/qstatictext_p.h151
-rw-r--r--src/gui/text/qsyntaxhighlighter.cpp95
-rw-r--r--src/gui/text/qtextcontrol.cpp27
-rw-r--r--src/gui/text/qtextcontrol_p.h3
-rw-r--r--src/gui/text/qtextcursor.cpp26
-rw-r--r--src/gui/text/qtextcursor.h1
-rw-r--r--src/gui/text/qtextdocument.cpp33
-rw-r--r--src/gui/text/qtextdocument.h7
-rw-r--r--src/gui/text/qtextdocument_p.cpp97
-rw-r--r--src/gui/text/qtextdocument_p.h3
-rw-r--r--src/gui/text/qtextengine.cpp14
-rw-r--r--src/gui/text/qtextengine_p.h1
-rw-r--r--src/gui/text/qtextlayout.cpp17
-rw-r--r--src/gui/text/qtextlayout.h1
-rw-r--r--src/gui/text/qtextodfwriter.cpp12
-rw-r--r--src/gui/text/qzip.cpp44
-rw-r--r--src/gui/text/qzipreader_p.h9
-rw-r--r--src/gui/text/qzipwriter_p.h2
-rw-r--r--src/gui/text/text.pri7
-rw-r--r--src/gui/util/qcompleter.cpp81
-rw-r--r--src/gui/util/qcompleter.h1
-rw-r--r--src/gui/util/qcompleter_p.h1
-rw-r--r--src/gui/util/qdesktopservices_s60.cpp4
-rw-r--r--src/gui/util/qdesktopservices_win.cpp16
-rw-r--r--src/gui/util/qsystemtrayicon_mac.mm115
-rw-r--r--src/gui/util/qsystemtrayicon_win.cpp3
-rw-r--r--src/gui/util/util.pri9
-rw-r--r--src/gui/widgets/qabstractscrollarea.cpp1
-rw-r--r--src/gui/widgets/qabstractscrollarea_p.h2
-rw-r--r--src/gui/widgets/qabstractslider.cpp18
-rw-r--r--src/gui/widgets/qabstractslider_p.h3
-rw-r--r--src/gui/widgets/qabstractspinbox.cpp5
-rw-r--r--src/gui/widgets/qcheckbox.cpp2
-rw-r--r--src/gui/widgets/qcocoamenu_mac.mm33
-rw-r--r--src/gui/widgets/qcocoamenu_mac_p.h4
-rw-r--r--src/gui/widgets/qcombobox.cpp15
-rw-r--r--src/gui/widgets/qcombobox.h4
-rw-r--r--src/gui/widgets/qdatetimeedit.cpp2
-rw-r--r--src/gui/widgets/qdialogbuttonbox.cpp43
-rw-r--r--src/gui/widgets/qdockarealayout.cpp70
-rw-r--r--src/gui/widgets/qdockarealayout_p.h5
-rw-r--r--src/gui/widgets/qdockwidget.cpp2
-rw-r--r--src/gui/widgets/qeffects.cpp6
-rw-r--r--src/gui/widgets/qfocusframe.cpp91
-rw-r--r--src/gui/widgets/qframe.cpp2
-rw-r--r--src/gui/widgets/qlabel.cpp98
-rw-r--r--src/gui/widgets/qlabel.h7
-rw-r--r--src/gui/widgets/qlabel_p.h2
-rw-r--r--src/gui/widgets/qlinecontrol.cpp17
-rw-r--r--src/gui/widgets/qlinecontrol_p.h613
-rw-r--r--src/gui/widgets/qlineedit.cpp42
-rw-r--r--src/gui/widgets/qlineedit.h6
-rw-r--r--src/gui/widgets/qmainwindow.cpp18
-rw-r--r--src/gui/widgets/qmenu.cpp99
-rw-r--r--src/gui/widgets/qmenu.h1
-rw-r--r--src/gui/widgets/qmenu_mac.mm279
-rw-r--r--src/gui/widgets/qmenu_p.h6
-rw-r--r--src/gui/widgets/qmenu_symbian.cpp2
-rw-r--r--src/gui/widgets/qmenubar.cpp17
-rw-r--r--src/gui/widgets/qmenubar_p.h1
-rw-r--r--src/gui/widgets/qplaintextedit.cpp31
-rw-r--r--src/gui/widgets/qplaintextedit.h2
-rw-r--r--src/gui/widgets/qradiobutton.cpp2
-rw-r--r--src/gui/widgets/qscrollarea.cpp4
-rw-r--r--src/gui/widgets/qscrollbar.cpp5
-rw-r--r--src/gui/widgets/qsplitter.cpp69
-rw-r--r--src/gui/widgets/qsplitter.h1
-rw-r--r--src/gui/widgets/qtabbar.cpp38
-rw-r--r--src/gui/widgets/qtabbar_p.h5
-rw-r--r--src/gui/widgets/qtextedit.cpp13
-rw-r--r--src/gui/widgets/qtoolbar.cpp9
-rw-r--r--src/gui/widgets/qtoolbar.h1
-rw-r--r--src/gui/widgets/qtoolbarlayout.cpp4
-rw-r--r--src/gui/widgets/qvalidator.cpp22
-rw-r--r--src/gui/widgets/qvalidator.h6
-rw-r--r--src/gui/widgets/qworkspace.cpp10
-rw-r--r--src/gui/widgets/widgets.pri2
333 files changed, 12980 insertions, 6635 deletions
diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp
index 52303f5e15..28cde3ea08 100644
--- a/src/gui/animation/qguivariantanimation.cpp
+++ b/src/gui/animation/qguivariantanimation.cpp
@@ -38,12 +38,11 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
-#ifndef QT_NO_ANIMATION
-
#include <QtCore/qvariantanimation.h>
#include <private/qvariantanimation_p.h>
+#ifndef QT_NO_ANIMATION
+
#include <QtGui/qcolor.h>
#include <QtGui/qvector2d.h>
#include <QtGui/qvector3d.h>
diff --git a/src/gui/dialogs/dialogs.pri b/src/gui/dialogs/dialogs.pri
index 63f64a2d0d..4e1b9a71d1 100644
--- a/src/gui/dialogs/dialogs.pri
+++ b/src/gui/dialogs/dialogs.pri
@@ -50,7 +50,8 @@ HEADERS += \
}
win32 {
- HEADERS += dialogs/qwizard_win_p.h
+ HEADERS += dialogs/qwizard_win_p.h \
+ dialogs/qfiledialog_win_p.h
SOURCES += dialogs/qdialogsbinarycompat_win.cpp \
dialogs/qfiledialog_win.cpp \
dialogs/qpagesetupdialog_win.cpp \
diff --git a/src/gui/dialogs/qabstractprintdialog.cpp b/src/gui/dialogs/qabstractprintdialog.cpp
index 4523433857..25d9ebbdb3 100644
--- a/src/gui/dialogs/qabstractprintdialog.cpp
+++ b/src/gui/dialogs/qabstractprintdialog.cpp
@@ -76,6 +76,7 @@ class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
\value AllPages All pages should be printed.
\value Selection Only the selection should be printed.
\value PageRange The specified page range should be printed.
+ \value CurrentPage Only the currently visible page should be printed.
\sa QPrinter::PrintRange
*/
@@ -89,7 +90,9 @@ class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
\value PrintToFile The print to file option is enabled.
\value PrintSelection The print selection option is enabled.
\value PrintPageRange The page range selection option is enabled.
- \value PrintCollateCopies
+ \value PrintShowPageSize Show the page size + margins page only if this is enabled.
+ \value PrintCollateCopies The collate copies option is enabled
+ \value PrintCurrentPage The print current page option is enabled
This value is obsolete and does nothing since Qt 4.5:
@@ -97,8 +100,6 @@ class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
would create a sheet by default the dialog was given a parent.
This is no longer supported in Qt 4.5. If you want to use sheets, use
QPrintDialog::open() instead.
-
- \value PrintShowPageSize Show the page size + margins page only if this is enabled.
*/
/*!
diff --git a/src/gui/dialogs/qabstractprintdialog.h b/src/gui/dialogs/qabstractprintdialog.h
index 4d867f6809..82e3df8103 100644
--- a/src/gui/dialogs/qabstractprintdialog.h
+++ b/src/gui/dialogs/qabstractprintdialog.h
@@ -65,7 +65,8 @@ public:
enum PrintRange {
AllPages,
Selection,
- PageRange
+ PageRange,
+ CurrentPage
};
enum PrintDialogOption {
@@ -75,7 +76,8 @@ public:
PrintPageRange = 0x0004,
PrintShowPageSize = 0x0008,
PrintCollateCopies = 0x0010,
- DontUseSheet = 0x0020
+ DontUseSheet = 0x0020,
+ PrintCurrentPage = 0x0040
};
Q_DECLARE_FLAGS(PrintDialogOptions, PrintDialogOption)
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index 8b40b52bcc..a6bd78ad5e 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -258,7 +258,7 @@ QT_BEGIN_NAMESPACE
QDialog::QDialog(QWidget *parent, Qt::WindowFlags f)
: QWidget(*new QDialogPrivate, parent,
- f | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0))
+ f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))
{
#ifdef Q_WS_WINCE
if (!qt_wince_is_smartphone())
@@ -295,7 +295,7 @@ QDialog::QDialog(QWidget *parent, const char *name, bool modal, Qt::WindowFlags
\internal
*/
QDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f)
- : QWidget(dd, parent, f | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0))
+ : QWidget(dd, parent, f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))
{
#ifdef Q_WS_WINCE
if (!qt_wince_is_smartphone())
@@ -641,13 +641,14 @@ void QDialog::contextMenuEvent(QContextMenuEvent *e)
while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis))
w = w->isWindow() ? 0 : w->parentWidget();
if (w) {
- QMenu p(this);
- QAction *wt = p.addAction(tr("What's This?"));
- if (p.exec(e->globalPos()) == wt) {
+ QWeakPointer<QMenu> p = new QMenu(this);
+ QAction *wt = p.data()->addAction(tr("What's This?"));
+ if (p.data()->exec(e->globalPos()) == wt) {
QHelpEvent e(QEvent::WhatsThis, w->rect().center(),
w->mapToGlobal(w->rect().center()));
QApplication::sendEvent(w, &e);
}
+ delete p.data();
}
#endif
}
diff --git a/src/gui/dialogs/qerrormessage.cpp b/src/gui/dialogs/qerrormessage.cpp
index 0bca811cfa..7be74812f1 100644
--- a/src/gui/dialogs/qerrormessage.cpp
+++ b/src/gui/dialogs/qerrormessage.cpp
@@ -70,10 +70,10 @@ extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
#if defined(QT_SOFTKEYS_ENABLED)
#include <qaction.h>
+#endif
#ifdef Q_WS_S60
#include "private/qt_s60_p.h"
#endif
-#endif
QT_BEGIN_NAMESPACE
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 089e04a04d..cb74a3c9a5 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -228,7 +228,8 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook
\value ReadOnly Indicates that the model is readonly.
- \value HideNameFilterDetails Indicates if the is hidden or not.
+ \value HideNameFilterDetails Indicates if the file name filter details are
+ hidden or not.
\value DontUseSheet In previous versions of Qt, the static
functions would create a sheet by default if the static function
@@ -722,9 +723,19 @@ void QFileDialog::setVisible(bool visible)
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
// updates the state correctly, but skips showing the non-native version:
setAttribute(Qt::WA_DontShowOnScreen);
+#ifndef QT_NO_FSCOMPLETER
+ //So the completer don't try to complete and therefore to show a popup
+ d->completer->setModel(0);
+#endif
} else {
d->nativeDialogInUse = false;
setAttribute(Qt::WA_DontShowOnScreen, false);
+#ifndef QT_NO_FSCOMPLETER
+ if (d->proxyModel != 0)
+ d->completer->setModel(d->proxyModel);
+ else
+ d->completer->setModel(d->model);
+#endif
}
}
diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm
index 67daced524..28acf241e1 100644
--- a/src/gui/dialogs/qfiledialog_mac.mm
+++ b/src/gui/dialogs/qfiledialog_mac.mm
@@ -295,10 +295,14 @@ QT_USE_NAMESPACE
if (!mQDirFilterEntryList->contains(info.fileName()))
return NO;
- // Always accept directories regardless of their names:
+ // Always accept directories regardless of their names (unless it is a bundle):
BOOL isDir;
- if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir] && isDir)
- return YES;
+ if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir] && isDir) {
+ if ([mSavePanel treatsFilePackagesAsDirectories] == NO) {
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO)
+ return YES;
+ }
+ }
// No filter means accept everything
if (mSelectedNameFilter->isEmpty())
@@ -489,7 +493,7 @@ QT_USE_NAMESPACE
for (int i=0; i<mNameFilterDropDownList->size(); ++i) {
QString filter = hideDetails ? [self removeExtensions:filters->at(i)] : filters->at(i);
[mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)];
- if (filters->at(i) == selectedFilter)
+ if (filters->at(i).startsWith(selectedFilter))
[mPopUpButton selectItemAtIndex:i];
}
}
@@ -725,6 +729,7 @@ Boolean QFileDialogPrivate::qt_mac_filedialog_filter_proc(AEDesc *theItem, void
NavFileOrFolderInfo *theInfo = static_cast<NavFileOrFolderInfo *>(info);
QString file;
+ QString path;
const QtMacFilterName &fn
= fileDialogPrivate->filterInfo.filters.at(fileDialogPrivate->filterInfo.currentSelection);
if (theItem->descriptorType == typeFSRef) {
@@ -732,10 +737,12 @@ Boolean QFileDialogPrivate::qt_mac_filedialog_filter_proc(AEDesc *theItem, void
AEGetDescData(theItem, &ref, sizeof(ref));
UInt8 str_buffer[1024];
FSRefMakePath(&ref, str_buffer, 1024);
- file = QString::fromUtf8(reinterpret_cast<const char *>(str_buffer));
- int slsh = file.lastIndexOf(QLatin1Char('/'));
+ path = QString::fromUtf8(reinterpret_cast<const char *>(str_buffer));
+ int slsh = path.lastIndexOf(QLatin1Char('/'));
if (slsh != -1)
- file = file.right(file.length() - slsh - 1);
+ file = path.right(path.length() - slsh - 1);
+ else
+ file = path;
}
QStringList reg = fn.regexp.split(QLatin1String(";"));
for (QStringList::const_iterator it = reg.constBegin(); it != reg.constEnd(); ++it) {
@@ -747,7 +754,13 @@ Boolean QFileDialogPrivate::qt_mac_filedialog_filter_proc(AEDesc *theItem, void
if (rg.exactMatch(file))
return true;
}
- return (theInfo->isFolder && !file.endsWith(QLatin1String(".app")));
+
+ if (theInfo->isFolder) {
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:qt_mac_QStringToNSString(path)])
+ return false;
+ return true;
+ }
+ return false;
}
void QFileDialogPrivate::qt_mac_filedialog_event_proc(const NavEventCallbackMessage msg,
diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp
index 5a7ace99fe..258707c2db 100644
--- a/src/gui/dialogs/qfiledialog_win.cpp
+++ b/src/gui/dialogs/qfiledialog_win.cpp
@@ -53,53 +53,27 @@
#include <qdir.h>
#include <qstringlist.h>
#include <qlibrary.h>
+#include "qfiledialog_win_p.h"
#ifndef QT_NO_THREAD
# include <private/qmutexpool_p.h>
#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>
-
-#if defined(__IFileDialog_INTERFACE_DEFINED__) \
- && defined(__IFileOpenDialog_INTERFACE_DEFINED__)
-#define USE_COMMON_ITEM_DIALOG
-#endif
-
#ifdef Q_WS_WINCE
+#include <shlobj.h>
#include <commdlg.h>
-# ifndef BFFM_SETSELECTION
-# define BFFM_SETSELECTION (WM_USER + 102)
-# endif
-// Windows Mobile has a broken definition for BROWSEINFO
-// Only compile fix
-typedef struct qt_priv_browseinfo {
- HWND hwndOwner;
- LPCITEMIDLIST pidlRoot;
- LPWSTR pszDisplayName;
- LPCWSTR lpszTitle;
- UINT ulFlags;
- BFFCALLBACK lpfn;
- LPARAM lParam;
- int iImage;
-} qt_BROWSEINFO;
bool qt_priv_ptr_valid = false;
+#else
+//we have to declare them here because they're not present for all SDK/compilers
+static const IID QT_IID_IFileOpenDialog = {0xd57c7288, 0xd4ad, 0x4768, {0xbe, 0x02, 0x9d, 0x96, 0x95, 0x32, 0xd9, 0x60} };
+static const IID QT_IID_IShellItem = {0x43826d1e, 0xe718, 0x42ee, {0xbc, 0x55, 0xa1, 0xe2, 0x61, 0xc3, 0x7b, 0xfe} };
+static const CLSID QT_CLSID_FileOpenDialog = {0xdc1c5a9c, 0xe88a, 0x4dde, {0xa5, 0xa1, 0x60, 0xf8, 0x2a, 0x20, 0xae, 0xf7} };
#endif
-// Don't remove the lines below!
-//
-// resolving the W methods manually is needed, because Windows 95 doesn't include
-// these methods in Shell32.lib (not even stubs!), so you'd get an unresolved symbol
-// when Qt calls getExistingDirectory(), etc.
-typedef LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(BROWSEINFO*);
+typedef qt_LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(qt_BROWSEINFO*);
static PtrSHBrowseForFolder ptrSHBrowseForFolder = 0;
-typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(LPITEMIDLIST,LPWSTR);
+typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(qt_LPITEMIDLIST, LPWSTR);
static PtrSHGetPathFromIDList ptrSHGetPathFromIDList = 0;
typedef HRESULT (WINAPI *PtrSHGetMalloc)(LPMALLOC *);
static PtrSHGetMalloc ptrSHGetMalloc = 0;
@@ -132,7 +106,7 @@ static void qt_win_resolve_libs()
ptrSHGetMalloc = (PtrSHGetMalloc) lib.resolve("SHGetMalloc");
#else
// CE stores them in a different lib and does not use unicode version
- HINSTANCE handle = LoadLibraryW(L"Ceshell");
+ HINSTANCE handle = LoadLibrary(L"Ceshell");
ptrSHBrowseForFolder = (PtrSHBrowseForFolder)GetProcAddress(handle, L"SHBrowseForFolder");
ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)GetProcAddress(handle, L"SHGetPathFromIDList");
ptrSHGetMalloc = (PtrSHGetMalloc)GetProcAddress(handle, L"SHGetMalloc");
@@ -244,7 +218,6 @@ static OPENFILENAME* qt_win_make_OFN(QWidget *parent,
memset(ofn, 0, sizeof(OPENFILENAME));
ofn->lStructSize = sizeof(OPENFILENAME);
- Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
ofn->hwndOwner = parent ? parent->winId() : 0;
ofn->lpstrFilter = (wchar_t*)tFilters.utf16();
ofn->lpstrFile = tInitSel;
@@ -421,7 +394,7 @@ QString qt_win_get_save_file_name(const QFileDialogArgs &args,
}
-#if defined(USE_COMMON_ITEM_DIALOG)
+#ifndef Q_WS_WINCE
typedef HRESULT (WINAPI *PtrSHCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
static PtrSHCreateItemFromParsingName pSHCreateItemFromParsingName = 0;
@@ -469,7 +442,7 @@ static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd,
// Add the filters to the file dialog.
if (numFilters) {
wchar_t *szData = (wchar_t*)winfilters.utf16();
- COMDLG_FILTERSPEC *filterSpec = new COMDLG_FILTERSPEC[numFilters];
+ qt_COMDLG_FILTERSPEC *filterSpec = new qt_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];
@@ -481,9 +454,8 @@ static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd,
tInitDir = QDir::toNativeSeparators(initialDirectory);
if (!tInitDir.isEmpty()) {
IShellItem *psiDefaultFolder;
- hr = pSHCreateItemFromParsingName((wchar_t*)tInitDir.utf16(),
- NULL,
- IID_PPV_ARGS(&psiDefaultFolder));
+ hr = pSHCreateItemFromParsingName((wchar_t*)tInitDir.utf16(), NULL, QT_IID_IShellItem,
+ reinterpret_cast<void**>(&psiDefaultFolder));
if (SUCCEEDED(hr)) {
hr = pfd->SetFolder(psiDefaultFolder);
@@ -522,7 +494,7 @@ static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd,
return SUCCEEDED(hr);
}
-QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
+static QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
QString *initialDirectory,
const QStringList &filterList,
QString *selectedFilter,
@@ -535,10 +507,8 @@ QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
QApplicationPrivate::enterModal(&modal_widget);
// Multiple selection is allowed only in IFileOpenDialog.
IFileOpenDialog *pfd = 0;
- HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_PPV_ARGS(&pfd));
+ HRESULT hr = CoCreateInstance(QT_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, QT_IID_IFileOpenDialog,
+ reinterpret_cast<void**>(&pfd));
if (SUCCEEDED(hr)) {
qt_win_set_IFileDialogOptions(pfd, args.selection,
@@ -612,6 +582,63 @@ QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
return result;
}
+QString qt_win_CID_get_existing_directory(const QFileDialogArgs &args)
+{
+ QString result;
+ QDialog modal_widget;
+ modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
+ modal_widget.setParent(args.parent, Qt::Window);
+ QApplicationPrivate::enterModal(&modal_widget);
+
+ IFileOpenDialog *pfd = 0;
+ HRESULT hr = CoCreateInstance(QT_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
+ QT_IID_IFileOpenDialog, reinterpret_cast<void**>(&pfd));
+
+ if (SUCCEEDED(hr)) {
+ qt_win_set_IFileDialogOptions(pfd, args.selection,
+ args.directory, args.caption,
+ QStringList(), QFileDialog::ExistingFiles,
+ args.options);
+
+ // Set the FOS_PICKFOLDERS flag
+ DWORD newOptions;
+ hr = pfd->GetOptions(&newOptions);
+ newOptions |= FOS_PICKFOLDERS;
+ if (SUCCEEDED(hr) && SUCCEEDED((hr = pfd->SetOptions(newOptions)))) {
+ 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 result
+ IShellItem *psi = 0;
+ hr = pfd->GetResult(&psi);
+ if (SUCCEEDED(hr)) {
+ // Retrieve the file name from shell item.
+ wchar_t *pszPath;
+ hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
+ if (SUCCEEDED(hr)) {
+ result = QString::fromWCharArray(pszPath);
+ CoTaskMemFree(pszPath);
+ }
+ psi->Release(); // Free the current item.
+ }
+ }
+ }
+ }
+ QApplicationPrivate::leaveModal(&modal_widget);
+
+ qt_win_eatMouseMove();
+
+ if (pfd)
+ pfd->Release();
+ return result;
+}
+
#endif
QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
@@ -643,7 +670,7 @@ QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
// 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)
+#ifndef Q_WS_WINCE
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
@@ -716,7 +743,7 @@ static int __stdcall winGetExistDirCallbackProc(HWND hwnd,
qt_win_resolve_libs();
if (ptrSHGetPathFromIDList) {
wchar_t path[MAX_PATH];
- ptrSHGetPathFromIDList(LPITEMIDLIST(lParam), path);
+ ptrSHGetPathFromIDList(qt_LPITEMIDLIST(lParam), path);
QString tmpStr = QString::fromWCharArray(path);
if (!tmpStr.isEmpty())
SendMessage(hwnd, BFFM_ENABLEOK, 1, 1);
@@ -728,13 +755,13 @@ static int __stdcall winGetExistDirCallbackProc(HWND hwnd,
return 0;
}
-#ifndef BIF_NEWDIALOGSTYLE
-#define BIF_NEWDIALOGSTYLE 0x0040 // Use the new dialog layout with the ability to resize
-#endif
-
-
QString qt_win_get_existing_directory(const QFileDialogArgs &args)
{
+#ifndef Q_WS_WINCE
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
+ return qt_win_CID_get_existing_directory(args);
+#endif
+
QString currentDir = QDir::currentPath();
QString result;
QWidget *parent = args.parent;
@@ -757,11 +784,7 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args)
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);
@@ -775,7 +798,7 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args)
qt_win_resolve_libs();
if (ptrSHBrowseForFolder) {
- LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder((BROWSEINFO*)&bi);
+ qt_LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder(&bi);
if (pItemIDList) {
ptrSHGetPathFromIDList(pItemIDList, path);
IMalloc *pMalloc;
diff --git a/src/gui/dialogs/qfiledialog_win_p.h b/src/gui/dialogs/qfiledialog_win_p.h
new file mode 100644
index 0000000000..7079925b11
--- /dev/null
+++ b/src/gui/dialogs/qfiledialog_win_p.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** 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 <objbase.h>
+#ifndef QFILEDIAG_WIN_P_H
+#define QFILEDIAG_WIN_P_H
+
+//these are the interface declarations needed for the file dialog on Vista and up
+
+//At some point we can hope that all compilers/sdk will support that interface
+//and we won't have to declare it ourselves
+
+//declarations
+#define FOS_OVERWRITEPROMPT 0x2
+#define FOS_STRICTFILETYPES 0x4
+#define FOS_NOCHANGEDIR 0x8
+#define FOS_PICKFOLDERS 0x20
+#define FOS_FORCEFILESYSTEM 0x40
+#define FOS_ALLNONSTORAGEITEMS 0x80
+#define FOS_NOVALIDATE 0x100
+#define FOS_ALLOWMULTISELECT 0x200
+#define FOS_PATHMUSTEXIST 0x800
+#define FOS_FILEMUSTEXIST 0x1000
+#define FOS_CREATEPROMPT 0x2000
+#define FOS_SHAREAWARE 0x4000
+#define FOS_NOREADONLYRETURN 0x8000
+#define FOS_NOTESTFILECREATE 0x10000
+#define FOS_HIDEMRUPLACES 0x20000
+#define FOS_HIDEPINNEDPLACES 0x40000
+#define FOS_NODEREFERENCELINKS 0x100000
+#define FOS_DONTADDTORECENT 0x2000000
+#define FOS_FORCESHOWHIDDEN 0x10000000
+#define FOS_DEFAULTNOMINIMODE 0x20000000
+#define FOS_FORCEPREVIEWPANEON 0x40000000
+
+typedef int GETPROPERTYSTOREFLAGS;
+#define GPS_DEFAULT 0x00000000
+#define GPS_HANDLERPROPERTIESONLY 0x00000001
+#define GPS_READWRITE 0x00000002
+#define GPS_TEMPORARY 0x00000004
+#define GPS_FASTPROPERTIESONLY 0x00000008
+#define GPS_OPENSLOWITEM 0x00000010
+#define GPS_DELAYCREATION 0x00000020
+#define GPS_BESTEFFORT 0x00000040
+#define GPS_MASK_VALID 0x0000007F
+
+typedef int (QT_WIN_CALLBACK* BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
+// message from browser
+#define BFFM_INITIALIZED 1
+#define BFFM_SELCHANGED 2
+#define BFFM_ENABLEOK (WM_USER + 101)
+#define BFFM_SETSELECTION (WM_USER + 103)
+#define BFFM_SETSTATUSTEXT (WM_USER + 104)
+
+// Browsing for directory.
+#define BIF_RETURNONLYFSDIRS 0x0001
+#define BIF_DONTGOBELOWDOMAIN 0x0002
+#define BIF_STATUSTEXT 0x0004
+#define BIF_RETURNFSANCESTORS 0x0008
+#define BIF_EDITBOX 0x0010
+#define BIF_VALIDATE 0x0020
+#define BIF_NEWDIALOGSTYLE 0x0040
+#define BIF_BROWSEINCLUDEURLS 0x0080
+#define BIF_UAHINT 0x0100
+#define BIF_NONEWFOLDERBUTTON 0x0200
+#define BIF_NOTRANSLATETARGETS 0x0400
+#define BIF_BROWSEFORCOMPUTER 0x1000
+#define BIF_BROWSEFORPRINTER 0x2000
+#define BIF_BROWSEINCLUDEFILES 0x4000
+#define BIF_SHAREABLE 0x8000
+
+//the enums
+typedef enum {
+ SIATTRIBFLAGS_AND = 0x1,
+ SIATTRIBFLAGS_OR = 0x2,
+ SIATTRIBFLAGS_APPCOMPAT = 0x3,
+ SIATTRIBFLAGS_MASK = 0x3
+} SIATTRIBFLAGS;
+typedef enum {
+ SIGDN_NORMALDISPLAY = 0x00000000,
+ SIGDN_PARENTRELATIVEPARSING = 0x80018001,
+ SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
+ SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
+ SIGDN_PARENTRELATIVEEDITING = 0x80031001,
+ SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
+ SIGDN_FILESYSPATH = 0x80058000,
+ SIGDN_URL = 0x80068000
+} SIGDN;
+typedef enum {
+ FDAP_BOTTOM = 0x00000000,
+ FDAP_TOP = 0x00000001
+} FDAP;
+typedef enum {
+ FDESVR_DEFAULT = 0x00000000,
+ FDESVR_ACCEPT = 0x00000001,
+ FDESVR_REFUSE = 0x00000002
+} FDE_SHAREVIOLATION_RESPONSE;
+typedef FDE_SHAREVIOLATION_RESPONSE FDE_OVERWRITE_RESPONSE;
+
+//the structs
+typedef struct {
+ LPCWSTR pszName;
+ LPCWSTR pszSpec;
+} qt_COMDLG_FILTERSPEC;
+typedef struct {
+ GUID fmtid;
+ DWORD pid;
+} qt_PROPERTYKEY;
+
+typedef struct {
+ USHORT cb;
+ BYTE abID[1];
+} qt_SHITEMID, *qt_LPSHITEMID;
+typedef struct {
+ qt_SHITEMID mkid;
+} qt_ITEMIDLIST, *qt_LPITEMIDLIST;
+typedef const qt_ITEMIDLIST *qt_LPCITEMIDLIST;
+typedef struct {
+ HWND hwndOwner;
+ qt_LPCITEMIDLIST pidlRoot;
+ LPWSTR pszDisplayName;
+ LPCWSTR lpszTitle;
+ UINT ulFlags;
+ BFFCALLBACK lpfn;
+ LPARAM lParam;
+ int iImage;
+} qt_BROWSEINFO;
+
+DECLARE_INTERFACE(IFileDialogEvents);
+DECLARE_INTERFACE_(IShellItem, IUnknown)
+{
+ STDMETHOD(BindToHandler)(THIS_ IBindCtx *pbc, REFGUID bhid, REFIID riid, void **ppv) PURE;
+ STDMETHOD(GetParent)(THIS_ IShellItem **ppsi) PURE;
+ STDMETHOD(GetDisplayName)(THIS_ SIGDN sigdnName, LPWSTR *ppszName) PURE;
+ STDMETHOD(GetAttributes)(THIS_ ULONG sfgaoMask, ULONG *psfgaoAttribs) PURE;
+ STDMETHOD(Compare)(THIS_ IShellItem *psi, DWORD hint, int *piOrder) PURE;
+};
+DECLARE_INTERFACE_(IShellItemFilter, IUnknown)
+{
+ STDMETHOD(IncludeItem)(THIS_ IShellItem *psi) PURE;
+ STDMETHOD(GetEnumFlagsForItem)(THIS_ IShellItem *psi, DWORD *pgrfFlags) PURE;
+};
+DECLARE_INTERFACE_(IEnumShellItems, IUnknown)
+{
+ STDMETHOD(Next)(THIS_ ULONG celt, IShellItem **rgelt, ULONG *pceltFetched) PURE;
+ STDMETHOD(Skip)(THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset)(THIS_) PURE;
+ STDMETHOD(Clone)(THIS_ IEnumShellItems **ppenum) PURE;
+};
+DECLARE_INTERFACE_(IShellItemArray, IUnknown)
+{
+ STDMETHOD(BindToHandler)(THIS_ IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppvOut) PURE;
+ STDMETHOD(GetPropertyStore)(THIS_ GETPROPERTYSTOREFLAGS flags, REFIID riid, void **ppv) PURE;
+ STDMETHOD(GetPropertyDescriptionList)(THIS_ const qt_PROPERTYKEY *keyType, REFIID riid, void **ppv) PURE;
+ STDMETHOD(GetAttributes)(THIS_ SIATTRIBFLAGS dwAttribFlags, ULONG sfgaoMask, ULONG *psfgaoAttribs) PURE;
+ STDMETHOD(GetCount)(THIS_ DWORD *pdwNumItems) PURE;
+ STDMETHOD(GetItemAt)(THIS_ DWORD dwIndex, IShellItem **ppsi) PURE;
+ STDMETHOD(EnumItems)(THIS_ IEnumShellItems **ppenumShellItems) PURE;
+};
+DECLARE_INTERFACE_(IModalWindow, IUnknown)
+{
+ STDMETHOD(Show)(THIS_ HWND hwndParent) PURE;
+};
+DECLARE_INTERFACE_(IFileDialog, IModalWindow)
+{
+ STDMETHOD(SetFileTypes)(THIS_ UINT cFileTypes, const qt_COMDLG_FILTERSPEC *rgFilterSpec) PURE;
+ STDMETHOD(SetFileTypeIndex)(THIS_ UINT iFileType) PURE;
+ STDMETHOD(GetFileTypeIndex)(THIS_ UINT *piFileType) PURE;
+ STDMETHOD(Advise)(THIS_ IFileDialogEvents *pfde, DWORD *pdwCookie) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwCookie) PURE;
+ STDMETHOD(SetOptions)(THIS_ DWORD fos) PURE;
+ STDMETHOD(GetOptions)(THIS_ DWORD *pfos) PURE;
+ STDMETHOD(SetDefaultFolder)(THIS_ IShellItem *psi) PURE;
+ STDMETHOD(SetFolder)(THIS_ IShellItem *psi) PURE;
+ STDMETHOD(GetFolder)(THIS_ IShellItem **ppsi) PURE;
+ STDMETHOD(GetCurrentSelection)(THIS_ IShellItem **ppsi) PURE;
+ STDMETHOD(SetFileName)(THIS_ LPCWSTR pszName) PURE;
+ STDMETHOD(GetFileName)(THIS_ LPWSTR *pszName) PURE;
+ STDMETHOD(SetTitle)(THIS_ LPCWSTR pszTitle) PURE;
+ STDMETHOD(SetOkButtonLabel)(THIS_ LPCWSTR pszText) PURE;
+ STDMETHOD(SetFileNameLabel)(THIS_ LPCWSTR pszLabel) PURE;
+ STDMETHOD(GetResult)(THIS_ IShellItem **ppsi) PURE;
+ STDMETHOD(AddPlace)(THIS_ IShellItem *psi, FDAP fdap) PURE;
+ STDMETHOD(SetDefaultExtension)(THIS_ LPCWSTR pszDefaultExtension) PURE;
+ STDMETHOD(Close)(THIS_ HRESULT hr) PURE;
+ STDMETHOD(SetClientGuid)(THIS_ REFGUID guid) PURE;
+ STDMETHOD(ClearClientData)(THIS_) PURE;
+ STDMETHOD(SetFilter)(THIS_ IShellItemFilter *pFilter) PURE;
+};
+DECLARE_INTERFACE_(IFileDialogEvents, IUnknown)
+{
+ STDMETHOD(OnFileOk)(THIS_ IFileDialog *pfd) PURE;
+ STDMETHOD(OnFolderChanging)(THIS_ IFileDialog *pfd, IShellItem *psiFolder) PURE;
+ STDMETHOD(OnFolderChange)(THIS_ IFileDialog *pfd) PURE;
+ STDMETHOD(OnSelectionChange)(THIS_ IFileDialog *pfd) PURE;
+ STDMETHOD(OnShareViolation)(THIS_ IFileDialog *pfd, IShellItem *psi, FDE_SHAREVIOLATION_RESPONSE *pResponse) PURE;
+ STDMETHOD(OnTypeChange)(THIS_ IFileDialog *pfd) PURE;
+ STDMETHOD(OnOverwrite)(THIS_ IFileDialog *pfd, IShellItem *psi, FDE_OVERWRITE_RESPONSE *pResponse) PURE;
+};
+DECLARE_INTERFACE_(IFileOpenDialog, IFileDialog)
+{
+ STDMETHOD(GetResults)(THIS_ IShellItemArray **ppenum) PURE;
+ STDMETHOD(GetSelectedItems)(THIS_ IShellItemArray **ppsai) PURE;
+};
+#endif \ No newline at end of file
diff --git a/src/gui/dialogs/qfileinfogatherer.cpp b/src/gui/dialogs/qfileinfogatherer.cpp
index 1f619578bb..3b279ae0f1 100644
--- a/src/gui/dialogs/qfileinfogatherer.cpp
+++ b/src/gui/dialogs/qfileinfogatherer.cpp
@@ -216,41 +216,10 @@ void QFileInfoGatherer::run()
}
}
-/*
- QFileInfo::permissions is different depending upon your platform.
-
- "normalize this" so they can mean the same to us.
-*/
-QFile::Permissions QFileInfoGatherer::translatePermissions(const QFileInfo &fileInfo) const {
- QFile::Permissions permissions = fileInfo.permissions();
-#ifdef Q_OS_WIN
- return permissions;
-#else
- QFile::Permissions p = permissions;
- p &= ~(QFile::ReadUser|QFile::WriteUser|QFile::ExeUser);
- if ( permissions & QFile::ReadOther
- || (fileInfo.ownerId() == userId && permissions & QFile::ReadOwner)
- || (fileInfo.groupId() == groupId && permissions & QFile::ReadGroup))
- p |= QFile::ReadUser;
-
- if ( permissions & QFile::WriteOther
- || (fileInfo.ownerId() == userId && permissions & QFile::WriteOwner)
- || (fileInfo.groupId() == groupId && permissions & QFile::WriteGroup))
- p |= QFile::WriteUser;
-
- if ( permissions & QFile::ExeOther
- || (fileInfo.ownerId() == userId && permissions & QFile::ExeOwner)
- || (fileInfo.groupId() == groupId && permissions & QFile::ExeGroup))
- p |= QFile::ExeUser;
- return p;
-#endif
-}
-
QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const
{
QExtendedInformation info(fileInfo);
info.icon = m_iconProvider->icon(fileInfo);
- info.setPermissions(translatePermissions(fileInfo));
info.displayType = m_iconProvider->type(fileInfo);
#ifndef QT_NO_FILESYSTEMWATCHER
// ### Not ready to listen all modifications
@@ -328,7 +297,8 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
return;
}
- QTime base = QTime::currentTime();
+ QElapsedTimer base;
+ base.start();
QFileInfo fileInfo;
bool firstTime = true;
QList<QPair<QString, QFileInfo> > updatedFiles;
@@ -354,11 +324,13 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
}
if (!updatedFiles.isEmpty())
emit updates(path, updatedFiles);
+ emit directoryLoaded(path);
}
-void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QTime &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path) {
+void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path) {
updatedFiles.append(QPair<QString, QFileInfo>(fileInfo.fileName(), fileInfo));
- QTime current = QTime::currentTime();
+ QElapsedTimer current;
+ current.start();
if ((firstTime && updatedFiles.count() > 100) || base.msecsTo(current) > 1000) {
emit updates(path, updatedFiles);
updatedFiles.clear();
diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h
index 0242178292..5abcd94fe6 100644
--- a/src/gui/dialogs/qfileinfogatherer_p.h
+++ b/src/gui/dialogs/qfileinfogatherer_p.h
@@ -60,9 +60,10 @@
#include <qfileiconprovider.h>
#include <qfsfileengine.h>
#include <qpair.h>
-#include <qdatetime.h>
#include <qstack.h>
+#include <qdatetime.h>
#include <qdir.h>
+#include <qelapsedtimer.h>
QT_BEGIN_NAMESPACE
@@ -88,11 +89,7 @@ public:
return fe.caseSensitive();
}
QFile::Permissions permissions() const {
- return mPermissions;
- }
-
- void setPermissions (QFile::Permissions permissions) {
- mPermissions = permissions;
+ return mFileInfo.permissions();
}
Type type() const {
@@ -140,7 +137,6 @@ public:
private :
QFileInfo mFileInfo;
- QFile::Permissions mPermissions;
};
class QFileIconProvider;
@@ -155,6 +151,7 @@ Q_SIGNALS:
void updates(const QString &directory, const QList<QPair<QString, QFileInfo> > &updates);
void newListOfFiles(const QString &directory, const QStringList &listOfFiles) const;
void nameResolved(const QString &fileName, const QString &resolvedName) const;
+ void directoryLoaded(const QString &path);
public:
QFileInfoGatherer(QObject *parent = 0);
@@ -178,9 +175,8 @@ protected:
void getFileInfos(const QString &path, const QStringList &files);
private:
- void fetch(const QFileInfo &info, QTime &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path);
+ void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path);
QString translateDriveName(const QFileInfo &drive) const;
- QFile::Permissions translatePermissions(const QFileInfo &fileInfo) const;
QMutex mutex;
QWaitCondition condition;
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index 24faa59d55..8a6190fd57 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -51,6 +51,9 @@
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif
+#ifdef Q_OS_WIN32
+#include <QtCore/QVarLengthArray>
+#endif
QT_BEGIN_NAMESPACE
@@ -150,6 +153,14 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \since 4.7
+ \fn void QFileSystemModel::directoryLoaded(const QString &path)
+
+ This signal is emitted when the gatherer thread has finished to load the \a path.
+
+*/
+
+/*!
\fn bool QFileSystemModel::remove(const QModelIndex &index) const
Removes the model item \a index from the file system model and \bold{deletes the
@@ -270,53 +281,38 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QM
return indexNode;
}
-#ifdef Q_OS_WIN
+#ifdef Q_OS_WIN32
static QString qt_GetLongPathName(const QString &strShortPath)
{
- QString longPath;
- int i = 0;
- if (strShortPath == QLatin1String(".")
- || (strShortPath.startsWith(QLatin1String("//")))
- || (strShortPath.startsWith(QLatin1String("\\\\")))) // unc
+ if (strShortPath.isEmpty()
+ || strShortPath == QLatin1String(".") || strShortPath == QLatin1String(".."))
return strShortPath;
- QString::const_iterator it = strShortPath.constBegin();
- QString::const_iterator constEnd = strShortPath.constEnd();
- do {
- bool isSep = (*it == QLatin1Char('\\') || *it == QLatin1Char('/'));
- if (isSep || it == constEnd) {
- QString section = (it == constEnd ? strShortPath : strShortPath.left(i));
- // FindFirstFile does not handle volumes ("C:"), so we have to catch that ourselves.
- if (section.endsWith(QLatin1Char(':'))) {
- longPath.append(section.toUpper());
- } else {
- HANDLE h;
-#ifndef Q_OS_WINCE
- //We add the extend length prefix to handle long path
- QString longSection = QLatin1String("\\\\?\\")+QDir::toNativeSeparators(section);
-#else
- QString longSection = QDir::toNativeSeparators(section);
-#endif
- 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;
- }
- }
- if (it != constEnd)
- longPath.append(*it);
- else
- break;
- }
- ++it;
- if (isSep && it == constEnd) // break out if the last character is a separator
- break;
- ++i;
- } while (true);
- return longPath;
+ if (strShortPath.length() == 2 && strShortPath.endsWith(QLatin1Char(':')))
+ return strShortPath.toUpper();
+ const QString absPath = QDir(strShortPath).absolutePath();
+ if (absPath.startsWith(QLatin1String("//"))
+ || absPath.startsWith(QLatin1String("\\\\"))) // unc
+ return QDir::fromNativeSeparators(absPath);
+ if (absPath.startsWith(QLatin1Char('/')))
+ return QString();
+ const QString inputString = QLatin1String("\\\\?\\") + QDir::toNativeSeparators(absPath);
+ QVarLengthArray<TCHAR, MAX_PATH> buffer(MAX_PATH);
+ DWORD result = ::GetLongPathName((wchar_t*)inputString.utf16(),
+ buffer.data(),
+ buffer.size());
+ if (result > DWORD(buffer.size())) {
+ buffer.resize(result);
+ result = ::GetLongPathName((wchar_t*)inputString.utf16(),
+ buffer.data(),
+ buffer.size());
+ }
+ if (result > 4) {
+ QString longPath = QString::fromWCharArray(buffer.data() + 4); // ignoring prefix
+ longPath[0] = longPath.at(0).toUpper(); // capital drive letters
+ return QDir::fromNativeSeparators(longPath);
+ } else {
+ return QDir::fromNativeSeparators(strShortPath);
+ }
}
#endif
@@ -334,7 +330,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
// Construct the nodes up to the new root path if they need to be built
QString absolutePath;
-#ifdef Q_OS_WIN
+#ifdef Q_OS_WIN32
QString longPath = qt_GetLongPathName(path);
#else
QString longPath = path;
@@ -673,7 +669,7 @@ QVariant QFileSystemModel::data(const QModelIndex &index, int role) const
case Qt::EditRole:
case Qt::DisplayRole:
switch (index.column()) {
- case 0: return d->name(index);
+ case 0: return d->displayName(index);
case 1: return d->size(index);
case 2: return d->type(index);
case 3: return d->time(index);
@@ -789,13 +785,25 @@ QString QFileSystemModelPrivate::name(const QModelIndex &index) const
if (resolvedSymLinks.contains(fullPath))
return resolvedSymLinks[fullPath];
}
- // ### TODO it would be nice to grab the volume name if dirNode->parent == root
return dirNode->fileName;
}
/*!
\internal
*/
+QString QFileSystemModelPrivate::displayName(const QModelIndex &index) const
+{
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ QFileSystemNode *dirNode = node(index);
+ if (!dirNode->volumeName.isNull())
+ return dirNode->volumeName + QLatin1String(" (") + name(index) + QLatin1Char(')');
+#endif
+ return name(index);
+}
+
+/*!
+ \internal
+*/
QIcon QFileSystemModelPrivate::icon(const QModelIndex &index) const
{
if (!index.isValid())
@@ -1337,7 +1345,11 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath)
{
Q_D(QFileSystemModel);
#ifdef Q_OS_WIN
- QString longNewPath = QDir::fromNativeSeparators(qt_GetLongPathName(newPath));
+#ifdef Q_OS_WIN32
+ QString longNewPath = qt_GetLongPathName(newPath);
+#else
+ QString longNewPath = QDir::fromNativeSeparators(newPath);
+#endif
#else
QString longNewPath = newPath;
#endif
@@ -1650,6 +1662,18 @@ QFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFile
#ifndef QT_NO_FILESYSTEMWATCHER
node->populate(info);
#endif
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ //The parentNode is "" so we are listing the drives
+ if (parentNode->fileName.isEmpty()) {
+ wchar_t name[MAX_PATH + 1];
+ //GetVolumeInformation requires to add trailing backslash
+ const QString nodeName = fileName + QLatin1String("\\");
+ BOOL success = ::GetVolumeInformation((wchar_t *)(nodeName.utf16()),
+ name, MAX_PATH + 1, NULL, 0, NULL, NULL, 0);
+ if (success && name[0])
+ node->volumeName = QString::fromWCharArray(name);
+ }
+#endif
parentNode->children.insert(fileName, node);
return node;
}
@@ -1879,7 +1903,16 @@ void QFileSystemModelPrivate::init()
q, SLOT(_q_fileSystemChanged(QString,QList<QPair<QString,QFileInfo> >)));
q->connect(&fileInfoGatherer, SIGNAL(nameResolved(QString,QString)),
q, SLOT(_q_resolvedName(QString,QString)));
+ q->connect(&fileInfoGatherer, SIGNAL(directoryLoaded(QString)),
+ q, SIGNAL(directoryLoaded(QString)));
q->connect(&delayedSortTimer, SIGNAL(timeout()), q, SLOT(_q_performDelayedSort()), Qt::QueuedConnection);
+
+ QHash<int, QByteArray> roles = q->roleNames();
+ roles.insertMulti(QFileSystemModel::FileIconRole, "fileIcon"); // == Qt::decoration
+ roles.insert(QFileSystemModel::FilePathRole, "filePath");
+ roles.insert(QFileSystemModel::FileNameRole, "fileName");
+ roles.insert(QFileSystemModel::FilePermissions, "filePermissions");
+ q->setRoleNames(roles);
}
/*!
diff --git a/src/gui/dialogs/qfilesystemmodel.h b/src/gui/dialogs/qfilesystemmodel.h
index 4dcfe26835..d8178c70b0 100644
--- a/src/gui/dialogs/qfilesystemmodel.h
+++ b/src/gui/dialogs/qfilesystemmodel.h
@@ -70,6 +70,7 @@ class Q_GUI_EXPORT QFileSystemModel : public QAbstractItemModel
Q_SIGNALS:
void rootPathChanged(const QString &newPath);
void fileRenamed(const QString &path, const QString &oldName, const QString &newName);
+ void directoryLoaded(const QString &path);
public:
enum Roles {
diff --git a/src/gui/dialogs/qfilesystemmodel_p.h b/src/gui/dialogs/qfilesystemmodel_p.h
index 6c85a7c348..03e0bfb8bd 100644
--- a/src/gui/dialogs/qfilesystemmodel_p.h
+++ b/src/gui/dialogs/qfilesystemmodel_p.h
@@ -97,6 +97,9 @@ public:
}
QString fileName;
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ QString volumeName;
+#endif
inline qint64 size() const { if (info && !info->isDir()) return info->size(); return 0; }
inline QString type() const { if (info) return info->displayType; return QLatin1String(""); }
@@ -278,6 +281,7 @@ public:
QIcon icon(const QModelIndex &index) const;
QString name(const QModelIndex &index) const;
+ QString displayName(const QModelIndex &index) const;
QString filePath(const QModelIndex &index) const;
QString size(const QModelIndex &index) const;
static QString size(qint64 bytes);
diff --git a/src/gui/dialogs/qfontdialog.cpp b/src/gui/dialogs/qfontdialog.cpp
index a4bf15dff2..b159fa79a3 100644
--- a/src/gui/dialogs/qfontdialog.cpp
+++ b/src/gui/dialogs/qfontdialog.cpp
@@ -174,6 +174,11 @@ void QFontDialogPrivate::init()
{
Q_Q(QFontDialog);
+#ifdef Q_WS_MAC
+ nativeDialogInUse = false;
+ delegate = 0;
+#endif
+
q->setSizeGripEnabled(true);
q->setWindowTitle(QFontDialog::tr("Select Font"));
@@ -329,10 +334,6 @@ void QFontDialogPrivate::init()
familyList->setFocus();
retranslateStrings();
-
-#ifdef Q_WS_MAC
- delegate = 0;
-#endif
}
/*!
@@ -345,8 +346,7 @@ QFontDialog::~QFontDialog()
#ifdef Q_WS_MAC
Q_D(QFontDialog);
if (d->delegate) {
- QFontDialogPrivate::closeCocoaFontPanel(d->delegate);
- QFontDialogPrivate::sharedFontPanelAvailable = true;
+ d->closeCocoaFontPanel();
return;
}
#endif
@@ -428,14 +428,6 @@ QFont QFontDialog::getFont(bool *ok, QWidget *parent)
QFont QFontDialogPrivate::getFont(bool *ok, const QFont &initial, QWidget *parent,
const QString &title, QFontDialog::FontDialogOptions options)
{
-#ifdef Q_WS_MAC
- if (!(options & QFontDialog::DontUseNativeDialog)
- && QFontDialogPrivate::sharedFontPanelAvailable) {
- return QFontDialogPrivate::execCocoaFontPanel(ok, initial, parent,
- title.isEmpty() ? QFontDialog::tr("Select Font") : title, options);
- }
-#endif
-
QFontDialog dlg(parent);
dlg.setOptions(options);
dlg.setCurrentFont(initial);
@@ -988,13 +980,10 @@ void QFontDialog::open(QObject *receiver, const char *member)
*/
void QFontDialog::setVisible(bool visible)
{
- Q_D(QFontDialog);
- if (visible) {
- if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
- return;
- } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) != visible)
return;
#ifdef Q_WS_MAC
+ Q_D(QFontDialog);
if (d->canBeNativeDialog()){
if (d->setVisible_sys(visible)){
d->nativeDialogInUse = true;
diff --git a/src/gui/dialogs/qfontdialog_mac.mm b/src/gui/dialogs/qfontdialog_mac.mm
index 67d32b8daf..919790b733 100644
--- a/src/gui/dialogs/qfontdialog_mac.mm
+++ b/src/gui/dialogs/qfontdialog_mac.mm
@@ -58,6 +58,14 @@
typedef float CGFloat; // Should only not be defined on 32-bit platforms
#endif
+QT_BEGIN_NAMESPACE
+
+extern void macStartInterceptNSPanelCtor();
+extern void macStopInterceptNSPanelCtor();
+extern NSButton *macCreateButton(const char *text, NSView *superview);
+extern bool qt_mac_is_macsheet(const QWidget *w); // qwidget_mac.mm
+
+QT_END_NAMESPACE
QT_USE_NAMESPACE
// should a priori be kept in sync with qcolordialog_mac.mm
@@ -95,7 +103,8 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin
BOOL mPanelHackedWithButtons;
CGFloat mDialogExtraWidth;
CGFloat mDialogExtraHeight;
- NSModalSession mModalSession;
+ int mReturnCode;
+ BOOL mAppModal;
}
- (id)initWithFontPanel:(NSFontPanel *)panel
stolenContentView:(NSView *)stolenContentView
@@ -104,9 +113,11 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin
priv:(QFontDialogPrivate *)priv
extraWidth:(CGFloat)extraWidth
extraHeight:(CGFloat)extraHeight;
+- (void)showModelessPanel;
+- (void)showWindowModalSheet:(QWidget *)docWidget;
+- (void)runApplicationModalPanel;
- (void)changeFont:(id)sender;
- (void)changeAttributes:(id)sender;
-- (void)setModalSession:(NSModalSession)session;
- (BOOL)windowShouldClose:(id)window;
- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
- (void)relayout;
@@ -163,7 +174,8 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
mPanelHackedWithButtons = (okButton != 0);
mDialogExtraWidth = extraWidth;
mDialogExtraHeight = extraHeight;
- mModalSession = 0;
+ mReturnCode = -1;
+ mAppModal = false;
if (mPanelHackedWithButtons) {
[self relayout];
@@ -174,6 +186,20 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
[cancelButton setAction:@selector(onCancelClicked)];
[cancelButton setTarget:self];
}
+
+#ifdef QT_MAC_USE_COCOA
+ // Stack the native dialog in front of its parent, if any:
+ QFontDialog *q = mPriv->fontDialog();
+ if (!qt_mac_is_macsheet(q)) {
+ if (QWidget *parent = q->parentWidget()) {
+ if (parent->isWindow()) {
+ [qt_mac_window_for(parent)
+ addChildWindow:[mStolenContentView window] ordered:NSWindowAbove];
+ }
+ }
+ }
+#endif
+
mQtFont = new QFont();
return self;
}
@@ -184,6 +210,50 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
[super dealloc];
}
+- (void)showModelessPanel
+{
+ mAppModal = false;
+ NSWindow *ourPanel = [mStolenContentView window];
+ [ourPanel makeKeyAndOrderFront:self];
+}
+
+- (void)runApplicationModalPanel
+{
+ QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
+ mAppModal = true;
+ NSWindow *ourPanel = [mStolenContentView window];
+ [NSApp runModalForWindow:ourPanel];
+ QAbstractEventDispatcher::instance()->interrupt();
+
+ if (mReturnCode == NSOKButton)
+ mPriv->fontDialog()->accept();
+ else
+ mPriv->fontDialog()->reject();
+}
+
+- (void)showWindowModalSheet:(QWidget *)docWidget
+{
+#ifdef QT_MAC_USE_COCOA
+ NSWindow *window = qt_mac_window_for(docWidget);
+#else
+ WindowRef hiwindowRef = qt_mac_window_for(docWidget);
+ NSWindow *window = [[NSWindow alloc] initWithWindowRef:hiwindowRef];
+ CFRetain(hiwindowRef);
+#endif
+
+ mAppModal = false;
+ NSWindow *ourPanel = [mStolenContentView window];
+ [NSApp beginSheet:ourPanel
+ modalForWindow:window
+ modalDelegate:0
+ didEndSelector:0
+ contextInfo:0 ];
+
+#ifndef QT_MAC_USE_COCOA
+ CFRelease(hiwindowRef);
+#endif
+}
+
- (void)changeFont:(id)sender
{
NSFont *dummyFont = [NSFont userFontOfSize:12.0];
@@ -216,12 +286,6 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
mPriv->updateSampleFont(*mQtFont);
}
-- (void)setModalSession:(NSModalSession)session
-{
- Q_ASSERT(!mModalSession);
- mModalSession = session;
-}
-
- (BOOL)windowShouldClose:(id)window
{
Q_UNUSED(window);
@@ -282,9 +346,8 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
NSSize cancelSizeHint = [mCancelButton frame].size;
const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth,
- qMax(okSizeHint.width, cancelSizeHint.width)),
- CGFloat((frameSize.width - 2.0 * ButtonSideMargin
- - ButtonSpacing) * 0.5));
+ qMax(okSizeHint.width, cancelSizeHint.width)),
+ CGFloat((frameSize.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5));
const CGFloat ButtonHeight = qMax(ButtonMinHeight,
qMax(okSizeHint.height, cancelSizeHint.height));
@@ -317,14 +380,12 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
NSFontManager *fontManager = [NSFontManager sharedFontManager];
[self setQtFont:qfontForCocoaFont([fontManager convertFont:[fontManager selectedFont]],
*mQtFont)];
- [[mStolenContentView window] close];
[self finishOffWithCode:NSOKButton];
}
- (void)onCancelClicked
{
Q_ASSERT(mPanelHackedWithButtons);
- [[mStolenContentView window] close];
[self finishOffWithCode:NSCancelButton];
}
@@ -368,20 +429,26 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
- (void)finishOffWithCode:(NSInteger)code
{
- if (mPriv) {
- if (mModalSession) {
- [NSApp endModalSession:mModalSession];
- mModalSession = 0;
+#ifdef QT_MAC_USE_COCOA
+ QFontDialog *q = mPriv->fontDialog();
+ if (QWidget *parent = q->parentWidget()) {
+ if (parent->isWindow()) {
+ [qt_mac_window_for(parent) removeChildWindow:[mStolenContentView window]];
}
- // Hack alert!
- // Since this code path was never intended to be followed when starting from exec
- // we need to force the dialog to communicate the new font, otherwise the signal
- // won't get emitted.
- if(code == NSOKButton)
- mPriv->sampleEdit->setFont([self qtFont]);
- mPriv->done((code == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
- } else {
+ }
+#endif
+
+ if(code == NSOKButton)
+ mPriv->sampleEdit->setFont([self qtFont]);
+
+ if (mAppModal) {
+ mReturnCode = code;
[NSApp stopModalWithCode:code];
+ } else {
+ if (code == NSOKButton)
+ mPriv->fontDialog()->accept();
+ else
+ mPriv->fontDialog()->reject();
}
}
@@ -408,206 +475,16 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
QT_BEGIN_NAMESPACE
-extern void macStartInterceptNSPanelCtor();
-extern void macStopInterceptNSPanelCtor();
-extern NSButton *macCreateButton(const char *text, NSView *superview);
-
-void *QFontDialogPrivate::openCocoaFontPanel(const QFont &initial,
- QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options,
- QFontDialogPrivate *priv)
-{
- Q_UNUSED(parent); // we would use the parent if only NSFontPanel could be a sheet
- QMacCocoaAutoReleasePool pool;
-
- /*
- The standard Cocoa font panel has no OK or Cancel button and
- is created as a utility window. For strange reasons (which seem
- to stem from the fact that the font panel is based on a NIB
- file), the approach we use for the color panel doesn't work for
- the font panel (and, inversely, the approach we use here doesn't
- quite work for color panel, and crashed last time I tried). So
- instead, we take the following steps:
-
- 1. Constructs a plain NSPanel that looks the way we want it
- to look. Specifically, if the NoButtons option is off, we
- construct a panel without the NSUtilityWindowMask flag
- and with buttons (OK and Cancel).
-
- 2. Steal the content view from the shared NSFontPanel and
- put it inside our new NSPanel's content view, together
- with the OK and Cancel buttons.
-
- 3. Lay out the original content view and the buttons when
- the font panel is shown and whenever it is resized.
-
- 4. Clean up after ourselves.
-
- PS. Some customization is also done in QCocoaApplication
- validModesForFontPanel:.
- */
-
- Qt::WindowModality modality = Qt::ApplicationModal;
- if (priv)
- modality = priv->fontDialog()->windowModality();
-
- bool needButtons = !(options & QFontDialog::NoButtons);
- // don't need our own panel if the title bar isn't visible anyway (in a sheet)
- bool needOwnPanel = (needButtons && modality != Qt::WindowModal);
-
- bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
- NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
- [sharedFontPanel setHidesOnDeactivate:false];
-
- // hack to ensure that QCocoaApplication's validModesForFontPanel:
- // implementation is honored
- if (!sharedFontPanelExisted && needOwnPanel) {
- [sharedFontPanel makeKeyAndOrderFront:sharedFontPanel];
- [sharedFontPanel close];
- }
-
- NSPanel *ourPanel = 0;
- NSView *stolenContentView = 0;
- NSButton *okButton = 0;
- NSButton *cancelButton = 0;
-
- CGFloat dialogExtraWidth = 0.0;
- CGFloat dialogExtraHeight = 0.0;
-
- if (!needOwnPanel) {
- // we can reuse the NSFontPanel unchanged
- ourPanel = sharedFontPanel;
- } else {
- // compute dialogExtra{Width,Height}
- dialogExtraWidth = 2.0 * DialogSideMargin;
- dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight
- + ButtonBottomMargin;
-
- // compute initial contents rectangle
- NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
- contentRect.size.width += dialogExtraWidth;
- contentRect.size.height += dialogExtraHeight;
-
- // create the new panel
- ourPanel = [[NSPanel alloc] initWithContentRect:contentRect
- styleMask:StyleMask
- backing:NSBackingStoreBuffered
- defer:YES];
- [ourPanel setReleasedWhenClosed:YES];
- }
-
- stolenContentView = [sharedFontPanel contentView];
-
- if (needButtons) {
- // steal the font panel's contents view
- [stolenContentView retain];
- [sharedFontPanel setContentView:0];
-
- // create a new content view and add the stolen one as a subview
- NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } };
- NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect];
- [ourContentView addSubview:stolenContentView];
-
- // create OK and Cancel buttons and add these as subviews
- okButton = macCreateButton("&OK", ourContentView);
- cancelButton = macCreateButton("Cancel", ourContentView);
-
- [ourPanel setContentView:ourContentView];
- [ourPanel setDefaultButtonCell:[okButton cell]];
- }
-
- // create a delegate and set it
- QCocoaFontPanelDelegate *delegate =
- [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
- stolenContentView:stolenContentView
- okButton:okButton
- cancelButton:cancelButton
- priv:priv
- extraWidth:dialogExtraWidth
- extraHeight:dialogExtraHeight];
- [ourPanel setDelegate:delegate];
- [[NSFontManager sharedFontManager] setDelegate:delegate];
-#ifdef QT_MAC_USE_COCOA
- [[NSFontManager sharedFontManager] setTarget:delegate];
-#endif
- setFont(delegate, initial);
-
- // hack to get correct initial layout
- NSRect frameRect = [ourPanel frame];
- frameRect.size.width += 1.0;
- [ourPanel setFrame:frameRect display:NO];
- frameRect.size.width -= 1.0;
- frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size];
- [ourPanel setFrame:frameRect display:NO];
- [ourPanel center];
-
- [ourPanel setTitle:(NSString*)(CFStringRef)QCFString(title)];
-
- if (priv) {
- switch (modality) {
- case Qt::WindowModal:
- if (parent) {
-#ifndef QT_MAC_USE_COCOA
- WindowRef hiwindowRef = qt_mac_window_for(parent);
- NSWindow *window =
- [[NSWindow alloc] initWithWindowRef:hiwindowRef];
- // Cocoa docs say I should retain the Carbon ref.
- CFRetain(hiwindowRef);
-#else
- NSWindow *window = qt_mac_window_for(parent);
-#endif
- [NSApp beginSheet:ourPanel
- modalForWindow:window
- modalDelegate:0
- didEndSelector:0
- contextInfo:0];
-#ifndef QT_MAC_USE_COCOA
- [window release];
-#endif
- break;
- }
- // fallthrough
- case Qt::ApplicationModal:
- [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]];
- break;
- default:
- [ourPanel makeKeyAndOrderFront:ourPanel];
- }
- }
- return delegate;
-}
-
-void QFontDialogPrivate::closeCocoaFontPanel(void *delegate)
+void QFontDialogPrivate::closeCocoaFontPanel()
{
QMacCocoaAutoReleasePool pool;
QCocoaFontPanelDelegate *theDelegate = static_cast<QCocoaFontPanelDelegate *>(delegate);
NSWindow *ourPanel = [theDelegate actualPanel];
[ourPanel close];
[theDelegate cleanUpAfterMyself];
- [theDelegate autorelease];
-}
-
-QFont QFontDialogPrivate::execCocoaFontPanel(bool *ok, const QFont &initial,
- QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options)
-{
- QMacCocoaAutoReleasePool pool;
- QCocoaFontPanelDelegate *delegate =
- static_cast<QCocoaFontPanelDelegate *>(
- openCocoaFontPanel(initial, parent, title, options));
- NSWindow *ourPanel = [delegate actualPanel];
- [ourPanel retain];
- int rval = [NSApp runModalForWindow:ourPanel];
- QFont font([delegate qtFont]);
- [ourPanel release];
- [delegate cleanUpAfterMyself];
- [delegate release];
- bool isOk = ((options & QFontDialog::NoButtons) || rval == NSOKButton);
- if (ok)
- *ok = isOk;
- if (isOk) {
- return font;
- } else {
- return initial;
- }
+ [theDelegate release];
+ this->delegate = 0;
+ sharedFontPanelAvailable = true;
}
void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
@@ -645,10 +522,13 @@ void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
[static_cast<QCocoaFontPanelDelegate *>(delegate) setQtFont:font];
}
-void *QFontDialogPrivate::_q_constructNativePanel()
+void QFontDialogPrivate::createNSFontPanelDelegate()
{
- QMacCocoaAutoReleasePool pool;
+ if (delegate)
+ return;
+ sharedFontPanelAvailable = false;
+ QMacCocoaAutoReleasePool pool;
bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
[sharedFontPanel setHidesOnDeactivate:false];
@@ -670,8 +550,7 @@ void *QFontDialogPrivate::_q_constructNativePanel()
// compute dialogExtra{Width,Height}
dialogExtraWidth = 2.0 * DialogSideMargin;
- dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight
- + ButtonBottomMargin;
+ dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight + ButtonBottomMargin;
// compute initial contents rectangle
NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
@@ -684,7 +563,6 @@ void *QFontDialogPrivate::_q_constructNativePanel()
backing:NSBackingStoreBuffered
defer:YES];
[ourPanel setReleasedWhenClosed:YES];
-
stolenContentView = [sharedFontPanel contentView];
// steal the font panel's contents view
@@ -704,21 +582,23 @@ void *QFontDialogPrivate::_q_constructNativePanel()
[ourPanel setContentView:ourContentView];
[ourPanel setDefaultButtonCell:[okButton cell]];
}
- // create a delegate and set it
- QCocoaFontPanelDelegate *delegate =
- [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
+
+ // create the delegate and set it
+ QCocoaFontPanelDelegate *del = [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
stolenContentView:stolenContentView
okButton:okButton
cancelButton:cancelButton
priv:this
extraWidth:dialogExtraWidth
extraHeight:dialogExtraHeight];
- [ourPanel setDelegate:delegate];
- [[NSFontManager sharedFontManager] setDelegate:delegate];
+ delegate = del;
+ [ourPanel setDelegate:del];
+
+ [[NSFontManager sharedFontManager] setDelegate:del];
#ifdef QT_MAC_USE_COCOA
- [[NSFontManager sharedFontManager] setTarget:delegate];
+ [[NSFontManager sharedFontManager] setTarget:del];
#endif
- setFont(delegate, QApplication::font());
+ setFont(del, q_func()->currentFont());
{
// hack to get correct initial layout
@@ -726,15 +606,12 @@ void *QFontDialogPrivate::_q_constructNativePanel()
frameRect.size.width += 1.0;
[ourPanel setFrame:frameRect display:NO];
frameRect.size.width -= 1.0;
- frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size];
+ frameRect.size = [del windowWillResize:ourPanel toSize:frameRect.size];
[ourPanel setFrame:frameRect display:NO];
[ourPanel center];
}
NSString *title = @"Select font";
[ourPanel setTitle:title];
-
- [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]];
- return delegate;
}
void QFontDialogPrivate::mac_nativeDialogModalHelp()
@@ -759,29 +636,47 @@ void QFontDialogPrivate::mac_nativeDialogModalHelp()
// and "adding" the buttons.
void QFontDialogPrivate::_q_macRunNativeAppModalPanel()
{
- QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
+ createNSFontPanelDelegate();
+ QCocoaFontPanelDelegate *del = static_cast<QCocoaFontPanelDelegate *>(delegate);
+ [del runApplicationModalPanel];
+}
+
+bool QFontDialogPrivate::showCocoaFontPanel()
+{
+ if (!sharedFontPanelAvailable)
+ return false;
+
Q_Q(QFontDialog);
- QCocoaFontPanelDelegate *delegate = (QCocoaFontPanelDelegate *)_q_constructNativePanel();
- NSWindow *ourPanel = [delegate actualPanel];
- [ourPanel retain];
- int rval = [NSApp runModalForWindow:ourPanel];
- QAbstractEventDispatcher::instance()->interrupt();
- [ourPanel release];
- [delegate cleanUpAfterMyself];
- [delegate release];
- bool isOk = (rval == NSOKButton);
- if(isOk)
- rescode = QDialog::Accepted;
+ QMacCocoaAutoReleasePool pool;
+ createNSFontPanelDelegate();
+ QCocoaFontPanelDelegate *del = static_cast<QCocoaFontPanelDelegate *>(delegate);
+ if (qt_mac_is_macsheet(q))
+ [del showWindowModalSheet:q->parentWidget()];
else
- rescode = QDialog::Rejected;
+ [del showModelessPanel];
+ return true;
}
+bool QFontDialogPrivate::hideCocoaFontPanel()
+{
+ if (!delegate){
+ // Nothing to do. We return false to leave the question
+ // open regarding whether or not to go native:
+ return false;
+ } else {
+ closeCocoaFontPanel();
+ // Even when we hide it, we are still using a
+ // native dialog, so return true:
+ return true;
+ }
+}
bool QFontDialogPrivate::setVisible_sys(bool visible)
{
Q_Q(QFontDialog);
if (!visible == q->isHidden())
return false;
- return visible;
+
+ return visible ? showCocoaFontPanel() : hideCocoaFontPanel();
}
QT_END_NAMESPACE
diff --git a/src/gui/dialogs/qfontdialog_p.h b/src/gui/dialogs/qfontdialog_p.h
index 7654a80f7c..8676be360f 100644
--- a/src/gui/dialogs/qfontdialog_p.h
+++ b/src/gui/dialogs/qfontdialog_p.h
@@ -139,25 +139,21 @@ public:
QByteArray memberToDisconnectOnClose;
#ifdef Q_WS_MAC
- static void *openCocoaFontPanel(const QFont &initial,
- QWidget *parent, const QString &title,
- QFontDialog::FontDialogOptions options,
- QFontDialogPrivate *priv = 0);
- static void closeCocoaFontPanel(void *delegate);
- static QFont execCocoaFontPanel(bool *ok, const QFont &initial, QWidget *parent,
- const QString &title, QFontDialog::FontDialogOptions options);
static void setFont(void *delegate, const QFont &font);
inline void done(int result) { q_func()->done(result); }
inline QFontDialog *fontDialog() { return q_func(); }
void *delegate;
+ void closeCocoaFontPanel();
bool nativeDialogInUse;
bool canBeNativeDialog();
bool setVisible_sys(bool visible);
- void *_q_constructNativePanel();
+ void createNSFontPanelDelegate();
void _q_macRunNativeAppModalPanel();
void mac_nativeDialogModalHelp();
+ bool showCocoaFontPanel();
+ bool hideCocoaFontPanel();
static bool sharedFontPanelAvailable;
#endif
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index ccc925c3ff..fe25b0f807 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -96,8 +96,8 @@ public:
{
#ifndef QT_NO_CONTEXTMENU
QMenu *menu = createStandardContextMenu();
- menu->exec(e->globalPos());
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(e->globalPos());
#else
Q_UNUSED(e);
#endif
@@ -122,14 +122,44 @@ public:
}
void setText(const QString &text) { textEdit->setPlainText(text); }
QString text() const { return textEdit->toPlainText(); }
- QString label(DetailButtonLabel label)
- { return label == ShowLabel ? QMessageBox::tr("Show Details...")
- : QMessageBox::tr("Hide Details..."); }
private:
TextEdit *textEdit;
};
#endif // QT_NO_TEXTEDIT
+class DetailButton : public QPushButton
+{
+public:
+ DetailButton(QWidget *parent) : QPushButton(label(ShowLabel), parent)
+ {
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ }
+
+ QString label(DetailButtonLabel label) const
+ { return label == ShowLabel ? QMessageBox::tr("Show Details...") : QMessageBox::tr("Hide Details..."); }
+
+ void setLabel(DetailButtonLabel lbl)
+ { setText(label(lbl)); }
+
+ QSize sizeHint() const
+ {
+ ensurePolished();
+ QStyleOptionButton opt;
+ initStyleOption(&opt);
+ const QFontMetrics fm = fontMetrics();
+ opt.text = label(ShowLabel);
+ QSize sz = fm.size(Qt::TextShowMnemonic, opt.text);
+ QSize ret = style()->sizeFromContents(QStyle::CT_PushButton, &opt, sz, this).
+ expandedTo(QApplication::globalStrut());
+ opt.text = label(HideLabel);
+ sz = fm.size(Qt::TextShowMnemonic, opt.text);
+ ret.expandedTo(style()->sizeFromContents(QStyle::CT_PushButton, &opt, sz, this).
+ expandedTo(QApplication::globalStrut()));
+ return ret;
+ }
+};
+
+
class QMessageBoxPrivate : public QDialogPrivate
{
Q_DECLARE_PUBLIC(QMessageBox)
@@ -185,7 +215,7 @@ public:
QAbstractButton *escapeButton;
QPushButton *defaultButton;
QAbstractButton *clickedButton;
- QPushButton *detailsButton;
+ DetailButton *detailsButton;
#ifndef QT_NO_TEXTEDIT
QMessageBoxDetailsText *detailsText;
#endif
@@ -435,7 +465,7 @@ void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button)
Q_Q(QMessageBox);
#ifndef QT_NO_TEXTEDIT
if (detailsButton && detailsText && button == detailsButton) {
- detailsButton->setText(detailsText->isHidden() ? detailsText->label(HideLabel) : detailsText->label(ShowLabel));
+ detailsButton->setLabel(detailsText->isHidden() ? HideLabel : ShowLabel);
detailsText->setHidden(!detailsText->isHidden());
updateSize();
} else
@@ -1905,7 +1935,7 @@ void QMessageBoxPrivate::retranslateStrings()
{
#ifndef QT_NO_TEXTEDIT
if (detailsButton)
- detailsButton->setText(detailsText->isHidden() ? detailsText->label(HideLabel) : detailsText->label(ShowLabel));
+ detailsButton->setLabel(detailsText->isHidden() ? HideLabel : ShowLabel);
#endif
}
@@ -2413,11 +2443,8 @@ void QMessageBox::setDetailedText(const QString &text)
grid->addWidget(d->detailsText, grid->rowCount(), 0, 1, grid->columnCount());
d->detailsText->hide();
}
- if (!d->detailsButton) {
- d->detailsButton = new QPushButton(d->detailsText->label(ShowLabel), this);
- QPushButton hideDetails(d->detailsText->label(HideLabel));
- d->detailsButton->setFixedSize(d->detailsButton->sizeHint().expandedTo(hideDetails.sizeHint()));
- }
+ if (!d->detailsButton)
+ d->detailsButton = new DetailButton(this);
d->detailsText->setText(text);
}
#endif // QT_NO_TEXTEDIT
diff --git a/src/gui/dialogs/qpagesetupdialog_mac.mm b/src/gui/dialogs/qpagesetupdialog_mac.mm
index 13ffa05e04..cfcde0ffdc 100644
--- a/src/gui/dialogs/qpagesetupdialog_mac.mm
+++ b/src/gui/dialogs/qpagesetupdialog_mac.mm
@@ -232,6 +232,11 @@ void QPageSetupDialogPrivate::openCocoaPageLayout(Qt::WindowModality modality)
void QPageSetupDialogPrivate::closeCocoaPageLayout()
{
+ // NSPageLayout can change the session behind our back and then our
+ // d->ep->session object will become a dangling pointer. Update it
+ // based on the "current" session
+ ep->session = static_cast<PMPrintSession>([ep->printInfo PMPrintSession]);
+
[pageLayout release];
pageLayout = 0;
}
diff --git a/src/gui/dialogs/qprintdialog_qws.cpp b/src/gui/dialogs/qprintdialog_qws.cpp
index 6b531a2659..b071427b4e 100644
--- a/src/gui/dialogs/qprintdialog_qws.cpp
+++ b/src/gui/dialogs/qprintdialog_qws.cpp
@@ -163,7 +163,7 @@ void QPrintDialogPrivate::_q_okClicked()
printer->setPaperSize(pageSize);
printer->setPageOrder(pageOrder2);
printer->setColorMode(colorMode2);
- printer->setNumCopies(numCopies);
+ printer->setCopyCount(numCopies);
switch ((rangeCombo->itemData(rangeCombo->currentIndex())).toInt()){
case (int)QPrintDialog::AllPages:
@@ -178,6 +178,10 @@ void QPrintDialogPrivate::_q_okClicked()
q->setPrintRange(QPrintDialog::PageRange);
q->setFromTo(firstPage->value(), lastPage->value());
break;
+ case (int)QPrintDialog::CurrentPage:
+ q->setPrintRange(QPrintDialog::CurrentPage);
+ q->setFromTo(0, 0);
+ break;
}
q->accept();
}
@@ -375,6 +379,7 @@ void QPrintDialogPrivate::setupOptions()
rangeCombo->addItem(QPrintDialog::tr("Print all"), QPrintDialog::AllPages);
rangeCombo->addItem(QPrintDialog::tr("Print selection"), QPrintDialog::Selection);
rangeCombo->addItem(QPrintDialog::tr("Print range"), QPrintDialog::PageRange);
+ rangeCombo->addItem(QPrintDialog::tr("Print current page"), QPrintDialog::CurrentPage);
QObject::connect(rangeCombo, SIGNAL(activated(int)),
q, SLOT(_q_printRangeSelected(int)));
@@ -479,8 +484,8 @@ void QPrintDialogPrivate::setPrinter(QPrinter *p, bool pickUpSettings)
printGray->setChecked(true);
// number of copies
- copies->setValue(p->numCopies());
- _q_setNumCopies(p->numCopies());
+ copies->setValue(p->copyCount());
+ _q_setNumCopies(p->copyCount());
}
if (p) {
@@ -490,6 +495,9 @@ void QPrintDialogPrivate::setPrinter(QPrinter *p, bool pickUpSettings)
if (!q->isOptionEnabled(QPrintDialog::PrintPageRange)
&& rangeCombo->findData(QPrintDialog::PageRange) > 0)
rangeCombo->removeItem(rangeCombo->findData(QPrintDialog::PageRange));
+ if (!q->isOptionEnabled(QPrintDialog::PrintCurrentPage)
+ && rangeCombo->findData(QPrintDialog::CurrentPage) > 0)
+ rangeCombo->removeItem(rangeCombo->findData(QPrintDialog::CurrentPage));
switch (q->printRange()) {
case QPrintDialog::AllPages:
@@ -501,6 +509,9 @@ void QPrintDialogPrivate::setPrinter(QPrinter *p, bool pickUpSettings)
case QPrintDialog::PageRange:
rangeCombo->setCurrentIndex((int)(QPrintDialog::PageRange));
break;
+ case QPrintDialog::CurrentPage:
+ rangeCombo->setCurrentIndex((int)(QPrintDialog::CurrentPage));
+ break;
}
}
diff --git a/src/gui/dialogs/qprintdialog_unix.cpp b/src/gui/dialogs/qprintdialog_unix.cpp
index 00dc3e62e5..e3c62be5e5 100644
--- a/src/gui/dialogs/qprintdialog_unix.cpp
+++ b/src/gui/dialogs/qprintdialog_unix.cpp
@@ -72,8 +72,6 @@
QT_BEGIN_NAMESPACE
-extern int qt_printerRealNumCopies(QPaintEngine *);
-
class QOptionTreeItem;
class QPPDOptionsModel;
@@ -442,7 +440,7 @@ void QPrintDialogPrivate::applyPrinterProperties(QPrinter *p)
case QPrinter::DuplexShortSide:
options.duplexShort->setChecked(true); break;
}
- options.copies->setValue(qt_printerRealNumCopies(p->paintEngine()));
+ options.copies->setValue(p->copyCount());
options.collate->setChecked(p->collateCopies());
options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);
top->d->applyPrinterProperties(p);
@@ -507,13 +505,16 @@ void QPrintDialogPrivate::setupPrinter()
} else if (options.printSelection->isChecked()) {
p->setPrintRange(QPrinter::Selection);
p->setFromTo(0,0);
+ } else if (options.printCurrentPage->isChecked()) {
+ p->setPrintRange(QPrinter::CurrentPage);
+ p->setFromTo(0,0);
} else if (options.printRange->isChecked()) {
p->setPrintRange(QPrinter::PageRange);
p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));
}
// copies
- p->setNumCopies(options.copies->value());
+ p->setCopyCount(options.copies->value());
p->setCollateCopies(options.collate->isChecked());
top->d->setupPrinter();
@@ -523,10 +524,12 @@ void QPrintDialogPrivate::updateWidgets()
{
Q_Q(QPrintDialog);
options.gbPrintRange->setVisible(q->isOptionEnabled(QPrintDialog::PrintPageRange) ||
- q->isOptionEnabled(QPrintDialog::PrintSelection));
+ q->isOptionEnabled(QPrintDialog::PrintSelection) ||
+ q->isOptionEnabled(QPrintDialog::PrintCurrentPage));
options.printRange->setEnabled(q->isOptionEnabled(QPrintDialog::PrintPageRange));
options.printSelection->setVisible(q->isOptionEnabled(QPrintDialog::PrintSelection));
+ options.printCurrentPage->setVisible(q->isOptionEnabled(QPrintDialog::PrintCurrentPage));
options.collate->setVisible(q->isOptionEnabled(QPrintDialog::PrintCollateCopies));
switch (q->printRange()) {
@@ -539,6 +542,10 @@ void QPrintDialogPrivate::updateWidgets()
case QPrintDialog::PageRange:
options.printRange->setChecked(true);
break;
+ case QPrintDialog::CurrentPage:
+ if (q->isOptionEnabled(QPrintDialog::PrintCurrentPage))
+ options.printCurrentPage->setChecked(true);
+ break;
default:
break;
}
@@ -696,12 +703,10 @@ QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p)
}
#endif
-#ifndef QT_NO_FILESYSTEMMODEL
+#if !defined(QT_NO_FILESYSTEMMODEL) && !defined(QT_NO_COMPLETER)
QFileSystemModel *fsm = new QFileSystemModel(widget.filename);
fsm->setRootPath(QDir::homePath());
-#if !defined(QT_NO_FSCOMPLETER) && !defined(QT_NO_FILEDIALOG)
- widget.filename->setCompleter(new QFSCompleter(fsm, widget.filename));
-#endif
+ widget.filename->setCompleter(new QCompleter(fsm, widget.filename));
#endif
_q_printerChanged(currentPrinterIndex);
diff --git a/src/gui/dialogs/qprintdialog_win.cpp b/src/gui/dialogs/qprintdialog_win.cpp
index 5ccd33d27b..38c8759b90 100644
--- a/src/gui/dialogs/qprintdialog_win.cpp
+++ b/src/gui/dialogs/qprintdialog_win.cpp
@@ -52,7 +52,7 @@
#include <private/qprintengine_win_p.h>
#include <private/qprinter_p.h>
-#if defined(Q_CC_MINGW) && !defined(PD_NOCURRENTPAGE)
+#if !defined(PD_NOCURRENTPAGE)
#define PD_NOCURRENTPAGE 0x00800000
#define PD_RESULT_PRINT 1
#define PD_RESULT_APPLY 2
@@ -128,17 +128,20 @@ static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, 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;
+ // Disable Current Page option if not required as default is Enabled
+ if (!pdlg->isOptionEnabled(QPrintDialog::PrintCurrentPage))
+ pd->Flags |= PD_NOCURRENTPAGE;
+
+ // Default to showing the General tab first
pd->nStartPage = START_PAGE_GENERAL;
+
+ // We don't support more than one page range in the QPrinter API yet.
pd->nPageRanges = 1;
pd->nMaxPageRanges = 1;
if (d->ep->printToFile)
pd->Flags |= PD_PRINTTOFILE;
- Q_ASSERT(parent != 0 && parent->testAttribute(Qt::WA_WState_Created));
+ Q_ASSERT(parent);
pd->hwndOwner = parent->window()->winId();
pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage());
pd->lpPageRanges[0].nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1;
@@ -153,7 +156,10 @@ static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPri
} else if (pd->Flags & PD_PAGENUMS) {
pdlg->setPrintRange(QPrintDialog::PageRange);
pdlg->setFromTo(pd->lpPageRanges[0].nFromPage, pd->lpPageRanges[0].nToPage);
- } else {
+ } else if (pd->Flags & PD_CURRENTPAGE) {
+ pdlg->setPrintRange(QPrintDialog::CurrentPage);
+ pdlg->setFromTo(0, 0);
+ } else { // PD_ALLPAGES
pdlg->setPrintRange(QPrintDialog::AllPages);
pdlg->setFromTo(0, 0);
}
diff --git a/src/gui/dialogs/qprintsettingsoutput.ui b/src/gui/dialogs/qprintsettingsoutput.ui
index fc57e863f9..be916790fb 100644
--- a/src/gui/dialogs/qprintsettingsoutput.ui
+++ b/src/gui/dialogs/qprintsettingsoutput.ui
@@ -1,121 +1,114 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
<class>QPrintSettingsOutput</class>
- <widget class="QWidget" name="QPrintSettingsOutput" >
- <property name="geometry" >
+ <widget class="QWidget" name="QPrintSettingsOutput">
+ <property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>416</width>
- <height>166</height>
+ <width>426</width>
+ <height>171</height>
</rect>
</property>
- <property name="windowTitle" >
+ <property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_2" >
- <property name="margin" >
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="margin">
<number>0</number>
</property>
<item>
- <widget class="QTabWidget" name="tabs" >
- <property name="currentIndex" >
+ <widget class="QTabWidget" name="tabs">
+ <property name="currentIndex">
<number>0</number>
</property>
- <widget class="QWidget" name="copiesTab" >
- <property name="geometry" >
- <rect>
- <x>0</x>
- <y>0</y>
- <width>412</width>
- <height>139</height>
- </rect>
- </property>
- <attribute name="title" >
+ <widget class="QWidget" name="copiesTab">
+ <attribute name="title">
<string>Copies</string>
</attribute>
- <layout class="QHBoxLayout" name="horizontalLayout" >
+ <layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="QGroupBox" name="gbPrintRange" >
- <property name="sizePolicy" >
- <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
+ <widget class="QGroupBox" name="gbPrintRange">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="title" >
+ <property name="title">
<string>Print range</string>
</property>
- <layout class="QVBoxLayout" name="_3" >
- <property name="spacing" >
+ <layout class="QVBoxLayout" name="_3">
+ <property name="spacing">
<number>4</number>
</property>
- <property name="margin" >
+ <property name="margin">
<number>6</number>
</property>
<item>
- <widget class="QRadioButton" name="printAll" >
- <property name="text" >
+ <widget class="QRadioButton" name="printAll">
+ <property name="text">
<string>Print all</string>
</property>
- <property name="checked" >
+ <property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
- <layout class="QHBoxLayout" name="_4" >
- <property name="spacing" >
+ <layout class="QHBoxLayout" name="_4">
+ <property name="spacing">
<number>6</number>
</property>
- <property name="margin" >
+ <property name="margin">
<number>0</number>
</property>
<item>
- <widget class="QRadioButton" name="printRange" >
- <property name="text" >
+ <widget class="QRadioButton" name="printRange">
+ <property name="text">
<string>Pages from</string>
</property>
</widget>
</item>
<item>
- <widget class="QSpinBox" name="from" >
- <property name="enabled" >
+ <widget class="QSpinBox" name="from">
+ <property name="enabled">
<bool>false</bool>
</property>
- <property name="minimum" >
+ <property name="minimum">
<number>1</number>
</property>
- <property name="maximum" >
+ <property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="label_3" >
- <property name="text" >
+ <widget class="QLabel" name="label_3">
+ <property name="text">
<string>to</string>
</property>
</widget>
</item>
<item>
- <widget class="QSpinBox" name="to" >
- <property name="enabled" >
+ <widget class="QSpinBox" name="to">
+ <property name="enabled">
<bool>false</bool>
</property>
- <property name="minimum" >
+ <property name="minimum">
<number>1</number>
</property>
- <property name="maximum" >
+ <property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item>
<spacer>
- <property name="orientation" >
+ <property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
@@ -126,18 +119,25 @@
</layout>
</item>
<item>
- <widget class="QRadioButton" name="printSelection" >
- <property name="text" >
+ <widget class="QRadioButton" name="printCurrentPage">
+ <property name="text">
+ <string>Current Page</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="printSelection">
+ <property name="text">
<string>Selection</string>
</property>
</widget>
</item>
<item>
- <spacer name="verticalSpacer" >
- <property name="orientation" >
+ <spacer name="verticalSpacer">
+ <property name="orientation">
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>1</height>
@@ -149,37 +149,37 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox" >
- <property name="title" >
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
<string>Output Settings</string>
</property>
- <layout class="QGridLayout" name="gridLayout" >
- <item row="0" column="0" >
- <widget class="QLabel" name="label" >
- <property name="text" >
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
<string>Copies:</string>
</property>
- <property name="buddy" >
+ <property name="buddy">
<cstring>copies</cstring>
</property>
</widget>
</item>
- <item row="0" column="1" colspan="2" >
- <widget class="QSpinBox" name="copies" >
- <property name="minimum" >
+ <item row="0" column="1" colspan="2">
+ <widget class="QSpinBox" name="copies">
+ <property name="minimum">
<number>1</number>
</property>
- <property name="maximum" >
+ <property name="maximum">
<number>999</number>
</property>
</widget>
</item>
- <item row="0" column="3" >
- <spacer name="horizontalSpacer" >
- <property name="orientation" >
+ <item row="0" column="3">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>91</width>
<height>20</height>
@@ -187,36 +187,36 @@
</property>
</spacer>
</item>
- <item row="1" column="0" colspan="2" >
- <widget class="QCheckBox" name="collate" >
- <property name="text" >
+ <item row="1" column="0" colspan="2">
+ <widget class="QCheckBox" name="collate">
+ <property name="text">
<string>Collate</string>
</property>
</widget>
</item>
- <item rowspan="2" row="1" column="2" colspan="2" >
- <widget class="QLabel" name="outputIcon" >
- <property name="sizePolicy" >
- <sizepolicy vsizetype="Ignored" hsizetype="Ignored" >
+ <item row="1" column="2" rowspan="2" colspan="2">
+ <widget class="QLabel" name="outputIcon">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Ignored" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
- <item row="2" column="0" colspan="2" >
- <widget class="QCheckBox" name="reverse" >
- <property name="text" >
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="reverse">
+ <property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
- <item row="3" column="0" colspan="4" >
- <spacer name="verticalSpacer_2" >
- <property name="orientation" >
+ <item row="3" column="0" colspan="4">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>1</height>
@@ -229,31 +229,23 @@
</item>
</layout>
</widget>
- <widget class="QWidget" name="optionsTab" >
- <property name="geometry" >
- <rect>
- <x>0</x>
- <y>0</y>
- <width>412</width>
- <height>139</height>
- </rect>
- </property>
- <attribute name="title" >
+ <widget class="QWidget" name="optionsTab">
+ <attribute name="title">
<string>Options</string>
</attribute>
- <layout class="QGridLayout" name="gridLayout_2" >
- <item row="0" column="1" >
- <widget class="QGroupBox" name="colorMode" >
- <property name="title" >
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="1">
+ <widget class="QGroupBox" name="colorMode">
+ <property name="title">
<string>Color Mode</string>
</property>
- <layout class="QGridLayout" name="gridLayout_4" >
- <item row="2" column="0" >
- <spacer name="verticalSpacer_6" >
- <property name="orientation" >
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="2" column="0">
+ <spacer name="verticalSpacer_6">
+ <property name="orientation">
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>0</height>
@@ -261,19 +253,19 @@
</property>
</spacer>
</item>
- <item row="0" column="0" >
- <widget class="QRadioButton" name="color" >
- <property name="text" >
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="color">
+ <property name="text">
<string>Color</string>
</property>
</widget>
</item>
- <item rowspan="3" row="0" column="1" >
- <widget class="QLabel" name="colorIcon" />
+ <item row="0" column="1" rowspan="3">
+ <widget class="QLabel" name="colorIcon"/>
</item>
- <item row="1" column="0" >
- <widget class="QRadioButton" name="grayscale" >
- <property name="text" >
+ <item row="1" column="0">
+ <widget class="QRadioButton" name="grayscale">
+ <property name="text">
<string>Grayscale</string>
</property>
</widget>
@@ -281,42 +273,42 @@
</layout>
</widget>
</item>
- <item row="0" column="0" >
- <widget class="QGroupBox" name="duplex" >
- <property name="title" >
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="duplex">
+ <property name="title">
<string>Duplex Printing</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout" >
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QRadioButton" name="noDuplex" >
- <property name="text" >
+ <widget class="QRadioButton" name="noDuplex">
+ <property name="text">
<string>None</string>
</property>
- <property name="checked" >
+ <property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
- <widget class="QRadioButton" name="duplexLong" >
- <property name="text" >
+ <widget class="QRadioButton" name="duplexLong">
+ <property name="text">
<string>Long side</string>
</property>
</widget>
</item>
<item>
- <widget class="QRadioButton" name="duplexShort" >
- <property name="text" >
+ <widget class="QRadioButton" name="duplexShort">
+ <property name="text">
<string>Short side</string>
</property>
</widget>
</item>
<item>
- <spacer name="verticalSpacer_42" >
- <property name="orientation" >
+ <spacer name="verticalSpacer_42">
+ <property name="orientation">
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>0</height>
@@ -341,11 +333,11 @@
<receiver>from</receiver>
<slot>setEnabled(bool)</slot>
<hints>
- <hint type="sourcelabel" >
+ <hint type="sourcelabel">
<x>76</x>
<y>59</y>
</hint>
- <hint type="destinationlabel" >
+ <hint type="destinationlabel">
<x>122</x>
<y>57</y>
</hint>
@@ -357,11 +349,11 @@
<receiver>to</receiver>
<slot>setEnabled(bool)</slot>
<hints>
- <hint type="sourcelabel" >
+ <hint type="sourcelabel">
<x>69</x>
<y>67</y>
</hint>
- <hint type="destinationlabel" >
+ <hint type="destinationlabel">
<x>215</x>
<y>67</y>
</hint>
diff --git a/src/gui/dialogs/qprogressdialog.cpp b/src/gui/dialogs/qprogressdialog.cpp
index 4fffdba83b..a2d7b232ff 100644
--- a/src/gui/dialogs/qprogressdialog.cpp
+++ b/src/gui/dialogs/qprogressdialog.cpp
@@ -46,7 +46,6 @@
#include "qshortcut.h"
#include "qpainter.h"
#include "qdrawutil.h"
-#include "qdatetime.h"
#include "qlabel.h"
#include "qprogressbar.h"
#include "qapplication.h"
@@ -54,6 +53,7 @@
#include "qpushbutton.h"
#include "qcursor.h"
#include "qtimer.h"
+#include "qelapsedtimer.h"
#include <private/qdialog_p.h>
#include <limits.h>
@@ -103,7 +103,7 @@ public:
QTimer *forceTimer;
bool shown_once;
bool cancellation_flag;
- QTime starttime;
+ QElapsedTimer starttime;
#ifndef QT_NO_CURSOR
QCursor parentCursor;
#endif
diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp
index a58057dc77..8607529a4f 100644
--- a/src/gui/dialogs/qwizard.cpp
+++ b/src/gui/dialogs/qwizard.cpp
@@ -218,8 +218,8 @@ public:
: topLevelMarginLeft(-1), topLevelMarginRight(-1), topLevelMarginTop(-1),
topLevelMarginBottom(-1), childMarginLeft(-1), childMarginRight(-1),
childMarginTop(-1), childMarginBottom(-1), hspacing(-1), vspacing(-1),
- wizStyle(QWizard::ClassicStyle), header(false), watermark(false), title(false),
- subTitle(false), extension(false) {}
+ wizStyle(QWizard::ClassicStyle), header(false), watermark(false), title(false),
+ subTitle(false), extension(false), sideWidget(false) {}
int topLevelMarginLeft;
int topLevelMarginRight;
@@ -238,6 +238,7 @@ public:
bool title;
bool subTitle;
bool extension;
+ bool sideWidget;
bool operator==(const QWizardLayoutInfo &other);
inline bool operator!=(const QWizardLayoutInfo &other) { return !operator==(other); }
@@ -261,7 +262,8 @@ bool QWizardLayoutInfo::operator==(const QWizardLayoutInfo &other)
&& watermark == other.watermark
&& title == other.title
&& subTitle == other.subTitle
- && extension == other.extension;
+ && extension == other.extension
+ && sideWidget == other.sideWidget;
}
class QWizardHeader : public QWidget
@@ -425,6 +427,40 @@ public:
: QWizardHeader(Ruler, parent) {}
};
+class QWatermarkLabel : public QLabel
+{
+public:
+ QWatermarkLabel(QWidget *parent, QWidget *sideWidget) : QLabel(parent), m_sideWidget(sideWidget) {
+ m_layout = new QVBoxLayout(this);
+ if (m_sideWidget)
+ m_layout->addWidget(m_sideWidget);
+ }
+
+ QSize minimumSizeHint() const {
+ if (!pixmap() && !pixmap()->isNull())
+ return pixmap()->size();
+ return QFrame::minimumSizeHint();
+ }
+
+ void setSideWidget(QWidget *widget) {
+ if (m_sideWidget == widget)
+ return;
+ if (m_sideWidget) {
+ m_layout->removeWidget(m_sideWidget);
+ m_sideWidget->hide();
+ }
+ m_sideWidget = widget;
+ if (m_sideWidget)
+ m_layout->addWidget(m_sideWidget);
+ }
+ QWidget *sideWidget() const {
+ return m_sideWidget;
+ }
+private:
+ QVBoxLayout *m_layout;
+ QWidget *m_sideWidget;
+};
+
class QWizardPagePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QWizardPage)
@@ -501,6 +537,7 @@ public:
inline QWizardPrivate()
: start(-1)
+ , startSetByUser(false)
, current(-1)
, canContinue(false)
, canFinish(false)
@@ -513,6 +550,7 @@ public:
, placeholderWidget2(0)
, headerWidget(0)
, watermarkLabel(0)
+ , sideWidget(0)
, titleLabel(0)
, subTitleLabel(0)
, bottomRuler(0)
@@ -581,6 +619,7 @@ public:
QList<int> history;
QSet<int> initialized; // ### remove and move bit to QWizardPage?
int start;
+ bool startSetByUser;
int current;
bool canContinue;
bool canFinish;
@@ -612,7 +651,8 @@ public:
QWidget *placeholderWidget1;
QWidget *placeholderWidget2;
QWizardHeader *headerWidget;
- QLabel *watermarkLabel;
+ QWatermarkLabel *watermarkLabel;
+ QWidget *sideWidget;
QFrame *pageFrame;
QLabel *titleLabel;
QLabel *subTitleLabel;
@@ -907,11 +947,12 @@ QWizardLayoutInfo QWizardPrivate::layoutInfoForCurrentPage()
info.header = (info.wizStyle == QWizard::ClassicStyle || info.wizStyle == QWizard::ModernStyle)
&& !(opts & QWizard::IgnoreSubTitles) && !subTitleText.isEmpty();
+ info.sideWidget = sideWidget;
info.watermark = (info.wizStyle != QWizard::MacStyle) && (info.wizStyle != QWizard::AeroStyle)
&& !watermarkPixmap.isNull();
info.title = !info.header && !titleText.isEmpty();
info.subTitle = !(opts & QWizard::IgnoreSubTitles) && !info.header && !subTitleText.isEmpty();
- info.extension = info.watermark && (opts & QWizard::ExtendedWatermarkPixmap);
+ info.extension = (info.watermark || info.sideWidget) && (opts & QWizard::ExtendedWatermarkPixmap);
return info;
}
@@ -954,7 +995,7 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
int numColumns;
if (mac) {
numColumns = 3;
- } else if (info.watermark) {
+ } else if (info.watermark || info.sideWidget) {
numColumns = 2;
} else {
numColumns = 1;
@@ -1096,8 +1137,8 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
pageFrame->setContentsMargins(hMargin, vMargin, hMargin, vMargin);
}
- if (info.watermark && !watermarkLabel) {
- watermarkLabel = new QLabel(antiFlickerWidget);
+ if ((info.watermark || info.sideWidget) && !watermarkLabel) {
+ watermarkLabel = new QWatermarkLabel(antiFlickerWidget, sideWidget);
watermarkLabel->setBackgroundRole(QPalette::Base);
watermarkLabel->setMinimumHeight(1);
watermarkLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
@@ -1173,7 +1214,7 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
mainLayout->addLayout(buttonLayout, row++, buttonStartColumn, 1, buttonNumColumns);
- if (info.watermark) {
+ if (info.watermark || info.sideWidget) {
if (info.extension)
watermarkEndRow = row;
mainLayout->addWidget(watermarkLabel, watermarkStartRow, 0,
@@ -1193,7 +1234,7 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
if (bottomRuler)
bottomRuler->setVisible(classic || modern);
if (watermarkLabel)
- watermarkLabel->setVisible(info.watermark);
+ watermarkLabel->setVisible(info.watermark || info.sideWidget);
layoutInfo = info;
}
@@ -1233,10 +1274,17 @@ void QWizardPrivate::updateLayout()
titleFmt, subTitleFmt);
}
- if (info.watermark) {
- Q_ASSERT(page);
- watermarkLabel->setPixmap(page->pixmap(QWizard::WatermarkPixmap));
+ if (info.watermark || info.sideWidget) {
+ QPixmap pix;
+ if (info.watermark) {
+ if (page)
+ pix = page->pixmap(QWizard::WatermarkPixmap);
+ else
+ pix = q->pixmap(QWizard::WatermarkPixmap);
+ }
+ watermarkLabel->setPixmap(pix); // in case there is no watermark and we show the side widget we need to clear the watermark
}
+
if (info.title) {
Q_ASSERT(page);
titleLabel->setTextFormat(titleFmt);
@@ -1267,7 +1315,7 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
minimumSize.setWidth(headerWidget->maximumWidth());
maximumSize.setWidth(headerWidget->maximumWidth());
}
- if (info.watermark) {
+ if (info.watermark && !info.sideWidget) {
minimumSize.setHeight(mainLayout->totalSizeHint().height());
maximumSize.setHeight(mainLayout->totalSizeHint().height());
}
@@ -2149,7 +2197,7 @@ QWizard::~QWizard()
The ID is guaranteed to be larger than any other ID in the
QWizard so far.
- \sa setPage(), page()
+ \sa setPage(), page(), pageAdded()
*/
int QWizard::addPage(QWizardPage *page)
{
@@ -2166,7 +2214,10 @@ int QWizard::addPage(QWizardPage *page)
Adds the given \a page to the wizard with the given \a id.
- \sa addPage(), page()
+ \note Adding a page may influence the value of the startId property
+ in case it was not set explicitly.
+
+ \sa addPage(), page(), pageAdded()
*/
void QWizard::setPage(int theid, QWizardPage *page)
{
@@ -2210,12 +2261,19 @@ void QWizard::setPage(int theid, QWizardPage *page)
// hide new page and reset layout to old status
page->hide();
d->pageVBoxLayout->setEnabled(pageVBoxLayoutEnabled);
+
+ if (!d->startSetByUser && d->pageMap.constBegin().key() == theid)
+ d->start = theid;
+ emit pageAdded(theid);
}
/*!
Removes the page with the given \a id. cleanupPage() will be called if necessary.
+
+ \note Removing a page may influence the value of the startId property.
+
\since 4.5
- \sa addPage(), setPage()
+ \sa addPage(), setPage(), pageRemoved(), startId()
*/
void QWizard::removePage(int id)
{
@@ -2223,8 +2281,24 @@ void QWizard::removePage(int id)
QWizardPage *removedPage = 0;
- if (d->start == id)
- d->start = -1;
+ // update startItem accordingly
+ if (d->pageMap.count() > 0) { // only if we have any pages
+ if (d->start == id) {
+ const int firstId = d->pageMap.constBegin().key();
+ if (firstId == id) {
+ if (d->pageMap.count() > 1)
+ d->start = (++d->pageMap.constBegin()).key(); // secondId
+ else
+ d->start = -1; // removing the last page
+ } else { // startSetByUser has to be "true" here
+ d->start = firstId;
+ }
+ d->startSetByUser = false;
+ }
+ }
+
+ if (d->pageMap.contains(id))
+ emit pageRemoved(id);
if (!d->history.contains(id)) {
// Case 1: removing a page not in the history
@@ -2334,21 +2408,27 @@ QList<int> QWizard::pageIds() const
void QWizard::setStartId(int theid)
{
Q_D(QWizard);
- if (!d->pageMap.contains(theid)) {
- qWarning("QWizard::setStartId: Invalid page ID %d", theid);
+ int newStart = theid;
+ if (theid == -1)
+ newStart = d->pageMap.count() ? d->pageMap.constBegin().key() : -1;
+
+ if (d->start == newStart) {
+ d->startSetByUser = theid != -1;
return;
}
- d->start = theid;
+
+ if (!d->pageMap.contains(newStart)) {
+ qWarning("QWizard::setStartId: Invalid page ID %d", newStart);
+ return;
+ }
+ d->start = newStart;
+ d->startSetByUser = theid != -1;
}
int QWizard::startId() const
{
Q_D(const QWizard);
- if (d->start != -1)
- return d->start;
- if (!d->pageMap.isEmpty())
- return d->pageMap.constBegin().key();
- return -1;
+ return d->start;
}
/*!
@@ -2825,6 +2905,55 @@ void QWizard::setDefaultProperty(const char *className, const char *property,
}
/*!
+ \since 4.7
+
+ Sets the given \a widget to be shown on the left side of the wizard.
+ For styles which use the WatermarkPixmap (ClassicStyle and ModernStyle)
+ the side widget is displayed on top of the watermark, for other styles
+ or when the watermark is not provided the side widget is displayed
+ on the left side of the wizard.
+
+ Passing 0 shows no side widget.
+
+ When the \a widget is not 0 the wizard reparents it.
+
+ Any previous side widget is hidden.
+
+ You may call setSideWidget() with the same widget at different
+ times.
+
+ All widgets set here will be deleted by the wizard when it is
+ destroyed unless you separately reparent the widget after setting
+ some other side widget (or 0).
+
+ By default, no side widget is present.
+*/
+void QWizard::setSideWidget(QWidget *widget)
+{
+ Q_D(QWizard);
+
+ d->sideWidget = widget;
+ if (d->watermarkLabel) {
+ d->watermarkLabel->setSideWidget(widget);
+ d->updateLayout();
+ }
+}
+
+/*!
+ \since 4.7
+
+ Returns the widget on the left side of the wizard or 0.
+
+ By default, no side widget is present.
+*/
+QWidget *QWizard::sideWidget() const
+{
+ Q_D(const QWizard);
+
+ return d->sideWidget;
+}
+
+/*!
\reimp
*/
void QWizard::setVisible(bool visible)
@@ -2878,6 +3007,28 @@ QSize QWizard::sizeHint() const
*/
/*!
+ \fn void QWizard::pageAdded(int id)
+
+ \since 4.7
+
+ This signal is emitted whenever a page is added to the
+ wizard. The page's \a id is passed as parameter.
+
+ \sa addPage(), setPage(), startId()
+*/
+
+/*!
+ \fn void QWizard::pageRemoved(int id)
+
+ \since 4.7
+
+ This signal is emitted whenever a page is removed from the
+ wizard. The page's \a id is passed as parameter.
+
+ \sa removePage(), startId()
+*/
+
+/*!
\fn void QWizard::helpRequested()
This signal is emitted when the user clicks the \gui Help button.
diff --git a/src/gui/dialogs/qwizard.h b/src/gui/dialogs/qwizard.h
index 58b13fe3a6..b146147453 100644
--- a/src/gui/dialogs/qwizard.h
+++ b/src/gui/dialogs/qwizard.h
@@ -165,6 +165,9 @@ public:
void setPixmap(WizardPixmap which, const QPixmap &pixmap);
QPixmap pixmap(WizardPixmap which) const;
+ void setSideWidget(QWidget *widget);
+ QWidget *sideWidget() const;
+
void setDefaultProperty(const char *className, const char *property,
const char *changedSignal);
@@ -175,6 +178,8 @@ Q_SIGNALS:
void currentIdChanged(int id);
void helpRequested();
void customButtonClicked(int which);
+ void pageAdded(int id);
+ void pageRemoved(int id);
public Q_SLOTS:
void back();
diff --git a/src/gui/dialogs/qwizard_win_p.h b/src/gui/dialogs/qwizard_win_p.h
index fe01587eb1..5f3b6c2bcb 100644
--- a/src/gui/dialogs/qwizard_win_p.h
+++ b/src/gui/dialogs/qwizard_win_p.h
@@ -82,7 +82,6 @@ class QWizard;
class QVistaHelper : public QObject
{
- Q_OBJECT
public:
QVistaHelper(QWizard *wizard);
~QVistaHelper();
diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri
index bf25438efc..c6c020d307 100644
--- a/src/gui/egl/egl.pri
+++ b/src/gui/egl/egl.pri
@@ -3,6 +3,7 @@ contains(QT_CONFIG, egl): {
HEADERS += \
egl/qegl_p.h \
+ egl/qeglcontext_p.h \
egl/qeglproperties_p.h
SOURCES += \
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
index ee192169d9..bf9f530f32 100644
--- a/src/gui/egl/qegl.cpp
+++ b/src/gui/egl/qegl.cpp
@@ -43,7 +43,10 @@
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
#include <QtCore/qdebug.h>
+
#include "qegl_p.h"
+#include "qeglcontext_p.h"
+
QT_BEGIN_NAMESPACE
@@ -54,12 +57,10 @@ QT_BEGIN_NAMESPACE
static QEglContext * volatile currentGLContext = 0;
static QEglContext * volatile currentVGContext = 0;
-EGLDisplay QEglContext::dpy = EGL_NO_DISPLAY;
-
QEglContext::QEglContext()
: apiType(QEgl::OpenGL)
, ctx(EGL_NO_CONTEXT)
- , cfg(0)
+ , cfg(QEGL_NO_CONFIG)
, currentSurface(EGL_NO_SURFACE)
, current(false)
, ownsContext(true)
@@ -87,15 +88,177 @@ bool QEglContext::isCurrent() const
return current;
}
+EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options)
+{
+ if ( (devType != QInternal::Pixmap) && ((options & Renderable) == 0))
+ qWarning("QEgl::defaultConfig() - Only configs for pixmaps make sense to be read-only!");
+
+ EGLConfig* targetConfig = 0;
+
+ static EGLConfig defaultVGConfigs[] = {
+ QEGL_NO_CONFIG, // 0 Window Renderable Translucent
+ QEGL_NO_CONFIG, // 1 Window Renderable Opaque
+ QEGL_NO_CONFIG, // 2 Pixmap Renderable Translucent
+ QEGL_NO_CONFIG, // 3 Pixmap Renderable Opaque
+ QEGL_NO_CONFIG, // 4 Pixmap ReadOnly Translucent
+ QEGL_NO_CONFIG // 5 Pixmap ReadOnly Opaque
+ };
+ if (api == OpenVG) {
+ if (devType == QInternal::Widget) {
+ if (options & Translucent)
+ targetConfig = &(defaultVGConfigs[0]);
+ else
+ targetConfig = &(defaultVGConfigs[1]);
+ } else if (devType == QInternal::Pixmap) {
+ if (options & Renderable) {
+ if (options & Translucent)
+ targetConfig = &(defaultVGConfigs[2]);
+ else // Opaque
+ targetConfig = &(defaultVGConfigs[3]);
+ } else { // Read-only
+ if (options & Translucent)
+ targetConfig = &(defaultVGConfigs[4]);
+ else // Opaque
+ targetConfig = &(defaultVGConfigs[5]);
+ }
+ }
+ }
+
+
+ static EGLConfig defaultGLConfigs[] = {
+ QEGL_NO_CONFIG, // 0 Window Renderable Translucent
+ QEGL_NO_CONFIG, // 1 Window Renderable Opaque
+ QEGL_NO_CONFIG, // 2 PBuffer Renderable Translucent
+ QEGL_NO_CONFIG, // 3 PBuffer Renderable Opaque
+ QEGL_NO_CONFIG, // 4 Pixmap Renderable Translucent
+ QEGL_NO_CONFIG, // 5 Pixmap Renderable Opaque
+ QEGL_NO_CONFIG, // 6 Pixmap ReadOnly Translucent
+ QEGL_NO_CONFIG // 7 Pixmap ReadOnly Opaque
+ };
+ if (api == OpenGL) {
+ if (devType == QInternal::Widget) {
+ if (options & Translucent)
+ targetConfig = &(defaultGLConfigs[0]);
+ else // Opaque
+ targetConfig = &(defaultGLConfigs[1]);
+ } else if (devType == QInternal::Pbuffer) {
+ if (options & Translucent)
+ targetConfig = &(defaultGLConfigs[2]);
+ else // Opaque
+ targetConfig = &(defaultGLConfigs[3]);
+ } else if (devType == QInternal::Pixmap) {
+ if (options & Renderable) {
+ if (options & Translucent)
+ targetConfig = &(defaultGLConfigs[4]);
+ else // Opaque
+ targetConfig = &(defaultGLConfigs[5]);
+ } else { // ReadOnly
+ if (options & Translucent)
+ targetConfig = &(defaultGLConfigs[6]);
+ else // Opaque
+ targetConfig = &(defaultGLConfigs[7]);
+ }
+ }
+ }
+
+ if (!targetConfig) {
+ qWarning("QEgl::defaultConfig() - No default config for device/api/options combo");
+ return QEGL_NO_CONFIG;
+ }
+ if (*targetConfig != QEGL_NO_CONFIG)
+ return *targetConfig;
+
+
+ // We haven't found an EGL config for the target config yet, so do it now:
+
+
+ // Allow overriding from an environment variable:
+ QByteArray configId;
+ if (api == OpenVG)
+ configId = qgetenv("QT_VG_EGL_CONFIG");
+ else
+ configId = qgetenv("QT_GL_EGL_CONFIG");
+ if (!configId.isEmpty()) {
+ // Overriden, so get the EGLConfig for the specified config ID:
+ EGLint properties[] = {
+ EGL_CONFIG_ID, (EGLint)configId.toInt(),
+ EGL_NONE
+ };
+ EGLint configCount = 0;
+ eglChooseConfig(display(), properties, targetConfig, 1, &configCount);
+ if (configCount > 0)
+ return *targetConfig;
+ qWarning() << "QEgl::defaultConfig() -" << configId << "appears to be invalid";
+ }
+
+ QEglProperties configAttribs;
+ configAttribs.setRenderableType(api);
+
+ EGLint surfaceType;
+ switch (devType) {
+ case QInternal::Widget:
+ surfaceType = EGL_WINDOW_BIT;
+ break;
+ case QInternal::Pixmap:
+ surfaceType = EGL_PIXMAP_BIT;
+ break;
+ case QInternal::Pbuffer:
+ surfaceType = EGL_PBUFFER_BIT;
+ break;
+ default:
+ qWarning("QEgl::defaultConfig() - Can't create EGL surface for %d device type", devType);
+ return QEGL_NO_CONFIG;
+ };
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ // For OpenVG, we try to create a surface using a pre-multiplied format if
+ // the surface needs to have an alpha channel:
+ if (api == OpenVG && (options & Translucent))
+ surfaceType |= EGL_VG_ALPHA_FORMAT_PRE_BIT;
+#endif
+ configAttribs.setValue(EGL_SURFACE_TYPE, surfaceType);
+
+#ifdef EGL_BIND_TO_TEXTURE_RGBA
+ if (devType == QInternal::Pixmap || devType == QInternal::Pbuffer) {
+ if (options & Translucent)
+ configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
+ else
+ configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
+ }
+#endif
+
+ // Add paint engine requirements
+ if (api == OpenVG) {
+#ifndef QVG_SCISSOR_CLIP
+ configAttribs.setValue(EGL_ALPHA_MASK_SIZE, 1);
+#endif
+ } else {
+ // Both OpenGL paint engines need to have stencil and sample buffers
+ configAttribs.setValue(EGL_STENCIL_SIZE, 1);
+ configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
+#ifndef QT_OPENGL_ES_2
+ // Aditionally, the GL1 engine likes to have a depth buffer for clipping
+ configAttribs.setValue(EGL_DEPTH_SIZE, 1);
+#endif
+ }
+
+ if (options & Translucent)
+ configAttribs.setValue(EGL_ALPHA_SIZE, 1);
+
+ *targetConfig = chooseConfig(&configAttribs, QEgl::BestPixelFormat);
+ return *targetConfig;
+}
+
+
// Choose a configuration that matches "properties".
-bool QEglContext::chooseConfig
- (const QEglProperties& properties, QEgl::PixelFormatMatch match)
+EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match)
{
- QEglProperties props(properties);
+ QEglProperties props(*properties);
+ EGLConfig cfg = QEGL_NO_CONFIG;
do {
// Get the number of matching configurations for this set of properties.
EGLint matching = 0;
- if (!eglChooseConfig(display(), props.properties(), 0, 0, &matching) || !matching)
+ EGLDisplay dpy = QEgl::display();
+ if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching)
continue;
// If we want the best pixel format, then return the first
@@ -104,7 +267,7 @@ bool QEglContext::chooseConfig
eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
if (matching < 1)
continue;
- return true;
+ return cfg;
}
// Fetch all of the matching configurations and find the
@@ -125,7 +288,7 @@ bool QEglContext::chooseConfig
alpha == props.value(EGL_ALPHA_SIZE))) {
cfg = configs[index];
delete [] configs;
- return true;
+ return cfg;
}
}
delete [] configs;
@@ -142,19 +305,38 @@ bool QEglContext::chooseConfig
qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
qWarning() << "Requested:" << props.toString();
qWarning() << "Available:";
- dumpAllConfigs();
+ QEgl::dumpAllConfigs();
}
- return false;
+ return QEGL_NO_CONFIG;
}
+bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match)
+{
+ cfg = QEgl::chooseConfig(&properties, match);
+ return cfg != QEGL_NO_CONFIG;
+}
+
+EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties *properties)
+{
+ return QEgl::createSurface(device, cfg, properties);
+}
+
+
// Create the EGLContext.
bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties)
{
// We need to select the correct API before calling eglCreateContext().
+#ifdef QT_OPENGL_ES
#ifdef EGL_OPENGL_ES_API
if (apiType == QEgl::OpenGL)
eglBindAPI(EGL_OPENGL_ES_API);
#endif
+#else
+#ifdef EGL_OPENGL_API
+ if (apiType == QEgl::OpenGL)
+ eglBindAPI(EGL_OPENGL_API);
+#endif
+#endif //defined(QT_OPENGL_ES)
#ifdef EGL_OPENVG_API
if (apiType == QEgl::OpenVG)
eglBindAPI(EGL_OPENVG_API);
@@ -164,7 +346,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties
QEglProperties contextProps;
if (properties)
contextProps = *properties;
-#if defined(QT_OPENGL_ES_2)
+#ifdef QT_OPENGL_ES_2
if (apiType == QEgl::OpenGL)
contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
#endif
@@ -172,9 +354,9 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties
if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
shareContext = 0;
if (shareContext) {
- ctx = eglCreateContext(display(), cfg, shareContext->ctx, contextProps.properties());
+ ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties());
if (ctx == EGL_NO_CONTEXT) {
- qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
+ qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString();
shareContext = 0;
} else {
sharing = true;
@@ -183,7 +365,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties
if (ctx == EGL_NO_CONTEXT) {
ctx = eglCreateContext(display(), cfg, 0, contextProps.properties());
if (ctx == EGL_NO_CONTEXT) {
- qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
+ qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString();
return false;
}
}
@@ -217,6 +399,11 @@ bool QEglContext::makeCurrent(EGLSurface surface)
return false;
}
+ if (surface == EGL_NO_SURFACE) {
+ qWarning() << "QEglContext::makeCurrent(): Cannot make invalid surface current";
+ return false;
+ }
+
// If lazyDoneCurrent() was called on the surface, then we may be able
// to assume that it is still current within the thread.
if (surface == currentSurface && currentContext(apiType) == this) {
@@ -240,9 +427,9 @@ bool QEglContext::makeCurrent(EGLSurface surface)
eglBindAPI(EGL_OPENVG_API);
#endif
- bool ok = eglMakeCurrent(display(), surface, surface, ctx);
+ bool ok = eglMakeCurrent(QEgl::display(), surface, surface, ctx);
if (!ok)
- qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError());
+ qWarning() << "QEglContext::makeCurrent(" << surface << "):" << QEgl::errorString();
return ok;
}
@@ -269,9 +456,9 @@ bool QEglContext::doneCurrent()
eglBindAPI(EGL_OPENVG_API);
#endif
- bool ok = eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ bool ok = eglMakeCurrent(QEgl::display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ok)
- qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError());
+ qWarning() << "QEglContext::doneCurrent():" << QEgl::errorString();
return ok;
}
@@ -291,108 +478,134 @@ bool QEglContext::swapBuffers(EGLSurface surface)
if(ctx == EGL_NO_CONTEXT)
return false;
- bool ok = eglSwapBuffers(display(), surface);
+ bool ok = eglSwapBuffers(QEgl::display(), surface);
if (!ok)
- qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError());
+ qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString();
return ok;
}
-// Wait for native rendering operations to complete before starting
-// to use OpenGL/OpenVG operations.
-void QEglContext::waitNative()
+int QEglContext::configAttrib(int name) const
{
-#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 value of a configuration attribute.
-bool QEglContext::configAttrib(int name, EGLint *value) const
-{
- return eglGetConfigAttrib(display(), cfg, name, value);
+ EGLint value;
+ EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value);
+ if (success)
+ return value;
+ else
+ return EGL_DONT_CARE;
}
-void QEglContext::clearError()
-{
- eglGetError();
-}
+typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*);
+typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
-EGLint QEglContext::error()
-{
- return eglGetError();
-}
+// Defined in qegl.cpp:
+static _eglCreateImageKHR qt_eglCreateImageKHR = 0;
+static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0;
-// 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(display(), cfg, name, &value))
- props.setValue(name, value);
- }
- eglGetError(); // Clear the error state.
- return props;
-}
-EGLDisplay QEglContext::display()
+EGLDisplay QEgl::display()
{
+ static EGLDisplay dpy = EGL_NO_DISPLAY;
static bool openedDisplay = false;
if (!openedDisplay) {
dpy = eglGetDisplay(nativeDisplay());
openedDisplay = true;
if (dpy == EGL_NO_DISPLAY) {
- qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY");
+ qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY");
dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
}
if (dpy == EGL_NO_DISPLAY) {
- qWarning("QEglContext::display(): Can't even open the default display");
+ qWarning("QEgl::display(): Can't even open the default display");
return EGL_NO_DISPLAY;
}
if (!eglInitialize(dpy, NULL, NULL)) {
- qWarning() << "QEglContext::display(): Cannot initialize EGL display:" << errorString(eglGetError());
+ qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString();
return EGL_NO_DISPLAY;
}
+
+ // Resolve the egl extension function pointers:
+#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
+ if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) {
+ qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
+ qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
+ }
+#endif
}
return dpy;
}
-#if !defined(Q_WS_X11) && !defined(Q_WS_WINCE) // WinCE & X11 implement this properly
-EGLNativeDisplayType QEglContext::nativeDisplay()
+EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
{
- return EGL_DEFAULT_DISPLAY;
+ if (qt_eglCreateImageKHR)
+ return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
+
+ QEgl::display(); // Initialises function pointers
+ if (qt_eglCreateImageKHR)
+ return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
+
+ qWarning("QEgl::eglCreateImageKHR() called but EGL_KHR_image(_base) extension not present");
+ return 0;
+}
+
+EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+{
+ if (qt_eglDestroyImageKHR)
+ return qt_eglDestroyImageKHR(dpy, img);
+
+ QEgl::display(); // Initialises function pointers
+ if (qt_eglDestroyImageKHR)
+ return qt_eglDestroyImageKHR(dpy, img);
+
+ qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present");
+ return 0;
+}
+
+
+#ifndef Q_WS_X11
+EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, 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 = nativePixmap(static_cast<QPixmap *>(device));
+ ok = (pixmapDrawable != 0);
+ } else if (devType == QInternal::Widget) {
+ windowDrawable = nativeWindow(static_cast<QWidget *>(device));
+ ok = (windowDrawable != 0);
+ } else {
+ ok = false;
+ }
+ if (!ok) {
+ qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
+ return EGL_NO_SURFACE;
+ }
+
+ // Create the EGL surface to draw into, based on the native drawable.
+ const int *props;
+ if (properties)
+ props = properties->properties();
+ else
+ props = 0;
+ EGLSurface surf;
+ if (devType == QInternal::Widget)
+ surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props);
+ else
+ surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props);
+ if (surf == EGL_NO_SURFACE) {
+ qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
+ }
+ return surf;
}
#endif
+
// Return the error string associated with a specific code.
-QString QEglContext::errorString(EGLint code)
+QString QEgl::errorString(EGLint code)
{
static const char * const errors[] = {
"Success (0x3000)", // No tr
@@ -419,7 +632,7 @@ QString QEglContext::errorString(EGLint code)
}
// Dump all of the EGL configurations supported by the system.
-void QEglContext::dumpAllConfigs()
+void QEgl::dumpAllConfigs()
{
QEglProperties props;
EGLint count = 0;
@@ -428,23 +641,23 @@ void QEglContext::dumpAllConfigs()
EGLConfig *configs = new EGLConfig [count];
eglGetConfigs(display(), configs, count, &count);
for (EGLint index = 0; index < count; ++index) {
- props = configProperties(configs[index]);
+ props = QEglProperties(configs[index]);
qWarning() << props.toString();
}
delete [] configs;
}
-QString QEglContext::extensions()
+QString QEgl::extensions()
{
- const char* exts = eglQueryString(QEglContext::display(), EGL_EXTENSIONS);
+ const char* exts = eglQueryString(QEgl::display(), EGL_EXTENSIONS);
return QString(QLatin1String(exts));
}
-bool QEglContext::hasExtension(const char* extensionName)
+bool QEgl::hasExtension(const char* extensionName)
{
QList<QByteArray> extensions =
QByteArray(reinterpret_cast<const char *>
- (eglQueryString(QEglContext::display(), EGL_EXTENSIONS))).split(' ');
+ (eglQueryString(QEgl::display(), EGL_EXTENSIONS))).split(' ');
return extensions.contains(extensionName);
}
diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h
index e08e1dd18d..6c562ef5c6 100644
--- a/src/gui/egl/qegl_p.h
+++ b/src/gui/egl/qegl_p.h
@@ -53,13 +53,58 @@
// We mean it.
//
-#include <QtCore/qsize.h>
-#include <QtGui/qimage.h>
+QT_BEGIN_INCLUDE_NAMESPACE
-#include <private/qeglproperties_p.h>
+#ifndef QT_NO_EGL
+#if defined(QT_OPENGL_ES_2)
+# include <GLES2/gl2.h>
+#endif
-QT_BEGIN_INCLUDE_NAMESPACE
+#if defined(QT_GLES_EGL)
+# include <GLES/egl.h>
+#else
+# include <EGL/egl.h>
+#endif
+#else
+
+//types from egltypes.h for compiling stub without EGL headers
+typedef int EGLBoolean;
+typedef int EGLint;
+typedef int EGLenum;
+typedef int NativeDisplayType;
+typedef void* NativeWindowType;
+typedef void* NativePixmapType;
+typedef int EGLDisplay;
+typedef int EGLConfig;
+typedef int EGLSurface;
+typedef int EGLContext;
+typedef int EGLClientBuffer;
+#define EGL_NONE 0x3038 /* Attrib list terminator */
+
+#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
+#undef Unsorted
+#undef GrayScale
+#endif
+// Internally we use the EGL-prefixed native types which are used in EGL >= 1.3.
+// For older versions of EGL, we have to define these types ourselves here:
#if !defined(EGL_VERSION_1_3) && !defined(QEGL_NATIVE_TYPES_DEFINED)
#undef EGLNativeWindowType
#undef EGLNativePixmapType
@@ -69,74 +114,118 @@ typedef NativePixmapType EGLNativePixmapType;
typedef NativeDisplayType EGLNativeDisplayType;
#define QEGL_NATIVE_TYPES_DEFINED 1
#endif
+
QT_END_INCLUDE_NAMESPACE
+#include <QtGui/qpaintdevice.h>
+#include <QFlags>
+
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QEglContext
-{
-public:
- QEglContext();
- ~QEglContext();
+#define QEGL_NO_CONFIG ((EGLConfig)-1)
- bool isValid() const;
- bool isCurrent() const;
- bool isSharing() const { return sharing; }
+#ifndef EGLAPIENTRY
+#define EGLAPIENTRY
+#endif
- QEgl::API api() const { return apiType; }
- void setApi(QEgl::API api) { apiType = api; }
+// Try to get some info to debug the symbian build failues:
+#ifdef Q_OS_SYMBIAN
- bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
- bool createContext(QEglContext *shareContext = 0, const QEglProperties *properties = 0);
- void destroyContext();
- EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0);
- void destroySurface(EGLSurface surface);
+#ifdef EGL_KHR_image
+#warning "EGL_KHR_image is defined"
+#else
+#warning "EGL_KHR_image is NOT defined"
+#endif
- bool makeCurrent(EGLSurface surface);
- bool doneCurrent();
- bool lazyDoneCurrent();
- bool swapBuffers(EGLSurface surface);
+#ifdef EGL_KHR_image_base
+#warning "EGL_KHR_image_base is defined"
+#else
+#warning "EGL_KHR_image_base is NOT defined"
+#endif
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+#warning "EGL_EGLEXT_PROTOTYPES is defined"
+#else
+#warning "EGL_EGLEXT_PROTOTYPES NOT not defined"
+#endif
- void waitNative();
- void waitClient();
+#endif
- bool configAttrib(int name, EGLint *value) const;
- static void clearError();
- static EGLint error();
- static QString errorString(EGLint code);
+// Declare/define the bits of EGL_KHR_image_base we need:
+#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base)
+typedef void *EGLImageKHR;
+#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
+#define EGL_IMAGE_PRESERVED_KHR 0x30D2
+#define EGL_KHR_image_base
+#endif
- static EGLDisplay display();
+#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_pixmap)
+#define EGL_NATIVE_PIXMAP_KHR 0x30B0
+#define EGL_KHR_image_pixmap
+#endif
- EGLContext context() const { return ctx; }
- void setContext(EGLContext context) { ctx = context; ownsContext = false;}
- EGLConfig config() const { return cfg; }
- void setConfig(EGLConfig config) { cfg = config; }
+class QEglProperties;
+
+namespace QEgl {
+ enum API
+ {
+ OpenGL,
+ OpenVG
+ };
+
+ enum PixelFormatMatch
+ {
+ ExactPixelFormat,
+ BestPixelFormat
+ };
+
+ enum ConfigOption
+ {
+ NoOptions = 0,
+ Translucent = 0x01,
+ Renderable = 0x02 // Config will be compatable with the paint engines (VG or GL)
+ };
+ Q_DECLARE_FLAGS(ConfigOptions, ConfigOption)
+
+ // Most of the time we use the same config for things like widgets & pixmaps, so rather than
+ // go through the eglChooseConfig loop every time, we use defaultConfig, which will return
+ // the config for a particular device/api/option combo. This function assumes that once a
+ // config is chosen for a particular combo, it's safe to always use that combo.
+ Q_GUI_EXPORT EGLConfig defaultConfig(int devType, API api, ConfigOptions options);
+
+ Q_GUI_EXPORT EGLConfig chooseConfig(const QEglProperties* configAttribs, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
+ Q_GUI_EXPORT EGLSurface createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *surfaceAttribs = 0);
+
+ Q_GUI_EXPORT void dumpAllConfigs();
+
+#ifdef QT_NO_EGL
+ Q_GUI_EXPORT QString errorString(EGLint code = 0);
+#else
+ Q_GUI_EXPORT QString errorString(EGLint code = eglGetError());
+#endif
- QEglProperties configProperties(EGLConfig cfg = 0) const;
+ Q_GUI_EXPORT QString extensions();
+ Q_GUI_EXPORT bool hasExtension(const char* extensionName);
- void dumpAllConfigs();
+ Q_GUI_EXPORT EGLDisplay display();
- static QString extensions();
- static bool hasExtension(const char* extensionName);
+ Q_GUI_EXPORT EGLNativeDisplayType nativeDisplay();
+ Q_GUI_EXPORT EGLNativeWindowType nativeWindow(QWidget*);
+ Q_GUI_EXPORT EGLNativePixmapType nativePixmap(QPixmap*);
-private:
- QEgl::API apiType;
- EGLContext ctx;
- EGLConfig cfg;
- EGLSurface currentSurface;
- bool current;
- bool ownsContext;
- bool sharing;
+ // Extension functions
+ Q_GUI_EXPORT EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+ Q_GUI_EXPORT EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img);
- static EGLDisplay dpy;
- static EGLNativeDisplayType nativeDisplay();
+#ifdef Q_WS_X11
+ Q_GUI_EXPORT VisualID getCompatibleVisualId(EGLConfig config);
+#endif
+}
- static QEglContext *currentContext(QEgl::API api);
- static void setCurrentContext(QEgl::API api, QEglContext *context);
-};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QEgl::ConfigOptions)
QT_END_NAMESPACE
-#endif // QEGL_P_H
+#endif //QEGL_P_H
diff --git a/src/gui/egl/qegl_qws.cpp b/src/gui/egl/qegl_qws.cpp
index 2a61beb9c8..56383a5f1a 100644
--- a/src/gui/egl/qegl_qws.cpp
+++ b/src/gui/egl/qegl_qws.cpp
@@ -42,7 +42,9 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
+
#include "qegl_p.h"
+#include "qeglcontext_p.h"
#if !defined(QT_NO_EGL)
@@ -53,17 +55,6 @@
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.
-EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
-{
- Q_UNUSED(device);
- Q_UNUSED(properties);
- return EGL_NO_SURFACE;
-}
-
static QScreen *screenForDevice(QPaintDevice *device)
{
QScreen *screen = qt_screen;
@@ -101,6 +92,23 @@ void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
setPixelFormat(screen->pixelFormat());
}
+EGLNativeDisplayType QEgl::nativeDisplay()
+{
+ return EGL_DEFAULT_DISPLAY;
+}
+
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
+{
+ return (EGLNativeWindowType)(widget->winId()); // Might work
+}
+
+EGLNativePixmapType QEgl::nativePixmap(QPixmap*)
+{
+ qWarning("QEgl: EGL pixmap surfaces not supported on QWS");
+ return (EGLNativePixmapType)0;
+}
+
+
QT_END_NAMESPACE
#endif // !QT_NO_EGL
diff --git a/src/gui/egl/qegl_stub.cpp b/src/gui/egl/qegl_stub.cpp
index 0363103987..0bd3451e38 100644
--- a/src/gui/egl/qegl_stub.cpp
+++ b/src/gui/egl/qegl_stub.cpp
@@ -45,6 +45,8 @@
#include <QtCore/qdebug.h>
#include "qegl_p.h"
+#include "qeglcontext_p.h"
+
QT_BEGIN_NAMESPACE
@@ -55,12 +57,10 @@ static void noegl(const char *fn)
#define NOEGL noegl(__FUNCTION__);
-EGLDisplay QEglContext::dpy = 0;
-
QEglContext::QEglContext()
: apiType(QEgl::OpenGL)
, ctx(0)
- , cfg(0)
+ , cfg(QEGL_NO_CONFIG)
, currentSurface(0)
, current(false)
, ownsContext(true)
@@ -86,6 +86,25 @@ bool QEglContext::isCurrent() const
return false;
}
+EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options)
+{
+ Q_UNUSED(devType)
+ Q_UNUSED(api)
+ Q_UNUSED(options)
+ NOEGL
+ return QEGL_NO_CONFIG;
+}
+
+
+// Choose a configuration that matches "properties".
+EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match)
+{
+ Q_UNUSED(properties)
+ Q_UNUSED(match)
+ NOEGL
+ return QEGL_NO_CONFIG;
+}
+
bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match)
{
Q_UNUSED(properties)
@@ -157,34 +176,61 @@ bool QEglContext::swapBuffers(EGLSurface surface)
return false;
}
-bool QEglContext::configAttrib(int name, EGLint *value) const
+int QEglContext::configAttrib(int name) const
{
Q_UNUSED(name)
- Q_UNUSED(value)
NOEGL
- return false;
+ return 0;
}
-void QEglContext::clearError()
+typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*);
+typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
+
+// Defined in qegl.cpp:
+static _eglCreateImageKHR qt_eglCreateImageKHR = 0;
+static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0;
+
+
+EGLDisplay QEgl::display()
{
NOEGL
- return;
+ return 0;
}
-EGLint QEglContext::error()
+EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
{
+ Q_UNUSED(dpy)
+ Q_UNUSED(ctx)
+ Q_UNUSED(target)
+ Q_UNUSED(buffer)
+ Q_UNUSED(attrib_list)
NOEGL
return 0;
}
-EGLDisplay QEglContext::display()
+EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
{
+ Q_UNUSED(dpy)
+ Q_UNUSED(img)
NOEGL
return 0;
}
+
+#ifndef Q_WS_X11
+EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties)
+{
+ Q_UNUSED(device)
+ Q_UNUSED(cfg)
+ Q_UNUSED(properties)
+ NOEGL
+ return 0;
+}
+#endif
+
+
// Return the error string associated with a specific code.
-QString QEglContext::errorString(EGLint code)
+QString QEgl::errorString(EGLint code)
{
Q_UNUSED(code)
NOEGL
@@ -192,18 +238,18 @@ QString QEglContext::errorString(EGLint code)
}
// Dump all of the EGL configurations supported by the system.
-void QEglContext::dumpAllConfigs()
+void QEgl::dumpAllConfigs()
{
NOEGL
}
-QString QEglContext::extensions()
+QString QEgl::extensions()
{
NOEGL
return QString();
}
-bool QEglContext::hasExtension(const char* extensionName)
+bool QEgl::hasExtension(const char* extensionName)
{
Q_UNUSED(extensionName)
NOEGL
@@ -224,27 +270,23 @@ void QEglContext::setCurrentContext(QEgl::API api, QEglContext *context)
NOEGL
}
-EGLNativeDisplayType QEglContext::nativeDisplay()
+EGLNativeDisplayType QEgl::nativeDisplay()
{
NOEGL
return 0;
}
-void QEglContext::waitClient()
-{
- NOEGL
-}
-
-void QEglContext::waitNative()
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
{
+ Q_UNUSED(widget)
NOEGL
+ return (EGLNativeWindowType)0;
}
-QEglProperties QEglContext::configProperties(EGLConfig cfg) const
+EGLNativePixmapType QEgl::nativePixmap(QPixmap*)
{
- Q_UNUSED(cfg)
NOEGL
- return QEglProperties();
+ return (EGLNativePixmapType)0;
}
QT_END_NAMESPACE
diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp
index 5a010cd5d6..9744ed094a 100644
--- a/src/gui/egl/qegl_symbian.cpp
+++ b/src/gui/egl/qegl_symbian.cpp
@@ -42,48 +42,28 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
+
#include "qegl_p.h"
+#include "qeglcontext_p.h"
#include <coecntrl.h>
QT_BEGIN_NAMESPACE
-EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
+EGLNativeDisplayType QEgl::nativeDisplay()
{
- // 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 EGL_NO_SURFACE;
- }
+ return EGL_DEFAULT_DISPLAY;
+}
- // Create the EGL surface to draw into, based on the native drawable.
- const int *props;
- if (properties)
- props = properties->properties();
- else
- props = 0;
- EGLSurface surf;
- 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 surf;
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
+{
+ return (EGLNativeWindowType)(widget->winId()->DrawableWindow());
+}
+
+EGLNativePixmapType QEgl::nativePixmap(QPixmap*)
+{
+ qWarning("QEgl: EGL pixmap surfaces not implemented yet on Symbian");
+ return (EGLNativePixmapType)0;
}
// Set pixel format and other properties based on a paint device.
diff --git a/src/gui/egl/qegl_wince.cpp b/src/gui/egl/qegl_wince.cpp
index 87ec648e4c..2d08805f72 100644
--- a/src/gui/egl/qegl_wince.cpp
+++ b/src/gui/egl/qegl_wince.cpp
@@ -42,55 +42,18 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
+
#include "qegl_p.h"
+#include "qeglcontext_p.h"
#include <windows.h>
QT_BEGIN_NAMESPACE
-EGLSurface 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 EGL_NO_SURFACE;
- }
-
- // Create the EGL surface to draw into, based on the native drawable.
- const int *props;
- if (properties)
- props = properties->properties();
- else
- props = 0;
- EGLSurface surf;
- 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 surf;
-}
-
-EGLNativeDisplayType QEglContext::nativeDisplay()
+EGLNativeDisplayType QEgl::nativeDisplay()
{
HDC myDc = GetDC(0);
-
if (!myDc) {
qWarning("QEglContext::nativeDisplay(): WinCE display is not open");
return EGL_DEFAULT_DISPLAY;
@@ -98,6 +61,17 @@ EGLNativeDisplayType QEglContext::nativeDisplay()
return EGLNativeDisplayType(myDc);
}
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
+{
+ return (EGLNativeWindowType)(widget->winId());
+}
+
+EGLNativePixmapType QEgl::nativePixmap(QPixmap*)
+{
+ qWarning("QEgl: EGL pixmap surfaces not supported on WinCE");
+ return (EGLNativePixmapType)0;
+}
+
// Set pixel format and other properties based on a paint device.
void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
{
diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp
index 634ff13208..cb8dcda713 100644
--- a/src/gui/egl/qegl_x11.cpp
+++ b/src/gui/egl/qegl_x11.cpp
@@ -41,59 +41,24 @@
#include <QtCore/qdebug.h>
-#include <private/qt_x11_p.h>
+#include <QtGui/private/qt_x11_p.h>
#include <QtGui/qx11info_x11.h>
-#include <private/qpixmapdata_p.h>
-#include <private/qpixmap_x11_p.h>
+#include <QtGui/private/qpixmapdata_p.h>
+#include <QtGui/private/qpixmap_x11_p.h>
+#include <QtGui/private/qimagepixmapcleanuphooks_p.h>
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
-#include "qegl_p.h"
+#include <QtGui/qcolormap.h>
+#include "QtGui/private/qegl_p.h"
+#include "QtGui/private/qeglcontext_p.h"
QT_BEGIN_NAMESPACE
-EGLSurface 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 EGL_NO_SURFACE;
- }
- // Create the EGL surface to draw into, based on the native drawable.
- const int *props;
- if (properties)
- props = properties->properties();
- else
- props = 0;
- EGLSurface surf;
- 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 surf;
-}
-
-EGLNativeDisplayType QEglContext::nativeDisplay()
+EGLNativeDisplayType QEgl::nativeDisplay()
{
Display *xdpy = QX11Info::display();
if (!xdpy) {
@@ -103,6 +68,16 @@ EGLNativeDisplayType QEglContext::nativeDisplay()
return EGLNativeDisplayType(xdpy);
}
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
+{
+ return (EGLNativeWindowType)(widget->winId());
+}
+
+EGLNativePixmapType QEgl::nativePixmap(QPixmap* pixmap)
+{
+ return (EGLNativePixmapType)(pixmap->handle());
+}
+
static int countBits(unsigned long mask)
{
int count = 0;
@@ -153,4 +128,331 @@ void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
setVisualFormat(qt_x11Info(dev));
}
+//#define QT_DEBUG_X11_VISUAL_SELECTION 1
+
+VisualID QEgl::getCompatibleVisualId(EGLConfig config)
+{
+ VisualID visualId = 0;
+ EGLint eglValue = 0;
+
+ EGLint configRedSize = 0;
+ eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &configRedSize);
+
+ EGLint configGreenSize = 0;
+ eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &configGreenSize);
+
+ EGLint configBlueSize = 0;
+ eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &configBlueSize);
+
+ EGLint configAlphaSize = 0;
+ eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &configAlphaSize);
+
+ eglGetConfigAttrib(display(), config, EGL_CONFIG_ID, &eglValue);
+ int configId = eglValue;
+
+ // See if EGL provided a valid VisualID:
+ eglGetConfigAttrib(display(), config, EGL_NATIVE_VISUAL_ID, &eglValue);
+ visualId = (VisualID)eglValue;
+ if (visualId) {
+ // EGL has suggested a visual id, so get the rest of the visual info for that id:
+ XVisualInfo visualInfoTemplate;
+ memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
+ visualInfoTemplate.visualid = visualId;
+
+ XVisualInfo *chosenVisualInfo;
+ int matchingCount = 0;
+ chosenVisualInfo = XGetVisualInfo(X11->display, VisualIDMask, &visualInfoTemplate, &matchingCount);
+ if (chosenVisualInfo) {
+ int visualRedSize = countBits(chosenVisualInfo->red_mask);
+ int visualGreenSize = countBits(chosenVisualInfo->green_mask);
+ int visualBlueSize = countBits(chosenVisualInfo->blue_mask);
+ int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size
+
+#if !defined(QT_NO_XRENDER)
+ if (X11->use_xrender) {
+ // If we have XRender, actually check the visual supplied by EGL is ARGB
+ XRenderPictFormat *format;
+ format = XRenderFindVisualFormat(X11->display, chosenVisualInfo->visual);
+ if (format && (format->type == PictTypeDirect))
+ visualAlphaSize = countBits(format->direct.alphaMask);
+ }
+#endif
+
+ bool visualMatchesConfig = false;
+ if ( visualRedSize == configRedSize &&
+ visualGreenSize == configGreenSize &&
+ visualBlueSize == configBlueSize )
+ {
+ // We need XRender to check the alpha channel size of the visual. If we don't have
+ // the alpha size, we don't check it against the EGL config's alpha size.
+ if (visualAlphaSize >= 0)
+ visualMatchesConfig = visualAlphaSize == configAlphaSize;
+ else
+ visualMatchesConfig = true;
+ }
+
+ if (!visualMatchesConfig) {
+ if (visualAlphaSize >= 0) {
+ qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable",
+ (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize,
+ configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize);
+ } else {
+ qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable",
+ (int)visualId, visualRedSize, visualGreenSize, visualBlueSize,
+ configId, configRedSize, configGreenSize, configBlueSize);
+ }
+ visualId = 0;
+ }
+ } else {
+ qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
+ (int)visualId, configId);
+ visualId = 0;
+ }
+ XFree(chosenVisualInfo);
+ }
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+ else
+ qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
+#endif
+
+ if (visualId) {
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+ if (configAlphaSize > 0)
+ qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId);
+ else
+ qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId);
+#endif
+ return visualId;
+ }
+
+
+ // If EGL didn't give us a valid visual ID, try XRender
+#if !defined(QT_NO_XRENDER)
+ if (!visualId && X11->use_xrender) {
+ XVisualInfo visualInfoTemplate;
+ memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
+
+ visualInfoTemplate.c_class = TrueColor;
+
+ XVisualInfo *matchingVisuals;
+ int matchingCount = 0;
+ matchingVisuals = XGetVisualInfo(X11->display,
+ VisualClassMask,
+ &visualInfoTemplate,
+ &matchingCount);
+
+ for (int i = 0; i < matchingCount; ++i) {
+ XRenderPictFormat *format;
+ format = XRenderFindVisualFormat(X11->display, matchingVisuals[i].visual);
+
+ // Check the format for the visual matches the EGL config
+ if ( (countBits(format->direct.redMask) == configRedSize) &&
+ (countBits(format->direct.greenMask) == configGreenSize) &&
+ (countBits(format->direct.blueMask) == configBlueSize) &&
+ (countBits(format->direct.alphaMask) == configAlphaSize) )
+ {
+ visualId = matchingVisuals[i].visualid;
+ break;
+ }
+ }
+ if (matchingVisuals)
+ XFree(matchingVisuals);
+
+ }
+ if (visualId) {
+# ifdef QT_DEBUG_X11_VISUAL_SELECTION
+ if (configAlphaSize > 0)
+ qDebug("Using ARGB Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId);
+ else
+ qDebug("Using Opaque Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId);
+# endif // QT_DEBUG_X11_VISUAL_SELECTION
+ return visualId;
+ }
+# ifdef QT_DEBUG_X11_VISUAL_SELECTION
+ else
+ qDebug("Failed to find an XVisual which matches EGL config %d using XRender", configId);
+# endif // QT_DEBUG_X11_VISUAL_SELECTION
+
+#endif //!defined(QT_NO_XRENDER)
+
+
+ // Finally, if XRender also failed to find a visual (or isn't present), try to
+ // use XGetVisualInfo and only use the bit depths to match on:
+ if (!visualId) {
+ XVisualInfo visualInfoTemplate;
+ memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
+ XVisualInfo *matchingVisuals;
+ int matchingCount = 0;
+
+ visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
+ matchingVisuals = XGetVisualInfo(X11->display,
+ VisualDepthMask,
+ &visualInfoTemplate,
+ &matchingCount);
+ if (!matchingVisuals) {
+ // Try again without taking the alpha channel into account:
+ visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize;
+ matchingVisuals = XGetVisualInfo(X11->display,
+ VisualDepthMask,
+ &visualInfoTemplate,
+ &matchingCount);
+ }
+
+ if (matchingVisuals) {
+ visualId = matchingVisuals[0].visualid;
+ XFree(matchingVisuals);
+ }
+ }
+
+ if (visualId) {
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+ qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId);
+#endif
+ return visualId;
+ }
+
+ qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
+ return (VisualID)0;
+}
+
+void qt_set_winid_on_widget(QWidget* w, Qt::HANDLE id)
+{
+ w->create(id);
+}
+
+
+// NOTE: The X11 version of createSurface will re-create the native drawable if it's visual doesn't
+// match the one for the passed in EGLConfig
+EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEglProperties *unusedProperties)
+{
+ Q_UNUSED(unusedProperties);
+
+ int devType = device->devType();
+
+ if (devType == QInternal::Pbuffer) {
+ // TODO
+ return EGL_NO_SURFACE;
+ }
+
+ QX11PixmapData *x11PixmapData = 0;
+ if (devType == QInternal::Pixmap) {
+ QPixmapData *pmd = static_cast<QPixmap*>(device)->data_ptr().data();
+ if (pmd->classId() == QPixmapData::X11Class)
+ x11PixmapData = static_cast<QX11PixmapData*>(pmd);
+ else {
+ // TODO: Replace the pixmap's data with a new QX11PixmapData
+ qWarning("WARNING: Creating an EGL surface on a QPixmap is only supported for QX11PixmapData");
+ return EGL_NO_SURFACE;
+ }
+ } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
+ qWarning("WARNING: Creating an EGLSurface for device type %d isn't supported", devType);
+ return EGL_NO_SURFACE;
+ }
+
+ VisualID visualId = QEgl::getCompatibleVisualId(config);
+ EGLint alphaSize;
+ eglGetConfigAttrib(QEgl::display(), config, EGL_ALPHA_SIZE, &alphaSize);
+
+ if (devType == QInternal::Widget) {
+ QWidget *widget = static_cast<QWidget*>(device);
+
+ VisualID currentVisualId = 0;
+ if (widget->testAttribute(Qt::WA_WState_Created))
+ currentVisualId = XVisualIDFromVisual((Visual*)widget->x11Info().visual());
+
+ if (currentVisualId != visualId) {
+ // The window is either not created or has the wrong visual. Either way, we need
+ // to create a window with the correct visual and call create() on the widget:
+
+ bool visible = widget->isVisible();
+ if (visible)
+ widget->hide();
+
+ XVisualInfo visualInfo;
+ visualInfo.visualid = visualId;
+ {
+ XVisualInfo *visualInfoPtr;
+ int matchingCount = 0;
+ visualInfoPtr = XGetVisualInfo(widget->x11Info().display(), VisualIDMask,
+ &visualInfo, &matchingCount);
+ Q_ASSERT(visualInfoPtr); // visualId really should be valid!
+ visualInfo = *visualInfoPtr;
+ XFree(visualInfoPtr);
+ }
+
+ Window parentWindow = RootWindow(widget->x11Info().display(), widget->x11Info().screen());
+ if (widget->parentWidget())
+ parentWindow = widget->parentWidget()->winId();
+
+ XSetWindowAttributes windowAttribs;
+ QColormap colmap = QColormap::instance(widget->x11Info().screen());
+ windowAttribs.background_pixel = colmap.pixel(widget->palette().color(widget->backgroundRole()));
+ windowAttribs.border_pixel = colmap.pixel(Qt::black);
+
+ unsigned int valueMask = CWBackPixel|CWBorderPixel;
+ if (alphaSize > 0) {
+ windowAttribs.colormap = XCreateColormap(widget->x11Info().display(), parentWindow,
+ visualInfo.visual, AllocNone);
+ valueMask |= CWColormap;
+ }
+
+ Window window = XCreateWindow(widget->x11Info().display(), parentWindow,
+ widget->x(), widget->y(), widget->width(), widget->height(),
+ 0, visualInfo.depth, InputOutput, visualInfo.visual,
+ valueMask, &windowAttribs);
+
+ // This is a nasty hack to get round the fact that we can't be a friend of QWidget:
+ qt_set_winid_on_widget(widget, window);
+
+ if (visible)
+ widget->show();
+ }
+
+ // At this point, the widget's window should be created and have the correct visual. Now we
+ // just need to create the EGL surface for it:
+ return eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), 0);
+ }
+
+ if (x11PixmapData) {
+ // X11 Pixmaps are only created with a depth, so that's all we need to check
+ EGLint configDepth;
+ eglGetConfigAttrib(QEgl::display(), config, EGL_BUFFER_SIZE , &configDepth);
+ if (x11PixmapData->depth() != configDepth) {
+ // The bit depths are wrong which means the EGLConfig isn't compatable with
+ // this pixmap. So we need to replace the pixmap's existing data with a new
+ // one which is created with the correct depth:
+
+#ifndef QT_NO_XRENDER
+ if (configDepth == 32) {
+ qWarning("Warning: EGLConfig's depth (32) != pixmap's depth (%d), converting to ARGB32",
+ x11PixmapData->depth());
+ x11PixmapData->convertToARGB32(true);
+ } else
+#endif
+ {
+ qWarning("Warning: EGLConfig's depth (%d) != pixmap's depth (%d)",
+ configDepth, x11PixmapData->depth());
+ }
+ }
+
+ QEglProperties surfaceAttribs;
+
+ // If the pixmap can't be bound to a texture, it's pretty useless
+ surfaceAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
+ if (alphaSize > 0)
+ surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
+ else
+ surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);
+
+ EGLSurface surf = eglCreatePixmapSurface(QEgl::display(), config,
+ (EGLNativePixmapType) x11PixmapData->handle(),
+ surfaceAttribs.properties());
+ x11PixmapData->gl_surface = (void*)surf;
+ QImagePixmapCleanupHooks::enableCleanupHooks(x11PixmapData);
+ return surf;
+ }
+
+ return EGL_NO_SURFACE;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/egl/qeglcontext_p.h b/src/gui/egl/qeglcontext_p.h
new file mode 100644
index 0000000000..ccde00d91c
--- /dev/null
+++ b/src/gui/egl/qeglcontext_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** 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 QEGLCONTEXT_P_H
+#define QEGLCONTEXT_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 <QtGui/private/qegl_p.h>
+#include <QtGui/private/qeglproperties_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QEglContext
+{
+public:
+ QEglContext();
+ ~QEglContext();
+
+ bool isValid() const;
+ bool isCurrent() const;
+ bool isSharing() const { return sharing; }
+
+ QEgl::API api() const { return apiType; }
+ void setApi(QEgl::API api) { apiType = api; }
+
+ bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
+ bool createContext(QEglContext *shareContext = 0, const QEglProperties *properties = 0);
+ void destroyContext();
+ EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0);
+ void destroySurface(EGLSurface surface);
+
+ bool makeCurrent(EGLSurface surface);
+ bool doneCurrent();
+ bool lazyDoneCurrent();
+ bool swapBuffers(EGLSurface surface);
+
+ int configAttrib(int name) const;
+
+ EGLContext context() const { return ctx; }
+ void setContext(EGLContext context) { ctx = context; ownsContext = false;}
+
+ EGLDisplay display() {return QEgl::display();}
+
+ EGLConfig config() const { return cfg; }
+ void setConfig(EGLConfig config) { cfg = config; }
+
+private:
+ QEgl::API apiType;
+ EGLContext ctx;
+ EGLConfig cfg;
+ EGLSurface currentSurface;
+ bool current;
+ bool ownsContext;
+ bool sharing;
+
+ static QEglContext *currentContext(QEgl::API api);
+ static void setCurrentContext(QEgl::API api, QEglContext *context);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLCONTEXT_P_H
diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp
index d0d5de736e..3638de5b37 100644
--- a/src/gui/egl/qeglproperties.cpp
+++ b/src/gui/egl/qeglproperties.cpp
@@ -43,12 +43,10 @@
#include <QtCore/qstringlist.h>
#include "qeglproperties_p.h"
+#include "qeglcontext_p.h"
QT_BEGIN_NAMESPACE
-#include "qegl_p.h"
-
-
// Initialize a property block.
QEglProperties::QEglProperties()
{
@@ -60,7 +58,7 @@ QEglProperties::QEglProperties(EGLConfig cfg)
props.append(EGL_NONE);
for (int name = 0x3020; name <= 0x304F; ++name) {
EGLint value;
- if (name != EGL_NONE && eglGetConfigAttrib(QEglContext::display(), cfg, name, &value))
+ if (name != EGL_NONE && eglGetConfigAttrib(QEgl::display(), cfg, name, &value))
setValue(name, value);
}
eglGetError(); // Clear the error state.
@@ -82,19 +80,19 @@ int QEglProperties::value(int name) const
case EGL_GREEN_SIZE: return 0;
case EGL_BLUE_SIZE: return 0;
case EGL_ALPHA_SIZE: return 0;
-#if defined(EGL_LUMINANCE_SIZE)
+#ifdef EGL_LUMINANCE_SIZE
case EGL_LUMINANCE_SIZE: return 0;
#endif
-#if defined(EGL_ALPHA_MASK_SIZE)
+#ifdef EGL_ALPHA_MASK_SIZE
case EGL_ALPHA_MASK_SIZE: return 0;
#endif
-#if defined(EGL_BIND_TO_TEXTURE_RGB)
+#ifdef EGL_BIND_TO_TEXTURE_RGB
case EGL_BIND_TO_TEXTURE_RGB: return EGL_DONT_CARE;
#endif
-#if defined(EGL_BIND_TO_TEXTURE_RGBA)
+#ifdef EGL_BIND_TO_TEXTURE_RGBA
case EGL_BIND_TO_TEXTURE_RGBA: return EGL_DONT_CARE;
#endif
-#if defined(EGL_COLOR_BUFFER_TYPE)
+#ifdef EGL_COLOR_BUFFER_TYPE
case EGL_COLOR_BUFFER_TYPE: return EGL_RGB_BUFFER;
#endif
case EGL_CONFIG_CAVEAT: return EGL_DONT_CARE;
@@ -105,7 +103,7 @@ int QEglProperties::value(int name) const
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)
+#ifdef EGL_RENDERABLE_TYPE
case EGL_RENDERABLE_TYPE: return EGL_OPENGL_ES_BIT;
#endif
case EGL_SAMPLE_BUFFERS: return 0;
@@ -117,7 +115,7 @@ int QEglProperties::value(int name) const
case EGL_TRANSPARENT_GREEN_VALUE: return EGL_DONT_CARE;
case EGL_TRANSPARENT_BLUE_VALUE: return EGL_DONT_CARE;
-#if defined(EGL_VERSION_1_3)
+#ifdef EGL_VERSION_1_3
case EGL_CONFORMANT: return 0;
case EGL_MATCH_NATIVE_PIXMAP: return EGL_NONE;
#endif
@@ -166,6 +164,17 @@ bool QEglProperties::removeValue(int name)
return false;
}
+void QEglProperties::setDeviceType(int devType)
+{
+ if (devType == QInternal::Pixmap || devType == QInternal::Image)
+ setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
+ else if (devType == QInternal::Pbuffer)
+ setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
+ else
+ setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+}
+
+
// 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)
@@ -206,15 +215,18 @@ void QEglProperties::setPixelFormat(QImage::Format pixelFormat)
void QEglProperties::setRenderableType(QEgl::API api)
{
-#if defined(EGL_RENDERABLE_TYPE)
+#ifdef 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);
+#elif defined(EGL_OPENGL_BIT)
+ if (api == QEgl::OpenGL)
+ setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT);
#endif
-#if defined(EGL_OPENVG_BIT)
+#ifdef EGL_OPENVG_BIT
if (api == QEgl::OpenVG)
setValue(EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT);
#endif
@@ -229,6 +241,19 @@ void QEglProperties::setRenderableType(QEgl::API api)
// reductions in complexity are possible.
bool QEglProperties::reduceConfiguration()
{
+ if (value(EGL_SWAP_BEHAVIOR) != EGL_DONT_CARE)
+ removeValue(EGL_SWAP_BEHAVIOR);
+
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't
+ // find a config which supports pre-multiplied formats, remove the flag on the surface type:
+ EGLint surfaceType = value(EGL_SURFACE_TYPE);
+ if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) {
+ surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT;
+ setValue(EGL_SURFACE_TYPE, surfaceType);
+ return true;
+ }
+#endif
// EGL chooses configs with the highest color depth over
// those with smaller (but faster) lower color depths. One
// way around this is to set EGL_BUFFER_SIZE to 16, which
@@ -253,7 +278,7 @@ bool QEglProperties::reduceConfiguration()
return true;
if (removeValue(EGL_DEPTH_SIZE))
return true;
-#if defined(EGL_BIND_TO_TEXTURE_RGB)
+#ifdef EGL_BIND_TO_TEXTURE_RGB
if (removeValue(EGL_BIND_TO_TEXTURE_RGB))
return true;
#endif
@@ -270,20 +295,6 @@ static void addTag(QString& str, const QString& tag)
str += tag;
}
-void QEglProperties::dumpAllConfigs()
-{
- EGLint count = 0;
- eglGetConfigs(QEglContext::display(), 0, 0, &count);
- if (count < 1)
- return;
-
- EGLConfig *configs = new EGLConfig [count];
- eglGetConfigs(QEglContext::display(), 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
{
@@ -308,6 +319,10 @@ QString QEglProperties::toString() const
if ((val & EGL_OPENGL_ES2_BIT) != 0)
types += QLatin1String("es2");
#endif
+#ifdef EGL_OPENGL_BIT
+ if ((val & EGL_OPENGL_BIT) != 0)
+ types += QLatin1String("gl");
+#endif
if ((val & EGL_OPENVG_BIT) != 0)
types += QLatin1String("vg");
if ((val & ~7) != 0)
diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h
index b38577365a..b1f9642c7b 100644
--- a/src/gui/egl/qeglproperties_p.h
+++ b/src/gui/egl/qeglproperties_p.h
@@ -56,74 +56,10 @@
#include <QtCore/qvarlengtharray.h>
#include <QtGui/qimage.h>
-QT_BEGIN_INCLUDE_NAMESPACE
-
-#ifndef QT_NO_EGL
-#if defined(QT_OPENGL_ES_2)
-# include <GLES2/gl2.h>
-#endif
-
-#if defined(QT_GLES_EGL)
-# include <GLES/egl.h>
-#else
-# include <EGL/egl.h>
-#endif
-#else
-
-//types from egltypes.h for compiling stub without EGL headers
-typedef int EGLBoolean;
-typedef int EGLint;
-typedef int EGLenum;
-typedef int NativeDisplayType;
-typedef void* NativeWindowType;
-typedef void* NativePixmapType;
-typedef int EGLDisplay;
-typedef int EGLConfig;
-typedef int EGLSurface;
-typedef int EGLContext;
-typedef int EGLClientBuffer;
-#define EGL_NONE 0x3038 /* Attrib list terminator */
-
-#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
+#include <QtGui/private/qegl_p.h>
QT_BEGIN_NAMESPACE
-namespace QEgl {
- enum API
- {
- OpenGL,
- OpenVG
- };
-
- enum PixelFormatMatch
- {
- ExactPixelFormat,
- BestPixelFormat
- };
-}
-
class QX11Info;
class QPaintDevice;
@@ -146,16 +82,14 @@ public:
#ifdef Q_WS_X11
void setVisualFormat(const QX11Info *xinfo);
#endif
- void setRenderableType(QEgl::API api);
-
+ void setDeviceType(int devType);
void setPaintDeviceFormat(QPaintDevice *dev);
+ void setRenderableType(QEgl::API api);
bool reduceConfiguration();
QString toString() const;
- static void dumpAllConfigs();
-
private:
QVarLengthArray<int> props;
};
diff --git a/src/gui/egl/qeglproperties_stub.cpp b/src/gui/egl/qeglproperties_stub.cpp
index bf5e47b0f4..2012ebdf06 100644
--- a/src/gui/egl/qeglproperties_stub.cpp
+++ b/src/gui/egl/qeglproperties_stub.cpp
@@ -43,6 +43,7 @@
#include <QtCore/qstringlist.h>
#include "qeglproperties_p.h"
+#include "qeglcontext_p.h"
QT_BEGIN_NAMESPACE
@@ -90,6 +91,13 @@ bool QEglProperties::removeValue(int name)
return false;
}
+void QEglProperties::setDeviceType(int devType)
+{
+ Q_UNUSED(devType)
+ NOEGL
+}
+
+
// 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)
@@ -115,6 +123,13 @@ bool QEglProperties::reduceConfiguration()
return false;
}
+static void addTag(QString& str, const QString& tag)
+{
+ Q_UNUSED(str)
+ Q_UNUSED(tag)
+ NOEGL
+}
+
// Convert a property list to a string suitable for debug output.
QString QEglProperties::toString() const
{
@@ -128,11 +143,6 @@ void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
NOEGL
}
-void QEglProperties::dumpAllConfigs()
-{
- NOEGL
-}
-
QT_END_NAMESPACE
diff --git a/src/gui/embedded/directfb.pri b/src/gui/embedded/directfb.pri
index 1795bbd566..75d693e0b4 100644
--- a/src/gui/embedded/directfb.pri
+++ b/src/gui/embedded/directfb.pri
@@ -15,7 +15,7 @@
#DEFINES += QT_DIRECTFB_TIMING
#DEFINES += QT_NO_DIRECTFB_OPAQUE_DETECTION
#DEFINES += QT_NO_DIRECTFB_STRETCHBLIT
-DIRECTFB_DRAWINGOPERATIONS=DRAW_RECTS|DRAW_LINES|DRAW_IMAGE|DRAW_PIXMAP|DRAW_TILED_PIXMAP|STROKE_PATH|DRAW_PATH|DRAW_POINTS|DRAW_ELLIPSE|DRAW_POLYGON|DRAW_TEXT|FILL_PATH|FILL_RECT|DRAW_COLORSPANS|DRAW_ROUNDED_RECT
+DIRECTFB_DRAWINGOPERATIONS=DRAW_RECTS|DRAW_LINES|DRAW_IMAGE|DRAW_PIXMAP|DRAW_TILED_PIXMAP|STROKE_PATH|DRAW_PATH|DRAW_POINTS|DRAW_ELLIPSE|DRAW_POLYGON|DRAW_TEXT|FILL_PATH|FILL_RECT|DRAW_COLORSPANS|DRAW_ROUNDED_RECT|DRAW_STATICTEXT
#DEFINES += \"QT_DIRECTFB_WARN_ON_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\"
#DEFINES += \"QT_DIRECTFB_DISABLE_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\"
diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp
index 9bd73a485c..a3fe1abfc5 100644
--- a/src/gui/embedded/qscreen_qws.cpp
+++ b/src/gui/embedded/qscreen_qws.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
#include "qscreen_qws.h"
#include "qcolormap.h"
@@ -3223,13 +3224,13 @@ QScreen * qt_probe_bus()
return qt_dodriver("unaccel.so",0,0);
}
- DIR * dirptr=opendir("/proc/bus/pci");
+ QT_DIR *dirptr = QT_OPENDIR("/proc/bus/pci");
if(!dirptr)
return qt_dodriver("unaccel.so",0,0);
- DIR * dirptr2;
- dirent * cards;
+ QT_DIR * dirptr2;
+ QT_DIRENT *cards;
- dirent * busses=readdir(dirptr);
+ QT_DIRENT *busses = QT_READDIR(dirptr);
while(busses) {
if(busses->d_name[0]!='.') {
@@ -3237,9 +3238,9 @@ QScreen * qt_probe_bus()
strcpy(buf,"/proc/bus/pci/");
qstrcpy(buf+14,busses->d_name);
int p=strlen(buf);
- dirptr2=opendir(buf);
+ dirptr2 = QT_OPENDIR(buf);
if(dirptr2) {
- cards=readdir(dirptr2);
+ cards = QT_READDIR(dirptr2);
while(cards) {
if(cards->d_name[0]!='.') {
buf[p]='/';
@@ -3248,14 +3249,14 @@ QScreen * qt_probe_bus()
if(ret)
return ret;
}
- cards=readdir(dirptr2);
+ cards = QT_READDIR(dirptr2);
}
- closedir(dirptr2);
+ QT_CLOSEDIR(dirptr2);
}
}
- busses=readdir(dirptr);
+ busses = QT_READDIR(dirptr);
}
- closedir(dirptr);
+ QT_CLOSEDIR(dirptr);
return qt_dodriver("unaccel.so",0,0);
}
diff --git a/src/gui/embedded/qscreenlinuxfb_qws.cpp b/src/gui/embedded/qscreenlinuxfb_qws.cpp
index 8a21022403..1effcfaeb2 100644
--- a/src/gui/embedded/qscreenlinuxfb_qws.cpp
+++ b/src/gui/embedded/qscreenlinuxfb_qws.cpp
@@ -91,6 +91,7 @@ public:
int startuph;
int startupd;
bool blank;
+ QLinuxFbScreen::DriverTypes driverType;
bool doGraphicsMode;
#ifdef QT_QWS_DEPTH_GENERIC
@@ -165,6 +166,36 @@ void QLinuxFbScreenPrivate::closeTty()
}
/*!
+ \enum QLinuxFbScreen::DriverTypes
+
+ This enum describes the driver type.
+
+ \value GenericDriver Generic Linux framebuffer driver
+ \value EInk8Track e-Ink framebuffer driver using the 8Track chipset
+ */
+
+/*!
+ \fn QLinuxFbScreen::fixupScreenInfo(fb_fix_screeninfo &finfo, fb_var_screeninfo &vinfo)
+
+ Adjust the values returned by the framebuffer driver, to work
+ around driver bugs or nonstandard behavior in certain drivers.
+ \a finfo and \a vinfo specify the fixed and variable screen info
+ returned by the driver.
+ */
+void QLinuxFbScreen::fixupScreenInfo(fb_fix_screeninfo &finfo, fb_var_screeninfo &vinfo)
+{
+ // 8Track e-ink devices (as found in Sony PRS-505) lie
+ // about their bit depth -- they claim they're 1 bit per
+ // pixel while the only supported mode is 8 bit per pixel
+ // grayscale.
+ // Caused by this, they also miscalculate their line length.
+ if(!strcmp(finfo.id, "8TRACKFB") && vinfo.bits_per_pixel == 1) {
+ vinfo.bits_per_pixel = 8;
+ finfo.line_length = vinfo.xres;
+ }
+}
+
+/*!
\internal
\class QLinuxFbScreen
@@ -306,6 +337,8 @@ bool QLinuxFbScreen::connect(const QString &displaySpec)
return false;
}
+ d_ptr->driverType = strcmp(finfo.id, "8TRACKFB") ? GenericDriver : EInk8Track;
+
if (finfo.type == FB_TYPE_VGA_PLANES) {
qWarning("VGA16 video mode not supported");
return false;
@@ -318,6 +351,8 @@ bool QLinuxFbScreen::connect(const QString &displaySpec)
return false;
}
+ fixupScreenInfo(finfo, vinfo);
+
grayscale = vinfo.grayscale;
d = vinfo.bits_per_pixel;
if (d == 24) {
@@ -664,11 +699,6 @@ bool QLinuxFbScreen::initDevice()
vinfo.transp.msb_right);
#endif
- d_ptr->startupw=vinfo.xres;
- d_ptr->startuph=vinfo.yres;
- d_ptr->startupd=vinfo.bits_per_pixel;
- grayscale = vinfo.grayscale;
-
if (ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) {
perror("QLinuxFbScreen::initDevice");
qCritical("Error reading fixed information in card init");
@@ -677,6 +707,13 @@ bool QLinuxFbScreen::initDevice()
return true;
}
+ fixupScreenInfo(finfo, vinfo);
+
+ d_ptr->startupw=vinfo.xres;
+ d_ptr->startuph=vinfo.yres;
+ d_ptr->startupd=vinfo.bits_per_pixel;
+ grayscale = vinfo.grayscale;
+
#ifdef __i386__
// Now init mtrr
if(!::getenv("QWS_NOMTRR")) {
@@ -1122,6 +1159,7 @@ void QLinuxFbScreen::setMode(int nw,int nh,int nd)
qFatal("Error reading fixed information");
}
+ fixupScreenInfo(finfo, vinfo);
disconnect();
connect(d_ptr->displaySpec);
exposeRegion(region(), 0);
@@ -1200,6 +1238,26 @@ int QLinuxFbScreen::sharedRamSize(void * end)
/*!
\reimp
*/
+void QLinuxFbScreen::setDirty(const QRect &r)
+{
+ if(d_ptr->driverType == EInk8Track) {
+ // e-Ink displays need a trigger to actually show what is
+ // in their framebuffer memory. The 8-Track driver does this
+ // by adding custom IOCTLs - FBIO_EINK_DISP_PIC (0x46a2) takes
+ // an argument specifying whether or not to flash the screen
+ // while updating.
+ // There doesn't seem to be a way to tell it to just update
+ // a subset of the screen.
+ if(r.left() == 0 && r.top() == 0 && r.width() == dw && r.height() == dh)
+ ioctl(d_ptr->fd, 0x46a2, 1);
+ else
+ ioctl(d_ptr->fd, 0x46a2, 0);
+ }
+}
+
+/*!
+ \reimp
+*/
void QLinuxFbScreen::blank(bool on)
{
if (d_ptr->blank == on)
@@ -1315,7 +1373,9 @@ void QLinuxFbScreen::setPixelFormat(struct fb_var_screeninfo info)
bool QLinuxFbScreen::useOffscreen()
{
- if ((mapsize - size) < 16*1024)
+ // Not done for 8Track because on e-Ink displays,
+ // everything is offscreen anyway
+ if (d_ptr->driverType == EInk8Track || ((mapsize - size) < 16*1024))
return false;
return true;
diff --git a/src/gui/embedded/qscreenlinuxfb_qws.h b/src/gui/embedded/qscreenlinuxfb_qws.h
index ac488b71a6..6abadbff29 100644
--- a/src/gui/embedded/qscreenlinuxfb_qws.h
+++ b/src/gui/embedded/qscreenlinuxfb_qws.h
@@ -88,6 +88,8 @@ public:
virtual bool useOffscreen();
+ enum DriverTypes { GenericDriver, EInk8Track };
+
virtual void disconnect();
virtual void shutdownDevice();
virtual void setMode(int,int,int);
@@ -98,6 +100,7 @@ public:
virtual uchar * cache(int);
virtual void uncache(uchar *);
virtual int sharedRamSize(void *);
+ virtual void setDirty(const QRect&);
QLinuxFb_Shared * shared;
@@ -109,6 +112,7 @@ protected:
int dataoffset;
int cacheStart;
+ virtual void fixupScreenInfo(fb_fix_screeninfo &finfo, fb_var_screeninfo &vinfo);
static void clearCache(QScreen *instance, int);
private:
diff --git a/src/gui/embedded/qwsmanager_qws.cpp b/src/gui/embedded/qwsmanager_qws.cpp
index d6ef14858b..79076c5785 100644
--- a/src/gui/embedded/qwsmanager_qws.cpp
+++ b/src/gui/embedded/qwsmanager_qws.cpp
@@ -267,8 +267,10 @@ void QWSManager::mouseMoveEvent(QMouseEvent *e)
#ifndef QT_NO_CURSOR
- QWSDisplay *qwsd = QApplication::desktop()->qwsDisplay();
- qwsd->selectCursor(d->managed, regionToShape(d->cachedRegionAt()));
+ if (d->managed->minimumSize() != d->managed->maximumSize()) {
+ QWSDisplay *qwsd = QApplication::desktop()->qwsDisplay();
+ qwsd->selectCursor(d->managed, regionToShape(d->cachedRegionAt()));
+ }
#endif //QT_NO_CURSOR
if (d->activeRegion)
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 42abe59f85..326f130abd 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -381,7 +381,9 @@
\value ItemSendsGeometryChanges The item enables itemChange()
notifications for ItemPositionChange, ItemPositionHasChanged,
- ItemMatrixChange, ItemTransformChange, and ItemTransformHasChanged. For
+ ItemMatrixChange, ItemTransformChange, ItemTransformHasChanged,
+ ItemRotationChange, ItemRotationHasChanged, ItemScaleChange, ItemScaleHasChanged,
+ ItemTransformOriginPointChange, and ItemTransformOriginPointHasChanged. 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.
@@ -475,6 +477,52 @@
(same as transform()), and QGraphicsItem ignores the return value for this
notification (i.e., a read-only notification).
+ \value ItemRotationChange The item's rotation property changes. This
+ notification is sent if the ItemSendsGeometryChanges flag is enabled, and
+ when the item's rotation property changes (i.e., as a result of calling
+ setRotation()). The value argument is the new rotation (i.e., a double);
+ to get the old rotation, call rotation(). Do not call setRotation() in
+ itemChange() as this notification is delivered; instead, you can return
+ the new rotation from itemChange().
+
+ \value ItemRotationHasChanged The item's rotation property has changed.
+ This notification is sent if the ItemSendsGeometryChanges flag is enabled,
+ and after the item's rotation property has changed. The value argument is
+ the new rotation (i.e., a double), and QGraphicsItem ignores the return
+ value for this notification (i.e., a read-only notification). Do not call
+ setRotation() in itemChange() as this notification is delivered.
+
+ \value ItemScaleChange The item's scale property changes. This notification
+ is sent if the ItemSendsGeometryChanges flag is enabled, and when the item's
+ scale property changes (i.e., as a result of calling setScale()). The value
+ argument is the new scale (i.e., a double); to get the old scale, call
+ scale(). Do not call setScale() in itemChange() as this notification is
+ delivered; instead, you can return the new scale from itemChange().
+
+ \value ItemScaleHasChanged The item's scale property has changed. This
+ notification is sent if the ItemSendsGeometryChanges flag is enabled, and
+ after the item's scale property has changed. The value argument is the new
+ scale (i.e., a double), and QGraphicsItem ignores the return value for this
+ notification (i.e., a read-only notification). Do not call setScale() in
+ itemChange() as this notification is delivered.
+
+ \value ItemTransformOriginPointChange The item's transform origin point
+ property changes. This notification is sent if the ItemSendsGeometryChanges
+ flag is enabled, and when the item's transform origin point property changes
+ (i.e., as a result of calling setTransformOriginPoint()). The value argument
+ is the new origin point (i.e., a QPointF); to get the old origin point, call
+ transformOriginPoint(). Do not call setTransformOriginPoint() in itemChange()
+ as this notification is delivered; instead, you can return the new transform
+ origin point from itemChange().
+
+ \value ItemTransformOriginPointHasChanged The item's transform origin point
+ property has changed. This notification is sent if the ItemSendsGeometryChanges
+ flag is enabled, and after the item's transform origin point property has
+ changed. The value argument is the new origin point (i.e., a QPointF), and
+ QGraphicsItem ignores the return value for this notification (i.e., a read-only
+ notification). Do not call setTransformOriginPoint() in itemChange() as this
+ notification is delivered.
+
\value ItemSelectedChange The item's selected state changes. If the item is
presently selected, it will become unselected, and vice verca. The value
argument is the new selected state (i.e., true or false). Do not call
@@ -673,6 +721,7 @@
#include <QtCore/qtimer.h>
#include <QtCore/qvariant.h>
#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qnumeric.h>
#include <QtGui/qapplication.h>
#include <QtGui/qbitmap.h>
#include <QtGui/qpainter.h>
@@ -682,6 +731,9 @@
#include <QtGui/qevent.h>
#include <QtGui/qinputcontext.h>
#include <QtGui/qgraphicseffect.h>
+#ifndef QT_NO_ACCESSIBILITY
+# include "qaccessible.h"
+#endif
#include <private/qgraphicsitem_p.h>
#include <private/qgraphicswidget_p.h>
@@ -689,6 +741,7 @@
#include <private/qtextdocumentlayout_p.h>
#include <private/qtextengine_p.h>
#include <private/qwidget_p.h>
+#include <private/qapplication_p.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
@@ -1184,6 +1237,8 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q
}
dirtySceneTransform = 1;
+ if (!inDestructor && (transformData || (newParent && newParent->d_ptr->transformData)))
+ transformChanged();
// Restore the sub focus chain.
if (subFocusItem) {
@@ -1355,8 +1410,16 @@ QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent,
*/
QGraphicsItem::~QGraphicsItem()
{
- if (d_ptr->isObject)
- QObjectPrivate::get(static_cast<QGraphicsObject *>(this))->wasDeleted = true;
+ if (d_ptr->isObject) {
+ QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
+ QObjectPrivate *p = QObjectPrivate::get(o);
+ p->wasDeleted = true;
+ if (p->declarativeData) {
+ QAbstractDeclarativeData::destroyed(p->declarativeData, o);
+ p->declarativeData = 0;
+ }
+ }
+
d_ptr->inDestructor = 1;
d_ptr->removeExtraItemCache();
@@ -3484,7 +3547,10 @@ void QGraphicsItem::setX(qreal x)
if (d_ptr->inDestructor)
return;
- d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
+ if (qIsNaN(x))
+ return;
+
+ setPos(QPointF(x, d_ptr->pos.y()));
}
/*!
@@ -3508,7 +3574,10 @@ void QGraphicsItem::setY(qreal y)
if (d_ptr->inDestructor)
return;
- d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
+ if (qIsNaN(y))
+ return;
+
+ setPos(QPointF(d_ptr->pos.x(), y));
}
/*!
@@ -3555,6 +3624,7 @@ void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform)
q_ptr->prepareGeometryChange();
transformData->transform = transform;
dirtySceneTransform = 1;
+ transformChanged();
}
/*!
@@ -3576,7 +3646,7 @@ void QGraphicsItem::setPos(const QPointF &pos)
return;
// Update and repositition.
- if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ if (!(d_ptr->flags & (ItemSendsGeometryChanges | ItemSendsScenePositionChanges))) {
d_ptr->setPosHelper(pos);
return;
}
@@ -3721,14 +3791,32 @@ qreal QGraphicsItem::rotation() const
void QGraphicsItem::setRotation(qreal angle)
{
prepareGeometryChange();
+ qreal newRotation = angle;
+
+ if (d_ptr->flags & ItemSendsGeometryChanges) {
+ // Notify the item that the rotation is changing.
+ const QVariant newRotationVariant(itemChange(ItemRotationChange, angle));
+ newRotation = newRotationVariant.toReal();
+ }
+
if (!d_ptr->transformData)
d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->rotation = angle;
+
+ if (d_ptr->transformData->rotation == newRotation)
+ return;
+
+ d_ptr->transformData->rotation = newRotation;
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
+ // Send post-notification.
+ if (d_ptr->flags & ItemSendsGeometryChanges)
+ itemChange(ItemRotationHasChanged, newRotation);
+
if (d_ptr->isObject)
emit static_cast<QGraphicsObject *>(this)->rotationChanged();
+
+ d_ptr->transformChanged();
}
/*!
@@ -3769,14 +3857,32 @@ qreal QGraphicsItem::scale() const
void QGraphicsItem::setScale(qreal factor)
{
prepareGeometryChange();
+ qreal newScale = factor;
+
+ if (d_ptr->flags & ItemSendsGeometryChanges) {
+ // Notify the item that the scale is changing.
+ const QVariant newScaleVariant(itemChange(ItemScaleChange, factor));
+ newScale = newScaleVariant.toReal();
+ }
+
if (!d_ptr->transformData)
d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->scale = factor;
+
+ if (d_ptr->transformData->scale == newScale)
+ return;
+
+ d_ptr->transformData->scale = newScale;
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
+ // Send post-notification.
+ if (d_ptr->flags & ItemSendsGeometryChanges)
+ itemChange(ItemScaleHasChanged, newScale);
+
if (d_ptr->isObject)
emit static_cast<QGraphicsObject *>(this)->scaleChanged();
+
+ d_ptr->transformChanged();
}
@@ -3832,6 +3938,24 @@ void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transf
transformations.at(i)->d_func()->setItem(this);
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
+ d_ptr->transformChanged();
+}
+
+/*!
+ \internal
+*/
+void QGraphicsItemPrivate::prependGraphicsTransform(QGraphicsTransform *t)
+{
+ if (!transformData)
+ transformData = new QGraphicsItemPrivate::TransformData;
+ if (!transformData->graphicsTransforms.contains(t))
+ transformData->graphicsTransforms.prepend(t);
+
+ Q_Q(QGraphicsItem);
+ t->d_func()->setItem(q);
+ transformData->onlyTransform = false;
+ dirtySceneTransform = 1;
+ transformChanged();
}
/*!
@@ -3848,6 +3972,7 @@ void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t)
t->d_func()->setItem(q);
transformData->onlyTransform = false;
dirtySceneTransform = 1;
+ transformChanged();
}
/*!
@@ -3876,12 +4001,31 @@ QPointF QGraphicsItem::transformOriginPoint() const
void QGraphicsItem::setTransformOriginPoint(const QPointF &origin)
{
prepareGeometryChange();
+ QPointF newOrigin = origin;
+
+ if (d_ptr->flags & ItemSendsGeometryChanges) {
+ // Notify the item that the origin point is changing.
+ const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange,
+ qVariantFromValue<QPointF>(origin)));
+ newOrigin = newOriginVariant.toPointF();
+ }
+
if (!d_ptr->transformData)
d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->xOrigin = origin.x();
- d_ptr->transformData->yOrigin = origin.y();
+
+ if (d_ptr->transformData->xOrigin == newOrigin.x()
+ && d_ptr->transformData->yOrigin == newOrigin.y()) {
+ return;
+ }
+
+ d_ptr->transformData->xOrigin = newOrigin.x();
+ d_ptr->transformData->yOrigin = newOrigin.y();
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
+
+ // Send post-notification.
+ if (d_ptr->flags & ItemSendsGeometryChanges)
+ itemChange(ItemTransformOriginPointHasChanged, qVariantFromValue<QPointF>(newOrigin));
}
/*!
@@ -5225,6 +5369,8 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
needSortChildren = 1; // ### maybe 0
child->d_ptr->siblingIndex = children.size();
children.append(child);
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
}
/*!
@@ -5247,6 +5393,8 @@ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
// the child is not guaranteed to be at the index after the list is sorted.
// (see ensureSortedChildren()).
child->d_ptr->siblingIndex = -1;
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
}
/*!
@@ -6982,7 +7130,8 @@ void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
// Root items that ignore transformations need to
// calculate their diff by mapping viewport coordinates
// directly to parent coordinates.
- QTransform viewToParentTransform = (item->transform().translate(item->d_ptr->pos.x(), item->d_ptr->pos.y()))
+ // COMBINE
+ QTransform viewToParentTransform = (item->d_func()->transformData->computedFullTransform().translate(item->d_ptr->pos.x(), item->d_ptr->pos.y()))
* (item->sceneTransform() * view->viewportTransform()).inverted();
currentParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->screenPos())));
buttonDownParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton))));
@@ -7176,6 +7325,41 @@ void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints)
{
Q_D(QGraphicsItem);
d->imHints = hints;
+ if (!hasFocus())
+ return;
+ d->scene->d_func()->updateInputMethodSensitivityInViews();
+#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
+ QWidget *fw = QApplication::focusWidget();
+ if (!fw)
+ return;
+ for (int i = 0 ; i < scene()->views().count() ; ++i)
+ if (scene()->views().at(i) == fw)
+ if (QInputContext *inputContext = fw->inputContext())
+ inputContext->update();
+#endif
+}
+
+/*!
+ Updates the item's micro focus.
+
+ \since 4.7
+
+ \sa QInputContext
+*/
+void QGraphicsItem::updateMicroFocus()
+{
+#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
+ if (QWidget *fw = QApplication::focusWidget()) {
+ for (int i = 0 ; i < scene()->views().count() ; ++i)
+ if (scene()->views().at(i) == fw)
+ if (QInputContext *inputContext = fw->inputContext())
+ inputContext->update();
+#ifndef QT_NO_ACCESSIBILITY
+ // ##### is this correct
+ QAccessible::updateAccessibility(fw, 0, QAccessible::StateChanged);
+#endif
+ }
+#endif
}
/*!
@@ -7454,6 +7638,109 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
}
}
+void QGraphicsObject::updateMicroFocus()
+{
+ QGraphicsItem::updateMicroFocus();
+}
+
+void QGraphicsItemPrivate::children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item)
+{
+ QGraphicsItemPrivate::get(item)->setParentItemHelper(static_cast<QGraphicsObject *>(list->object), /*newParentVariant=*/0, /*thisPointerVariant=*/0);
+}
+
+int QGraphicsItemPrivate::children_count(QDeclarativeListProperty<QGraphicsObject> *list)
+{
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object));
+ return d->children.count();
+}
+
+QGraphicsObject *QGraphicsItemPrivate::children_at(QDeclarativeListProperty<QGraphicsObject> *list, int index)
+{
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object));
+ if (index >= 0 && index < d->children.count())
+ return d->children.at(index)->toGraphicsObject();
+ else
+ return 0;
+}
+
+/*!
+ Returns a list of this item's children.
+
+ The items are sorted by stacking order. This takes into account both the
+ items' insertion order and their Z-values.
+
+*/
+QDeclarativeListProperty<QGraphicsObject> QGraphicsItemPrivate::childrenList()
+{
+ Q_Q(QGraphicsItem);
+ if (isObject) {
+ QGraphicsObject *that = static_cast<QGraphicsObject *>(q);
+ return QDeclarativeListProperty<QGraphicsObject>(that, &children, children_append,
+ children_count, children_at);
+ } else {
+ //QGraphicsItem is not supported for this property
+ return QDeclarativeListProperty<QGraphicsObject>();
+ }
+}
+
+/*!
+ \internal
+ Returns the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::width() const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ Set the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setWidth(qreal w)
+{
+ Q_UNUSED(w);
+}
+
+/*!
+ \internal
+ Reset the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetWidth()
+{
+}
+
+/*!
+ \internal
+ Returns the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::height() const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ Set the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setHeight(qreal h)
+{
+ Q_UNUSED(h);
+}
+
+/*!
+ \internal
+ Reset the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetHeight()
+{
+}
+
/*!
\property QGraphicsObject::parent
\brief the parent of the item
@@ -7640,6 +7927,23 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
\sa scale, rotation, QGraphicsItem::transformOriginPoint()
*/
+/*!
+ \fn void QGraphicsObject::widthChanged()
+ \internal
+*/
+
+/*!
+ \fn void QGraphicsObject::heightChanged()
+ \internal
+*/
+
+/*!
+
+ \fn QGraphicsObject::childrenChanged()
+
+ This signal gets emitted whenever the children list changes
+ \internal
+*/
/*!
\class QAbstractGraphicsShapeItem
@@ -9802,6 +10106,9 @@ bool QGraphicsTextItem::sceneEvent(QEvent *event)
#endif //QT_NO_IM
}
break;
+ case QEvent::ShortcutOverride:
+ dd->sendControlEvent(event);
+ return true;
default:
break;
}
@@ -10928,14 +11235,14 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
&newEffectTransform, false, true);
} else if (deviceCoordinates) {
// Device coordinates with info.
- scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion,
+ scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0,
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,
+ scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0,
info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform,
info->drawItem);
}
@@ -11071,6 +11378,24 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change)
case QGraphicsItem::ItemScenePositionHasChanged:
str = "ItemScenePositionHasChanged";
break;
+ case QGraphicsItem::ItemRotationChange:
+ str = "ItemRotationChange";
+ break;
+ case QGraphicsItem::ItemRotationHasChanged:
+ str = "ItemRotationHasChanged";
+ break;
+ case QGraphicsItem::ItemScaleChange:
+ str = "ItemScaleChange";
+ break;
+ case QGraphicsItem::ItemScaleHasChanged:
+ str = "ItemScaleHasChanged";
+ break;
+ case QGraphicsItem::ItemTransformOriginPointChange:
+ str = "ItemTransformOriginPointChange";
+ break;
+ case QGraphicsItem::ItemTransformOriginPointHasChanged:
+ str = "ItemTransformOriginPointHasChanged";
+ break;
}
debug << str;
return debug;
@@ -11140,7 +11465,7 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags)
{
debug << '(';
bool f = false;
- for (int i = 0; i < 16; ++i) {
+ for (int i = 0; i < 17; ++i) {
if (flags & (1 << i)) {
if (f)
debug << '|';
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index d72833bc6e..9891af35fc 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -139,7 +139,13 @@ public:
ItemZValueHasChanged,
ItemOpacityChange,
ItemOpacityHasChanged,
- ItemScenePositionHasChanged
+ ItemScenePositionHasChanged,
+ ItemRotationChange,
+ ItemRotationHasChanged,
+ ItemScaleChange,
+ ItemScaleHasChanged,
+ ItemTransformOriginPointChange,
+ ItemTransformOriginPointHasChanged
};
enum CacheMode {
@@ -418,6 +424,7 @@ public:
void removeSceneEventFilter(QGraphicsItem *filterItem);
protected:
+ void updateMicroFocus();
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
virtual bool sceneEvent(QEvent *event);
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
@@ -540,13 +547,20 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem
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(QPointF pos READ pos WRITE setPos FINAL)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL)
+ Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged FINAL)
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)
+#ifndef QT_NO_GRAPHICSEFFECT
+ Q_PROPERTY(QGraphicsEffect *effect READ graphicsEffect WRITE setGraphicsEffect)
+#endif
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), QDeclarativeListProperty<QGraphicsObject> children READ childrenList DESIGNABLE false NOTIFY childrenChanged)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL)
+ Q_CLASSINFO("DefaultProperty", "children")
Q_INTERFACES(QGraphicsItem)
public:
QGraphicsObject(QGraphicsItem *parent = 0);
@@ -561,6 +575,9 @@ public:
void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags());
void ungrabGesture(Qt::GestureType type);
+protected Q_SLOTS:
+ void updateMicroFocus();
+
Q_SIGNALS:
void parentChanged();
void opacityChanged();
@@ -571,6 +588,9 @@ Q_SIGNALS:
void zChanged();
void rotationChanged();
void scaleChanged();
+ void childrenChanged();
+ void widthChanged();
+ void heightChanged();
protected:
QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index e737773157..569a32965d 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -71,6 +71,63 @@ QT_BEGIN_NAMESPACE
class QGraphicsItemPrivate;
+#ifndef QDECLARATIVELISTPROPERTY
+#define QDECLARATIVELISTPROPERTY
+template<typename T>
+class QDeclarativeListProperty {
+public:
+ typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*);
+ typedef int (*CountFunction)(QDeclarativeListProperty<T> *);
+ typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int);
+ typedef void (*ClearFunction)(QDeclarativeListProperty<T> *);
+
+ QDeclarativeListProperty()
+ : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {}
+ QDeclarativeListProperty(QObject *o, QList<T *> &list)
+ : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at),
+ clear(qlist_clear), dummy1(0), dummy2(0) {}
+ QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0,
+ ClearFunction r = 0)
+ : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {}
+
+ bool operator==(const QDeclarativeListProperty &o) const {
+ return object == o.object &&
+ data == o.data &&
+ append == o.append &&
+ count == o.count &&
+ at == o.at &&
+ clear == o.clear;
+ }
+
+ QObject *object;
+ void *data;
+
+ AppendFunction append;
+
+ CountFunction count;
+ AtFunction at;
+
+ ClearFunction clear;
+
+ void *dummy1;
+ void *dummy2;
+
+private:
+ static void qlist_append(QDeclarativeListProperty *p, T *v) {
+ ((QList<T *> *)p->data)->append(v);
+ }
+ static int qlist_count(QDeclarativeListProperty *p) {
+ return ((QList<T *> *)p->data)->count();
+ }
+ static T *qlist_at(QDeclarativeListProperty *p, int idx) {
+ return ((QList<T *> *)p->data)->at(idx);
+ }
+ static void qlist_clear(QDeclarativeListProperty *p) {
+ return ((QList<T *> *)p->data)->clear();
+ }
+};
+#endif
+
class QGraphicsItemCache
{
public:
@@ -156,8 +213,8 @@ public:
needSortChildren(0),
allChildrenDirty(0),
fullUpdatePending(0),
- flags(0),
dirtyChildrenBoundingRect(1),
+ flags(0),
paintedViewBoundingRectsNeedRepaint(0),
dirtySceneTransform(1),
geometryChanged(1),
@@ -180,6 +237,7 @@ public:
scenePosDescendants(0),
pendingPolish(0),
mayHaveChildWithGraphicsEffect(0),
+ isDeclarativeItem(0),
globalStackingOrder(-1),
q_ptr(0)
{
@@ -220,11 +278,13 @@ public:
virtual void setPosHelper(const QPointF &pos);
void setTransformHelper(const QTransform &transform);
+ void prependGraphicsTransform(QGraphicsTransform *t);
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 ignoreVisibleBit = false,
bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
+ virtual void transformChanged() {}
int depth() const;
#ifndef QT_NO_GRAPHICSEFFECT
enum InvalidateReason {
@@ -237,6 +297,7 @@ public:
void resolveDepth();
void addChild(QGraphicsItem *child);
void removeChild(QGraphicsItem *child);
+ QDeclarativeListProperty<QGraphicsObject> childrenList();
void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant,
const QVariant *thisPointerVariant);
void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
@@ -421,6 +482,10 @@ public:
void resetFocusProxy();
virtual void subFocusItemChange();
+ static void children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item);
+ static int children_count(QDeclarativeListProperty<QGraphicsObject> *list);
+ static QGraphicsObject *children_at(QDeclarativeListProperty<QGraphicsObject> *list, int);
+
inline QTransform transformToParent() const;
inline void ensureSortedChildren();
static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
@@ -428,6 +493,15 @@ public:
inline void sendScenePosChange();
virtual void siblingOrderChange();
+ // Private Properties
+ virtual qreal width() const;
+ virtual void setWidth(qreal);
+ virtual void resetWidth();
+
+ virtual qreal height() const;
+ virtual void setHeight(qreal);
+ virtual void resetHeight();
+
QRectF childrenBoundingRect;
QRectF needsRepaint;
QMap<QWidget *, QRect> paintedViewBoundingRects;
@@ -475,11 +549,11 @@ public:
quint32 inSetPosHelper : 1;
quint32 needSortChildren : 1;
quint32 allChildrenDirty : 1;
+ quint32 fullUpdatePending : 1;
+ quint32 dirtyChildrenBoundingRect : 1;
// Packed 32 bits
- quint32 fullUpdatePending : 1;
quint32 flags : 17;
- quint32 dirtyChildrenBoundingRect : 1;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
quint32 dirtySceneTransform : 1;
quint32 geometryChanged : 1;
@@ -493,10 +567,10 @@ public:
quint32 sceneTransformTranslateOnly : 1;
quint32 notifyBoundingRectChanged : 1;
quint32 notifyInvalidated : 1;
-
- // New 32 bits
quint32 mouseSetsFocus : 1;
quint32 explicitActivate : 1;
+
+ // New 32 bits
quint32 wantsActive : 1;
quint32 holesInSiblingIndex : 1;
quint32 sequentialOrdering : 1;
@@ -504,6 +578,8 @@ public:
quint32 scenePosDescendants : 1;
quint32 pendingPolish : 1;
quint32 mayHaveChildWithGraphicsEffect : 1;
+ quint32 isDeclarativeItem : 1;
+ quint32 padding : 24;
// Optional stacking order
int globalStackingOrder;
@@ -609,7 +685,7 @@ public:
return item->type() == QGraphicsPixmapItem::Type
&& !(item->flags() & QGraphicsItem::ItemIsSelectable)
&& item->d_ptr->children.size() == 0;
- //|| (item->d_ptr->isObject && qobject_cast<QmlGraphicsImage *>(q_func()));
+ //|| (item->d_ptr->isObject && qobject_cast<QDeclarativeImage *>(q_func()));
}
inline const QStyleOption *styleOption() const
@@ -792,7 +868,7 @@ inline void QGraphicsItemPrivate::markParentDirty(bool updateBoundingRect)
static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()
->source->d_func())->invalidateCache();
}
- if (parentp->graphicsEffect->isEnabled()) {
+ if (parentp->scene && parentp->graphicsEffect->isEnabled()) {
parentp->dirty = 1;
parentp->fullUpdatePending = 1;
}
diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp
index 6a9eb29cd4..9722683d3c 100644
--- a/src/gui/graphicsview/qgraphicslinearlayout.cpp
+++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp
@@ -554,6 +554,8 @@ void QGraphicsLinearLayout::dump(int indent) const
d->orientation == Qt::Horizontal ? "Horizontal" : "Vertical");
d->engine.dump(indent + 1);
}
+#else
+ Q_UNUSED(indent);
#endif
}
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index ad7cf5dd2f..320395ef53 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -975,6 +975,7 @@ bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event)
d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
}
break;
+#ifndef QT_NO_TOOLTIP
case QEvent::ToolTipChange:
// Propagate tooltip change to the proxy.
if (!d->tooltipChangeMode) {
@@ -983,6 +984,7 @@ bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event)
d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
}
break;
+#endif
default:
break;
}
@@ -1024,9 +1026,18 @@ void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *even
// Map event position from us to the receiver
pos = d->mapToReceiver(pos, receiver);
+ QPoint globalPos = receiver->mapToGlobal(pos.toPoint());
+ //If the receiver by-pass the proxy its popups
+ //will be top level QWidgets therefore they need
+ //the screen position. mapToGlobal expect the widget to
+ //have proper coordinates in regards of the windowing system
+ //but it's not true because the widget is embedded.
+ if (bypassGraphicsProxyWidget(receiver))
+ globalPos = event->screenPos();
+
// Send mouse event. ### Doesn't propagate the event.
QContextMenuEvent contextMenuEvent(QContextMenuEvent::Reason(event->reason()),
- pos.toPoint(), receiver->mapToGlobal(pos.toPoint()), event->modifiers());
+ pos.toPoint(), globalPos, event->modifiers());
QApplication::sendEvent(receiver, &contextMenuEvent);
event->setAccepted(contextMenuEvent.isAccepted());
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index b368a82cf4..bd0f0d8e34 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -228,6 +228,7 @@
#include <QtCore/qstack.h>
#include <QtCore/qtimer.h>
#include <QtCore/qvarlengtharray.h>
+#include <QtCore/QMetaMethod>
#include <QtGui/qapplication.h>
#include <QtGui/qdesktopwidget.h>
#include <QtGui/qevent.h>
@@ -277,8 +278,6 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph
hover->setAccepted(mouseEvent->isAccepted());
}
-int QGraphicsScenePrivate::changedSignalIndex;
-
/*!
\internal
*/
@@ -329,9 +328,10 @@ void QGraphicsScenePrivate::init()
index = new QGraphicsSceneBspTreeIndex(q);
// Keep this index so we can check for connected slots later on.
- if (!changedSignalIndex) {
- changedSignalIndex = signalIndex("changed(QList<QRectF>)");
- }
+ changedSignalIndex = signalIndex("changed(QList<QRectF>)");
+ processDirtyItemsIndex = q->metaObject()->indexOfSlot("_q_processDirtyItems()");
+ polishItemsIndex = q->metaObject()->indexOfSlot("_q_polishItems()");
+
qApp->d_func()->scene_list.append(q);
q->update();
}
@@ -693,6 +693,18 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
--selectionChanging;
if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize)
emit q->selectionChanged();
+
+ QHash<QGesture *, QGraphicsObject *>::iterator it;
+ for (it = gestureTargets.begin(); it != gestureTargets.end();) {
+ if (it.value() == item)
+ it = gestureTargets.erase(it);
+ else
+ ++it;
+ }
+ QGraphicsObject *dummy = static_cast<QGraphicsObject *>(item);
+ cachedTargetItems.removeOne(dummy);
+ cachedItemGestures.remove(dummy);
+ cachedAlreadyDeliveredGestures.remove(dummy);
}
/*!
@@ -2525,8 +2537,10 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
return;
}
- if (d->unpolishedItems.isEmpty())
- QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
+ if (d->unpolishedItems.isEmpty()) {
+ QMetaMethod method = metaObject()->method(d->polishItemsIndex);
+ method.invoke(this, Qt::QueuedConnection);
+ }
d->unpolishedItems.append(item);
item->d_ptr->pendingPolish = true;
@@ -4245,6 +4259,8 @@ static void _q_paintItem(QGraphicsItem *item, QPainter *painter,
widgetItem->paintWindowFrame(painter, option, widget);
if (painterStateProtection)
painter->restore();
+ } else if (widgetItem->autoFillBackground()) {
+ painter->fillRect(option->exposedRect, widgetItem->palette().window());
}
widgetItem->paint(painter, option, widget);
@@ -4710,7 +4726,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
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);
+ painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent);
QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
(source->d_func());
@@ -4876,7 +4892,9 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b
return;
if (!processDirtyItemsEmitted) {
- QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
+ QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex);
+ method.invoke(q_ptr, Qt::QueuedConnection);
+// QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
processDirtyItemsEmitted = true;
}
@@ -5898,45 +5916,51 @@ void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel)
dispatchHoverEvent(&hoverEvent);
}
-void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures,
- QWidget *viewport,
- QMap<Qt::GestureType, QGesture *> *conflictedGestures,
- QList<QList<QGraphicsObject *> > *conflictedItems,
- QHash<QGesture *, QGraphicsObject *> *normalGestures)
+void QGraphicsScenePrivate::gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures,
+ Qt::GestureFlag flag,
+ QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
+ QSet<QGraphicsObject *> *itemsSet,
+ QSet<QGesture *> *normal,
+ QSet<QGesture *> *conflicts)
{
+ QSet<QGesture *> normalGestures; // that are not in conflicted state.
foreach (QGesture *gesture, gestures) {
- Qt::GestureType gestureType = gesture->gestureType();
- if (gesture->hasHotSpot()) {
- QPoint screenPos = gesture->hotSpot().toPoint();
- QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
- QList<QGraphicsObject *> result;
- for (int j = 0; j < items.size(); ++j) {
- QGraphicsItem *item = items.at(j);
+ if (!gesture->hasHotSpot())
+ continue;
+ const Qt::GestureType gestureType = gesture->gestureType();
+ QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), gesture->d_func()->sceneHotSpot, 0);
+ for (int j = 0; j < items.size(); ++j) {
+ QGraphicsItem *item = items.at(j);
- // Check if the item is blocked by a modal panel and use it as
- // a target instead of this item.
- (void) item->isBlockedByModalPanel(&item);
+ // Check if the item is blocked by a modal panel and use it as
+ // a target instead of this item.
+ (void) item->isBlockedByModalPanel(&item);
- if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
- QGraphicsItemPrivate *d = item->d_func();
- if (d->gestureContext.contains(gestureType)) {
- result.append(itemobj);
+ if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
+ QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
+ QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator it =
+ d->gestureContext.find(gestureType);
+ if (it != d->gestureContext.end() && (!flag || (it.value() & flag))) {
+ if (normalGestures.contains(gesture)) {
+ normalGestures.remove(gesture);
+ if (conflicts)
+ conflicts->insert(gesture);
+ } else {
+ normalGestures.insert(gesture);
}
+ if (targets)
+ (*targets)[itemobj].insert(gesture);
+ if (itemsSet)
+ (*itemsSet).insert(itemobj);
}
- // Don't propagate through panels.
- if (item->isPanel())
- break;
- }
- DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
- << gesture << result;
- if (result.size() == 1) {
- normalGestures->insert(gesture, result.first());
- } else if (!result.isEmpty()) {
- conflictedGestures->insert(gestureType, gesture);
- conflictedItems->append(result);
}
+ // Don't propagate through panels.
+ if (item->isPanel())
+ break;
}
}
+ if (normal)
+ *normal = normalGestures;
}
void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
@@ -5944,200 +5968,220 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
QWidget *viewport = event->widget();
if (!viewport)
return;
+ QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent());
+ if (!graphicsView)
+ return;
+
QList<QGesture *> allGestures = event->gestures();
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "Delivering gestures:" << allGestures;
-
- typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem;
- GesturesPerItem gesturesPerItem;
+ << "Gestures:" << allGestures;
QSet<QGesture *> startedGestures;
+ QPoint delta = viewport->mapFromGlobal(QPoint());
+ QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
+ * graphicsView->viewportTransform().inverted();
foreach (QGesture *gesture, allGestures) {
+ // cache scene coordinates of the hot spot
+ if (gesture->hasHotSpot()) {
+ gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot());
+ } else {
+ gesture->d_func()->sceneHotSpot = QPointF();
+ }
+
QGraphicsObject *target = gestureTargets.value(gesture, 0);
if (!target) {
// when we are not in started mode but don't have a target
// then the only one interested in gesture is the view/scene
if (gesture->state() == Qt::GestureStarted)
startedGestures.insert(gesture);
- } else {
- gesturesPerItem[target].append(gesture);
}
}
- QMap<Qt::GestureType, QGesture *> conflictedGestures;
- QList<QList<QGraphicsObject *> > conflictedItems;
- QHash<QGesture *, QGraphicsObject *> normalGestures;
- getGestureTargets(startedGestures, viewport, &conflictedGestures, &conflictedItems,
- &normalGestures);
- DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "Conflicting gestures:" << conflictedGestures.values() << conflictedItems;
- Q_ASSERT((conflictedGestures.isEmpty() && conflictedItems.isEmpty()) ||
- (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()));
-
- // gestures that were sent as override events, but no one accepted them
- QHash<QGesture *, QGraphicsObject *> ignoredConflictedGestures;
-
- // deliver conflicted gestures as override events first
- while (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()) {
- // get the topmost item to deliver the override event
- Q_ASSERT(!conflictedItems.isEmpty());
- Q_ASSERT(!conflictedItems.first().isEmpty());
- QGraphicsObject *topmost = conflictedItems.first().first();
- for (int i = 1; i < conflictedItems.size(); ++i) {
- QGraphicsObject *item = conflictedItems.at(i).first();
- if (qt_closestItemFirst(item, topmost)) {
- topmost = item;
- }
- }
- // get a list of gestures to send to the item
- QList<Qt::GestureType> grabbedGestures =
- topmost->QGraphicsItem::d_func()->gestureContext.keys();
- QList<QGesture *> gestures;
- for (int i = 0; i < grabbedGestures.size(); ++i) {
- if (QGesture *g = conflictedGestures.value(grabbedGestures.at(i), 0)) {
- gestures.append(g);
- if (!ignoredConflictedGestures.contains(g))
- ignoredConflictedGestures.insert(g, topmost);
- }
- }
-
- // send gesture override to the topmost item
- QGestureEvent ev(gestures);
- ev.t = QEvent::GestureOverride;
- ev.setWidget(event->widget());
- // mark event and individual gestures as ignored
- ev.ignore();
- foreach(QGesture *g, gestures)
- ev.setAccepted(g, false);
+ if (!startedGestures.isEmpty()) {
+ QSet<QGesture *> normalGestures; // that have just one target
+ QSet<QGesture *> conflictedGestures; // that have multiple possible targets
+ gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures, 0,
+ &normalGestures, &conflictedGestures);
+ cachedTargetItems = cachedItemGestures.keys();
+ qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "delivering override to"
- << topmost << gestures;
- sendEvent(topmost, &ev);
- // mark all accepted gestures to deliver them as normal gesture events
- foreach (QGesture *g, gestures) {
- if (ev.isAccepted() || ev.isAccepted(g)) {
- conflictedGestures.remove(g->gestureType());
- gestureTargets.remove(g);
- // add the gesture to the list of normal delivered gestures
- normalGestures.insert(g, topmost);
+ << "Normal gestures:" << normalGestures
+ << "Conflicting gestures:" << conflictedGestures;
+
+ // deliver conflicted gestures as override events AND remember
+ // initial gesture targets
+ if (!conflictedGestures.isEmpty()) {
+ for (int i = 0; i < cachedTargetItems.size(); ++i) {
+ QWeakPointer<QGraphicsObject> item = cachedTargetItems.at(i);
+
+ // get gestures to deliver to the current item
+ QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data());
+ if (gestures.isEmpty())
+ continue;
+
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "override was accepted:"
- << g << topmost;
- ignoredConflictedGestures.remove(g);
+ << "delivering override to"
+ << item.data() << gestures;
+ // send gesture override
+ QGestureEvent ev(gestures.toList());
+ ev.t = QEvent::GestureOverride;
+ ev.setWidget(event->widget());
+ // mark event and individual gestures as ignored
+ ev.ignore();
+ foreach(QGesture *g, gestures)
+ ev.setAccepted(g, false);
+ sendEvent(item.data(), &ev);
+ // mark all accepted gestures to deliver them as normal gesture events
+ foreach (QGesture *g, gestures) {
+ if (ev.isAccepted() || ev.isAccepted(g)) {
+ conflictedGestures.remove(g);
+ // mark the item as a gesture target
+ if (item)
+ gestureTargets.insert(g, item.data());
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "override was accepted:"
+ << g << item.data();
+ }
+ // remember the first item that received the override event
+ // as it most likely become a target if noone else accepts
+ // the override event
+ if (!gestureTargets.contains(g) && item)
+ gestureTargets.insert(g, item.data());
+
+ }
+ if (conflictedGestures.isEmpty())
+ break;
}
}
- // remove the item that we've already delivered from the list
- for (int i = 0; i < conflictedItems.size(); ) {
- QList<QGraphicsObject *> &items = conflictedItems[i];
- if (items.first() == topmost) {
- items.removeFirst();
- if (items.isEmpty()) {
- conflictedItems.removeAt(i);
- continue;
+ // remember the initial target item for each gesture that was not in
+ // the conflicted state.
+ if (!normalGestures.isEmpty()) {
+ for (int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) {
+ QGraphicsObject *item = cachedTargetItems.at(i);
+
+ // get gestures to deliver to the current item
+ foreach (QGesture *g, cachedItemGestures.value(item)) {
+ if (!gestureTargets.contains(g)) {
+ gestureTargets.insert(g, item);
+ normalGestures.remove(g);
+ }
}
}
- ++i;
}
}
- // put back those started gestures that are not in the conflicted state
- // and remember their targets
- QHash<QGesture *, QGraphicsObject *>::const_iterator it = normalGestures.begin(),
- e = normalGestures.end();
- for (; it != e; ++it) {
- QGesture *g = it.key();
- QGraphicsObject *receiver = it.value();
- Q_ASSERT(!gestureTargets.contains(g));
- gestureTargets.insert(g, receiver);
- gesturesPerItem[receiver].append(g);
- }
- it = ignoredConflictedGestures.begin();
- e = ignoredConflictedGestures.end();
- for (; it != e; ++it) {
- QGesture *g = it.key();
- QGraphicsObject *receiver = it.value();
- Q_ASSERT(!gestureTargets.contains(g));
- gestureTargets.insert(g, receiver);
- gesturesPerItem[receiver].append(g);
- }
-
- DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "Started gestures:" << normalGestures.keys()
- << "All gestures:" << gesturesPerItem.values();
-
- // deliver all events
- QList<QGesture *> alreadyIgnoredGestures;
- QHash<QGraphicsObject *, QSet<QGesture *> > itemIgnoredGestures;
- QList<QGraphicsObject *> targetItems = gesturesPerItem.keys();
- qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
- for (int i = 0; i < targetItems.size(); ++i) {
- QGraphicsObject *item = targetItems.at(i);
- QList<QGesture *> gestures = gesturesPerItem.value(item);
- // remove gestures that were already delivered once and were ignored
- DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "already ignored gestures for item"
- << item << ":" << itemIgnoredGestures.value(item);
-
- if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item
- continue;
- QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func();
- foreach(QGesture *g, alreadyIgnoredGestures) {
- QMap<Qt::GestureType, Qt::GestureFlags>::iterator contextit =
- gid->gestureContext.find(g->gestureType());
- bool deliver = contextit != gid->gestureContext.end() &&
- (g->state() == Qt::GestureStarted ||
- (contextit.value() & Qt::ReceivePartialGestures));
- if (deliver)
- gestures += g;
+ // deliver all gesture events
+ QSet<QGesture *> undeliveredGestures;
+ QSet<QGesture *> parentPropagatedGestures;
+ foreach (QGesture *gesture, allGestures) {
+ if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) {
+ cachedItemGestures[target].insert(gesture);
+ cachedTargetItems.append(target);
+ undeliveredGestures.insert(gesture);
+ QGraphicsItemPrivate *d = target->QGraphicsItem::d_func();
+ const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
+ if (flags & Qt::IgnoredGesturesPropagateToParent)
+ parentPropagatedGestures.insert(gesture);
+ } else {
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "no target for" << gesture << "at"
+ << gesture->hotSpot() << gesture->d_func()->sceneHotSpot;
}
+ }
+ qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
+ for (int i = 0; i < cachedTargetItems.size(); ++i) {
+ QWeakPointer<QGraphicsObject> receiver = cachedTargetItems.at(i);
+ QSet<QGesture *> gestures =
+ undeliveredGestures & cachedItemGestures.value(receiver.data());
+ gestures -= cachedAlreadyDeliveredGestures.value(receiver.data());
+
if (gestures.isEmpty())
continue;
+
+ cachedAlreadyDeliveredGestures[receiver.data()] += gestures;
+ const bool isPanel = receiver.data()->isPanel();
+
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
<< "delivering to"
- << item << gestures;
- QGestureEvent ev(gestures);
+ << receiver.data() << gestures;
+ QGestureEvent ev(gestures.toList());
ev.setWidget(event->widget());
- sendEvent(item, &ev);
+ sendEvent(receiver.data(), &ev);
QSet<QGesture *> ignoredGestures;
foreach (QGesture *g, gestures) {
if (!ev.isAccepted() && !ev.isAccepted(g)) {
- ignoredGestures.insert(g);
+ // if the gesture was ignored by its target, we will update the
+ // targetItems list with a possible target items (items that
+ // want to receive partial gestures).
+ // ### wont' work if the target was destroyed in the event
+ // we will just stop delivering it.
+ if (receiver && receiver.data() == gestureTargets.value(g, 0))
+ ignoredGestures.insert(g);
} else {
- if (g->state() == Qt::GestureStarted)
- gestureTargets[g] = item;
+ if (receiver && g->state() == Qt::GestureStarted) {
+ // someone accepted the propagated initial GestureStarted
+ // event, let it be the new target for all following events.
+ gestureTargets[g] = receiver.data();
+ }
+ undeliveredGestures.remove(g);
}
}
- if (!ignoredGestures.isEmpty()) {
- // get a list of items under the (current) hotspot of each ignored
- // gesture and start delivery again from the beginning
- DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "item has ignored the event, will propagate."
- << item << ignoredGestures;
- itemIgnoredGestures[item] += ignoredGestures;
- QMap<Qt::GestureType, QGesture *> conflictedGestures;
- QList<QList<QGraphicsObject *> > itemsForConflictedGestures;
- QHash<QGesture *, QGraphicsObject *> normalGestures;
- getGestureTargets(ignoredGestures, viewport,
- &conflictedGestures, &itemsForConflictedGestures,
- &normalGestures);
- QSet<QGraphicsObject *> itemsSet = targetItems.toSet();
- for (int k = 0; k < itemsForConflictedGestures.size(); ++k)
- itemsSet += itemsForConflictedGestures.at(k).toSet();
- targetItems = itemsSet.toList();
- qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
- alreadyIgnoredGestures = conflictedGestures.values();
+ if (undeliveredGestures.isEmpty())
+ break;
+
+ // ignoredGestures list is only filled when delivering to the gesture
+ // target item, so it is safe to assume item == target.
+ if (!ignoredGestures.isEmpty() && !isPanel) {
+ // look for new potential targets for gestures that were ignored
+ // and should be propagated.
+
+ QSet<QGraphicsObject *> targetsSet = cachedTargetItems.toSet();
+
+ if (receiver) {
+ // first if the gesture should be propagated to parents only
+ for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
+ it != ignoredGestures.end();) {
+ if (parentPropagatedGestures.contains(*it)) {
+ QGesture *gesture = *it;
+ const Qt::GestureType gestureType = gesture->gestureType();
+ QGraphicsItem *item = receiver.data();
+ while (item) {
+ if (QGraphicsObject *obj = item->toGraphicsObject()) {
+ if (item->d_func()->gestureContext.contains(gestureType)) {
+ targetsSet.insert(obj);
+ cachedItemGestures[obj].insert(gesture);
+ }
+ }
+ if (item->isPanel())
+ break;
+ item = item->parentItem();
+ }
+
+ it = ignoredGestures.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ }
+
+ gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures,
+ &cachedItemGestures, &targetsSet, 0, 0);
+
+ cachedTargetItems = targetsSet.toList();
+ qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "new targets:" << targetItems;
+ << "new targets:" << cachedTargetItems;
i = -1; // start delivery again
continue;
}
}
+
foreach (QGesture *g, startedGestures) {
if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
DEBUG() << "lets try to cancel some";
// find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
- cancelGesturesForChildren(g, event->widget());
+ cancelGesturesForChildren(g);
}
}
@@ -6152,9 +6196,13 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
break;
}
}
+
+ cachedTargetItems.clear();
+ cachedItemGestures.clear();
+ cachedAlreadyDeliveredGestures.clear();
}
-void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original, QWidget *viewport)
+void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original)
{
Q_ASSERT(original);
QGraphicsItem *originalItem = gestureTargets.value(original);
@@ -6210,8 +6258,7 @@ void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original, QWidge
if (!g->hasHotSpot())
continue;
- QPoint screenPos = g->hotSpot().toPoint();
- QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
+ QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot, 0);
for (int j = 0; j < items.size(); ++j) {
QGraphicsObject *item = items.at(j)->toGraphicsObject();
if (!item)
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 04ffe0f90e..11e250efca 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -87,7 +87,9 @@ public:
static QGraphicsScenePrivate *get(QGraphicsScene *q);
- static int changedSignalIndex;
+ int changedSignalIndex;
+ int processDirtyItemsIndex;
+ int polishItemsIndex;
QGraphicsScene::ItemIndexMethod indexMethod;
QGraphicsSceneIndex *index;
@@ -294,13 +296,18 @@ public:
bool allItemsIgnoreTouchEvents;
void enableTouchEventsOnViews();
+ QList<QGraphicsObject *> cachedTargetItems;
+ QHash<QGraphicsObject *, QSet<QGesture *> > cachedItemGestures;
+ QHash<QGraphicsObject *, QSet<QGesture *> > cachedAlreadyDeliveredGestures;
QHash<QGesture *, QGraphicsObject *> gestureTargets;
void gestureEventHandler(QGestureEvent *event);
- void getGestureTargets(const QSet<QGesture *> &gestures, QWidget *viewport,
- QMap<Qt::GestureType, QGesture *> *conflictedGestures,
- QList<QList<QGraphicsObject *> > *conflictedItems,
- QHash<QGesture *, QGraphicsObject *> *normalGestures);
- void cancelGesturesForChildren(QGesture *original, QWidget *viewport);
+ void gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures,
+ Qt::GestureFlag flag,
+ QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
+ QSet<QGraphicsObject *> *itemsSet = 0,
+ QSet<QGesture *> *normal = 0,
+ QSet<QGesture *> *conflicts = 0);
+ void cancelGesturesForChildren(QGesture *original);
void updateInputMethodSensitivityInViews();
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index a767987c35..c951dcef61 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -733,11 +733,13 @@ void QGraphicsViewPrivate::_q_unsetViewportCursor()
}
// Restore the original viewport cursor.
- hasStoredOriginalCursor = false;
- if (dragMode == QGraphicsView::ScrollHandDrag)
- viewport->setCursor(Qt::OpenHandCursor);
- else
- viewport->setCursor(originalCursor);
+ if (hasStoredOriginalCursor) {
+ hasStoredOriginalCursor = false;
+ if (dragMode == QGraphicsView::ScrollHandDrag)
+ viewport->setCursor(Qt::OpenHandCursor);
+ else
+ viewport->setCursor(originalCursor);
+ }
}
#endif
@@ -1035,10 +1037,28 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg
void QGraphicsViewPrivate::updateInputMethodSensitivity()
{
Q_Q(QGraphicsView);
- bool enabled = scene && scene->focusItem()
- && (scene->focusItem()->flags() & QGraphicsItem::ItemAcceptsInputMethod);
+ QGraphicsItem *focusItem = 0;
+ bool enabled = scene && (focusItem = scene->focusItem())
+ && (focusItem->d_ptr->flags & QGraphicsItem::ItemAcceptsInputMethod);
q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled);
+
+ if (!enabled) {
+ q->setInputMethodHints(0);
+ return;
+ }
+
+ QGraphicsProxyWidget *proxy = focusItem->d_ptr->isWidget && focusItem->d_ptr->isProxyWidget()
+ ? static_cast<QGraphicsProxyWidget *>(focusItem) : 0;
+ if (!proxy) {
+ q->setInputMethodHints(focusItem->inputMethodHints());
+ } else if (QWidget *widget = proxy->widget()) {
+ if (QWidget *fw = widget->focusWidget())
+ widget = fw;
+ q->setInputMethodHints(widget->inputMethodHints());
+ } else {
+ q->setInputMethodHints(0);
+ }
}
/*!
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index 1c66d07c98..80e3ec1dbd 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -65,7 +65,7 @@
QT_BEGIN_NAMESPACE
-class Q_AUTOTEST_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
+class Q_GUI_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
{
Q_DECLARE_PUBLIC(QGraphicsView)
public:
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 8b80bc8f6c..bc8ccb0130 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -324,6 +324,14 @@ void QGraphicsWidget::resize(const QSizeF &size)
*/
/*!
+
+ \fn QGraphicsWidget::geometryChanged()
+
+ This signal gets emitted whenever the geometry of the item changes
+ \internal
+*/
+
+/*!
\property QGraphicsWidget::geometry
\brief the geometry of the widget
@@ -384,18 +392,28 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
}
QSizeF oldSize = size();
QGraphicsLayoutItem::setGeometry(newGeom);
-
+ emit geometryChanged();
// Send resize event
bool resized = newGeom.size() != oldSize;
if (resized) {
QGraphicsSceneResizeEvent re;
re.setOldSize(oldSize);
re.setNewSize(newGeom.size());
+ if (oldSize.width() != newGeom.size().width())
+ emit widthChanged();
+ if (oldSize.height() != newGeom.size().height())
+ emit heightChanged();
QApplication::sendEvent(this, &re);
}
}
/*!
+ \fn QGraphicsWidget::geometryChanged()
+
+ This signal gets emitted whenever the geometry is changed in setGeometry().
+*/
+
+/*!
\fn QRectF QGraphicsWidget::rect() const
Returns the item's local rect as a QRectF. This function is equivalent
@@ -789,6 +807,7 @@ void QGraphicsWidget::setLayout(QGraphicsLayout *l)
l->setParentLayoutItem(this);
l->d_func()->reparentChildItems(this);
l->invalidate();
+ emit layoutChanged();
}
/*!
@@ -967,6 +986,36 @@ void QGraphicsWidget::setPalette(const QPalette &palette)
}
/*!
+ \property QGraphicsWidget::autoFillBackground
+ \brief whether the widget background is filled automatically
+ \since 4.7
+
+ If enabled, this property will cause Qt to fill the background of the
+ widget before invoking the paint() method. The color used is defined by the
+ QPalette::Window color role from the widget's \l{QPalette}{palette}.
+
+ In addition, Windows are always filled with QPalette::Window, unless the
+ WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
+
+ By default, this property is false.
+
+ \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
+*/
+bool QGraphicsWidget::autoFillBackground() const
+{
+ Q_D(const QGraphicsWidget);
+ return d->autoFillBackground;
+}
+void QGraphicsWidget::setAutoFillBackground(bool enabled)
+{
+ Q_D(QGraphicsWidget);
+ if (d->autoFillBackground != enabled) {
+ d->autoFillBackground = enabled;
+ update();
+ }
+}
+
+/*!
If this widget is currently managed by a layout, this function notifies
the layout that the widget's size hints have changed and the layout
may need to resize and reposition the widget accordingly.
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index f1d382bb44..a22b64228e 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -73,7 +73,7 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay
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(QSizeF size READ size WRITE resize NOTIFY geometryChanged)
Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize)
Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize)
Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize)
@@ -81,11 +81,12 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay
Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy)
Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle)
- Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
+ Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry NOTIFY geometryChanged)
+ Q_PROPERTY(bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground)
+ Q_PROPERTY(QGraphicsLayout* layout READ layout WRITE setLayout NOTIFY layoutChanged)
public:
QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
~QGraphicsWidget();
-
QGraphicsLayout *layout() const;
void setLayout(QGraphicsLayout *layout);
void adjustSize();
@@ -103,6 +104,9 @@ public:
QPalette palette() const;
void setPalette(const QPalette &palette);
+ bool autoFillBackground() const;
+ void setAutoFillBackground(bool enabled);
+
void resize(const QSizeF &size);
inline void resize(qreal w, qreal h) { resize(QSizeF(w, h)); }
QSizeF size() const;
@@ -175,6 +179,10 @@ public:
using QObject::children;
#endif
+Q_SIGNALS:
+ void geometryChanged();
+ void layoutChanged();
+
public Q_SLOTS:
bool close();
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 1835c74f17..6e397b67ef 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -44,6 +44,7 @@
#ifndef QT_NO_GRAPHICSVIEW
#include <QtCore/qdebug.h>
+#include <QtCore/qnumeric.h>
#include "qgraphicswidget_p.h"
#include "qgraphicslayout.h"
#include "qgraphicsscene_p.h"
@@ -825,6 +826,56 @@ void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l)
}
}
+qreal QGraphicsWidgetPrivate::width() const
+{
+ Q_Q(const QGraphicsWidget);
+ return q->geometry().width();
+}
+
+void QGraphicsWidgetPrivate::setWidth(qreal w)
+{
+ if (qIsNaN(w))
+ return;
+ Q_Q(QGraphicsWidget);
+ if (q->geometry().width() == w)
+ return;
+
+ QRectF oldGeom = q->geometry();
+
+ q->setGeometry(QRectF(q->x(), q->y(), w, height()));
+}
+
+void QGraphicsWidgetPrivate::resetWidth()
+{
+ Q_Q(QGraphicsWidget);
+ q->setGeometry(QRectF(q->x(), q->y(), 0, height()));
+}
+
+qreal QGraphicsWidgetPrivate::height() const
+{
+ Q_Q(const QGraphicsWidget);
+ return q->geometry().height();
+}
+
+void QGraphicsWidgetPrivate::setHeight(qreal h)
+{
+ if (qIsNaN(h))
+ return;
+ Q_Q(QGraphicsWidget);
+ if (q->geometry().height() == h)
+ return;
+
+ QRectF oldGeom = q->geometry();
+
+ q->setGeometry(QRectF(q->x(), q->y(), width(), h));
+}
+
+void QGraphicsWidgetPrivate::resetHeight()
+{
+ Q_Q(QGraphicsWidget);
+ q->setGeometry(QRectF(q->x(), q->y(), width(), 0));
+}
+
QT_END_NAMESPACE
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h
index 2c5b3bfedd..7116a2337b 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.h
+++ b/src/gui/graphicsview/qgraphicswidget_p.h
@@ -80,6 +80,7 @@ public:
inSetGeometry(0),
polished(0),
inSetPos(0),
+ autoFillBackground(0),
focusPolicy(Qt::NoFocus),
focusNext(0),
focusPrev(0),
@@ -130,6 +131,15 @@ public:
void windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event);
bool hasDecoration() const;
+ // Private Properties
+ qreal width() const;
+ void setWidth(qreal);
+ void resetWidth();
+
+ qreal height() const;
+ void setHeight(qreal);
+ void resetHeight();
+
// State
inline int attributeToBitIndex(Qt::WidgetAttribute att) const
{
@@ -172,6 +182,7 @@ public:
quint32 inSetGeometry : 1;
quint32 polished: 1;
quint32 inSetPos : 1;
+ quint32 autoFillBackground : 1;
// Focus
Qt::FocusPolicy focusPolicy;
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 8b5883582d..a6370b20d2 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -41,7 +41,7 @@ include(math3d/math3d.pri)
include(effects/effects.pri)
include(egl/egl.pri)
-
+win32:!wince*: DEFINES += QT_NO_EGL
embedded: QT += network
QMAKE_LIBS += $$QMAKE_LIBS_GUI
@@ -51,12 +51,14 @@ 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: {
+symbian {
TARGET.UID3=0x2001B2DD
- # ro-section in gui can exceed default allocated space, so move rw-section a little further
- QMAKE_LFLAGS.ARMCC += --rw-base 0x800000
- QMAKE_LFLAGS.GCCE += -Tdata 0xC00000
+ symbian-abld|symbian-sbsv2 {
+ # ro-section in gui can exceed default allocated space, so move rw-section a little further
+ QMAKE_LFLAGS.ARMCC += --rw-base 0x800000
+ QMAKE_LFLAGS.GCCE += -Tdata 0xC00000
+ }
# Partial upgrade SIS file
vendorinfo = \
@@ -69,7 +71,7 @@ symbian: {
pu_header = "; Partial upgrade package for testing QtGui changes without reinstalling everything" \
"$${LITERAL_HASH}{\"Qt gui\"}, (0x2001E61C), $${QT_MAJOR_VERSION},$${QT_MINOR_VERSION},$${QT_PATCH_VERSION}, TYPE=PU"
partial_upgrade.pkg_prerules = pu_header vendorinfo
- partial_upgrade.sources = qtgui.dll
+ partial_upgrade.sources = $$QMAKE_LIBDIR_QT/QtGui.dll
partial_upgrade.path = c:/sys/bin
DEPLOYMENT = partial_upgrade $$DEPLOYMENT
}
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index b67be55f39..8d75fdd078 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -96,6 +96,7 @@ SOURCES += \
unix:LIBS_PRIVATE += -lpng
win32:LIBS += libpng.lib
} else {
+ DEFINES *= QT_USE_BUNDLED_LIBPNG
!isEqual(QT_ARCH, i386):!isEqual(QT_ARCH, x86_64):DEFINES += PNG_NO_ASSEMBLER_CODE
INCLUDEPATH += ../3rdparty/libpng ../3rdparty/zlib
SOURCES += ../3rdparty/libpng/png.c \
@@ -112,8 +113,7 @@ SOURCES += \
../3rdparty/libpng/pngwio.c \
../3rdparty/libpng/pngwrite.c \
../3rdparty/libpng/pngwtran.c \
- ../3rdparty/libpng/pngwutil.c \
- ../3rdparty/libpng/pnggccrd.c
+ ../3rdparty/libpng/pngwutil.c
}
} else {
DEFINES *= QT_NO_IMAGEFORMAT_PNG
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index fad51f41ae..bc52e994a4 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -879,6 +879,25 @@ QList<QSize> QIcon::availableSizes(Mode mode, State state) const
}
/*!
+ \since 4.7
+
+ Returns the name used to create the icon, if available.
+
+ Depending on the way the icon was created, it may have an associated
+ name. This is the case for icons created with fromTheme() or icons
+ using a QIconEngine which supports the QIconEngineV2::IconNameHook.
+
+ \sa fromTheme(), QIconEngine
+*/
+QString QIcon::name() const
+{
+ if (!d || !d->engine || d->engine_version < 2)
+ return QString();
+ QIconEngineV2 *engine = static_cast<QIconEngineV2*>(d->engine);
+ return engine->iconName();
+}
+
+/*!
\since 4.6
Sets the search paths for icon themes to \a paths.
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index 2812703572..faef07be51 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -81,6 +81,8 @@ public:
QSize actualSize(const QSize &size, Mode mode = Normal, State state = Off) const;
+ QString name() const;
+
void paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const;
inline void paint(QPainter *painter, int x, int y, int w, int h, Qt::Alignment alignment = Qt::AlignCenter, Mode mode = Normal, State state = Off) const
{ paint(painter, QRect(x, y, w, h), alignment, mode, state); }
diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp
index 4c7c7287b7..050d48d525 100644
--- a/src/gui/image/qiconengine.cpp
+++ b/src/gui/image/qiconengine.cpp
@@ -183,6 +183,10 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI
that should be filled with icon sizes. Engines that work in terms
of a scalable, vectorial format normally return an empty list.
+ \value IconNameHook Allows to query the name used to create the
+ icon, for example when instantiating an icon using
+ QIcon::fromTheme().
+
\sa virtual_hook()
*/
@@ -301,4 +305,20 @@ QList<QSize> QIconEngineV2::availableSizes(QIcon::Mode mode, QIcon::State state)
return arg.sizes;
}
+/*!
+ \since 4.7
+
+ Returns the name used to create the engine, if available.
+
+ \note This is a helper method and the actual work is done by
+ virtual_hook() method, hence this method depends on icon engine support
+ and may not work with all icon engines.
+ */
+QString QIconEngineV2::iconName()
+{
+ QString name;
+ virtual_hook(QIconEngineV2::IconNameHook, reinterpret_cast<void*>(&name));
+ return name;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h
index 1f9266bd3b..6d8b6ade71 100644
--- a/src/gui/image/qiconengine.h
+++ b/src/gui/image/qiconengine.h
@@ -80,7 +80,7 @@ public:
virtual void virtual_hook(int id, void *data);
public:
- enum IconEngineHook { AvailableSizesHook = 1 };
+ enum IconEngineHook { AvailableSizesHook = 1, IconNameHook };
struct AvailableSizesArgument
{
@@ -92,6 +92,9 @@ public:
// ### Qt 5: make this function const and virtual.
QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal,
QIcon::State state = QIcon::Off);
+
+ // ### Qt 5: make this function const and virtual.
+ QString iconName();
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 72ec2e85d4..a515ef8bec 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -554,6 +554,12 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
}
}
break;
+ case QIconEngineV2::IconNameHook:
+ {
+ QString &name = *reinterpret_cast<QString*>(data);
+ name = m_iconName;
+ }
+ break;
default:
QIconEngineV2::virtual_hook(id, data);
}
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index d46f40e4e0..85be5b1ff3 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -480,9 +480,12 @@ bool QImageData::checkForAlphaPixels() const
\row
\o Low-level information
\o
+
The depth() function returns the depth of the image. The supported
- depths are 1 (monochrome), 8 and 32 (for more information see the
- \l {QImage#Image Formats}{Image Formats} section).
+ depths are 1 (monochrome), 8, 16, 24 and 32 bits. The
+ bitPlaneCount() function tells how many of those bits that are
+ used. For more information see the
+ \l {QImage#Image Formats}{Image Formats} section.
The format(), bytesPerLine(), and byteCount() functions provide
low-level information about the data stored in the image.
@@ -707,7 +710,7 @@ bool QImageData::checkForAlphaPixels() const
packed with the less significant bit (LSB) first.
\value Format_Indexed8 The image is stored using 8-bit indexes
- into a colormap.
+ into a colormap.
\value Format_RGB32 The image is stored using a 32-bit RGB format (0xffRRGGBB).
@@ -1580,12 +1583,12 @@ QRect QImage::rect() const
/*!
Returns the depth of the image.
- The image depth is the number of bits used to encode a single
+ The image depth is the number of bits used to store a single
pixel, also called bits per pixel (bpp).
The supported depths are 1, 8, 16, 24 and 32.
- \sa convertToFormat(), {QImage#Image Formats}{Image Formats},
+ \sa bitPlaneCount(), convertToFormat(), {QImage#Image Formats}{Image Formats},
{QImage#Image Information}{Image Information}
*/
@@ -1835,7 +1838,7 @@ void QImage::setColor(int i, QRgb c)
qAlpha() to access the pixels.
\sa bytesPerLine(), bits(), {QImage#Pixel Manipulation}{Pixel
- Manipulation}
+ Manipulation}, constScanLine()
*/
uchar *QImage::scanLine(int i)
{
@@ -1865,6 +1868,28 @@ const uchar *QImage::scanLine(int i) const
/*!
+ Returns a pointer to the pixel data at the scanline with index \a
+ i. The first scanline is at index 0.
+
+ The scanline data is aligned on a 32-bit boundary.
+
+ Note that QImage uses \l{Implicit Data Sharing} {implicit data
+ sharing}, but this function does \e not perform a deep copy of the
+ shared pixel data, because the returned data is const.
+
+ \sa scanLine(), constBits()
+ \since 4.7
+*/
+const uchar *QImage::constScanLine(int i) const
+{
+ if (!d)
+ return 0;
+
+ Q_ASSERT(i >= 0 && i < height());
+ return d->data + i * d->bytes_per_line;
+}
+
+/*!
Returns a pointer to the first pixel data. This is equivalent to
scanLine(0).
@@ -1873,7 +1898,7 @@ const uchar *QImage::scanLine(int i) const
data, thus ensuring that this QImage is the only one using the
current return value.
- \sa scanLine(), byteCount()
+ \sa scanLine(), byteCount(), constBits()
*/
uchar *QImage::bits()
{
@@ -1901,6 +1926,20 @@ const uchar *QImage::bits() const
}
+/*!
+ Returns a pointer to the first pixel data.
+
+ Note that QImage uses \l{Implicit Data Sharing} {implicit data
+ sharing}, but this function does \e not perform a deep copy of the
+ shared pixel data, because the returned data is const.
+
+ \sa bits(), constScanLine()
+ \since 4.7
+*/
+const uchar *QImage::constBits() const
+{
+ return d ? d->data : 0;
+}
/*!
\fn void QImage::reset()
@@ -2949,19 +2988,19 @@ static void convert_Indexed8_to_X32(QImageData *dest, const QImageData *src, Qt:
colorTable.resize(256);
for (int i=0; i<256; ++i)
colorTable[i] = qRgb(i, i, i);
-
}
int w = src->width;
const uchar *src_data = src->data;
uchar *dest_data = dest->data;
+ int tableSize = colorTable.size() - 1;
for (int y = 0; y < src->height; y++) {
uint *p = (uint *)dest_data;
const uchar *b = src_data;
uint *end = p + w;
while (p < end)
- *p++ = colorTable.at(*b++);
+ *p++ = colorTable.at(qMin<int>(tableSize, *b++));
src_data += src->bytes_per_line;
dest_data += dest->bytes_per_line;
@@ -5665,12 +5704,12 @@ void QImage::setAlphaChannel(const QImage &alphaChannel)
return;
}
- detach();
-
- QImage converted = convertToFormat(QImage::Format_ARGB32_Premultiplied);
- if (!converted.isNull())
- *this = converted;
+ if (d->format == QImage::Format_ARGB32_Premultiplied)
+ detach();
else
+ *this = convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
+ if (isNull())
return;
// Slight optimization since alphachannels are returned as 8-bit grays.
@@ -5816,6 +5855,48 @@ bool QImage::hasAlphaChannel() const
}
+/*!
+ \since 4.7
+ Returns the number of bit planes in the image.
+
+ The number of bit planes is the number of bits of color and
+ transparency information for each pixel. This is different from
+ (i.e. smaller than) the depth when the image format contains
+ unused bits.
+
+ \sa depth(), format(), {QImage#Image Formats}{Image Formats}
+*/
+int QImage::bitPlaneCount() const
+{
+ if (!d)
+ return 0;
+ int bpc = 0;
+ switch (d->format) {
+ case QImage::Format_Invalid:
+ break;
+ case QImage::Format_RGB32:
+ bpc = 24;
+ break;
+ case QImage::Format_RGB666:
+ bpc = 18;
+ break;
+ case QImage::Format_RGB555:
+ bpc = 15;
+ break;
+ case QImage::Format_ARGB8555_Premultiplied:
+ bpc = 23;
+ break;
+ case QImage::Format_RGB444:
+ bpc = 12;
+ break;
+ default:
+ bpc = depthForFormat(d->format);
+ break;
+ }
+ return bpc;
+}
+
+
#ifdef QT3_SUPPORT
#if defined(Q_WS_X11)
QT_BEGIN_INCLUDE_NAMESPACE
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index ac973a1de9..896061ffc0 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -169,6 +169,7 @@ public:
QT_DEPRECATED int numColors() const;
#endif
int colorCount() const;
+ int bitPlaneCount() const;
QRgb color(int i) const;
void setColor(int i, QRgb c);
@@ -182,6 +183,7 @@ public:
uchar *bits();
const uchar *bits() const;
+ const uchar *constBits() const;
#ifdef QT_DEPRECATED
QT_DEPRECATED int numBytes() const;
#endif
@@ -189,6 +191,7 @@ public:
uchar *scanLine(int);
const uchar *scanLine(int) const;
+ const uchar *constScanLine(int) const;
int bytesPerLine() const;
bool valid(int x, int y) const;
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 9320cfcf7d..27f9627478 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -503,7 +503,7 @@ QImageReaderPrivate::~QImageReaderPrivate()
bool QImageReaderPrivate::initHandler()
{
// check some preconditions
- if (!device || (!deleteDevice && !device->isOpen())) {
+ if (!device || (!deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly))) {
imageReaderError = QImageReader::DeviceError;
errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Invalid device"));
return false;
diff --git a/src/gui/image/qpaintengine_pic.cpp b/src/gui/image/qpaintengine_pic.cpp
index e7f41e7fbc..fd1ee6a525 100644
--- a/src/gui/image/qpaintengine_pic.cpp
+++ b/src/gui/image/qpaintengine_pic.cpp
@@ -486,8 +486,11 @@ void QPicturePaintEngine::drawTextItem(const QPointF &p , const QTextItem &ti)
qDebug() << " -> drawTextItem():" << p << ti.text();
#endif
+ const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
+ if (si.chars == 0)
+ QPaintEngine::drawTextItem(p, ti); // Draw as path
+
if (d->pic_d->formatMajor >= 9) {
- const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
int pos;
SERIALIZE_CMD(QPicturePrivate::PdcDrawTextItem);
QFont fnt = ti.font();
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index 48d2de3e3b..20a1dce96e 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -440,36 +440,6 @@ bool QPicture::play(QPainter *painter)
return true; // no end-command
}
-
-//
-// QFakeDevice is used to create fonts with a custom DPI
-//
-class QFakeDevice : public QPaintDevice
-{
-public:
- QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
- void setDpiX(int dpi) { dpi_x = dpi; }
- void setDpiY(int dpi) { dpi_y = dpi; }
- QPaintEngine *paintEngine() const { return 0; }
- int metric(PaintDeviceMetric m) const
- {
- switch(m) {
- case PdmPhysicalDpiX:
- case PdmDpiX:
- return dpi_x;
- case PdmPhysicalDpiY:
- case PdmDpiY:
- return dpi_y;
- default:
- return QPaintDevice::metric(m);
- }
- }
-
-private:
- int dpi_x;
- int dpi_y;
-};
-
/*!
\internal
Iterates over the internal picture data and draws the picture using
@@ -679,13 +649,16 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
if (d->formatMajor >= 9) {
s >> dbl;
- QFont fnt(font);
- if (dbl != 1.0) {
- QFakeDevice fake;
- fake.setDpiX(qRound(dbl*qt_defaultDpiX()));
- fake.setDpiY(qRound(dbl*qt_defaultDpiY()));
- fnt = QFont(font, &fake);
- }
+ QFont fnt(font, painter->device());
+
+ // Fonts that specify a pixel size should not be scaled - QPicture already
+ // have a matrix set to compensate for the DPI differences between the
+ // default Qt DPI and the actual target device DPI, and we have to take that
+ // into consideration in the case where the font has a pixel size set.
+
+ qreal scale = fnt.pointSize() == -1 ? 1 : painter->device()->logicalDpiY() / (dbl*qt_defaultDpiY());
+ painter->save();
+ painter->scale(1/scale, 1/scale);
qreal justificationWidth;
s >> justificationWidth;
@@ -694,15 +667,16 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
QSizeF size(1, 1);
if (justificationWidth > 0) {
- size.setWidth(justificationWidth);
+ size.setWidth(justificationWidth*scale);
flags |= Qt::TextJustificationForced;
flags |= Qt::AlignJustify;
}
QFontMetrics fm(fnt);
- QPointF pt(p.x(), p.y() - fm.ascent());
+ QPointF pt(p.x()*scale, p.y()*scale - fm.ascent());
qt_format_text(fnt, QRectF(pt, size), flags, /*opt*/0,
str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
+ painter->restore();
} else {
qt_format_text(font, QRectF(p, QSizeF(1, 1)), Qt::TextSingleLine | Qt::TextDontClip, /*opt*/0,
str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 7b225ebbdd..474cd2efa7 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1071,6 +1071,9 @@ QPixmap QPixmap::grabWidget(QWidget * widget, const QRect &rect)
if (widget->testAttribute(Qt::WA_PendingResizeEvent) || !widget->testAttribute(Qt::WA_WState_Created))
sendResizeEvents(widget);
+ widget->d_func()->prepareToRender(QRegion(),
+ QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
+
QRect r(rect);
if (r.width() < 0)
r.setWidth(widget->width() - rect.x());
@@ -1081,8 +1084,8 @@ QPixmap QPixmap::grabWidget(QWidget * widget, const QRect &rect)
return QPixmap();
QPixmap res(r.size());
- widget->render(&res, QPoint(), r,
- QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
+ widget->d_func()->render(&res, QPoint(), r, QWidget::DrawWindowBackground
+ | QWidget::DrawChildren | QWidget::IgnoreMask, true);
return res;
}
@@ -1363,10 +1366,27 @@ void QPixmap::deref()
*/
/*!
- \fn bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
+ Replaces this pixmap's data with the given \a image using the
+ specified \a flags to control the conversion. The \a flags
+ argument is a bitwise-OR of the \l{Qt::ImageConversionFlags}.
+ Passing 0 for \a flags sets all the default options. Returns true
+ if the result is that this pixmap is not null.
- Use the static fromImage() function instead.
+ Note: this function was part of Qt 3 support in Qt 4.6 and earlier.
+ It has been promoted to official API status in 4.7 to support updating
+ the pixmap's image without creating a new QPixmap as fromImage() would.
+
+ \sa fromImage()
+ \since 4.7
*/
+bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
+{
+ if (image.isNull() || !data)
+ *this = QPixmap::fromImage(image, flags);
+ else
+ data->fromImage(image, flags);
+ return !isNull();
+}
/*!
\fn QPixmap QPixmap::xForm(const QMatrix &matrix) const
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 46363f05a1..180af3be1b 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -141,6 +141,8 @@ public:
bool save(const QString& fileName, const char* format = 0, int quality = -1) const;
bool save(QIODevice* device, const char* format = 0, int quality = -1) const;
+ bool convertFromImage(const QImage &img, Qt::ImageConversionFlags flags = Qt::AutoColor);
+
#if defined(Q_WS_WIN)
enum HBitmapFormat {
NoAlpha,
@@ -224,8 +226,6 @@ public:
QT3_SUPPORT QPixmap &operator=(const QImage &);
inline QT3_SUPPORT QImage convertToImage() const { return toImage(); }
QT3_SUPPORT bool convertFromImage(const QImage &, ColorMode mode);
- QT3_SUPPORT bool convertFromImage(const QImage &img, Qt::ImageConversionFlags flags = Qt::AutoColor)
- { (*this) = fromImage(img, flags); return !isNull(); }
inline QT3_SUPPORT operator QImage() const { return toImage(); }
inline QT3_SUPPORT QPixmap xForm(const QMatrix &matrix) const { return transformed(QTransform(matrix)); }
inline QT3_SUPPORT bool selfMask() const { return false; }
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index a440dcc7ce..9dc15fc20a 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -182,6 +182,7 @@ void QRasterPixmapData::fromImage(const QImage &sourceImage,
QImage::Format opaqueFormat = QNativeImage::systemFormat();
QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
+#ifndef QT_HAVE_NEON
switch (opaqueFormat) {
case QImage::Format_RGB16:
alphaFormat = QImage::Format_ARGB8565_Premultiplied;
@@ -189,6 +190,7 @@ void QRasterPixmapData::fromImage(const QImage &sourceImage,
default: // We don't care about the others...
break;
}
+#endif
if (!sourceImage.hasAlphaChannel()
|| ((flags & Qt::NoOpaqueDetection) == 0
@@ -238,6 +240,7 @@ void QRasterPixmapData::fill(const QColor &color)
if (alpha != 255) {
if (!image.hasAlphaChannel()) {
QImage::Format toFormat;
+#ifndef QT_HAVE_NEON
if (image.format() == QImage::Format_RGB16)
toFormat = QImage::Format_ARGB8565_Premultiplied;
else if (image.format() == QImage::Format_RGB666)
@@ -247,6 +250,7 @@ void QRasterPixmapData::fill(const QColor &color)
else if (image.format() == QImage::Format_RGB444)
toFormat = QImage::Format_ARGB4444_Premultiplied;
else
+#endif
toFormat = QImage::Format_ARGB32_Premultiplied;
image = QImage(image.width(), image.height(), toFormat);
}
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index f6905d773a..6bebefc0fa 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -314,8 +314,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),
- flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0), gl_surface(0),
+ : QPixmapData(type, X11Class), gl_surface(0), hd(0),
+ flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0),
share_mode(QPixmap::ImplicitlyShared), pengine(0)
{
}
@@ -1142,7 +1142,7 @@ void QX11PixmapData::fromImage(const QImage &img,
}
}
-void QX11PixmapData::bitmapFromImage(const QImage &image)
+Qt::HANDLE QX11PixmapData::createBitmapFromImage(const QImage &image)
{
QImage img = image.convertToFormat(QImage::Format_MonoLSB);
const QRgb c0 = QColor(Qt::black).rgb();
@@ -1155,10 +1155,8 @@ void QX11PixmapData::bitmapFromImage(const QImage &image)
char *bits;
uchar *tmp_bits;
- w = img.width();
- h = img.height();
- d = 1;
- is_null = (w <= 0 || h <= 0);
+ int w = img.width();
+ int h = img.height();
int bpl = (w + 7) / 8;
int ibpl = img.bytesPerLine();
if (bpl != ibpl) {
@@ -1177,18 +1175,26 @@ void QX11PixmapData::bitmapFromImage(const QImage &image)
bits = (char *)img.bits();
tmp_bits = 0;
}
- hd = (Qt::HANDLE)XCreateBitmapFromData(xinfo.display(),
- RootWindow(xinfo.display(), xinfo.screen()),
+ Qt::HANDLE hd = (Qt::HANDLE)XCreateBitmapFromData(X11->display,
+ QX11Info::appRootWindow(),
bits, w, h);
+ if (tmp_bits) // Avoid purify complaint
+ delete [] tmp_bits;
+ return hd;
+}
+void QX11PixmapData::bitmapFromImage(const QImage &image)
+{
+ w = image.width();
+ h = image.height();
+ d = 1;
+ is_null = (w <= 0 || h <= 0);
+ hd = createBitmapFromImage(image);
#ifndef QT_NO_XRENDER
if (X11->use_xrender)
picture = XRenderCreatePicture(X11->display, hd,
XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
#endif // QT_NO_XRENDER
-
- if (tmp_bits) // Avoid purify complaint
- delete [] tmp_bits;
}
void QX11PixmapData::fill(const QColor &fillColor)
diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h
index 20fb65470e..7575838163 100644
--- a/src/gui/image/qpixmap_x11_p.h
+++ b/src/gui/image/qpixmap_x11_p.h
@@ -92,6 +92,13 @@ public:
Qt::HANDLE handle() const { return hd; }
Qt::HANDLE x11ConvertToDefaultDepth();
+ static Qt::HANDLE createBitmapFromImage(const QImage &image);
+
+ void* gl_surface;
+#ifndef QT_NO_XRENDER
+ void convertToARGB32(bool preserveContents = true);
+#endif
+
protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;
@@ -103,6 +110,7 @@ private:
friend class QRasterWindowSurface;
friend class QGLContextPrivate; // Needs to access xinfo, gl_surface & flags
friend class QEglContext; // Needs gl_surface
+ friend class QGLContext; // Needs gl_surface
friend class QX11GLPixmapData; // Needs gl_surface
friend bool qt_createEGLSurfaceForPixmap(QPixmapData*, bool); // Needs gl_surface
@@ -128,10 +136,6 @@ private:
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
QPixmap::ShareMode share_mode;
QX11PaintEngine *pengine;
diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp
index 664d5d520f..70770c47ce 100644
--- a/src/gui/image/qpixmapfilter.cpp
+++ b/src/gui/image/qpixmapfilter.cpp
@@ -726,7 +726,7 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp
int img_height = img.height();
for (int row = 0; row < img_height; ++row) {
- for (int i = 0; i <= improvedQuality; ++i)
+ for (int i = 0; i <= int(improvedQuality); ++i)
qt_blurrow<aprec, zprec, alphaOnly>(img, row, alpha);
}
@@ -759,7 +759,7 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp
img_height = temp.height();
for (int row = 0; row < img_height; ++row) {
- for (int i = 0; i <= improvedQuality; ++i)
+ for (int i = 0; i <= int(improvedQuality); ++i)
qt_blurrow<aprec, zprec, alphaOnly>(temp, row, alpha);
}
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index d5406cb847..dd31834cae 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -50,8 +50,13 @@
#include <qvariant.h>
#include <qvector.h>
+#ifdef QT_USE_BUNDLED_LIBPNG
+#include <../../3rdparty/libpng/png.h>
+#include <../../3rdparty/libpng/pngconf.h>
+#else
#include <png.h>
#include <pngconf.h>
+#endif
#ifdef Q_OS_WINCE
#define CALLBACK_CALL_TYPE __cdecl
@@ -162,11 +167,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
png_uint_32 height;
int bit_depth;
int color_type;
+ png_bytep trans_alpha = 0;
+ png_color_16p trans_color_p = 0;
+ int num_trans;
+ png_colorp palette = 0;
+ int num_palette;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
if (color_type == PNG_COLOR_TYPE_GRAY) {
// Black & White or 8-bit grayscale
- if (bit_depth == 1 && info_ptr->channels == 1) {
+ if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
png_set_invert_mono(png_ptr);
png_read_update_info(png_ptr, info_ptr);
if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {
@@ -207,20 +217,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
int c = i*255/(ncols-1);
image.setColor(i, qRgba(c,c,c,0xff));
}
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
- const int g = info_ptr->trans_values.gray;
-#else
- const int g = info_ptr->trans_color.gray;
-#endif
+ if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
+ const int g = trans_color_p->gray;
if (g < ncols) {
image.setColor(g, 0);
}
}
}
} else if (color_type == PNG_COLOR_TYPE_PALETTE
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
- && info_ptr->num_palette <= 256)
+ && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+ && num_palette <= 256)
{
// 1-bit and 8-bit color
if (bit_depth != 1)
@@ -233,29 +239,26 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
if (image.isNull())
return;
}
- image.setColorCount(info_ptr->num_palette);
+ png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
+ image.setColorCount(num_palette);
int i = 0;
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
- while (i < info_ptr->num_trans) {
+ if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
+ while (i < num_trans) {
image.setColor(i, qRgba(
- info_ptr->palette[i].red,
- info_ptr->palette[i].green,
- info_ptr->palette[i].blue,
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
- info_ptr->trans[i]
-#else
- info_ptr->trans_alpha[i]
-#endif
+ palette[i].red,
+ palette[i].green,
+ palette[i].blue,
+ trans_alpha[i]
)
);
i++;
}
}
- while (i < info_ptr->num_palette) {
+ while (i < num_palette) {
image.setColor(i, qRgba(
- info_ptr->palette[i].red,
- info_ptr->palette[i].green,
- info_ptr->palette[i].blue,
+ palette[i].red,
+ palette[i].green,
+ palette[i].blue,
0xff
)
);
@@ -531,33 +534,36 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
QImage::Format format = QImage::Format_Invalid;
png_uint_32 width, height;
int bit_depth, color_type;
- if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) {
+ png_colorp palette;
+ int num_palette;
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
+ if (color_type == PNG_COLOR_TYPE_GRAY) {
// Black & White or 8-bit grayscale
- if (info_ptr->bit_depth == 1 && info_ptr->channels == 1) {
+ if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
format = QImage::Format_Mono;
- } else if (info_ptr->bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
format = QImage::Format_ARGB32;
} else {
format = QImage::Format_Indexed8;
}
- } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
- && info_ptr->num_palette <= 256)
+ } else if (color_type == PNG_COLOR_TYPE_PALETTE
+ && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+ && num_palette <= 256)
{
// 1-bit and 8-bit color
- if (info_ptr->bit_depth != 1)
+ if (bit_depth != 1)
png_set_packing(png_ptr);
png_read_update_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
} else {
// 32-bit
- if (info_ptr->bit_depth == 16)
+ if (bit_depth == 16)
png_set_strip_16(png_ptr);
format = QImage::Format_ARGB32;
// Only add filler if no alpha, or we can get 5 channel data.
- if (!(info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if (!(color_type & PNG_COLOR_MASK_ALPHA)
&& !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
// We want 4 bytes, but it isn't an alpha channel
format = QImage::Format_RGB32;
@@ -648,7 +654,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
text_ptr[i].text = qstrdup(value.constData());
text_ptr[i].text_length = 0;
text_ptr[i].itxt_length = value.size();
- text_ptr[i].lang = "UTF-8";
+ text_ptr[i].lang = const_cast<char*>("UTF-8");
text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());
#endif
++i;
@@ -735,64 +741,51 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_set_compression_level(png_ptr, quality);
}
- if (gamma != 0.0) {
- png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
- }
-
png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);
- info_ptr->channels =
- (image.depth() == 32)
- ? (image.format() == QImage::Format_RGB32 ? 3 : 4)
- : 1;
-
png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
image.depth() == 1 ? 1 : 8 /* per channel */,
image.depth() == 32
? image.format() == QImage::Format_RGB32
? PNG_COLOR_TYPE_RGB
: PNG_COLOR_TYPE_RGB_ALPHA
- : PNG_COLOR_TYPE_PALETTE, 0, 0, 0);
+ : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); // also sets #channels
+ if (gamma != 0.0) {
+ png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
+ }
- //png_set_sBIT(png_ptr, info_ptr, 8);
- info_ptr->sig_bit.red = 8;
- info_ptr->sig_bit.green = 8;
- info_ptr->sig_bit.blue = 8;
+ png_color_8 sig_bit;
+ sig_bit.red = 8;
+ sig_bit.green = 8;
+ sig_bit.blue = 8;
+ sig_bit.alpha = image.hasAlphaChannel() ? 8 : 0;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
if (image.format() == QImage::Format_MonoLSB)
png_set_packswap(png_ptr);
- png_colorp palette = 0;
- png_bytep copy_trans = 0;
if (image.colorCount()) {
// Paletted
- int num_palette = image.colorCount();
- palette = new png_color[num_palette];
- png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
- int* trans = new int[num_palette];
+ int num_palette = qMin(256, image.colorCount());
+ png_color palette[256];
+ png_byte trans[256];
int num_trans = 0;
for (int i=0; i<num_palette; i++) {
- QRgb rgb=image.color(i);
- info_ptr->palette[i].red = qRed(rgb);
- info_ptr->palette[i].green = qGreen(rgb);
- info_ptr->palette[i].blue = qBlue(rgb);
- trans[i] = rgb >> 24;
+ QRgb rgba=image.color(i);
+ palette[i].red = qRed(rgba);
+ palette[i].green = qGreen(rgba);
+ palette[i].blue = qBlue(rgba);
+ trans[i] = qAlpha(rgba);
if (trans[i] < 255) {
num_trans = i+1;
}
}
+ png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
+
if (num_trans) {
- copy_trans = new png_byte[num_trans];
- for (int i=0; i<num_trans; i++)
- copy_trans[i] = trans[i];
- png_set_tRNS(png_ptr, info_ptr, copy_trans, num_trans, 0);
+ png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);
}
- delete [] trans;
- }
-
- if (image.format() != QImage::Format_RGB32) {
- info_ptr->sig_bit.alpha = 8;
}
// Swap ARGB to RGBA (normal PNG format) before saving on
@@ -868,11 +861,6 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_write_end(png_ptr, info_ptr);
frames_written++;
- if (palette)
- delete [] palette;
- if (copy_trans)
- delete [] copy_trans;
-
png_destroy_write_struct(&png_ptr, &info_ptr);
return true;
@@ -958,7 +946,8 @@ QVariant QPngHandler::option(ImageOption option) const
else if (option == Description)
return d->description;
else if (option == Size)
- return QSize(d->info_ptr->width, d->info_ptr->height);
+ return QSize(png_get_image_width(d->png_ptr, d->info_ptr),
+ png_get_image_height(d->png_ptr, d->info_ptr));
else if (option == ImageFormat)
return d->readImageFormat();
return 0;
diff --git a/src/gui/inputmethod/qwininputcontext_p.h b/src/gui/inputmethod/qwininputcontext_p.h
index 08cc3d2420..d5bedf49b7 100644
--- a/src/gui/inputmethod/qwininputcontext_p.h
+++ b/src/gui/inputmethod/qwininputcontext_p.h
@@ -56,7 +56,7 @@
#include "QtGui/qinputcontext.h"
#include "QtCore/qt_windows.h"
-#if defined(Q_CC_MINGW) && !defined(IMR_RECONVERTSTRING)
+#if !defined(IMR_RECONVERTSTRING)
typedef struct tagRECONVERTSTRING {
DWORD dwSize;
DWORD dwVersion;
diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp
index 68ade3823a..d048b360c9 100644
--- a/src/gui/inputmethod/qximinputcontext_x11.cpp
+++ b/src/gui/inputmethod/qximinputcontext_x11.cpp
@@ -344,7 +344,13 @@ static XFontSet getFontSet(const QFont &f)
return (fontsetCache[i] == (XFontSet)-1) ? 0 : fontsetCache[i];
}
-
+extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp
+#ifndef QT_NO_XKB
+extern void q_getLocaleAndDirection(QLocale *locale,
+ Qt::LayoutDirection *direction,
+ const QByteArray &layoutName,
+ const QByteArray &variantName);
+#endif
QXIMInputContext::QXIMInputContext()
{
@@ -375,6 +381,52 @@ QXIMInputContext::QXIMInputContext()
else
QXIMInputContext::create_xim();
#endif // USE_X11R6_XIM
+
+#ifndef QT_NO_XKB
+ if (X11->use_xkb) {
+ QByteArray layoutName;
+ QByteArray variantName;
+
+ Atom type = XNone;
+ int format = 0;
+ ulong nitems = 0;
+ ulong bytesAfter = 0;
+ uchar *data = 0;
+ if (XGetWindowProperty(X11->display, RootWindow(X11->display, 0), ATOM(_XKB_RULES_NAMES), 0, 1024,
+ false, XA_STRING, &type, &format, &nitems, &bytesAfter, &data) == Success
+ && type == XA_STRING && format == 8 && nitems > 2) {
+
+ char *names[5] = { 0, 0, 0, 0, 0 };
+ char *p = reinterpret_cast<char *>(data), *end = p + nitems;
+ int i = 0;
+ do {
+ names[i++] = p;
+ p += qstrlen(p) + 1;
+ } while (p < end);
+
+ QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(',');
+ QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(',');
+ for (int i = 0; i < qMin(layoutNames.count(), variantNames.count()); ++i ) {
+ QLocale keyboardInputLocale;
+ Qt::LayoutDirection keyboardInputDirection;
+ QByteArray variantName = variantNames.at(i);
+ const int dashPos = variantName.indexOf("-");
+ if (dashPos >= 0)
+ variantName.truncate(dashPos);
+ q_getLocaleAndDirection(&keyboardInputLocale,
+ &keyboardInputDirection,
+ layoutNames.at(i),
+ variantName);
+ if (keyboardInputDirection == Qt::RightToLeft)
+ qt_use_rtl_extensions = true;
+ }
+ }
+
+ if (data)
+ XFree(data);
+ }
+#endif // QT_NO_XKB
+
}
diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp
index 2faf7558fd..97fd6e1da9 100644
--- a/src/gui/itemviews/qabstractitemview.cpp
+++ b/src/gui/itemviews/qabstractitemview.cpp
@@ -104,8 +104,10 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate()
horizontalScrollMode(QAbstractItemView::ScrollPerItem),
currentIndexSet(false),
wrapItemText(false),
- delayedPendingLayout(false)
+ delayedPendingLayout(true),
+ moveCursorUpdatedView(false)
{
+ keyboardInputTime.invalidate();
}
QAbstractItemViewPrivate::~QAbstractItemViewPrivate()
@@ -131,8 +133,6 @@ void QAbstractItemViewPrivate::init()
viewport->setBackgroundRole(QPalette::Base);
- doDelayedItemsLayout();
-
q->setAttribute(Qt::WA_InputMethodEnabled);
#ifdef QT_SOFTKEYS_ENABLED
@@ -2090,7 +2090,7 @@ void QAbstractItemView::focusInEvent(QFocusEvent *event)
bool autoScroll = d->autoScroll;
d->autoScroll = false;
QModelIndex index = moveCursor(MoveNext, Qt::NoModifier); // first visible index
- if (index.isValid() && d->isIndexEnabled(index))
+ if (index.isValid() && d->isIndexEnabled(index) && event->reason() != Qt::MouseFocusReason)
selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
d->autoScroll = autoScroll;
}
@@ -2210,6 +2210,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
#endif
QPersistentModelIndex newCurrent;
+ d->moveCursorUpdatedView = false;
switch (event->key()) {
case Qt::Key_Down:
newCurrent = moveCursor(MoveDown, event->modifiers());
@@ -2266,6 +2267,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
QRect rect(d->pressedPosition - d->offset(), QSize(1, 1));
setSelection(rect, command);
}
+ event->accept();
return;
}
}
@@ -2297,6 +2299,8 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
case Qt::Key_Escape:
case Qt::Key_Shift:
case Qt::Key_Control:
+ case Qt::Key_Delete:
+ case Qt::Key_Backspace:
event->ignore();
break;
case Qt::Key_Space:
@@ -2361,6 +2365,8 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
}
break; }
}
+ if (d->moveCursorUpdatedView)
+ event->accept();
}
/*!
@@ -2837,16 +2843,16 @@ void QAbstractItemView::keyboardSearch(const QString &search)
QModelIndex start = currentIndex().isValid() ? currentIndex()
: d->model->index(0, 0, d->root);
- QTime now(QTime::currentTime());
bool skipRow = false;
- if (search.isEmpty()
- || (d->keyboardInputTime.msecsTo(now) > QApplication::keyboardInputInterval())) {
+ bool keyboardTimeWasValid = d->keyboardInputTime.isValid();
+ qint64 keyboardInputTimeElapsed = d->keyboardInputTime.restart();
+ if (search.isEmpty() || !keyboardTimeWasValid
+ || keyboardInputTimeElapsed > QApplication::keyboardInputInterval()) {
d->keyboardInput = search;
skipRow = currentIndex().isValid(); //if it is not valid we should really start at QModelIndex(0,0)
} else {
d->keyboardInput += search;
}
- d->keyboardInputTime = now;
// special case for searches with same key like 'aaaaa'
bool sameKey = false;
diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h
index 82fd1a6334..fce74f3f54 100644
--- a/src/gui/itemviews/qabstractitemview_p.h
+++ b/src/gui/itemviews/qabstractitemview_p.h
@@ -56,7 +56,6 @@
#include "private/qabstractscrollarea_p.h"
#include "private/qabstractitemmodel_p.h"
#include "QtGui/qapplication.h"
-#include "QtCore/qdatetime.h"
#include "QtGui/qevent.h"
#include "QtGui/qmime.h"
#include "QtGui/qpainter.h"
@@ -65,6 +64,7 @@
#include "QtCore/qdebug.h"
#include "QtGui/qpainter.h"
#include "QtCore/qbasictimer.h"
+#include "QtCore/qelapsedtimer.h"
#ifndef QT_NO_ITEMVIEWS
@@ -390,7 +390,7 @@ public:
#endif
QString keyboardInput;
- QTime keyboardInputTime;
+ QElapsedTimer keyboardInputTime;
bool autoScroll;
QBasicTimer autoScrollTimer;
@@ -419,6 +419,7 @@ public:
bool wrapItemText;
mutable bool delayedPendingLayout;
+ bool moveCursorUpdatedView;
private:
mutable QBasicTimer delayedLayout;
diff --git a/src/gui/itemviews/qdirmodel.cpp b/src/gui/itemviews/qdirmodel.cpp
index ea608c1b3c..48599bc477 100644
--- a/src/gui/itemviews/qdirmodel.cpp
+++ b/src/gui/itemviews/qdirmodel.cpp
@@ -185,12 +185,12 @@ void QDirModelPrivate::invalidate()
/*!
\class QDirModel
-
+ \obsolete
\brief The QDirModel class provides a data model for the local filesystem.
\ingroup model-view
- \note The usage of QDirModel is not recommended anymore. The
+ The usage of QDirModel is not recommended anymore. The
QFileSystemModel class is a more performant alternative.
This class provides access to the local filesystem, providing functions
@@ -1182,12 +1182,18 @@ QFileInfo QDirModel::fileInfo(const QModelIndex &index) const
void QDirModelPrivate::init()
{
+ Q_Q(QDirModel);
filters = QDir::AllEntries | QDir::NoDotAndDotDot;
sort = QDir::Name;
nameFilters << QLatin1String("*");
root.parent = 0;
root.info = QFileInfo();
clear(&root);
+ QHash<int, QByteArray> roles = q->roleNames();
+ roles.insertMulti(QDirModel::FileIconRole, "fileIcon"); // == Qt::decoration
+ roles.insert(QDirModel::FilePathRole, "filePath");
+ roles.insert(QDirModel::FileNameRole, "fileName");
+ q->setRoleNames(roles);
}
QDirModelPrivate::QDirNode *QDirModelPrivate::node(int row, QDirNode *parent) const
diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp
index 673065c39b..5dbd1f08b8 100644
--- a/src/gui/itemviews/qfileiconprovider.cpp
+++ b/src/gui/itemviews/qfileiconprovider.cpp
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QFileIconProvider
- \brief The QFileIconProvider class provides file icons for the QDirModel class.
+ \brief The QFileIconProvider class provides file icons for the QDirModel and the QFileSystemModel classes.
*/
/*!
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index 8a456e6b9c..cd9ee15168 100644
--- a/src/gui/itemviews/qheaderview.cpp
+++ b/src/gui/itemviews/qheaderview.cpp
@@ -1698,13 +1698,10 @@ void QHeaderView::sectionsInserted(const QModelIndex &parent,
if (!d->sectionHidden.isEmpty()) {
QBitArray sectionHidden(d->sectionHidden);
sectionHidden.resize(sectionHidden.count() + insertCount);
- //sectionHidden.fill(false, logicalFirst, logicalLast + 1);
- for (int i = logicalFirst; i <= logicalLast; ++i)
- // visual == logical in this range (see previous block)
- sectionHidden.setBit(i, false);
+ sectionHidden.fill(false, logicalFirst, logicalLast + 1);
for (int j = logicalLast + 1; j < sectionHidden.count(); ++j)
- sectionHidden.setBit(d->visualIndex(j),
- d->sectionHidden.testBit(d->visualIndex(j - insertCount)));
+ //here we simply copy the old sectionHidden
+ sectionHidden.setBit(j, d->sectionHidden.testBit(j - insertCount));
d->sectionHidden = sectionHidden;
}
@@ -1853,11 +1850,9 @@ void QHeaderViewPrivate::_q_layoutChanged()
persistentHiddenSections.clear();
return;
}
+
+ QBitArray oldSectionHidden = sectionHidden;
bool sectionCountChanged = false;
- for (int i = 0; i < sectionHidden.count(); ++i) {
- if (sectionHidden.testBit(i))
- q->setSectionHidden(logicalIndex(i), false);
- }
for (int i = 0; i < persistentHiddenSections.count(); ++i) {
QModelIndex index = persistentHiddenSections.at(i);
@@ -1866,6 +1861,7 @@ void QHeaderViewPrivate::_q_layoutChanged()
? index.column()
: index.row());
q->setSectionHidden(logical, true);
+ oldSectionHidden.setBit(logical, false);
} else if (!sectionCountChanged && (modelSectionCount() != sectionCount)) {
sectionCountChanged = true;
break;
@@ -1873,6 +1869,11 @@ void QHeaderViewPrivate::_q_layoutChanged()
}
persistentHiddenSections.clear();
+ for (int i = 0; i < oldSectionHidden.count(); ++i) {
+ if (oldSectionHidden.testBit(i))
+ q->setSectionHidden(logicalIndex(i), false);
+ }
+
// the number of sections changed; we need to reread the state of the model
if (sectionCountChanged)
q->initializeSections();
@@ -2033,7 +2034,7 @@ bool QHeaderView::event(QEvent *e)
updateSection(d->hover);
}
break; }
- case QEvent::Timer: { // ### reimplement timerEvent() instead ?
+ case QEvent::Timer: {
QTimerEvent *te = static_cast<QTimerEvent*>(e);
if (te->timerId() == d->delayedResize.timerId()) {
d->delayedResize.stop();
@@ -2217,24 +2218,27 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e)
return;
}
case QHeaderViewPrivate::MoveSection: {
- if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance()) {
- int indicatorCenter = (d->orientation == Qt::Horizontal
- ? d->sectionIndicator->width()
- : d->sectionIndicator->height()) / 2;
- int centerOffset = indicatorCenter - d->sectionIndicatorOffset;
- // This will drop the moved section to the position under the center of the indicator.
- // If centerOffset is 0, the section will be moved to the position of the mouse cursor.
- int visual = visualIndexAt(pos + centerOffset);
+ if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance()
+ || !d->sectionIndicator->isHidden()) {
+ int visual = visualIndexAt(pos);
if (visual == -1)
return;
- d->target = d->logicalIndex(visual);
+ int posThreshold = d->headerSectionPosition(visual) + d->headerSectionSize(visual) / 2;
+ int moving = visualIndex(d->section);
+ if (visual < moving) {
+ if (pos < posThreshold)
+ d->target = d->logicalIndex(visual);
+ else
+ d->target = d->logicalIndex(visual + 1);
+ } else if (visual > moving) {
+ if (pos > posThreshold)
+ d->target = d->logicalIndex(visual);
+ else
+ d->target = d->logicalIndex(visual - 1);
+ } else {
+ d->target = d->section;
+ }
d->updateSectionIndicator(d->section, pos);
- } else {
- int visual = visualIndexAt(d->firstPos);
- if (visual == -1)
- return;
- d->target = d->logicalIndex(visual);
- d->updateSectionIndicator(d->section, d->firstPos);
}
return;
}
@@ -2300,7 +2304,7 @@ void QHeaderView::mouseReleaseEvent(QMouseEvent *e)
int section = logicalIndexAt(pos);
if (section != -1 && section == d->pressed) {
d->flipSortIndicator(section);
- emit sectionClicked(logicalIndexAt(pos));
+ emit sectionClicked(section);
}
if (d->pressed != -1)
updateSection(d->pressed);
@@ -2611,7 +2615,7 @@ void QHeaderView::updateGeometries()
Q_D(QHeaderView);
d->layoutChildren();
if (d->hasAutoResizeSections())
- resizeSections();
+ d->doDelayedResizeSections();
}
/*!
diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp
index 7d8e103f04..d5f6fd2423 100644
--- a/src/gui/itemviews/qitemdelegate.cpp
+++ b/src/gui/itemviews/qitemdelegate.cpp
@@ -69,6 +69,7 @@
#include <qdebug.h>
#include <qlocale.h>
#include <qdialog.h>
+#include <qmath.h>
#include <limits.h>
@@ -1023,7 +1024,7 @@ QPixmap QItemDelegate::decoration(const QStyleOptionViewItem &option, const QVar
// hacky but faster version of "QString::sprintf("%d-%d", i, enabled)"
static QString qPixmapSerial(quint64 i, bool enabled)
{
- ushort arr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', '0' + enabled };
+ ushort arr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', ushort('0' + enabled) };
ushort *ptr = &arr[16];
while (i > 0) {
@@ -1148,7 +1149,8 @@ QRect QItemDelegate::textRectangle(QPainter * /*painter*/, const QRect &rect,
d->textLayout.setTextOption(d->textOption);
d->textLayout.setFont(font);
d->textLayout.setText(QItemDelegatePrivate::replaceNewLine(text));
- const QSize size = d->doTextLayout(rect.width()).toSize();
+ QSizeF fpSize = d->doTextLayout(rect.width());
+ const QSize size = QSize(qCeil(fpSize.width()), qCeil(fpSize.height()));
// ###: textRectangle should take style option as argument
const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
return QRect(0, 0, size.width() + 2 * textMargin, size.height());
diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp
index cab002e9d8..f848321b75 100644
--- a/src/gui/itemviews/qitemselectionmodel.cpp
+++ b/src/gui/itemviews/qitemselectionmodel.cpp
@@ -292,6 +292,27 @@ static void indexesFromRange(const QItemSelectionRange &range, QModelIndexList &
}
/*!
+ Returns true if the selection range contains no selectable item
+ \since 4.7
+*/
+
+bool QItemSelectionRange::isEmpty() const
+{
+ if (!isValid() || !model())
+ return true;
+
+ for (int column = left(); column <= right(); ++column) {
+ for (int row = top(); row <= bottom(); ++row) {
+ QModelIndex index = model()->index(row, column, parent());
+ Qt::ItemFlags flags = model()->flags(index);
+ if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
+ return false;
+ }
+ }
+ return true;
+}
+
+/*!
Returns the list of model index items stored in the selection.
*/
@@ -527,6 +548,27 @@ void QItemSelection::split(const QItemSelectionRange &range,
}
}
+
+void QItemSelectionModelPrivate::initModel(QAbstractItemModel *model)
+{
+ this->model = model;
+ if (model) {
+ Q_Q(QItemSelectionModel);
+ QObject::connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+ q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QObject::connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
+ q, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
+ QObject::connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
+ q, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
+ QObject::connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
+ q, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
+ QObject::connect(model, SIGNAL(layoutAboutToBeChanged()),
+ q, SLOT(_q_layoutAboutToBeChanged()));
+ QObject::connect(model, SIGNAL(layoutChanged()),
+ q, SLOT(_q_layoutChanged()));
+ }
+}
+
/*!
\internal
@@ -793,6 +835,10 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes)
while (++i < colSpans.count()) {
QModelIndex nextTl = colSpans.at(i).topLeft();
QModelIndex nextBr = colSpans.at(i).bottomRight();
+
+ if (nextTl.parent() != tl.parent())
+ break; // we can't merge selection ranges from different parents
+
if ((nextTl.column() == prevTl.column()) && (nextBr.column() == br.column())
&& (nextTl.row() == prevTl.row() + 1) && (nextBr.row() == br.row() + 1)) {
br = nextBr;
@@ -890,21 +936,7 @@ void QItemSelectionModelPrivate::_q_layoutChanged()
QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model)
: QObject(*new QItemSelectionModelPrivate, model)
{
- d_func()->model = model;
- if (model) {
- connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(layoutAboutToBeChanged()),
- this, SLOT(_q_layoutAboutToBeChanged()));
- connect(model, SIGNAL(layoutChanged()),
- this, SLOT(_q_layoutChanged()));
- }
+ d_func()->initModel(model);
}
/*!
@@ -913,21 +945,7 @@ QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model)
QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *parent)
: QObject(*new QItemSelectionModelPrivate, parent)
{
- d_func()->model = model;
- if (model) {
- connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(layoutAboutToBeChanged()),
- this, SLOT(_q_layoutAboutToBeChanged()));
- connect(model, SIGNAL(layoutChanged()),
- this, SLOT(_q_layoutChanged()));
- }
+ d_func()->initModel(model);
}
/*!
@@ -936,21 +954,7 @@ QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *par
QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model)
: QObject(dd, model)
{
- d_func()->model = model;
- if (model) {
- connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(layoutAboutToBeChanged()),
- this, SLOT(_q_layoutAboutToBeChanged()));
- connect(model, SIGNAL(layoutChanged()),
- this, SLOT(_q_layoutChanged()));
- }
+ dd.initModel(model);
}
/*!
@@ -958,21 +962,6 @@ QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstra
*/
QItemSelectionModel::~QItemSelectionModel()
{
- Q_D(QItemSelectionModel);
- if (d->model) {
- disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(layoutAboutToBeChanged()),
- this, SLOT(_q_layoutAboutToBeChanged()));
- disconnect(d->model, SIGNAL(layoutChanged()),
- this, SLOT(_q_layoutChanged()));
- }
}
/*!
diff --git a/src/gui/itemviews/qitemselectionmodel.h b/src/gui/itemviews/qitemselectionmodel.h
index 9980d0f4b7..436514fc6a 100644
--- a/src/gui/itemviews/qitemselectionmodel.h
+++ b/src/gui/itemviews/qitemselectionmodel.h
@@ -108,6 +108,8 @@ public:
&& top() <= bottom() && left() <= right());
}
+ bool isEmpty() const;
+
QModelIndexList indexes() const;
private:
diff --git a/src/gui/itemviews/qitemselectionmodel_p.h b/src/gui/itemviews/qitemselectionmodel_p.h
index 30583b2f1d..5afa90d15f 100644
--- a/src/gui/itemviews/qitemselectionmodel_p.h
+++ b/src/gui/itemviews/qitemselectionmodel_p.h
@@ -70,6 +70,8 @@ public:
QItemSelection expandSelection(const QItemSelection &selection,
QItemSelectionModel::SelectionFlags command) const;
+ void initModel(QAbstractItemModel *model);
+
void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
void _q_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index b2def39e4d..186909377a 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -1387,6 +1387,9 @@ void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl
/*!
\reimp
+
+ Since 4.7, the returned region only contains rectangles intersecting
+ (or included in) the viewport.
*/
QRegion QListView::visualRegionForSelection(const QItemSelection &selection) const
{
@@ -1394,6 +1397,7 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
// ### NOTE: this is a potential bottleneck in non-static mode
int c = d->column;
QRegion selectionRegion;
+ const QRect &viewportRect = d->viewport->rect();
for (int i = 0; i < selection.count(); ++i) {
if (!selection.at(i).isValid())
continue;
@@ -1405,8 +1409,11 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
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
- for (int r = t; r <= b; ++r)
- selectionRegion += QRegion(visualRect(d->model->index(r, c, parent)));
+ for (int r = t; r <= b; ++r) {
+ const QRect &rect = visualRect(d->model->index(r, c, parent));
+ if (viewportRect.intersects(rect))
+ selectionRegion += rect;
+ }
} else { // in static mode, we can optimize a bit
while (t <= b && d->isHidden(t)) ++t;
while (b >= t && d->isHidden(b)) --b;
@@ -1414,7 +1421,8 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
const QModelIndex bottom = d->model->index(b, c, parent);
QRect rect(visualRect(top).topLeft(),
visualRect(bottom).bottomRight());
- selectionRegion += QRegion(rect);
+ if (viewportRect.intersects(rect))
+ selectionRegion += rect;
}
}
@@ -1845,14 +1853,14 @@ void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step)
{
horizontalScrollBar()->setSingleStep(step.width() + spacing());
horizontalScrollBar()->setPageStep(viewport()->width());
- horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width() - 2 * spacing());
+ 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() - 2 * spacing());
+ verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height());
}
void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/)
@@ -2268,6 +2276,7 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info)
const QPoint topLeft = initStaticLayout(info);
QStyleOptionViewItemV4 option = viewOptions();
option.rect = info.bounds;
+ option.rect.adjust(info.spacing, info.spacing, -info.spacing, -info.spacing);
// The static layout data structures are as follows:
// One vector contains the coordinate in the direction of layout flow.
@@ -2897,8 +2906,13 @@ void QIconModeViewBase::doDynamicLayout(const QListViewLayoutInfo &info)
batchStartRow = info.last + 1;
bool done = (info.last >= rowCount() - 1);
// resize the content area
- if (done || !info.bounds.contains(item->rect()))
- contentsSize = QSize(rect.width(), rect.height());
+ if (done || !info.bounds.contains(item->rect())) {
+ contentsSize = rect.size();
+ if (info.flow == QListView::LeftToRight)
+ contentsSize.rheight() += info.spacing;
+ else
+ contentsSize.rwidth() += info.spacing;
+ }
// resize tree
int insertFrom = info.first;
if (done || info.first == 0) {
diff --git a/src/gui/itemviews/qproxymodel.h b/src/gui/itemviews/qproxymodel.h
index 1a6b14b4da..f179a7a3c7 100644
--- a/src/gui/itemviews/qproxymodel.h
+++ b/src/gui/itemviews/qproxymodel.h
@@ -67,19 +67,19 @@ public:
// implementing model interface
- QModelIndex index(int row, int column, const QModelIndex &parent) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
- int rowCount(const QModelIndex &parent) const;
- int columnCount(const QModelIndex &parent) const;
- bool hasChildren(const QModelIndex &parent) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
- QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value,
- int role);
+ int role = Qt::EditRole);
QStringList mimeTypes() const;
QMimeData *mimeData(const QModelIndexList &indexes) const;
@@ -87,16 +87,17 @@ public:
int row, int column, const QModelIndex &parent);
Qt::DropActions supportedDropActions() const;
- bool insertRows(int row, int count, const QModelIndex &parent);
- bool insertColumns(int column, int count, const QModelIndex &parent);
+ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex());
void fetchMore(const QModelIndex &parent);
Qt::ItemFlags flags(const QModelIndex &index) const;
- void sort(int column, Qt::SortOrder order);
+ void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
QModelIndexList match(const QModelIndex &start, int role, const QVariant &value,
- int hits, Qt::MatchFlags flags) const;
+ int hits = 1, Qt::MatchFlags flags =
+ Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const;
QSize span(const QModelIndex &index) const;
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index 41c984e37f..dce5c6a706 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -111,6 +111,35 @@ private:
};
+//this struct is used to store what are the rows that are removed
+//between a call to rowsAboutToBeRemoved and rowsRemoved
+//it avoids readding rows to the mapping that are currently being removed
+struct QRowsRemoval
+{
+ QRowsRemoval(const QModelIndex &parent_source, int start, int end) : parent_source(parent_source), start(start), end(end)
+ {
+ }
+
+ QRowsRemoval() : start(-1), end(-1)
+ {
+ }
+
+ bool contains(QModelIndex parent, int row)
+ {
+ do {
+ if (parent == parent_source)
+ return row >= start && row <= end;
+ row = parent.row();
+ parent = parent.parent();
+ } while (row >= 0);
+ return false;
+ }
+private:
+ QModelIndex parent_source;
+ int start;
+ int end;
+};
+
class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate
{
Q_DECLARE_PUBLIC(QSortFilterProxyModel)
@@ -122,10 +151,10 @@ public:
QVector<int> proxy_rows;
QVector<int> proxy_columns;
QVector<QModelIndex> mapped_children;
- QMap<QModelIndex, Mapping *>::const_iterator map_iter;
+ QHash<QModelIndex, Mapping *>::const_iterator map_iter;
};
- mutable QMap<QModelIndex, Mapping*> source_index_mapping;
+ mutable QHash<QModelIndex, Mapping*> source_index_mapping;
int source_sort_column;
int proxy_sort_column;
@@ -139,10 +168,11 @@ public:
int filter_role;
bool dynamic_sortfilter;
+ QRowsRemoval itemsBeingRemoved;
QModelIndexPairList saved_persistent_indexes;
- QMap<QModelIndex, Mapping *>::const_iterator create_mapping(
+ QHash<QModelIndex, Mapping *>::const_iterator create_mapping(
const QModelIndex &source_parent) const;
QModelIndex proxy_to_source(const QModelIndex &proxyIndex) const;
QModelIndex source_to_proxy(const QModelIndex &sourceIndex) const;
@@ -150,14 +180,14 @@ public:
void remove_from_mapping(const QModelIndex &source_parent);
- inline QMap<QModelIndex, Mapping *>::const_iterator index_to_iterator(
+ inline QHash<QModelIndex, Mapping *>::const_iterator index_to_iterator(
const QModelIndex &proxy_index) const
{
Q_ASSERT(proxy_index.isValid());
Q_ASSERT(proxy_index.model() == q_func());
const void *p = proxy_index.internalPointer();
Q_ASSERT(p);
- QMap<QModelIndex, Mapping *>::const_iterator it =
+ QHash<QModelIndex, Mapping *>::const_iterator it =
static_cast<const Mapping*>(p)->map_iter;
Q_ASSERT(it != source_index_mapping.constEnd());
Q_ASSERT(it.value());
@@ -165,7 +195,7 @@ public:
}
inline QModelIndex create_index(int row, int column,
- QMap<QModelIndex, Mapping*>::const_iterator it) const
+ QHash<QModelIndex, Mapping*>::const_iterator it) const
{
return q_func()->createIndex(row, column, *it);
}
@@ -246,7 +276,7 @@ public:
virtual void _q_sourceModelDestroyed();
};
-typedef QMap<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
+typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed()
{
@@ -270,6 +300,11 @@ void QSortFilterProxyModelPrivate::clear_mapping()
qDeleteAll(source_index_mapping);
source_index_mapping.clear();
+ if (dynamic_sortfilter && update_source_sort_column()) {
+ //update_source_sort_column might have created wrong mapping so we have to clear it again
+ qDeleteAll(source_index_mapping);
+ source_index_mapping.clear();
+ }
// update the persistent indexes
update_persistent_indexes(source_indexes);
@@ -287,11 +322,13 @@ IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping(
Mapping *m = new Mapping;
int source_rows = model->rowCount(source_parent);
+ m->source_rows.reserve(source_rows);
for (int i = 0; i < source_rows; ++i) {
if (q->filterAcceptsRow(i, source_parent))
m->source_rows.append(i);
}
int source_cols = model->columnCount(source_parent);
+ m->source_columns.reserve(source_cols);
for (int i = 0; i < source_cols; ++i) {
if (q->filterAcceptsColumn(i, source_parent))
m->source_columns.append(i);
@@ -558,7 +595,7 @@ QVector<QPair<int, QVector<int > > > QSortFilterProxyModelPrivate::proxy_interva
int proxy_item = 0;
int source_items_index = 0;
QVector<int> source_items_in_interval;
- bool compare = (orient == Qt::Vertical && source_sort_column >= 0);
+ bool compare = (orient == Qt::Vertical && source_sort_column >= 0 && dynamic_sortfilter);
while (source_items_index < source_items.size()) {
source_items_in_interval.clear();
int first_new_source_item = source_items.at(source_items_index);
@@ -1089,7 +1126,7 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
source_rows_change.append(source_row);
}
} else {
- if (q->filterAcceptsRow(source_row, source_parent)) {
+ if (!itemsBeingRemoved.contains(source_parent, source_row) && q->filterAcceptsRow(source_row, source_parent)) {
// This source row now satisfies the filter, so it must be added
source_rows_insert.append(source_row);
}
@@ -1180,13 +1217,13 @@ void QSortFilterProxyModelPrivate::_q_sourceAboutToBeReset()
{
Q_Q(QSortFilterProxyModel);
q->beginResetModel();
- invalidatePersistentIndexes();
- clear_mapping();
}
void QSortFilterProxyModelPrivate::_q_sourceReset()
{
Q_Q(QSortFilterProxyModel);
+ invalidatePersistentIndexes();
+ clear_mapping();
// All internal structures are deleted in clear()
q->endResetModel();
update_source_sort_column();
@@ -1208,11 +1245,6 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged()
void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged()
{
Q_Q(QSortFilterProxyModel);
- if (saved_persistent_indexes.isEmpty()) {
- clear_mapping();
- emit q->layoutChanged();
- return;
- }
qDeleteAll(source_index_mapping);
source_index_mapping.clear();
@@ -1220,7 +1252,11 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged()
update_persistent_indexes(saved_persistent_indexes);
saved_persistent_indexes.clear();
- update_source_sort_column();
+ if (dynamic_sortfilter && update_source_sort_column()) {
+ //update_source_sort_column might have created wrong mapping so we have to clear it again
+ qDeleteAll(source_index_mapping);
+ source_index_mapping.clear();
+ }
emit q->layoutChanged();
}
@@ -1240,13 +1276,14 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsInserted(
const QModelIndex &source_parent, int start, int end)
{
source_items_inserted(source_parent, start, end, Qt::Vertical);
- if (update_source_sort_column()) //previous call to update_source_sort_column may fail if the model has no column.
+ if (update_source_sort_column() && dynamic_sortfilter) //previous call to update_source_sort_column may fail if the model has no column.
sort(); // now it should succeed so we need to make sure to sort again
}
void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(
const QModelIndex &source_parent, int start, int end)
{
+ itemsBeingRemoved = QRowsRemoval(source_parent, start, end);
source_items_about_to_be_removed(source_parent, start, end,
Qt::Vertical);
}
@@ -1254,6 +1291,7 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(
void QSortFilterProxyModelPrivate::_q_sourceRowsRemoved(
const QModelIndex &source_parent, int start, int end)
{
+ itemsBeingRemoved = QRowsRemoval();
source_items_removed(source_parent, start, end, Qt::Vertical);
}
@@ -1277,8 +1315,8 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsInserted(
if (source_parent.isValid())
return; //we sort according to the root column only
if (source_sort_column == -1) {
- //we update the source_sort_column depending on the prox_sort_column
- if (update_source_sort_column())
+ //we update the source_sort_column depending on the proxy_sort_column
+ if (update_source_sort_column() && dynamic_sortfilter)
sort();
} else {
if (start <= source_sort_column)
@@ -1481,7 +1519,6 @@ QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent)
d->filter_column = 0;
d->filter_role = Qt::DisplayRole;
d->dynamic_sortfilter = false;
- connect(this, SIGNAL(modelReset()), this, SLOT(invalidate()));
}
/*!
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp
index c4d1317221..80334a6bdf 100644
--- a/src/gui/itemviews/qtableview.cpp
+++ b/src/gui/itemviews/qtableview.cpp
@@ -1846,7 +1846,9 @@ void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionF
selection.append(QItemSelectionRange(topLeft, bottomRight));
}
} else { // nothing moved
- selection.append(QItemSelectionRange(tl, br));
+ QItemSelectionRange range(tl, br);
+ if (!range.isEmpty())
+ selection.append(range);
}
d->selectionModel->select(selection, command);
@@ -1857,6 +1859,9 @@ void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionF
Returns the rectangle from the viewport of the items in the given
\a selection.
+
+ Since 4.7, the returned region only contains rectangles intersecting
+ (or included in) the viewport.
*/
QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) const
{
@@ -1866,6 +1871,7 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
return QRegion();
QRegion selectionRegion;
+ const QRect &viewportRect = d->viewport->rect();
bool verticalMoved = verticalHeader()->sectionsMoved();
bool horizontalMoved = horizontalHeader()->sectionsMoved();
@@ -1875,8 +1881,11 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
if (range.parent() != d->root || !range.isValid())
continue;
for (int r = range.top(); r <= range.bottom(); ++r)
- for (int c = range.left(); c <= range.right(); ++c)
- selectionRegion += QRegion(visualRect(d->model->index(r, c, d->root)));
+ for (int c = range.left(); c <= range.right(); ++c) {
+ const QRect &rangeRect = visualRect(d->model->index(r, c, d->root));
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
+ }
}
} else if (horizontalMoved) {
for (int i = 0; i < selection.count(); ++i) {
@@ -1888,9 +1897,11 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
if (top > bottom)
qSwap<int>(top, bottom);
int height = bottom - top;
- for (int c = range.left(); c <= range.right(); ++c)
- selectionRegion += QRegion(QRect(columnViewportPosition(c), top,
- columnWidth(c), height));
+ for (int c = range.left(); c <= range.right(); ++c) {
+ const QRect rangeRect(columnViewportPosition(c), top, columnWidth(c), height);
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
+ }
}
} else if (verticalMoved) {
for (int i = 0; i < selection.count(); ++i) {
@@ -1902,9 +1913,11 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
if (left > right)
qSwap<int>(left, right);
int width = right - left;
- for (int r = range.top(); r <= range.bottom(); ++r)
- selectionRegion += QRegion(QRect(left, rowViewportPosition(r),
- width, rowHeight(r)));
+ for (int r = range.top(); r <= range.bottom(); ++r) {
+ const QRect rangeRect(left, rowViewportPosition(r), width, rowHeight(r));
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
+ }
}
} else { // nothing moved
const int gridAdjust = showGrid() ? 1 : 0;
@@ -1925,12 +1938,17 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
rleft = columnViewportPosition(range.right());
rright = columnViewportPosition(range.left()) + columnWidth(range.left());
}
- selectionRegion += QRect(QPoint(rleft, rtop), QPoint(rright - 1 - gridAdjust, rbottom - 1 - gridAdjust));
+ const QRect rangeRect(QPoint(rleft, rtop), QPoint(rright - 1 - gridAdjust, rbottom - 1 - gridAdjust));
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
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);
+ if (range.contains(s->top(), s->left(), range.parent())) {
+ const QRect &visualSpanRect = d->visualSpanRect(*s);
+ if (viewportRect.intersects(visualSpanRect))
+ selectionRegion += visualSpanRect;
+ }
}
}
}
@@ -1967,12 +1985,7 @@ QModelIndexList QTableView::selectedIndexes() const
void QTableView::rowCountChanged(int /*oldCount*/, int /*newCount*/ )
{
Q_D(QTableView);
- updateGeometries();
- if (verticalScrollMode() == QAbstractItemView::ScrollPerItem)
- d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
- else
- d->verticalHeader->setOffset(verticalScrollBar()->value());
- d->viewport->update();
+ d->doDelayedItemsLayout();
}
/*!
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index 37168eb319..b797776e20 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -674,21 +674,29 @@ 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
- int topViewIndex = d->viewIndex(topLeft);
- if (topViewIndex == 0)
- d->defaultItemHeight = indexRowSizeHint(topLeft);
bool sizeChanged = false;
+ int topViewIndex = d->viewIndex(topLeft);
+ if (topViewIndex == 0) {
+ int newDefaultItemHeight = indexRowSizeHint(topLeft);
+ sizeChanged = d->defaultItemHeight != newDefaultItemHeight;
+ d->defaultItemHeight = newDefaultItemHeight;
+ }
+
if (topViewIndex != -1) {
- if (topLeft == bottomRight) {
+ if (topLeft.row() == bottomRight.row()) {
int oldHeight = d->itemHeight(topViewIndex);
d->invalidateHeightCache(topViewIndex);
- sizeChanged = (oldHeight != d->itemHeight(topViewIndex));
+ sizeChanged |= (oldHeight != d->itemHeight(topViewIndex));
+ if (topLeft.column() == 0)
+ d->viewItems[topViewIndex].hasChildren = d->hasVisibleChildren(topLeft);
} else {
int bottomViewIndex = d->viewIndex(bottomRight);
for (int i = topViewIndex; i <= bottomViewIndex; ++i) {
int oldHeight = d->itemHeight(i);
d->invalidateHeightCache(i);
sizeChanged |= (oldHeight != d->itemHeight(i));
+ if (topLeft.column() == 0)
+ d->viewItems[i].hasChildren = d->hasVisibleChildren(d->viewItems.at(i).index);
}
}
}
@@ -954,16 +962,16 @@ void QTreeView::keyboardSearch(const QString &search)
else
start = d->model->index(0, 0, d->root);
- QTime now(QTime::currentTime());
bool skipRow = false;
- if (search.isEmpty()
- || (d->keyboardInputTime.msecsTo(now) > QApplication::keyboardInputInterval())) {
+ bool keyboardTimeWasValid = d->keyboardInputTime.isValid();
+ qint64 keyboardInputTimeElapsed = d->keyboardInputTime.restart();
+ if (search.isEmpty() || !keyboardTimeWasValid
+ || keyboardInputTimeElapsed > 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;
}
- d->keyboardInputTime = now;
// special case for searches with same key like 'aaaaa'
bool sameKey = false;
@@ -1228,17 +1236,17 @@ bool QTreeView::viewportEvent(QEvent *event)
int oldBranch = d->hoverBranch;
d->hoverBranch = d->itemDecorationAt(he->pos());
if (oldBranch != d->hoverBranch) {
- QModelIndex oldIndex = d->modelIndex(oldBranch),
- newIndex = d->modelIndex(d->hoverBranch);
- if (oldIndex != newIndex) {
- QRect oldRect = visualRect(oldIndex);
- QRect newRect = visualRect(newIndex);
- oldRect.setLeft(oldRect.left() - d->indent);
- newRect.setLeft(newRect.left() - d->indent);
- //we need to paint the whole items (including the decoration) so that when the user
- //moves the mouse over those elements they are updated
- viewport()->update(oldRect);
- viewport()->update(newRect);
+ //we need to paint the whole items (including the decoration) so that when the user
+ //moves the mouse over those elements they are updated
+ if (oldBranch >= 0) {
+ int y = d->coordinateForItem(oldBranch);
+ int h = d->itemHeight(oldBranch);
+ viewport()->update(QRect(0, y, viewport()->width(), h));
+ }
+ if (d->hoverBranch >= 0) {
+ int y = d->coordinateForItem(d->hoverBranch);
+ int h = d->itemHeight(d->hoverBranch);
+ viewport()->update(QRect(0, y, viewport()->width(), h));
}
}
break; }
@@ -1993,6 +2001,24 @@ QModelIndex QTreeView::indexBelow(const QModelIndex &index) const
void QTreeView::doItemsLayout()
{
Q_D(QTreeView);
+ if (d->hasRemovedItems) {
+ //clean the QSet that may contains old (and this invalid) indexes
+ d->hasRemovedItems = false;
+ QSet<QPersistentModelIndex>::iterator it = d->expandedIndexes.begin();
+ while (it != d->expandedIndexes.constEnd()) {
+ if (!it->isValid())
+ it = d->expandedIndexes.erase(it);
+ else
+ ++it;
+ }
+ it = d->hiddenIndexes.begin();
+ while (it != d->hiddenIndexes.constEnd()) {
+ if (!it->isValid())
+ it = d->hiddenIndexes.erase(it);
+ else
+ ++it;
+ }
+ }
d->viewItems.clear(); // prepare for new layout
QModelIndex parent = d->root;
if (d->model->hasChildren(parent)) {
@@ -2134,9 +2160,10 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
return d->modelIndex(d->above(vi), current.column());
case MoveLeft: {
QScrollBar *sb = horizontalScrollBar();
- if (vi < d->viewItems.count() && d->viewItems.at(vi).expanded && d->itemsExpandable && sb->value() == sb->minimum())
+ if (vi < d->viewItems.count() && d->viewItems.at(vi).expanded && d->itemsExpandable && sb->value() == sb->minimum()) {
d->collapse(vi, true);
- else {
+ d->moveCursorUpdatedView = true;
+ } else {
bool descend = style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren, 0, this);
if (descend) {
QModelIndex par = current.parent();
@@ -2156,7 +2183,10 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
return next;
}
+ int oldValue = sb->value();
sb->setValue(sb->value() - sb->singleStep());
+ if (oldValue != sb->value())
+ d->moveCursorUpdatedView = true;
}
}
@@ -2168,6 +2198,7 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
if (vi < d->viewItems.count() && !d->viewItems.at(vi).expanded && d->itemsExpandable
&& d->hasVisibleChildren(d->viewItems.at(vi).index)) {
d->expand(vi, true);
+ d->moveCursorUpdatedView = true;
} else {
bool descend = style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren, 0, this);
if (descend) {
@@ -2190,7 +2221,10 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
//last restort: we change the scrollbar value
QScrollBar *sb = horizontalScrollBar();
+ int oldValue = sb->value();
sb->setValue(sb->value() + sb->singleStep());
+ if (oldValue != sb->value())
+ d->moveCursorUpdatedView = true;
}
}
updateGeometries();
@@ -2249,6 +2283,9 @@ void QTreeView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl
/*!
Returns the rectangle from the viewport of the items in the given
\a selection.
+
+ Since 4.7, the returned region only contains rectangles intersecting
+ (or included in) the viewport.
*/
QRegion QTreeView::visualRegionForSelection(const QItemSelection &selection) const
{
@@ -2257,6 +2294,7 @@ QRegion QTreeView::visualRegionForSelection(const QItemSelection &selection) con
return QRegion();
QRegion selectionRegion;
+ const QRect &viewportRect = d->viewport->rect();
for (int i = 0; i < selection.count(); ++i) {
QItemSelectionRange range = selection.at(i);
if (!range.isValid())
@@ -2289,13 +2327,16 @@ QRegion QTreeView::visualRegionForSelection(const QItemSelection &selection) con
qSwap<int>(top, bottom);
int height = bottom - top + 1;
if (d->header->sectionsMoved()) {
- for (int c = range.left(); c <= range.right(); ++c)
- selectionRegion += QRegion(QRect(columnViewportPosition(c), top,
- columnWidth(c), height));
+ for (int c = range.left(); c <= range.right(); ++c) {
+ const QRect rangeRect(columnViewportPosition(c), top, columnWidth(c), height);
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
+ }
} else {
QRect combined = leftRect|rightRect;
combined.setX(columnViewportPosition(isRightToLeft() ? range.right() : range.left()));
- selectionRegion += combined;
+ if (viewportRect.intersects(combined))
+ selectionRegion += combined;
}
}
return selectionRegion;
@@ -2402,24 +2443,6 @@ void QTreeView::reexpand()
}
/*!
- \internal
-*/
-static bool treeViewItemLessThan(const QTreeViewItem &left,
- const QTreeViewItem &right)
-{
- if (left.level != right.level) {
- Q_ASSERT(left.level > right.level);
- QModelIndex leftParent = left.index.parent();
- QModelIndex rightParent = right.index.parent();
- // computer parent, don't get
- while (leftParent.isValid() && leftParent.parent() != rightParent)
- leftParent = leftParent.parent();
- return (leftParent.row() < right.index.row());
- }
- return (left.index.row() < right.index.row());
-}
-
-/*!
Informs the view that the rows from the \a start row to the \a end row
inclusive have been inserted into the \a parent model item.
*/
@@ -2448,84 +2471,7 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end)
const int parentItem = d->viewIndex(parent);
if (((parentItem != -1) && d->viewItems.at(parentItem).expanded && updatesEnabled())
|| (parent == d->root)) {
- const uint childLevel = (parentItem == -1)
- ? uint(0) : d->viewItems.at(parentItem).level + 1;
- const int firstChildItem = parentItem + 1;
- const int lastChildItem = firstChildItem + ((parentItem == -1)
- ? d->viewItems.count()
- : d->viewItems.at(parentItem).total) - 1;
-
- if (parentRowCount == end + 1 && start > 0) {
- //need to Update hasMoreSiblings
- int previousRow = start - 1;
- QModelIndex previousSibilingModelIndex = d->model->index(previousRow, 0, parent);
- bool isHidden = d->isRowHidden(previousSibilingModelIndex);
- while (isHidden && previousRow > 0) {
- previousRow--;
- previousSibilingModelIndex = d->model->index(previousRow, 0, parent);
- isHidden = d->isRowHidden(previousSibilingModelIndex);
- }
- if (!isHidden) {
- const int previousSibilling = d->viewIndex(previousSibilingModelIndex);
- if(previousSibilling != -1)
- d->viewItems[previousSibilling].hasMoreSiblings = true;
- }
- }
-
- QVector<QTreeViewItem> insertedItems(delta);
- for (int i = 0; i < delta; ++i) {
- QTreeViewItem &item = insertedItems[i];
- item.index = d->model->index(i + start, 0, parent);
- item.level = childLevel;
- item.hasChildren = d->hasVisibleChildren(item.index);
- item.hasMoreSiblings = !((i == delta - 1) && (parentRowCount == end +1));
- }
- if (d->viewItems.isEmpty())
- d->defaultItemHeight = indexRowSizeHint(insertedItems[0].index);
-
- int insertPos;
- if (lastChildItem < firstChildItem) { // no children
- insertPos = firstChildItem;
- } else {
- // do a binary search to figure out where to insert
- QVector<QTreeViewItem>::iterator it;
- it = qLowerBound(d->viewItems.begin() + firstChildItem,
- d->viewItems.begin() + lastChildItem + 1,
- insertedItems.at(0), treeViewItemLessThan);
- insertPos = it - d->viewItems.begin();
-
- // update stale model indexes of siblings
- for (int item = insertPos; item <= lastChildItem; ) {
- Q_ASSERT(d->viewItems.at(item).level == childLevel);
- const QModelIndex modelIndex = d->viewItems.at(item).index;
- //Q_ASSERT(modelIndex.parent() == parent);
- d->viewItems[item].index = d->model->index(
- modelIndex.row() + delta, modelIndex.column(), parent);
-
- if (!d->viewItems[item].index.isValid()) {
- // Something really bad is happening, a bad model is
- // often the cause. We can't optimize in this case :(
- qWarning() << "QTreeView::rowsInserted internal representation of the model has been corrupted, resetting.";
- doItemsLayout();
- return;
- }
-
- item += d->viewItems.at(item).total + 1;
- }
- }
-
- d->viewItems.insert(insertPos, delta, insertedItems.at(0));
- if (delta > 1) {
- qCopy(insertedItems.begin() + 1, insertedItems.end(),
- d->viewItems.begin() + insertPos + 1);
- }
-
- if (parentItem != -1)
- d->viewItems[parentItem].hasChildren = true;
- d->updateChildCount(parentItem, delta);
-
- updateGeometries();
- viewport()->update();
+ d->doDelayedItemsLayout();
} else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) {
d->doDelayedItemsLayout();
} else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) {
@@ -2543,8 +2489,8 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end)
void QTreeView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
Q_D(QTreeView);
- d->rowsRemoved(parent, start, end, false);
QAbstractItemView::rowsAboutToBeRemoved(parent, start, end);
+ d->viewItems.clear();
}
/*!
@@ -2556,7 +2502,10 @@ void QTreeView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e
void QTreeView::rowsRemoved(const QModelIndex &parent, int start, int end)
{
Q_D(QTreeView);
- d->rowsRemoved(parent, start, end, true);
+ d->viewItems.clear();
+ d->doDelayedItemsLayout();
+ d->hasRemovedItems = true;
+ d->_q_rowsRemoved(parent, start, end);
}
/*!
@@ -2658,17 +2607,8 @@ void QTreeView::expandAll()
{
Q_D(QTreeView);
d->viewItems.clear();
- d->expandedIndexes.clear();
d->interruptDelayedItemsLayout();
- d->layout(-1);
- for (int i = 0; i < d->viewItems.count(); ++i) {
- if (d->viewItems[i].expanded)
- continue;
- d->viewItems[i].expanded = true;
- d->layout(i);
- QModelIndex idx = d->viewItems.at(i).index;
- d->expandedIndexes.insert(idx);
- }
+ d->layout(-1, true);
updateGeometries();
d->viewport->update();
}
@@ -2949,6 +2889,39 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
}
}
+void QTreeViewPrivate::insertViewItems(int pos, int count, const QTreeViewItem &viewItem)
+{
+ viewItems.insert(pos, count, viewItem);
+ QTreeViewItem *items = viewItems.data();
+ for (int i = pos + count; i < viewItems.count(); i++)
+ if (items[i].parentItem >= pos)
+ items[i].parentItem += count;
+}
+
+void QTreeViewPrivate::removeViewItems(int pos, int count)
+{
+ viewItems.remove(pos, count);
+ QTreeViewItem *items = viewItems.data();
+ for (int i = pos; i < viewItems.count(); i++)
+ if (items[i].parentItem >= pos)
+ items[i].parentItem -= count;
+}
+
+#if 0
+bool QTreeViewPrivate::checkViewItems() const
+{
+ for (int i = 0; i < viewItems.count(); ++i) {
+ const QTreeViewItem &vi = viewItems.at(i);
+ if (vi.parentItem == -1) {
+ Q_ASSERT(!vi.index.parent().isValid() || vi.index.parent() == root);
+ } else {
+ Q_ASSERT(vi.index.parent() == viewItems.at(vi.parentItem).index);
+ }
+ }
+ return true;
+}
+#endif
+
void QTreeViewPrivate::collapse(int item, bool emitSignal)
{
Q_Q(QTreeView);
@@ -2977,14 +2950,11 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal)
expandedIndexes.erase(it);
viewItems[item].expanded = false;
int index = item;
- QModelIndex parent = modelIndex;
- while (parent.isValid() && parent != root) {
- Q_ASSERT(index > -1);
+ while (index > -1) {
viewItems[index].total -= total;
- parent = parent.parent();
- index = viewIndex(parent);
+ index = viewItems[index].parentItem;
}
- viewItems.remove(item + 1, total); // collapse
+ removeViewItems(item + 1, total); // collapse
q->setState(oldState);
if (emitSignal) {
@@ -3121,7 +3091,14 @@ void QTreeViewPrivate::_q_columnsRemoved(const QModelIndex &parent, int start, i
QAbstractItemViewPrivate::_q_columnsRemoved(parent, start, end);
}
-void QTreeViewPrivate::layout(int i)
+/** \internal
+ creates and initialize the viewItem structure of the children of the element \i
+
+ set \a recursiveExpanding if the function has to expand all the children (called from expandAll)
+ \a afterIsUninitialized is when we recurse from layout(-1), it means all the items after 'i' are
+ not yet initialized and need not to be moved
+ */
+void QTreeViewPrivate::layout(int i, bool recursiveExpanding, bool afterIsUninitialized)
{
Q_Q(QTreeView);
QModelIndex current;
@@ -3148,8 +3125,12 @@ void QTreeViewPrivate::layout(int i)
defaultItemHeight = q->indexRowSizeHint(index);
}
viewItems.resize(count);
+ afterIsUninitialized = true;
} else if (viewItems[i].total != (uint)count) {
- viewItems.insert(i + 1, count, QTreeViewItem()); // expand
+ if (!afterIsUninitialized)
+ insertViewItems(i + 1, count, QTreeViewItem()); // expand
+ else if (count > 0)
+ viewItems.resize(viewItems.count() + count);
} else {
expanding = false;
}
@@ -3171,15 +3152,18 @@ void QTreeViewPrivate::layout(int i)
item->hasMoreSiblings = true;
item = &viewItems[last];
item->index = current;
+ item->parentItem = i;
item->level = level;
item->height = 0;
item->spanning = q->isFirstColumnSpanned(current.row(), parent);
item->expanded = false;
item->total = 0;
item->hasMoreSiblings = false;
- if (isIndexExpanded(current)) {
+ if (recursiveExpanding || isIndexExpanded(current)) {
+ if (recursiveExpanding)
+ expandedIndexes.insert(current);
item->expanded = true;
- layout(last);
+ layout(last, recursiveExpanding, afterIsUninitialized);
item = &viewItems[last];
children += item->total;
item->hasChildren = item->total > 0;
@@ -3191,29 +3175,35 @@ void QTreeViewPrivate::layout(int i)
}
// remove hidden items
- if (hidden > 0)
- viewItems.remove(last + 1, hidden); // collapse
+ if (hidden > 0) {
+ if (!afterIsUninitialized)
+ removeViewItems(last + 1, hidden);
+ else
+ viewItems.resize(viewItems.size() - hidden);
+ }
if (!expanding)
return; // nothing changed
- while (parent != root) {
- Q_ASSERT(i > -1);
+ while (i > -1) {
viewItems[i].total += count - hidden;
- parent = parent.parent();
- i = viewIndex(parent);
+ i = viewItems[i].parentItem;
}
}
int QTreeViewPrivate::pageUp(int i) const
{
int index = itemAtCoordinate(coordinateForItem(i) - viewport->height());
+ while (isItemHiddenOrDisabled(index))
+ index--;
return index == -1 ? 0 : index;
}
int QTreeViewPrivate::pageDown(int i) const
{
int index = itemAtCoordinate(coordinateForItem(i) + viewport->height());
+ while (isItemHiddenOrDisabled(index))
+ index++;
return index == -1 ? viewItems.count() - 1 : index;
}
@@ -3356,46 +3346,39 @@ int QTreeViewPrivate::viewIndex(const QModelIndex &_index) const
const int totalCount = viewItems.count();
const QModelIndex index = _index.sibling(_index.row(), 0);
+ const int row = index.row();
+ const qint64 internalId = index.internalId();
-
- // A quick check near the last item to see if we are just incrementing
- const int start = lastViewedItem > 2 ? lastViewedItem - 2 : 0;
- const int end = lastViewedItem < totalCount - 2 ? lastViewedItem + 2 : totalCount;
- int row = index.row();
- for (int i = start; i < end; ++i) {
- const QModelIndex &idx = viewItems.at(i).index;
- if (idx.row() == row) {
- if (idx.internalId() == index.internalId()) {
- lastViewedItem = i;
- return i;
- }
+ // We start nearest to the lastViewedItem
+ int localCount = qMin(lastViewedItem - 1, totalCount - lastViewedItem);
+ for (int i = 0; i < localCount; ++i) {
+ const QModelIndex &idx1 = viewItems.at(lastViewedItem + i).index;
+ if (idx1.row() == row && idx1.internalId() == internalId) {
+ lastViewedItem = lastViewedItem + i;
+ return lastViewedItem;
+ }
+ const QModelIndex &idx2 = viewItems.at(lastViewedItem - i - 1).index;
+ if (idx2.row() == row && idx2.internalId() == internalId) {
+ lastViewedItem = lastViewedItem - i - 1;
+ return lastViewedItem;
}
}
- // NOTE: this function is slow if the item is outside the visible area
- // search in visible items first and below
- int t = firstVisibleItem();
- t = t > 100 ? t - 100 : 0; // start 100 items above the visible area
-
- for (int i = t; i < totalCount; ++i) {
- const QModelIndex &idx = viewItems.at(i).index;
- if (idx.row() == row) {
- if (idx.internalId() == index.internalId()) {
- lastViewedItem = i;
- return i;
- }
+ for (int j = qMax(0, lastViewedItem + localCount); j < totalCount; ++j) {
+ const QModelIndex &idx = viewItems.at(j).index;
+ if (idx.row() == row && idx.internalId() == internalId) {
+ lastViewedItem = j;
+ return j;
}
}
- // search from top to first visible
- for (int j = 0; j < t; ++j) {
+ for (int j = qMin(totalCount, lastViewedItem - localCount) - 1; j >= 0; --j) {
const QModelIndex &idx = viewItems.at(j).index;
- if (idx.row() == row) {
- if (idx.internalId() == index.internalId()) {
- lastViewedItem = j;
- return j;
- }
+ if (idx.row() == row && idx.internalId() == internalId) {
+ lastViewedItem = j;
+ return j;
}
}
+
// nothing found
return -1;
}
@@ -3445,25 +3428,6 @@ int QTreeViewPrivate::columnAt(int x) const
return header->logicalIndexAt(x);
}
-void QTreeViewPrivate::relayout(const QModelIndex &parent)
-{
- Q_Q(QTreeView);
- // do a local relayout of the items
- if (parent.isValid()) {
- int parentViewIndex = viewIndex(parent);
- if (parentViewIndex > -1 && viewItems.at(parentViewIndex).expanded) {
- collapse(parentViewIndex, false); // remove the current layout
- expand(parentViewIndex, false); // do the relayout
- q->updateGeometries();
- viewport->update();
- }
- } else {
- viewItems.clear();
- q->doItemsLayout();
- }
-}
-
-
void QTreeViewPrivate::updateScrollBars()
{
Q_Q(QTreeView);
@@ -3717,120 +3681,6 @@ bool QTreeViewPrivate::hasVisibleChildren(const QModelIndex& parent) const
return false;
}
-void QTreeViewPrivate::rowsRemoved(const QModelIndex &parent,
- int start, int end, bool after)
-{
- Q_Q(QTreeView);
- // if we are going to do a complete relayout anyway, there is no need to update
- if (delayedPendingLayout) {
- _q_rowsRemoved(parent, start, end);
- return;
- }
-
- const int parentItem = viewIndex(parent);
- if ((parentItem != -1) || (parent == root)) {
-
- const uint childLevel = (parentItem == -1)
- ? uint(0) : viewItems.at(parentItem).level + 1;
- Q_UNUSED(childLevel); // unused in release mode, used in assert below
-
- const int firstChildItem = parentItem + 1;
- int lastChildItem = firstChildItem + ((parentItem == -1)
- ? viewItems.count()
- : viewItems.at(parentItem).total) - 1;
-
- const int delta = end - start + 1;
-
- int previousSibiling = -1;
- int removedCount = 0;
- for (int item = firstChildItem; item <= lastChildItem; ) {
- Q_ASSERT(viewItems.at(item).level == childLevel);
- const QModelIndex modelIndex = viewItems.at(item).index;
- //Q_ASSERT(modelIndex.parent() == parent);
- const int count = viewItems.at(item).total + 1;
- if (modelIndex.row() < start) {
- previousSibiling = item;
- // not affected by the removal
- item += count;
- } else if (modelIndex.row() <= end) {
- // removed
- viewItems.remove(item, count);
- removedCount += count;
- lastChildItem -= count;
- } else {
- if (after) {
- // moved; update the model index
- viewItems[item].index = model->index(
- modelIndex.row() - delta, modelIndex.column(), parent);
- }
- item += count;
- }
- }
-
- if (previousSibiling != -1 && after && model->rowCount(parent) == start)
- viewItems[previousSibiling].hasMoreSiblings = false;
-
- if (parentItem != -1) {
- if (viewItems.at(parentItem).expanded) {
- updateChildCount(parentItem, -removedCount);
- if (viewItems.at(parentItem).total == 0)
- viewItems[parentItem].hasChildren = false; //every children have been removed;
- } else if (viewItems[parentItem].hasChildren && !hasVisibleChildren(parent)) {
- viewItems[parentItem].hasChildren = false;
- }
- }
- if (after) {
- q->updateGeometries();
- viewport->update();
- } else {
- //we have removed items: we should at least update the scroll bar values.
- // They are used to determine the item geometry.
- updateScrollBars();
- }
- } else {
- // If an ancestor of root is removed then relayout
- QModelIndex idx = root;
- while (idx.isValid()) {
- idx = idx.parent();
- if (idx == parent) {
- doDelayedItemsLayout();
- break;
- }
- }
- }
- _q_rowsRemoved(parent, start, end);
-
- QSet<QPersistentModelIndex>::iterator it = expandedIndexes.begin();
- while (it != expandedIndexes.constEnd()) {
- if (!it->isValid())
- it = expandedIndexes.erase(it);
- else
- ++it;
- }
- it = hiddenIndexes.begin();
- while (it != hiddenIndexes.constEnd()) {
- if (!it->isValid())
- it = hiddenIndexes.erase(it);
- else
- ++it;
- }
-}
-
-void QTreeViewPrivate::updateChildCount(const int parentItem, const int delta)
-{
- if ((parentItem != -1) && delta) {
- int level = viewItems.at(parentItem).level;
- int item = parentItem;
- do {
- Q_ASSERT(item >= 0);
- for ( ; int(viewItems.at(item).level) != level; --item) ;
- viewItems[item].total += delta;
- --level;
- } while (level >= 0);
- }
-}
-
-
void QTreeViewPrivate::_q_sortIndicatorChanged(int column, Qt::SortOrder order)
{
model->sort(column, order);
diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h
index 589a224da4..cbbfd0e36b 100644
--- a/src/gui/itemviews/qtreeview_p.h
+++ b/src/gui/itemviews/qtreeview_p.h
@@ -55,6 +55,7 @@
#include "private/qabstractitemview_p.h"
#include <QtCore/qvariantanimation.h>
+#include <QtCore/qabstractitemmodel.h>
#ifndef QT_NO_TREEVIEW
@@ -62,9 +63,10 @@ QT_BEGIN_NAMESPACE
struct QTreeViewItem
{
- QTreeViewItem() : expanded(false), spanning(false), hasChildren(false),
+ QTreeViewItem() : parentItem(-1), expanded(false), spanning(false), hasChildren(false),
hasMoreSiblings(false), total(0), level(0), height(0) {}
QModelIndex index; // we remove items whenever the indexes are invalidated
+ int parentItem; // parent item index in viewItems
uint expanded : 1;
uint spanning : 1;
uint hasChildren : 1; // if the item has visible children (even if collapsed)
@@ -74,6 +76,8 @@ struct QTreeViewItem
int height : 16; // row height
};
+Q_DECLARE_TYPEINFO(QTreeViewItem, Q_MOVABLE_TYPE);
+
class QTreeViewPrivate : public QAbstractItemViewPrivate
{
Q_DECLARE_PUBLIC(QTreeView)
@@ -87,7 +91,7 @@ public:
expandsOnDoubleClick(true),
allColumnsShowFocus(false), current(0), spanning(false),
animationsEnabled(false), columnResizeTimerID(0),
- autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false) {}
+ autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false), hasRemovedItems(false) {}
~QTreeViewPrivate() {}
void initialize();
@@ -123,7 +127,7 @@ public:
void _q_sortIndicatorChanged(int column, Qt::SortOrder order);
void _q_modelDestroyed();
- void layout(int item);
+ void layout(int item, bool recusiveExpanding = false, bool afterIsUninitialized = false);
int pageUp(int item) const;
int pageDown(int item) const;
@@ -136,11 +140,16 @@ public:
int viewIndex(const QModelIndex &index) const;
QModelIndex modelIndex(int i, int column = 0) const;
+ void insertViewItems(int pos, int count, const QTreeViewItem &viewItem);
+ void removeViewItems(int pos, int count);
+#if 0
+ bool checkViewItems() const;
+#endif
+
int firstVisibleItem(int *offset = 0) const;
int columnAt(int x) const;
bool hasVisibleChildren( const QModelIndex& parent) const;
- void relayout(const QModelIndex &parent);
bool expandOrCollapseItemAtPos(const QPoint &pos);
void updateScrollBars();
@@ -155,8 +164,6 @@ public:
QPair<int,int> startAndEndColumns(const QRect &rect) const;
void updateChildCount(const int parentItem, const int delta);
- void rowsRemoved(const QModelIndex &parent,
- int start, int end, bool before);
void paintAlternatingRowColors(QPainter *painter, QStyleOptionViewItemV4 *option, int y, int bottom) const;
@@ -232,6 +239,9 @@ public:
// used for blocking recursion when calling setViewportMargins from updateGeometries
bool geometryRecursionBlock;
+
+ // If we should clean the set
+ bool hasRemovedItems;
};
QT_END_NAMESPACE
diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp
index 19ed10b028..4c80325187 100644
--- a/src/gui/itemviews/qtreewidget.cpp
+++ b/src/gui/itemviews/qtreewidget.cpp
@@ -3039,10 +3039,14 @@ QList<QTreeWidgetItem*> QTreeWidget::selectedItems() const
Q_D(const QTreeWidget);
QModelIndexList indexes = selectionModel()->selectedIndexes();
QList<QTreeWidgetItem*> items;
+ items.reserve(indexes.count());
+ QSet<QTreeWidgetItem *> seen;
+ seen.reserve(indexes.count());
for (int i = 0; i < indexes.count(); ++i) {
QTreeWidgetItem *item = d->item(indexes.at(i));
- if (isItemHidden(item) || items.contains(item)) // ### slow, optimize later
+ if (isItemHidden(item) || seen.contains(item))
continue;
+ seen.insert(item);
items.append(item);
}
return items;
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 0993b86c2d..6fd45adf44 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -206,6 +206,7 @@ embedded {
OBJECTIVE_HEADERS += \
qcocoawindow_mac_p.h \
+ qcocoapanel_mac_p.h \
qcocoawindowdelegate_mac_p.h \
qcocoaview_mac_p.h \
qcocoaapplication_mac_p.h \
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
index 8ddd051ac3..a6d2594f6f 100644
--- a/src/gui/kernel/qaction.cpp
+++ b/src/gui/kernel/qaction.cpp
@@ -81,6 +81,7 @@ static QString qt_strippedText(QString s)
QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0),
visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false),
+ forceEnabledInSoftkeys(false), menuActionSoftkeys(false),
menuRole(QAction::TextHeuristicRole), softKeyRole(QAction::NoSoftKey),
priority(QAction::NormalPriority), iconVisibleInMenu(-1)
{
diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h
index 434136796b..538b04f77b 100644
--- a/src/gui/kernel/qaction.h
+++ b/src/gui/kernel/qaction.h
@@ -246,6 +246,9 @@ private:
friend class QMenuBar;
friend class QShortcutMap;
friend class QToolButton;
+#ifdef Q_WS_MAC
+ friend void qt_mac_clear_status_text(QAction *action);
+#endif
};
QT_BEGIN_INCLUDE_NAMESPACE
diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h
index b57e5d2c6b..899b01b4ae 100644
--- a/src/gui/kernel/qaction_p.h
+++ b/src/gui/kernel/qaction_p.h
@@ -75,6 +75,11 @@ public:
QActionPrivate();
~QActionPrivate();
+ static QActionPrivate *get(QAction *q)
+ {
+ return q->d_func();
+ }
+
bool showStatusText(QWidget *w, const QString &str);
QPointer<QActionGroup> group;
@@ -103,10 +108,16 @@ public:
uint checked : 1;
uint separator : 1;
uint fontSet : 1;
- QAction::MenuRole menuRole;
- QAction::SoftKeyRole softKeyRole;
- QAction::Priority priority;
+
+ //for soft keys management
+ uint forceEnabledInSoftkeys : 1;
+ uint menuActionSoftkeys : 1;
+
+ QAction::MenuRole menuRole : 3;
+ QAction::SoftKeyRole softKeyRole : 2;
+ QAction::Priority priority : 14;
int iconVisibleInMenu : 3; // Only has values -1, 0, and 1
+
QList<QWidget *> widgets;
#ifndef QT_NO_GRAPHICSVIEW
QList<QGraphicsWidget *> graphicsWidgets;
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index de74f53be5..ec635d4905 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -122,15 +122,19 @@ extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp
static void initResources()
{
#if defined(Q_WS_WINCE)
+ Q_INIT_RESOURCE_EXTERN(qstyle_wince)
Q_INIT_RESOURCE(qstyle_wince);
#elif defined(Q_OS_SYMBIAN)
+ Q_INIT_RESOURCE_EXTERN(qstyle_s60)
Q_INIT_RESOURCE(qstyle_s60);
#else
+ Q_INIT_RESOURCE_EXTERN(qstyle)
Q_INIT_RESOURCE(qstyle);
#endif
-
+ Q_INIT_RESOURCE_EXTERN(qmessagebox)
Q_INIT_RESOURCE(qmessagebox);
#if !defined(QT_NO_PRINTDIALOG)
+ Q_INIT_RESOURCE_EXTERN(qprintdialog)
Q_INIT_RESOURCE(qprintdialog);
#endif
@@ -182,6 +186,15 @@ QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::T
gestureManager = 0;
gestureWidget = 0;
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ move_cursor = 0;
+ copy_cursor = 0;
+ link_cursor = 0;
+#endif
+#if defined(Q_WS_WIN)
+ ignore_cursor = 0;
+#endif
+
if (!self)
self = this;
}
@@ -485,9 +498,7 @@ inline bool QApplicationPrivate::isAlien(QWidget *widget)
{
if (!widget)
return false;
-#if defined(Q_WS_MAC) // Fake alien behavior on the Mac :)
- return !widget->isWindow() && widget->window()->testAttribute(Qt::WA_DontShowOnScreen);
-#elif defined(Q_WS_QWS)
+#if defined(Q_WS_QWS)
return !widget->isWindow()
# ifdef Q_BACKINGSTORE_SUBSURFACES
&& !(widget->d_func()->maybeTopData() && widget->d_func()->maybeTopData()->windowSurface)
@@ -1034,6 +1045,15 @@ QApplication::~QApplication()
qt_clipboard = 0;
#endif
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ delete d->move_cursor; d->move_cursor = 0;
+ delete d->copy_cursor; d->copy_cursor = 0;
+ delete d->link_cursor; d->link_cursor = 0;
+#endif
+#if defined(Q_WS_WIN)
+ delete d->ignore_cursor; d->ignore_cursor = 0;
+#endif
+
delete QWidgetPrivate::mapper;
QWidgetPrivate::mapper = 0;
@@ -2291,6 +2311,22 @@ static bool qt_detectRTLLanguage()
" languages or to 'RTL' in right-to-left languages (such as Hebrew"
" and Arabic) to get proper widget layout.") == QLatin1String("RTL"));
}
+#if defined(Q_WS_MAC)
+static const char *application_menu_strings[] = {
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Services"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide %1"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide Others"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Show All"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Preferences..."),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Quit %1"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","About %1")
+ };
+QString qt_mac_applicationmenu_string(int type)
+{
+ return qApp->translate("MAC_APPLICATION_MENU",
+ application_menu_strings[type]);
+}
+#endif
#endif
/*!\reimp
@@ -2319,6 +2355,9 @@ bool QApplication::event(QEvent *e)
#ifndef QT_NO_TRANSLATION
setLayoutDirection(qt_detectRTLLanguage()?Qt::RightToLeft:Qt::LeftToRight);
#endif
+#if defined(QT_MAC_USE_COCOA)
+ qt_mac_post_retranslateAppMenu();
+#endif
QWidgetList list = topLevelWidgets();
for (int i = 0; i < list.size(); ++i) {
QWidget *w = list.at(i);
@@ -2993,7 +3032,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
return result;
}
-#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_WS_MAC)
/*
This function should only be called when the widget changes visibility, i.e.
when the \a widget is shown, hidden or deleted. This function does nothing
@@ -3053,7 +3092,7 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver);
#endif // QT_NO_CURSOR
}
-#endif // Q_WS_WIN || Q_WS_X11
+#endif // Q_WS_WIN || Q_WS_X11 || Q_WS_MAC
/*!
Returns the desktop widget (also called the root window).
@@ -5248,10 +5287,20 @@ QInputContext *QApplication::inputContext() const
qic = QInputContextFactory::create(QLatin1String("xim"), that);
that->d_func()->inputContext = qic;
}
-#elif defined(Q_WS_S60)
+#elif defined(Q_OS_SYMBIAN)
if (!d->inputContext) {
QApplication *that = const_cast<QApplication *>(this);
- that->d_func()->inputContext = QInputContextFactory::create(QString::fromLatin1("coefep"), that);
+ const QStringList keys = QInputContextFactory::keys();
+ // Try hbim and coefep first, then try others.
+ if (keys.contains(QLatin1String("hbim"))) {
+ that->d_func()->inputContext = QInputContextFactory::create(QLatin1String("hbim"), that);
+ } else if (keys.contains(QLatin1String("coefep"))) {
+ that->d_func()->inputContext = QInputContextFactory::create(QLatin1String("coefep"), that);
+ } else {
+ for (int c = 0; c < keys.size() && !d->inputContext; ++c) {
+ that->d_func()->inputContext = QInputContextFactory::create(keys[c], that);
+ }
+ }
}
#endif
return d->inputContext;
@@ -5691,6 +5740,230 @@ QGestureManager* QGestureManager::instance()
return qAppPriv->gestureManager;
}
+// These pixmaps approximate the images in the Windows User Interface Guidelines.
+
+// XPM
+
+static const char * const move_xpm[] = {
+"11 20 3 1",
+". c None",
+#if defined(Q_WS_WIN)
+"a c #000000",
+"X c #FFFFFF", // Windows cursor is traditionally white
+#else
+"a c #FFFFFF",
+"X c #000000", // X11 cursor is traditionally black
+#endif
+"aa.........",
+"aXa........",
+"aXXa.......",
+"aXXXa......",
+"aXXXXa.....",
+"aXXXXXa....",
+"aXXXXXXa...",
+"aXXXXXXXa..",
+"aXXXXXXXXa.",
+"aXXXXXXXXXa",
+"aXXXXXXaaaa",
+"aXXXaXXa...",
+"aXXaaXXa...",
+"aXa..aXXa..",
+"aa...aXXa..",
+"a.....aXXa.",
+"......aXXa.",
+".......aXXa",
+".......aXXa",
+"........aa."};
+
+#ifdef Q_WS_WIN
+/* XPM */
+static const char * const ignore_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa.....XXXX.....",
+".......aXXa..XXaaaaXX...",
+".......aXXa.XaaaaaaaaX..",
+"........aa.XaaaXXXXaaaX.",
+"...........XaaaaX..XaaX.",
+"..........XaaXaaaX..XaaX",
+"..........XaaXXaaaX.XaaX",
+"..........XaaX.XaaaXXaaX",
+"..........XaaX..XaaaXaaX",
+"...........XaaX..XaaaaX.",
+"...........XaaaXXXXaaaX.",
+"............XaaaaaaaaX..",
+".............XXaaaaXX...",
+"...............XXXX....."};
+#endif
+
+/* XPM */
+static const char * const copy_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+#if defined(Q_WS_WIN) // Windows cursor is traditionally white
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa..............",
+".......aXXa.............",
+".......aXXa.............",
+"........aa...aaaaaaaaaaa",
+#else
+"XX......................",
+"XaX.....................",
+"XaaX....................",
+"XaaaX...................",
+"XaaaaX..................",
+"XaaaaaX.................",
+"XaaaaaaX................",
+"XaaaaaaaX...............",
+"XaaaaaaaaX..............",
+"XaaaaaaaaaX.............",
+"XaaaaaaXXXX.............",
+"XaaaXaaX................",
+"XaaXXaaX................",
+"XaX..XaaX...............",
+"XX...XaaX...............",
+"X.....XaaX..............",
+"......XaaX..............",
+".......XaaX.............",
+".......XaaX.............",
+"........XX...aaaaaaaaaaa",
+#endif
+".............aXXXXXXXXXa",
+".............aXXXXXXXXXa",
+".............aXXXXaXXXXa",
+".............aXXXXaXXXXa",
+".............aXXaaaaaXXa",
+".............aXXXXaXXXXa",
+".............aXXXXaXXXXa",
+".............aXXXXXXXXXa",
+".............aXXXXXXXXXa",
+".............aaaaaaaaaaa"};
+
+/* XPM */
+static const char * const link_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+#if defined(Q_WS_WIN) // Windows cursor is traditionally white
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa..............",
+".......aXXa.............",
+".......aXXa.............",
+"........aa...aaaaaaaaaaa",
+#else
+"XX......................",
+"XaX.....................",
+"XaaX....................",
+"XaaaX...................",
+"XaaaaX..................",
+"XaaaaaX.................",
+"XaaaaaaX................",
+"XaaaaaaaX...............",
+"XaaaaaaaaX..............",
+"XaaaaaaaaaX.............",
+"XaaaaaaXXXX.............",
+"XaaaXaaX................",
+"XaaXXaaX................",
+"XaX..XaaX...............",
+"XX...XaaX...............",
+"X.....XaaX..............",
+"......XaaX..............",
+".......XaaX.............",
+".......XaaX.............",
+"........XX...aaaaaaaaaaa",
+#endif
+".............aXXXXXXXXXa",
+".............aXXXaaaaXXa",
+".............aXXXXaaaXXa",
+".............aXXXaaaaXXa",
+".............aXXaaaXaXXa",
+".............aXXaaXXXXXa",
+".............aXXaXXXXXXa",
+".............aXXXaXXXXXa",
+".............aXXXXXXXXXa",
+".............aaaaaaaaaaa"};
+
+QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape)
+{
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ if (!move_cursor) {
+ move_cursor = new QPixmap((const char **)move_xpm);
+ copy_cursor = new QPixmap((const char **)copy_xpm);
+ link_cursor = new QPixmap((const char **)link_xpm);
+#ifdef Q_WS_WIN
+ ignore_cursor = new QPixmap((const char **)ignore_xpm);
+#endif
+ }
+
+ switch (cshape) {
+ case Qt::DragMoveCursor:
+ return *move_cursor;
+ case Qt::DragCopyCursor:
+ return *copy_cursor;
+ case Qt::DragLinkCursor:
+ return *link_cursor;
+#ifdef Q_WS_WIN
+ case Qt::ForbiddenCursor:
+ return *ignore_cursor;
+#endif
+ default:
+ break;
+ }
+#endif
+ return QPixmap();
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index ee743501f3..c21b982a45 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -376,6 +376,7 @@ private:
Q_DECLARE_PRIVATE(QApplication)
friend class QGraphicsWidget;
+ friend class QGraphicsItem;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
friend class QWidget;
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
index 54a490137e..321492dfde 100644
--- a/src/gui/kernel/qapplication_mac.mm
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -184,7 +184,8 @@ bool qt_mac_app_fullscreen = false;
bool qt_scrollbar_jump_to_pos = false;
static bool qt_mac_collapse_on_dblclick = true;
extern int qt_antialiasing_threshold; // from qapplication.cpp
-QPointer<QWidget> qt_button_down; // widget got last button-down
+QWidget * qt_button_down; // widget got last button-down
+QPointer<QWidget> qt_last_mouse_receiver;
#ifndef QT_MAC_USE_COCOA
static bool qt_button_down_in_content; // whether the button_down was in the content area.
static bool qt_mac_previous_press_in_popup_mode = false;
@@ -1220,11 +1221,18 @@ void qt_init(QApplicationPrivate *priv, int)
}
#endif
- if (!app_proc_ae_handlerUPP) {
+ if (!app_proc_ae_handlerUPP && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor);
- for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i)
- AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
- app_proc_ae_handlerUPP, SRefCon(qApp), false);
+ for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) {
+ // Install apple event handler, but avoid overwriting an already
+ // existing handler (it means a 3rd party application has installed one):
+ SRefCon refCon = 0;
+ AEEventHandlerUPP current_handler = NULL;
+ AEGetEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, &current_handler, &refCon, false);
+ if (!current_handler)
+ AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
+ app_proc_ae_handlerUPP, SRefCon(qApp), false);
+ }
}
if (QApplicationPrivate::app_style) {
@@ -1237,7 +1245,7 @@ void qt_init(QApplicationPrivate *priv, int)
// Cocoa application delegate
#ifdef QT_MAC_USE_COCOA
- NSApplication *cocoaApp = [NSApplication sharedApplication];
+ NSApplication *cocoaApp = [QNSApplication sharedApplication];
QMacCocoaAutoReleasePool pool;
NSObject *oldDelegate = [cocoaApp delegate];
QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
@@ -1258,10 +1266,6 @@ void qt_init(QApplicationPrivate *priv, int)
[cocoaApp setMenu:[qtMenuLoader menu]];
[newDelegate setMenuLoader:qtMenuLoader];
[qtMenuLoader release];
-
- NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
- [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:)
- forEventClass:kInternetEventClass andEventID:kAEGetURL];
}
#endif
// Register for Carbon tablet proximity events on the event monitor target.
@@ -1361,12 +1365,39 @@ void QApplication::setMainWidget(QWidget *mainWidget)
/*****************************************************************************
QApplication cursor stack
*****************************************************************************/
+#ifdef QT_MAC_USE_COCOA
+void QApplicationPrivate::disableUsageOfCursorRects(bool disable)
+{
+ // In Cocoa there are two competing ways of setting the cursor; either
+ // by using cursor rects (see qcocoaview_mac.mm), or by pushing/popping
+ // the cursor manually. When we use override cursors, it makes most sense
+ // to use the latter. But then we need to tell cocoa to stop using the
+ // first approach so it doesn't change the cursor back when hovering over
+ // a cursor rect:
+ QWidgetList topLevels = qApp->topLevelWidgets();
+ for (int i=0; i<topLevels.size(); ++i) {
+ if (NSWindow *window = qt_mac_window_for(topLevels.at(i)))
+ disable ? [window disableCursorRects] : [window enableCursorRects];
+ }
+}
+
+void QApplicationPrivate::updateOverrideCursor()
+{
+ // Sometimes Cocoa forgets that we have set a Cursor
+ // manually. In those cases, remind it again:
+ if (QCursor *override = qApp->overrideCursor())
+ [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(*override)) set];
+}
+#endif
+
void QApplication::setOverrideCursor(const QCursor &cursor)
{
qApp->d_func()->cursor_list.prepend(cursor);
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
+ if (qApp->d_func()->cursor_list.size() == 1)
+ qApp->d_func()->disableUsageOfCursorRects(true);
[static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) push];
#else
if (qApp && qApp->activeWindow())
@@ -1383,6 +1414,8 @@ void QApplication::restoreOverrideCursor()
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
[NSCursor pop];
+ if (qApp->d_func()->cursor_list.isEmpty())
+ qApp->d_func()->disableUsageOfCursorRects(false);
#else
if (qApp && qApp->activeWindow()) {
const QCursor def(Qt::ArrowCursor);
@@ -1726,14 +1759,19 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
// (actually two events; one for horizontal and one for vertical).
// As a results of this, and to make sure we dont't receive duplicate events,
// we try to detect when this happend by checking the 'compatibilityEvent'.
+ // Since delta is delivered as pixels rather than degrees, we need to
+ // convert from pixels to degrees in a sensible manner.
+ // It looks like 1/4 degrees per pixel behaves most native.
+ // (NB: Qt expects the unit for delta to be 8 per degree):
+ const int pixelsToDegrees = 2;
SInt32 mdelt = 0;
GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0,
sizeof(mdelt), 0, &mdelt);
- wheel_deltaX = mdelt;
+ wheel_deltaX = mdelt * pixelsToDegrees;
mdelt = 0;
GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0,
sizeof(mdelt), 0, &mdelt);
- wheel_deltaY = mdelt;
+ wheel_deltaY = mdelt * pixelsToDegrees;
GetEventParameter(event, kEventParamEventRef, typeEventRef, 0,
sizeof(compatibilityEvent), 0, &compatibilityEvent);
} else if (ekind == kEventMouseWheelMoved) {
@@ -2408,25 +2446,30 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
}
if(!handled_event) {
if(cmd.commandID == kHICommandQuit) {
- handled_event = true;
- HiliteMenu(0);
- bool handle_quit = true;
- if(QApplicationPrivate::modalState()) {
- int visible = 0;
- const QWidgetList tlws = QApplication::topLevelWidgets();
- for(int i = 0; i < tlws.size(); ++i) {
- if(tlws.at(i)->isVisible())
- ++visible;
+ // Quitting the application is not Qt's responsibility if
+ // used in a plugin or just embedded into a native application.
+ // In that case, let the event pass down to the native apps event handler.
+ if (!QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
+ handled_event = true;
+ HiliteMenu(0);
+ bool handle_quit = true;
+ if(QApplicationPrivate::modalState()) {
+ int visible = 0;
+ const QWidgetList tlws = QApplication::topLevelWidgets();
+ for(int i = 0; i < tlws.size(); ++i) {
+ if(tlws.at(i)->isVisible())
+ ++visible;
+ }
+ handle_quit = (visible <= 1);
+ }
+ if(handle_quit) {
+ QCloseEvent ev;
+ QApplication::sendSpontaneousEvent(app, &ev);
+ if(ev.isAccepted())
+ app->quit();
+ } else {
+ QApplication::beep();
}
- handle_quit = (visible <= 1);
- }
- if(handle_quit) {
- QCloseEvent ev;
- QApplication::sendSpontaneousEvent(app, &ev);
- if(ev.isAccepted())
- app->quit();
- } else {
- QApplication::beep();
}
} else if(cmd.commandID == kHICommandSelectWindow) {
if((GetCurrentKeyModifiers() & cmdKey))
@@ -2457,6 +2500,35 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
#endif
}
+#ifdef QT_MAC_USE_COCOA
+void QApplicationPrivate::qt_initAfterNSAppStarted()
+{
+ setupAppleEvents();
+ updateOverrideCursor();
+}
+
+void QApplicationPrivate::setupAppleEvents()
+{
+ // This function is called from the event dispatcher when NSApplication has
+ // finished initialization, which appears to be just after [NSApplication run] has
+ // started to execute. By setting up our apple events handlers this late, we override
+ // the ones set up by NSApplication.
+
+ // If Qt is used as a plugin, we let the 3rd party application handle events
+ // like quit and open file events. Otherwise, if we install our own handlers, we
+ // easily end up breaking functionallity the 3rd party application depend on:
+ if (QApplication::testAttribute(Qt::AA_MacPluginApplication))
+ return;
+
+ QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
+ NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
+ [eventManager setEventHandler:newDelegate andSelector:@selector(appleEventQuit:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
+ [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:)
+ forEventClass:kInternetEventClass andEventID:kAEGetURL];
+}
+#endif
+
// In Carbon this is your one stop for apple events.
// In Cocoa, it ISN'T. This is the catch-all Apple Event handler that exists
// for the time between instantiating the NSApplication, but before the
@@ -3008,7 +3080,7 @@ void onApplicationWindowChangedActivation(QWidget *widget, bool activated)
}
QMenuBar::macUpdateMenuBar();
-
+ QApplicationPrivate::updateOverrideCursor();
#else
Q_UNUSED(widget);
Q_UNUSED(activated);
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index ce3933400b..01abe54059 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -459,6 +459,12 @@ public:
static OSStatus globalEventProcessor(EventHandlerCallRef, EventRef, void *);
static OSStatus globalAppleEventProcessor(const AppleEvent *, AppleEvent *, long);
static OSStatus tabletProximityCallback(EventHandlerCallRef, EventRef, void *);
+#ifdef QT_MAC_USE_COCOA
+ static void qt_initAfterNSAppStarted();
+ static void setupAppleEvents();
+ static void updateOverrideCursor();
+ static void disableUsageOfCursorRects(bool disable);
+#endif
static bool qt_mac_apply_settings();
#endif
@@ -508,12 +514,21 @@ public:
int symbianResourceChange(const QSymbianEvent *symbianEvent);
#endif
-#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_WS_MAC)
void sendSyntheticEnterLeave(QWidget *widget);
#endif
QGestureManager *gestureManager;
QWidget *gestureWidget;
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ QPixmap *move_cursor;
+ QPixmap *copy_cursor;
+ QPixmap *link_cursor;
+#endif
+#if defined(Q_WS_WIN)
+ QPixmap *ignore_cursor;
+#endif
+ QPixmap getPixmapCursor(Qt::CursorShape cshape);
QMap<int, QWeakPointer<QWidget> > widgetForTouchPointId;
QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints;
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 7087b4762e..5f7813b316 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -1262,11 +1262,13 @@ void qt_init(QApplicationPrivate * /* priv */, int)
}
#endif
+#ifdef QT_KEYPAD_NAVIGATION
if (touch) {
QApplicationPrivate::navigationMode = Qt::NavigationModeNone;
} else {
QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional;
}
+#endif
#ifndef QT_NO_CURSOR
//Check if window server pointer cursors are supported or not
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 49cb0f277c..fb2837ecf9 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -79,6 +79,7 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
#include "qlayout.h"
#include "qtooltip.h"
#include "qt_windows.h"
+#include "qscrollbar.h"
#if defined(QT_NON_COMMERCIAL)
#include "qnc_win.h"
#endif
@@ -441,7 +442,7 @@ extern QCursor *qt_grab_cursor();
#define __export
#endif
-extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
class QETWidget : public QWidget // event translator widget
{
@@ -701,6 +702,21 @@ void QApplicationPrivate::initializeWidgetPaletteHash()
QApplication::setPalette(menu, "QMenuBar");
}
+static void qt_set_windows_updateScrollBar(QWidget *widget)
+{
+ QList<QObject*> children = widget->children();
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *o = children.at(i);
+ if(!o->isWidgetType())
+ continue;
+ if (QWidget *w = static_cast<QWidget *>(o))
+ qt_set_windows_updateScrollBar(w);
+ }
+ if (qobject_cast<QScrollBar*>(widget))
+ widget->updateGeometry();
+}
+
+
/*****************************************************************************
qt_init() - initializes Qt for Windows
*****************************************************************************/
@@ -1400,8 +1416,7 @@ static bool qt_is_translatable_mouse_event(UINT message)
;
}
-extern "C"
-LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
bool result = true;
QEvent::Type evt_type = QEvent::None;
@@ -1579,6 +1594,10 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_XBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDBLCLK:
+ case WM_MBUTTONDBLCLK:
+ case WM_XBUTTONDBLCLK:
if (qt_win_ignoreNextMouseReleaseEvent)
qt_win_ignoreNextMouseReleaseEvent = false;
break;
@@ -1927,6 +1946,15 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
}
}
+ else if (msg.wParam == SPI_SETNONCLIENTMETRICS) {
+ widget = (QETWidget*)QWidget::find(hwnd);
+ if (widget && !widget->parentWidget()) {
+ qt_set_windows_updateScrollBar(widget);
+ QEvent e(QEvent::LayoutRequest);
+ QApplication::sendEvent(widget, &e);
+ }
+ }
+
break;
case WM_PAINT: // paint event
@@ -2279,7 +2307,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_GETOBJECT:
{
// Ignoring all requests while starting up
- if (QApplication::startingUp() || QApplication::closingDown() || (DWORD)lParam != OBJID_CLIENT) {
+ if (QApplication::startingUp() || QApplication::closingDown() || (LONG)lParam != OBJID_CLIENT) {
result = false;
break;
}
@@ -2560,6 +2588,17 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
break;
}
#endif // !defined(Q_WS_WINCE) || defined(QT_WINCE_GESTURES)
+#ifndef QT_NO_CURSOR
+ case WM_SETCURSOR: {
+ QCursor *ovr = QApplication::overrideCursor();
+ if (ovr) {
+ SetCursor(ovr->handle());
+ RETURN(TRUE);
+ }
+ result = false;
+ break;
+ }
+#endif
default:
result = false; // event was not processed
break;
@@ -2982,7 +3021,10 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
// most recent one.
msgPtr->lParam = mouseMsg.lParam;
msgPtr->wParam = mouseMsg.wParam;
- msgPtr->pt = mouseMsg.pt;
+ // Extract the x,y coordinates from the lParam as we do in the WndProc
+ msgPtr->pt.x = GET_X_LPARAM(mouseMsg.lParam);
+ msgPtr->pt.y = GET_Y_LPARAM(mouseMsg.lParam);
+ ClientToScreen(msg.hwnd, &(msgPtr->pt));
// Remove the mouse move message
PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE,
WM_MOUSEMOVE, PM_REMOVE);
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 25a7750d96..78fc704cb6 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -213,11 +213,8 @@ static const char * x11_atomnames = {
"_MOTIF_WM_HINTS\0"
"DTWM_IS_RUNNING\0"
- "KDE_FULL_SESSION\0"
- "KWIN_RUNNING\0"
- "KWM_RUNNING\0"
- "GNOME_BACKGROUND_PROPERTIES\0"
"ENLIGHTENMENT_DESKTOP\0"
+ "_DT_SAVE_MODE\0"
"_SGI_DESKS_MANAGER\0"
// EWMH (aka NETWM)
@@ -278,6 +275,8 @@ static const char * x11_atomnames = {
"_NET_SYSTEM_TRAY_VISUAL\0"
+ "_NET_ACTIVE_WINDOW\0"
+
// Property formats
"COMPOUND_TEXT\0"
"TEXT\0"
@@ -624,6 +623,11 @@ static int (*original_xio_errhandler)(Display *dpy);
static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
{
+ if (X11->display != dpy) {
+ // only handle X errors for our display
+ return 0;
+ }
+
switch (err->error_code) {
case BadAtom:
if (err->request_code == 20 /* X_GetProperty */
@@ -631,8 +635,6 @@ static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
|| err->resourceid == XA_RGB_DEFAULT_MAP
|| err->resourceid == ATOM(_NET_SUPPORTED)
|| err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK)
- || err->resourceid == ATOM(KDE_FULL_SESSION)
- || err->resourceid == ATOM(KWIN_RUNNING)
|| err->resourceid == ATOM(XdndProxy)
|| err->resourceid == ATOM(XdndAware))) {
// Perhaps we're running under SECURITY reduction? :/
@@ -667,11 +669,6 @@ static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
return 0;
break;
- case BadMatch:
- if (err->request_code == 42 /* X_SetInputFocus */)
- return 0;
- break;
-
default:
#if !defined(QT_NO_XINPUT)
if (err->request_code == X11->xinput_major
@@ -709,6 +706,10 @@ static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
extensionName = "XInputExtension";
else if (err->request_code == X11->mitshm_major)
extensionName = "MIT-SHM";
+#ifndef QT_NO_XKB
+ else if(err->request_code == X11->xkb_major)
+ extensionName = "XKEYBOARD";
+#endif
char minor_str[256];
if (extensionName) {
@@ -1635,6 +1636,11 @@ void qt_init(QApplicationPrivate *priv, int,
X11->xinput_eventbase = 0;
X11->xinput_errorbase = 0;
+ X11->use_xkb = false;
+ X11->xkb_major = 0;
+ X11->xkb_eventbase = 0;
+ X11->xkb_errorbase = 0;
+
// MIT-SHM
X11->use_mitshm = false;
X11->use_mitshm_pixmaps = false;
@@ -2108,6 +2114,33 @@ void qt_init(QApplicationPrivate *priv, int,
}
#endif // QT_NO_XINPUT
+#ifndef QT_NO_XKB
+ int xkblibMajor = XkbMajorVersion;
+ int xkblibMinor = XkbMinorVersion;
+ X11->use_xkb = XkbQueryExtension(X11->display,
+ &X11->xkb_major,
+ &X11->xkb_eventbase,
+ &X11->xkb_errorbase,
+ &xkblibMajor,
+ &xkblibMinor);
+ if (X11->use_xkb) {
+ // If XKB is detected, set the GrabsUseXKBState option so input method
+ // compositions continue to work (ie. deadkeys)
+ unsigned int state = XkbPCF_GrabsUseXKBStateMask;
+ (void) XkbSetPerClientControls(X11->display, state, &state);
+
+ // select for group change events
+ XkbSelectEventDetails(X11->display,
+ XkbUseCoreKbd,
+ XkbStateNotify,
+ XkbAllStateComponentsMask,
+ XkbGroupStateMask);
+
+ // current group state is queried when creating the keymapper, no need to do it here
+ }
+#endif
+
+
#if !defined(QT_NO_FONTCONFIG)
int dpi = 0;
getXDefault("Xft", FC_DPI, &dpi);
@@ -2186,15 +2219,6 @@ void qt_init(QApplicationPrivate *priv, int,
// initialize key mapper
QKeyMapper::changeKeyboard();
-#ifndef QT_NO_XKB
- if (qt_keymapper_private()->useXKB) {
- // If XKB is detected, set the GrabsUseXKBState option so input method
- // compositions continue to work (ie. deadkeys)
- unsigned int state = XkbPCF_GrabsUseXKBStateMask;
- (void) XkbSetPerClientControls(X11->display, state, &state);
- }
-#endif // QT_NO_XKB
-
// Misc. initialization
#if 0 //disabled for now..
QSegfaultHandler::initialize(priv->argv, priv->argc);
@@ -2227,87 +2251,66 @@ void qt_init(QApplicationPrivate *priv, int,
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;
- Atom typeReturned;
- int formatReturned;
- unsigned long nitemsReturned;
- unsigned long unused;
- unsigned char *data = 0;
- if (XGetWindowProperty(QX11Info::display(), QX11Info::appRootWindow(),
- ATOM(_NET_SUPPORTING_WM_CHECK),
- 0, 1024, False, XA_WINDOW, &typeReturned,
- &formatReturned, &nitemsReturned, &unused, &data)
- == Success) {
- if (typeReturned == XA_WINDOW && formatReturned == 32)
- windowManagerWindow = *((Window*) data);
- if (data)
- XFree(data);
+ Atom type;
+ int format;
+ unsigned long length, after;
+ uchar *data = 0;
+ int rc;
- if (windowManagerWindow != XNone) {
- QString wmName;
- Atom utf8atom = ATOM(UTF8_STRING);
- if (XGetWindowProperty(QX11Info::display(), windowManagerWindow, ATOM(_NET_WM_NAME),
- 0, 1024, False, utf8atom, &typeReturned,
- &formatReturned, &nitemsReturned, &unused, &data)
- == Success) {
- if (typeReturned == utf8atom && formatReturned == 8)
- wmName = QString::fromUtf8((const char*)data);
- if (data)
- XFree(data);
- if (wmName == QLatin1String("KWin"))
- X11->desktopEnvironment = DE_KDE;
- if (wmName == QLatin1String("Metacity"))
- X11->desktopEnvironment = DE_GNOME;
- }
+ do {
+ if (!qgetenv("KDE_FULL_SESSION").isEmpty()) {
+ X11->desktopEnvironment = DE_KDE;
+ X11->desktopVersion = qgetenv("KDE_SESSION_VERSION").toInt();
+ break;
}
- }
- // Running a different/newer/older window manager? Try some other things
- if (X11->desktopEnvironment == DE_UNKNOWN){
- Atom type;
- int format;
- unsigned long length, after;
- uchar *data = 0;
+ if (qgetenv("DESKTOP_SESSION") == "gnome") {
+ X11->desktopEnvironment = DE_GNOME;
+ break;
+ }
- QString session = QString::fromLocal8Bit(qgetenv("DESKTOP_SESSION"));
- if (session == QLatin1String("kde")) {
- X11->desktopEnvironment = DE_KDE;
- } else if (session == QLatin1String("gnome") || session == QLatin1String("xfce")) {
+ // GNOME_DESKTOP_SESSION_ID is deprecated for some reason, but still check it
+ if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) {
X11->desktopEnvironment = DE_GNOME;
- } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(DTWM_IS_RUNNING),
- 0, 1, False, AnyPropertyType, &type, &format, &length,
- &after, &data) == Success && length) {
+ break;
+ }
+
+ rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(_DT_SAVE_MODE),
+ 0, 2, False, XA_STRING, &type, &format, &length,
+ &after, &data);
+ if (rc == Success && length) {
+ if (!strcmp(reinterpret_cast<char *>(data), "xfce4")) {
+ // Pretend that xfce4 is gnome, as it uses the same libraries.
+ // The detection above is stolen from xdg-open.
+ X11->desktopEnvironment = DE_GNOME;
+ break;
+ }
+
+ // We got the property but it wasn't xfce4. Free data before it gets overwritten.
+ XFree(data);
+ data = 0;
+ }
+
+ rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(DTWM_IS_RUNNING),
+ 0, 1, False, AnyPropertyType, &type, &format, &length,
+ &after, &data);
+ if (rc == Success && length) {
// DTWM is running, meaning most likely CDE is running...
X11->desktopEnvironment = DE_CDE;
- } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
- ATOM(GNOME_BACKGROUND_PROPERTIES), 0, 1, False, AnyPropertyType,
- &type, &format, &length, &after, &data) == Success && length) {
- X11->desktopEnvironment = DE_GNOME;
- } else if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) {
- X11->desktopEnvironment = DE_GNOME;
- } else if ((XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KDE_FULL_SESSION),
- 0, 1, False, AnyPropertyType, &type, &format, &length, &after, &data) == Success
- && length)
- || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWIN_RUNNING),
- 0, 1, False, AnyPropertyType, &type, &format, &length,
- &after, &data) == Success
- && length)
- || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWM_RUNNING),
- 0, 1, False, AnyPropertyType, &type, &format, &length,
- &after, &data) == Success && length)) {
- X11->desktopEnvironment = DE_KDE;
- } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(_SGI_DESKS_MANAGER),
- 0, 1, False, XA_WINDOW, &type, &format, &length, &after, &data) == Success
- && length) {
+ break;
+ }
+
+ rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
+ ATOM(_SGI_DESKS_MANAGER), 0, 1, False, XA_WINDOW,
+ &type, &format, &length, &after, &data);
+ if (rc == Success && length) {
X11->desktopEnvironment = DE_4DWM;
+ break;
}
- if (data)
- XFree((char *)data);
- }
+ } while(0);
- if (X11->desktopEnvironment == DE_KDE)
- X11->desktopVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
+ if (data)
+ XFree((char *)data);
#if !defined(QT_NO_STYLE_GTK)
if (X11->desktopEnvironment == DE_GNOME) {
@@ -3052,6 +3055,8 @@ int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
if ((ulong) event->xclient.data.l[1] > X11->time)
X11->time = event->xclient.data.l[1];
QWidget *amw = activeModalWidget();
+ if (amw && amw->testAttribute(Qt::WA_X11DoNotAcceptFocus))
+ amw = 0;
if (amw && !QApplicationPrivate::tryModalHelper(widget, 0)) {
QWidget *p = amw->parentWidget();
while (p && p != widget)
@@ -3250,6 +3255,24 @@ int QApplication::x11ProcessEvent(XEvent* event)
QKeyMapper::changeKeyboard();
return 0;
}
+#ifndef QT_NO_XKB
+ else if (X11->use_xkb && event->type == X11->xkb_eventbase) {
+ XkbAnyEvent *xkbevent = (XkbAnyEvent *) event;
+ switch (xkbevent->xkb_type) {
+ case XkbStateNotify:
+ {
+ XkbStateNotifyEvent *xkbstateevent = (XkbStateNotifyEvent *) xkbevent;
+ if ((xkbstateevent->changed & XkbGroupStateMask) != 0) {
+ qt_keymapper_private()->xkb_currentGroup = xkbstateevent->group;
+ QKeyMapper::changeKeyboard();
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+#endif
if (!widget) { // don't know this windows
QWidget* popup = QApplication::activePopupWidget();
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index a59bb98236..f7c0b6ee2a 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -107,6 +107,12 @@ QT_BEGIN_NAMESPACE
store or retrieve the clipboard contents in response to timer or
non-user-input events.
+ \i Since there is no standard way to copy and paste files between
+ applications on X11, various MIME types and conventions are currently
+ in use. For instance, Nautilus expects files to be supplied with a
+ \c{x-special/gnome-copied-files} MIME type with data beginning with
+ the cut/copy action, a newline character, and the URL of the file.
+
\endlist
\section1 Notes for Mac OS X Users
diff --git a/src/gui/kernel/qclipboard_x11.cpp b/src/gui/kernel/qclipboard_x11.cpp
index 047bd09437..3bdc971ef7 100644
--- a/src/gui/kernel/qclipboard_x11.cpp
+++ b/src/gui/kernel/qclipboard_x11.cpp
@@ -65,7 +65,6 @@
#include "qapplication.h"
#include "qdesktopwidget.h"
#include "qbitmap.h"
-#include "qdatetime.h"
#include "qiodevice.h"
#include "qbuffer.h"
#include "qtextcodec.h"
@@ -76,6 +75,7 @@
#include "qt_x11_p.h"
#include "qx11info_x11.h"
#include "qimagewriter.h"
+#include "qelapsedtimer.h"
#include "qvariant.h"
#include "qdnd_p.h"
#include <private/qwidget_p.h>
@@ -516,8 +516,9 @@ static Bool checkForClipboardEvents(Display *, XEvent *e, XPointer)
bool QX11Data::clipboardWaitForEvent(Window win, int type, XEvent *event, int timeout)
{
- QTime started = QTime::currentTime();
- QTime now = started;
+ QElapsedTimer started;
+ started.start();
+ QElapsedTimer now = started;
if (QAbstractEventDispatcher::instance()->inherits("QtMotif")
|| QApplication::clipboard()->property("useEventLoopWhenWaiting").toBool()) {
@@ -545,9 +546,7 @@ bool QX11Data::clipboardWaitForEvent(Window win, int type, XEvent *event, int ti
XSync(X11->display, false);
usleep(50000);
- now = QTime::currentTime();
- if (started > now) // crossed midnight
- started = now;
+ now.start();
QEventLoop::ProcessEventsFlags flags(QEventLoop::ExcludeUserInputEvents
| QEventLoop::ExcludeSocketNotifiers
@@ -576,9 +575,7 @@ bool QX11Data::clipboardWaitForEvent(Window win, int type, XEvent *event, int ti
if (XCheckIfEvent(X11->display, &e, checkForClipboardEvents, 0))
qApp->x11ProcessEvent(&e);
- now = QTime::currentTime();
- if ( started > now ) // crossed midnight
- started = now;
+ now.start();
XFlush(X11->display);
diff --git a/src/gui/kernel/qcocoaapplication_mac.mm b/src/gui/kernel/qcocoaapplication_mac.mm
index 5b9842074e..496286374a 100644
--- a/src/gui/kernel/qcocoaapplication_mac.mm
+++ b/src/gui/kernel/qcocoaapplication_mac.mm
@@ -79,6 +79,8 @@
#include <private/qcocoaapplicationdelegate_mac_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
+QT_USE_NAMESPACE
+
@implementation NSApplication (QT_MANGLE_NAMESPACE(QApplicationIntegration))
- (void)QT_MANGLE_NAMESPACE(qt_setDockMenu):(NSMenu *)newMenu
@@ -107,5 +109,49 @@
| NSFontPanelStrikethroughEffectModeMask;
}
+- (void)qt_sendPostedMessage:(NSEvent *)event
+{
+ // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5!
+ // That is why we need to split the address in two parts:
+ quint64 lower = [event data1];
+ quint64 upper = [event data2];
+ QCocoaPostMessageArgs *args = reinterpret_cast<QCocoaPostMessageArgs *>(lower | (upper << 32));
+ [args->target performSelector:args->selector];
+ delete args;
+}
+
+- (BOOL)qt_sendEvent:(NSEvent *)event
+{
+ if ([event type] == NSApplicationDefined) {
+ switch ([event subtype]) {
+ case QtCocoaEventSubTypePostMessage:
+ [NSApp qt_sendPostedMessage:event];
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
@end
+
+@implementation QNSApplication
+
+// WARNING: If Qt did not create NSApplication (this can e.g.
+// happend if Qt is used as a plugin from a 3rd-party cocoa
+// application), QNSApplication::sendEvent will never be called.
+// SO DO NOT RELY ON THIS FUNCTION BEING AVAILABLE.
+// Plugin developers that _do_ control the NSApplication sub-class
+// implementation of the 3rd-party application can call qt_sendEvent
+// from the sub-class event handler (like we do here) to work around
+// any issues.
+- (void)sendEvent:(NSEvent *)event
+{
+ if (![self qt_sendEvent:event])
+ [super sendEvent:event];
+}
+
+@end
+
#endif
diff --git a/src/gui/kernel/qcocoaapplication_mac_p.h b/src/gui/kernel/qcocoaapplication_mac_p.h
index e845d58f98..5569feb2df 100644
--- a/src/gui/kernel/qcocoaapplication_mac_p.h
+++ b/src/gui/kernel/qcocoaapplication_mac_p.h
@@ -99,5 +99,13 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate)
- (QApplicationPrivate *)QT_MANGLE_NAMESPACE(qt_qappPrivate);
- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader);
- (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel;
+
+- (void)qt_sendPostedMessage:(NSEvent *)event;
+- (BOOL)qt_sendEvent:(NSEvent *)event;
+@end
+
+@interface QNSApplication : NSApplication {
+}
@end
+
#endif
diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
index 47a8026f34..5dcf613d63 100644
--- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
+++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
@@ -179,7 +179,7 @@ static void cleanupCocoaApplicationDelegate()
}
// This function will only be called when NSApp is actually running. Before
-// that, the kAEQuitApplication apple event will be sendt to
+// that, the kAEQuitApplication Apple event will be sent to
// QApplicationPrivate::globalAppleEventProcessor in qapplication_mac.mm
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
@@ -196,21 +196,18 @@ static void cleanupCocoaApplicationDelegate()
qAppInstance()->quit();
startedQuit = false;
}
+ return NSTerminateNow;
}
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
+ // 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;
}
+
+ return NSTerminateCancel;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
@@ -317,5 +314,12 @@ static void cleanupCocoaApplicationDelegate()
qt_sendSpontaneousEvent(qAppInstance(), &qtEvent);
}
+- (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
+{
+ Q_UNUSED(event);
+ Q_UNUSED(replyEvent);
+ [NSApp terminate:self];
+}
+
@end
#endif
diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm
index 18b377257f..8d65aa1f18 100644
--- a/src/gui/kernel/qcocoamenuloader_mac.mm
+++ b/src/gui/kernel/qcocoamenuloader_mac.mm
@@ -46,17 +46,29 @@
#include <private/qcocoamenuloader_mac_p.h>
#include <private/qapplication_p.h>
#include <private/qt_mac_p.h>
+#include <private/qmenubar_p.h>
#include <qmenubar.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
QT_FORWARD_DECLARE_CLASS(QCFString)
QT_FORWARD_DECLARE_CLASS(QString)
+#ifndef QT_NO_TRANSLATION
+ QT_BEGIN_NAMESPACE
+ extern QString qt_mac_applicationmenu_string(int type);
+ QT_END_NAMESPACE
+#endif
+
QT_USE_NAMESPACE
@implementation QT_MANGLE_NAMESPACE(QCocoaMenuLoader)
- (void)awakeFromNib
{
+ servicesItem = [[appMenu itemWithTitle:@"Services"] retain];
+ hideAllOthersItem = [[appMenu itemWithTitle:@"Hide Others"] retain];
+ showAllItem = [[appMenu itemWithTitle:@"Show All"] retain];
+
// Get the names in the nib to match the app name set by Qt.
NSString *appName = reinterpret_cast<const NSString*>(QCFString::toCFStringRef(qAppName()));
[quitItem setTitle:[[quitItem title] stringByReplacingOccurrencesOfString:@"NewApplication"
@@ -118,6 +130,10 @@ QT_USE_NAMESPACE
- (void)dealloc
{
+ [servicesItem release];
+ [hideAllOthersItem release];
+ [showAllItem release];
+
[lastAppSpecificItem release];
[theMenu release];
[appMenu release];
@@ -208,6 +224,24 @@ QT_USE_NAMESPACE
[NSApp hide:sender];
}
+- (void)qtUpdateMenubar
+{
+ QMenuBarPrivate::macUpdateMenuBarImmediatly();
+}
+
+- (void)qtTranslateApplicationMenu
+{
+#ifndef QT_NO_TRANSLATION
+ [servicesItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(0))];
+ [hideItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(1).arg(qAppName()))];
+ [hideAllOthersItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(2))];
+ [showAllItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(3))];
+ [preferencesItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(4))];
+ [quitItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(5).arg(qAppName()))];
+ [aboutItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(6).arg(qAppName()))];
+#endif
+}
+
- (IBAction)qtDispatcherToQAction:(id)sender
{
QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData);
diff --git a/src/gui/kernel/qcocoamenuloader_mac_p.h b/src/gui/kernel/qcocoamenuloader_mac_p.h
index 81c136eb87..a75ad0a21b 100644
--- a/src/gui/kernel/qcocoamenuloader_mac_p.h
+++ b/src/gui/kernel/qcocoamenuloader_mac_p.h
@@ -67,7 +67,9 @@
IBOutlet NSMenuItem *aboutQtItem;
IBOutlet NSMenuItem *hideItem;
NSMenuItem *lastAppSpecificItem;
-
+ NSMenuItem *servicesItem;
+ NSMenuItem *hideAllOthersItem;
+ NSMenuItem *showAllItem;
}
- (void)ensureAppMenuInMenu:(NSMenu *)menu;
- (void)removeActionsFromAppMenu;
@@ -85,6 +87,7 @@
- (IBAction)unhideAllApplications:(id)sender;
- (IBAction)hide:(id)sender;
- (IBAction)qtDispatcherToQAction:(id)sender;
+- (void)qtUpdateMenubar;
@end
#endif // QT_MAC_USE_COCOA
diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm
index 5e24c84ac6..0b48efd432 100644
--- a/src/gui/kernel/qcocoapanel_mac.mm
+++ b/src/gui/kernel/qcocoapanel_mac.mm
@@ -46,6 +46,7 @@
#import <private/qcocoawindowdelegate_mac_p.h>
#import <private/qcocoaview_mac_p.h>
#import <private/qcocoawindowcustomthemeframe_mac_p.h>
+#import <private/qcocoaapplication_mac_p.h>
#include <private/qapplication_p.h>
#include <private/qbackingstore_p.h>
diff --git a/src/gui/kernel/qcocoapanel_mac_p.h b/src/gui/kernel/qcocoapanel_mac_p.h
index fc83bd892a..3678f81a32 100644
--- a/src/gui/kernel/qcocoapanel_mac_p.h
+++ b/src/gui/kernel/qcocoapanel_mac_p.h
@@ -54,10 +54,16 @@
#ifdef QT_MAC_USE_COCOA
#import <Cocoa/Cocoa.h>
+QT_FORWARD_DECLARE_CLASS(QStringList);
+
@interface QT_MANGLE_NAMESPACE(QCocoaPanel) : NSPanel {
bool leftButtonIsRightButton;
+ QStringList *currentCustomDragTypes;
}
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
+- (void)registerDragTypes;
+
@end
#endif
+
diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
index d2b74d7420..86528160eb 100644
--- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
+++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
@@ -57,8 +57,31 @@
QT_BEGIN_NAMESPACE
extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp
+
+Q_GLOBAL_STATIC(QPointer<QWidget>, currentDragTarget);
+
QT_END_NAMESPACE
+- (id)initWithContentRect:(NSRect)contentRect
+ styleMask:(NSUInteger)windowStyle
+ backing:(NSBackingStoreType)bufferingType
+ defer:(BOOL)deferCreation
+{
+ self = [super initWithContentRect:contentRect styleMask:windowStyle
+ backing:bufferingType defer:deferCreation];
+ if (self) {
+ currentCustomDragTypes = 0;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ delete currentCustomDragTypes;
+ [super dealloc];
+}
+
- (BOOL)canBecomeKeyWindow
{
QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)];
@@ -68,30 +91,31 @@ QT_END_NAMESPACE
return !(isPopup || isToolTip);
}
-- (void)toggleToolbarShown:(id)sender
+- (BOOL)canBecomeMainWindow
{
- macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]);
- [super toggleToolbarShown:sender];
+ QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)];
+
+ bool isToolTip = (widget->windowType() == Qt::ToolTip);
+ bool isPopup = (widget->windowType() == Qt::Popup);
+ bool isTool = (widget->windowType() == Qt::Tool);
+ return !(isPopup || isToolTip || isTool);
}
-/*
- The methods keyDown, keyUp, and flagsChanged... These really shouldn't ever
- get hit. We automatically say we can be first responder if we are a window.
- So, the handling should get handled by the view. This is here more as a
- last resort (i.e., this is code that can potentially be removed).
- */
-- (void)keyDown:(NSEvent *)theEvent
+- (void)becomeMainWindow
{
- bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
- if (!keyOK)
- [super keyDown:theEvent];
+ [super becomeMainWindow];
+ // Cocoa sometimes tell a hidden window to become the
+ // main window (and as such, show it). This can e.g
+ // happend when the application gets activated. If
+ // this is the case, we tell it to hide again:
+ if (![self isVisible])
+ [self orderOut:self];
}
-- (void)keyUp:(NSEvent *)theEvent
+- (void)toggleToolbarShown:(id)sender
{
- bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
- if (!keyOK)
- [super keyUp:theEvent];
+ macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]);
+ [super toggleToolbarShown:sender];
}
- (void)flagsChanged:(NSEvent *)theEvent
@@ -106,10 +130,37 @@ QT_END_NAMESPACE
qt_dispatchTabletProximityEvent(tabletEvent);
}
+- (void)qtDispatcherToQAction:(id)sender
+{
+ // If this window is modal, the menu bar will be modally shaddowed.
+ // In that case, since the window will be in the first responder chain,
+ // we can still catch the trigger here and forward it to the menu bar.
+ // This is needed as a single modal dialog on Qt should be able to access
+ // the application menu (e.g. quit).
+ [[NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)] qtDispatcherToQAction:sender];
+}
+
+- (void)terminate:(id)sender
+{
+ // This function is called from the quit item in the menubar when this window
+ // is in the first responder chain (see also qtDispatcherToQAction above)
+ [NSApp terminate:sender];
+}
+
- (void)sendEvent:(NSEvent *)event
{
- QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self];
+ if ([event type] == NSApplicationDefined) {
+ switch ([event subtype]) {
+ case QtCocoaEventSubTypePostMessage:
+ [NSApp qt_sendPostedMessage:event];
+ return;
+ default:
+ break;
+ }
+ return;
+ }
+ QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self];
// Cocoa can hold onto the window after we've disavowed its knowledge. So,
// if we get sent an event afterwards just have it go through the super's
// version and don't do any stuff with Qt.
@@ -133,7 +184,7 @@ QT_END_NAMESPACE
qt_button_down = widget;
handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton);
// 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.)
break;
case NSRightMouseDown:
@@ -188,6 +239,115 @@ QT_END_NAMESPACE
return [super frameViewClassForStyleMask:styleMask];
}
+-(void)registerDragTypes
+{
+ // Calling registerForDraggedTypes below is slow, so only do
+ // it once for each window, or when the custom types change.
+ QMacCocoaAutoReleasePool pool;
+ const QStringList& customTypes = qEnabledDraggedTypes();
+ if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) {
+ if (currentCustomDragTypes == 0)
+ currentCustomDragTypes = new QStringList();
+ *currentCustomDragTypes = 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,
+ NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
+ NSFilesPromisePboardType, NSInkTextPboardType,
+ NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
+ // Add custom types supported by the application.
+ for (int i = 0; i < customTypes.size(); i++) {
+ [supportedTypes addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(customTypes[i]))];
+ }
+ [self registerForDraggedTypes:supportedTypes];
+ }
+}
+
+- (QWidget *)dragTargetHitTest:(id <NSDraggingInfo>)sender
+{
+ // Do a hittest to find the NSView under the
+ // mouse, and return the corresponding QWidget:
+ NSPoint windowPoint = [sender draggingLocation];
+ NSView *candidateView = [[self contentView] hitTest:windowPoint];
+ if (![candidateView isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]])
+ return 0;
+ return [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(candidateView) qt_qwidget];
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ // The user dragged something into the window. Send a draggingEntered message
+ // to the QWidget under the mouse. As the drag moves over the window, and over
+ // different widgets, we will handle enter and leave events from within
+ // draggingUpdated below. The reason why we handle this ourselves rather than
+ // subscribing for drag events directly in QCocoaView is that calling
+ // registerForDraggedTypes on the views will severly degrade initialization time
+ // for an application that uses a lot of drag subscribing widgets.
+
+ QWidget *target = [self dragTargetHitTest:sender];
+ if (!target)
+ return [super draggingEntered:sender];
+ if (target->testAttribute(Qt::WA_DropSiteRegistered) == false)
+ return NSDragOperationNone;
+
+ *currentDragTarget() = target;
+ return [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingEntered:sender];
+ }
+
+- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender
+{
+ QWidget *target = [self dragTargetHitTest:sender];
+ if (!target)
+ return [super draggingUpdated:sender];
+
+ if (target == *currentDragTarget()) {
+ // The drag continues to move over the widget that we have sendt
+ // a draggingEntered message to. So just update the view:
+ return [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingUpdated:sender];
+ } else {
+ // The widget under the mouse has changed.
+ // So we need to fake enter/leave events:
+ if (*currentDragTarget())
+ [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingExited:sender];
+ if (target->testAttribute(Qt::WA_DropSiteRegistered) == false) {
+ *currentDragTarget() = 0;
+ return NSDragOperationNone;
+ }
+ *currentDragTarget() = target;
+ return [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingEntered:sender];
+ }
+}
+
+- (void)draggingExited:(id < NSDraggingInfo >)sender
+{
+ QWidget *target = [self dragTargetHitTest:sender];
+ if (!target)
+ return [super draggingExited:sender];
+
+ if (*currentDragTarget()) {
+ [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingExited:sender];
+ *currentDragTarget() = 0;
+ }
+}
+
+- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender
+{
+ QWidget *target = [self dragTargetHitTest:sender];
+ if (!target)
+ return [super performDragOperation:sender];
+
+ BOOL dropResult = NO;
+ if (*currentDragTarget()) {
+ dropResult = [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) performDragOperation:sender];
+ *currentDragTarget() = 0;
+ }
+ return dropResult;
+}
+
- (void)displayIfNeeded
{
@@ -204,4 +364,56 @@ QT_END_NAMESPACE
[super displayIfNeeded];
}
+// This is a hack and it should be removed once we find the real cause for
+// the painting problems.
+// We have a static variable that signals if we have been called before or not.
+static bool firstDrawingInvocation = true;
+// The method below exists only as a workaround to draw/not draw the baseline
+// in the title bar. This is to support unifiedToolbar look.
+
+// This method is very special. To begin with, it is a
+// method that will get called only if we enable documentMode.
+// Furthermore, it won't get called as a normal method, we swap
+// this method with the normal implementation of drawRect in
+// _NSThemeFrame. When this method is active, its mission is to
+// first call the original drawRect implementation so the widget
+// gets proper painting. After that, it needs to detect if there
+// is a toolbar or not, in order to decide how to handle the unified
+// look. The distinction is important since the presence and
+// visibility of a toolbar change the way we enter into unified mode.
+// When there is a toolbar and that toolbar is visible, the problem
+// is as simple as to tell the toolbar not to draw its baseline.
+// However when there is not toolbar or the toolbar is not visible,
+// we need to draw a line on top of the baseline, because the baseline
+// in that case will belong to the title. For this case we need to draw
+// a line on top of the baseline.
+// As usual, there is a special case. When we first are called, we might
+// need to repaint ourselves one more time. We only need that if we
+// didn't get the activation, i.e. when we are launched via the command
+// line. And this only if the toolbar is visible from the beginning,
+// so we have a special flag that signals if we need to repaint or not.
+- (void)drawRectSpecial:(NSRect)rect
+{
+ // Call the original drawing method.
+ [self drawRectOriginal:rect];
+ NSWindow *window = [self window];
+ NSToolbar *toolbar = [window toolbar];
+ if(!toolbar) {
+ // There is no toolbar, we have to draw a line on top of the line drawn by Cocoa.
+ macDrawRectOnTop((void *)window);
+ } else {
+ if([toolbar isVisible]) {
+ // We tell Cocoa to avoid drawing the line at the end.
+ if(firstDrawingInvocation) {
+ firstDrawingInvocation = false;
+ macSyncDrawingOnFirstInvocation((void *)window);
+ } else
+ [toolbar setShowsBaselineSeparator:NO];
+ } else {
+ // There is a toolbar but it is not visible so
+ // we have to draw a line on top of the line drawn by Cocoa.
+ macDrawRectOnTop((void *)window);
+ }
+ }
+}
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index ad64a91251..4953c48c9d 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -81,24 +81,9 @@ Q_GLOBAL_STATIC(DnDParams, qMacDnDParams);
extern void qt_mac_update_cursor_at_global_pos(const QPoint &globalPos); // qcursor_mac.mm
extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp
extern OSViewRef qt_mac_nativeview_for(const QWidget *w); // qwidget_mac.mm
-extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp
extern QPointer<QWidget> qt_mouseover; //qapplication_mac.mm
extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
-
-Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
-{
- if (buttonNum == 0)
- return Qt::LeftButton;
- if (buttonNum == 1)
- return Qt::RightButton;
- if (buttonNum == 2)
- return Qt::MidButton;
- if (buttonNum == 3)
- return Qt::XButton1;
- if (buttonNum == 4)
- return Qt::XButton2;
- return Qt::NoButton;
-}
+extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum);
struct dndenum_mapper
{
@@ -200,6 +185,9 @@ extern "C" {
extern NSString *NSTextInputReplacementRangeAttributeName;
}
+#ifdef ALIEN_DEBUG
+static int qCocoaViewCount = 0;
+#endif
@implementation QT_MANGLE_NAMESPACE(QCocoaView)
@@ -209,10 +197,16 @@ extern "C" {
if (self) {
[self finishInitWithQWidget:widget widgetPrivate:widgetprivate];
}
+ [self setFocusRingType:NSFocusRingTypeNone];
composingText = new QString();
+
+#ifdef ALIEN_DEBUG
+ ++qCocoaViewCount;
+ qDebug() << "init: qCocoaViewCount is" << qCocoaViewCount;
+#endif
+
composing = false;
sendKeyEvents = true;
- currentCustomTypes = 0;
[self setHidden:YES];
return self;
}
@@ -227,36 +221,12 @@ extern "C" {
object:self];
}
--(void)registerDragTypes
-{
- QMacCocoaAutoReleasePool pool;
- // Calling registerForDraggedTypes is slow, so only do it once for each widget
- // or when the custom types change.
- const QStringList& customTypes = qEnabledDraggedTypes();
- if (currentCustomTypes == 0 || *currentCustomTypes != customTypes) {
- if (currentCustomTypes == 0)
- 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,
- NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
- NSFilesPromisePboardType, NSInkTextPboardType,
- NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
- // Add custom types supported by the application.
- for (int i = 0; i < customTypes.size(); i++) {
- [supportedTypes addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(customTypes[i]))];
- }
- [self registerForDraggedTypes:supportedTypes];
- }
-}
-
- (void)resetCursorRects
{
+ // [NSView addCursorRect] is slow, so bail out early if we can:
+ if (NSIsEmptyRect([self visibleRect]))
+ return;
+
QWidget *cursorWidget = qwidget;
if (cursorWidget->testAttribute(Qt::WA_TransparentForMouseEvents))
@@ -272,7 +242,8 @@ extern "C" {
QRegion mask = qt_widget_private(cursorWidget)->extra->mask;
NSCursor *nscursor = static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursorWidget->cursor()));
- if (mask.isEmpty()) {
+ // The mask could have the WA_MouseNoMask attribute set and that means that we have to ignore the mask.
+ if (mask.isEmpty() || cursorWidget->testAttribute(Qt::WA_MouseNoMask)) {
[self addCursorRect:[qt_mac_nativeview_for(cursorWidget) visibleRect] cursor:nscursor];
} else {
const QVector<QRect> &rects = mask.rects();
@@ -300,15 +271,9 @@ extern "C" {
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
- if (qwidget->testAttribute(Qt::WA_DropSiteRegistered) == false)
- return NSDragOperationNone;
+ // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly
+ // from Cocoa. They modify the drag target, and might fake enter/leave events.
NSPoint windowPoint = [sender draggingLocation];
- if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
- // pass the drag enter event to the view underneath.
- NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
- if (candidateView && candidateView != self)
- return [candidateView draggingEntered:sender];
- }
dragEnterSequence = [sender draggingSequenceNumber];
[self addDropData:sender];
QMimeData *mimeData = dropData;
@@ -361,13 +326,9 @@ extern "C" {
}
- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender
{
+ // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly
+ // from Cocoa. They modify the drag target, and might fake enter/leave events.
NSPoint windowPoint = [sender draggingLocation];
- if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
- // pass the drag move event to the view underneath.
- NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
- if (candidateView && candidateView != self)
- return [candidateView draggingUpdated:sender];
- }
// in cases like QFocusFrame, the view under the mouse might
// not have received the drag enter. Generate a synthetic
// drag enter event for that view.
@@ -417,14 +378,10 @@ extern "C" {
- (void)draggingExited:(id < NSDraggingInfo >)sender
{
+ // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly
+ // from Cocoa. They modify the drag target, and might fake enter/leave events.
+ Q_UNUSED(sender);
dragEnterSequence = -1;
- if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
- // try sending the leave event to the last view which accepted drag enter.
- DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent];
- NSView *candidateView = [[[self window] contentView] hitTest:dndParams->activeDragEnterPos];
- if (candidateView && candidateView != self)
- return [candidateView draggingExited:sender];
- }
// drag enter event was rejected, so ignore the move event.
if (dropData) {
QDragLeaveEvent de;
@@ -435,14 +392,10 @@ extern "C" {
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
+ // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly
+ // from Cocoa. They modify the drag target, and might fake enter/leave events.
NSPoint windowPoint = [sender draggingLocation];
dragEnterSequence = -1;
- if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
- // pass the drop event to the view underneath.
- NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
- if (candidateView && candidateView != self)
- return [candidateView performDragOperation:sender];
- }
[self addDropData:sender];
NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
@@ -472,13 +425,19 @@ extern "C" {
{
delete composingText;
[[NSNotificationCenter defaultCenter] removeObserver:self];
- delete currentCustomTypes;
- [self unregisterDraggedTypes];
+
+#ifdef ALIEN_DEBUG
+ --qCocoaViewCount;
+ qDebug() << "qCocoaViewCount is" << qCocoaViewCount;
+#endif
+
[super dealloc];
}
- (BOOL)isOpaque;
{
+ if (!qwidgetprivate)
+ return [super isOpaque];
return qwidgetprivate->isOpaque;
}
@@ -487,7 +446,11 @@ extern "C" {
return YES;
}
-- (BOOL) preservesContentDuringLiveResize;
+// We preserve the content of the view if WA_StaticContents is defined.
+//
+// More info in the Cocoa documentation:
+// http://developer.apple.com/mac/library/documentation/cocoa/conceptual/CocoaViewsGuide/Optimizing/Optimizing.html
+- (BOOL) preservesContentDuringLiveResize
{
return qwidget->testAttribute(Qt::WA_StaticContents);
}
@@ -510,20 +473,36 @@ extern "C" {
}
// Make sure the opengl context is updated on resize.
- if (qwidgetprivate->isGLWidget) {
+ if (qwidgetprivate && qwidgetprivate->isGLWidget) {
qwidgetprivate->needWindowChange = true;
QEvent event(QEvent::MacGLWindowChange);
qApp->sendEvent(qwidget, &event);
}
}
+// We catch the 'setNeedsDisplay:' message in order to avoid a useless full repaint.
+// During the resize, the top of the widget is repainted, probably because of the
+// change of coordinate space (Quartz vs Qt). This is then followed by this message:
+// -[NSView _setNeedsDisplayIfTopLeftChanged]
+// which force a full repaint by sending the message 'setNeedsDisplay:'.
+// That is what we are preventing here.
+- (void)setNeedsDisplay:(BOOL)flag {
+ if (![self inLiveResize] || !(qwidget->testAttribute(Qt::WA_StaticContents))) {
+ [super setNeedsDisplay:flag];
+ }
+}
+
- (void)drawRect:(NSRect)aRect
{
+ if (!qwidget)
+ return;
+
if (QApplicationPrivate::graphicsSystem() != 0) {
- if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore()) {
+ if (qwidgetprivate->maybeBackingStore()) {
// Drawing is handled on the window level
- // See qcocoasharedwindowmethods_mac_p.
- return;
+ // See qcocoasharedwindowmethods_mac_p.h
+ if (!qwidget->testAttribute(Qt::WA_PaintOnScreen))
+ return;
}
}
CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
@@ -535,7 +514,15 @@ extern "C" {
qWarning("QWidget::repaint: Recursive repaint detected");
const QRect qrect = QRect(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height);
- QRegion qrgn(qrect);
+ QRegion qrgn;
+
+ const NSRect *rects;
+ NSInteger count;
+ [self getRectsBeingDrawn:&rects count:&count];
+ for (int i = 0; i < count; ++i) {
+ QRect tmpRect = QRect(rects[i].origin.x, rects[i].origin.y, rects[i].size.width, rects[i].size.height);
+ qrgn += tmpRect;
+ }
if (!qwidget->isWindow() && !qobject_cast<QAbstractScrollArea *>(qwidget->parent())) {
const QRegion &parentMask = qwidget->window()->mask();
@@ -569,6 +556,10 @@ extern "C" {
CGContextClearRect(cg, NSRectToCGRect(aRect));
}
+ // Check for alien widgets, use qwidgetPrivate->drawWidget() to draw the widget if this
+ // is the case. This makes sure child widgets are drawn as well, Cocoa does not know about
+ // those and wont send them drawRect calls.
+ if (qwidget->testAttribute(Qt::WA_NativeWindow) && qt_widget_private(qwidget)->hasAlienChildren == false) {
if (engine && !qwidget->testAttribute(Qt::WA_NoSystemBackground)
&& (qwidget->isWindow() || qwidget->autoFillBackground())
|| qwidget->testAttribute(Qt::WA_TintedBackground)
@@ -588,6 +579,12 @@ extern "C" {
e.setErased(true);
#endif
qt_sendSpontaneousEvent(qwidget, &e);
+ } else {
+ qwidget->setAttribute(Qt::WA_WState_InPaintEvent, false); // QWidgetPrivate::drawWidget sets this
+ QWidgetPrivate *qwidgetPrivate = qt_widget_private(qwidget);
+ qwidgetPrivate->drawWidget(qwidget, qrgn, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen | QWidgetPrivate::DrawRecursive, 0);
+ }
+
if (!redirectionOffset.isNull())
QPainter::restoreRedirected(qwidget);
if (engine)
@@ -603,12 +600,18 @@ extern "C" {
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
+ if (!qwidget)
+ return NO;
+
Q_UNUSED(theEvent);
return !qwidget->testAttribute(Qt::WA_MacNoClickThrough);
}
- (NSView *)hitTest:(NSPoint)aPoint
{
+ if (!qwidget)
+ return [super hitTest:aPoint];
+
if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents))
return nil; // You cannot hit a transparent for mouse event widget.
return [super hitTest:aPoint];
@@ -616,6 +619,13 @@ extern "C" {
- (void)updateTrackingAreas
{
+ if (!qwidget)
+ return;
+
+ // [NSView addTrackingArea] is slow, so bail out early if we can:
+ if (NSIsEmptyRect([self visibleRect]))
+ return;
+
QMacCocoaAutoReleasePool pool;
if (NSArray *trackingArray = [self trackingAreas]) {
NSUInteger size = [trackingArray count];
@@ -645,28 +655,45 @@ extern "C" {
- (void)mouseEntered:(NSEvent *)event
{
+ if (!qwidget)
+ return;
if (qwidgetprivate->data.in_destructor)
return;
- QEvent enterEvent(QEvent::Enter);
- NSPoint windowPoint = [event locationInWindow];
- NSPoint globalPoint = [[event window] convertBaseToScreen:windowPoint];
- NSPoint viewPoint = [self convertPoint:windowPoint fromView:nil];
+
if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) {
+ QEvent enterEvent(QEvent::Enter);
+ NSPoint windowPoint = [event locationInWindow];
+ NSPoint globalPoint = [[event window] convertBaseToScreen:windowPoint];
+ NSPoint viewPoint = [self convertPoint:windowPoint fromView:nil];
QApplication::sendEvent(qwidget, &enterEvent);
qt_mouseover = qwidget;
- // Update cursor and dispatch hover events.
+ // Update cursor icon:
qt_mac_update_cursor_at_global_pos(flipPoint(globalPoint).toPoint());
- if (qwidget->testAttribute(Qt::WA_Hover) &&
- (!qAppInstance()->activePopupWidget() || qAppInstance()->activePopupWidget() == qwidget->window())) {
- QHoverEvent he(QEvent::HoverEnter, QPoint(viewPoint.x, viewPoint.y), QPoint(-1, -1));
- QApplicationPrivate::instance()->notify_helper(qwidget, &he);
+
+ // Send mouse move and hover events as well:
+ if (!qAppInstance()->activePopupWidget() || qAppInstance()->activePopupWidget() == qwidget->window()) {
+ // This mouse move event should be sendt, even when mouse
+ // tracking is switched off (to trigger tooltips):
+ NSEvent *mouseEvent = [NSEvent mouseEventWithType:NSMouseMoved
+ location:windowPoint modifierFlags:[event modifierFlags] timestamp:[event timestamp]
+ windowNumber:[event windowNumber] context:[event context] eventNumber:[event eventNumber]
+ clickCount:0 pressure:0];
+ qt_mac_handleMouseEvent(self, mouseEvent, QEvent::MouseMove, Qt::NoButton);
+
+ if (qwidget->testAttribute(Qt::WA_Hover)) {
+ QHoverEvent he(QEvent::HoverEnter, QPoint(viewPoint.x, viewPoint.y), QPoint(-1, -1));
+ QApplicationPrivate::instance()->notify_helper(qwidget, &he);
+ }
}
}
}
- (void)mouseExited:(NSEvent *)event
{
+ if (!qwidget)
+ return;
+
QEvent leaveEvent(QEvent::Leave);
NSPoint globalPoint = [[event window] convertBaseToScreen:[event locationInWindow]];
if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) {
@@ -685,6 +712,9 @@ extern "C" {
- (void)flagsChanged:(NSEvent *)theEvent
{
+ if (!qwidget)
+ return;
+
QWidget *widgetToGetKey = qwidget;
QWidget *popup = qAppInstance()->activePopupWidget();
@@ -696,6 +726,9 @@ extern "C" {
- (void)mouseMoved:(NSEvent *)theEvent
{
+ if (!qwidget)
+ return;
+
// 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
@@ -815,11 +848,12 @@ extern "C" {
// The mouse device containts pixel scroll wheel support (Mighty Mouse, Trackpad).
// Since deviceDelta is delivered as pixels rather than degrees, we need to
// convert from pixels to degrees in a sensible manner.
- // It looks like four degrees per pixel behaves most native.
- // Qt expects the unit for delta to be 1/8 of a degree:
- deltaX = [theEvent deviceDeltaX];
- deltaY = [theEvent deviceDeltaY];
- deltaZ = [theEvent deviceDeltaZ];
+ // It looks like 1/4 degrees per pixel behaves most native.
+ // (NB: Qt expects the unit for delta to be 8 per degree):
+ const int pixelsToDegrees = 2; // 8 * 1/4
+ deltaX = [theEvent deviceDeltaX] * pixelsToDegrees;
+ deltaY = [theEvent deviceDeltaY] * pixelsToDegrees;
+ deltaZ = [theEvent deviceDeltaZ] * pixelsToDegrees;
} else {
// carbonEventKind == kEventMouseWheelMoved
// Remove acceleration, and use either -120 or 120 as delta:
@@ -986,6 +1020,8 @@ extern "C" {
- (void)frameDidChange:(NSNotification *)note
{
Q_UNUSED(note);
+ if (!qwidget)
+ return;
if (qwidget->isWindow())
return;
NSRect newFrame = [self frame];
@@ -1009,7 +1045,7 @@ extern "C" {
{
QMacCocoaAutoReleasePool pool;
[super setEnabled:flag];
- if (qwidget->isEnabled() != flag)
+ if (qwidget && qwidget->isEnabled() != flag)
qwidget->setEnabled(flag);
}
@@ -1020,17 +1056,39 @@ extern "C" {
- (BOOL)acceptsFirstResponder
{
- if (qwidget->isWindow())
+ if (!qwidget)
+ return NO;
+ // disabled widget shouldn't get focus even if it's a window.
+ // hence disabled windows will not get any key or mouse events.
+ if (!qwidget->isEnabled())
+ return NO;
+ // Before accepting the focus for a window, we check that
+ // the focusWidget (if any) is not contained in the same window.
+ if (qwidget->isWindow() && !qt_widget_private(qwidget)->topData()->embedded
+ && (!qApp->focusWidget() || qApp->focusWidget()->window() != qwidget)) {
return YES; // Always do it, so that windows can accept key press events.
+ }
return qwidget->focusPolicy() != Qt::NoFocus;
}
- (BOOL)resignFirstResponder
{
+ if (!qwidget)
+ return NO;
// Seems like the following test only triggers if this
// view is inside a QMacNativeWidget:
if (qwidget == QApplication::focusWidget())
- QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason);
+ qwidget->clearFocus();
+ return YES;
+}
+
+- (BOOL)becomeFirstResponder
+{
+ // see the comment in the acceptsFirstResponder - if the window "stole" focus
+ // let it become the responder, but don't tell Qt
+ if (qwidget && qt_widget_private(qwidget->window())->topData()->embedded
+ && !QApplication::focusWidget() && qwidget->focusPolicy() != Qt::NoFocus)
+ qwidget->setFocus(Qt::OtherFocusReason);
return YES;
}
@@ -1062,6 +1120,12 @@ extern "C" {
return qwidget;
}
+- (void) qt_clearQWidget
+{
+ qwidget = 0;
+ qwidgetprivate = 0;
+}
+
- (BOOL)qt_leftButtonIsRightButton
{
return leftButtonIsRightButton;
@@ -1098,8 +1162,15 @@ extern "C" {
}
if (sendKeyEvents && !composing) {
bool keyOK = qt_dispatchKeyEvent(theEvent, widgetToGetKey);
- if (!keyOK && !sendToPopup)
- [super keyDown:theEvent];
+ if (!keyOK && !sendToPopup) {
+ // find the first responder that is not created by Qt and forward
+ // the event to it (for example if Qt widget is embedded into native).
+ QWidget *toplevel = qwidget->window();
+ if (toplevel && qt_widget_private(toplevel)->topData()->embedded) {
+ if (NSResponder *w = [qt_mac_nativeview_for(toplevel) superview])
+ [w keyDown:theEvent];
+ }
+ }
}
}
@@ -1108,16 +1179,23 @@ extern "C" {
{
if (sendKeyEvents) {
bool keyOK = qt_dispatchKeyEvent(theEvent, qwidget);
- if (!keyOK)
- [super keyUp:theEvent];
+ if (!keyOK) {
+ QWidget *toplevel = qwidget->window();
+ if (toplevel && qt_widget_private(toplevel)->topData()->embedded) {
+ if (NSResponder *w = [qt_mac_nativeview_for(toplevel) superview])
+ [w keyUp:theEvent];
+ }
+ }
}
}
- (void)viewWillMoveToWindow:(NSWindow *)window
{
+ if (qwidget == 0)
+ return;
+
if (qwidget->windowFlags() & Qt::MSWindowsOwnDC
&& (window != [self window])) { // OpenGL Widget
- // Create a stupid ClearDrawable Event
QEvent event(QEvent::MacGLClearDrawable);
qApp->sendEvent(qwidget, &event);
}
@@ -1125,6 +1203,9 @@ extern "C" {
- (void)viewDidMoveToWindow
{
+ if (qwidget == 0)
+ return;
+
if (qwidget->windowFlags() & Qt::MSWindowsOwnDC && [self window]) {
// call update paint event
qwidgetprivate->needWindowChange = true;
@@ -1320,6 +1401,9 @@ extern "C" {
- (NSArray*) validAttributesForMarkedText
{
+ if (qwidget == 0)
+ return nil;
+
if (!qwidget->testAttribute(Qt::WA_InputMethodEnabled))
return nil; // Not sure if that's correct, but it's saves a malloc.
@@ -1470,7 +1554,8 @@ Qt::DropAction QDragManager::drag(QDrag *o)
qt_button_down = 0;
[dndParams.view release];
[image release];
- dragPrivate()->executed_action = Qt::IgnoreAction;
+ if (dragPrivate())
+ dragPrivate()->executed_action = Qt::IgnoreAction;
object = 0;
Qt::DropAction performedAction(qt_mac_mapNSDragOperation(qMacDnDParams()->performedAction));
// do post drag processing, if required.
diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h
index 797b4d5b2a..33aaa24f8b 100644
--- a/src/gui/kernel/qcocoaview_mac_p.h
+++ b/src/gui/kernel/qcocoaview_mac_p.h
@@ -87,7 +87,6 @@ Q_GUI_EXPORT
int composingLength;
bool sendKeyEvents;
QString *composingText;
- QStringList *currentCustomTypes;
NSInteger dragEnterSequence;
}
- (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate;
@@ -97,7 +96,6 @@ Q_GUI_EXPORT
- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender;
- (void)draggingExited:(id < NSDraggingInfo >)sender;
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
-- (void)registerDragTypes;
- (void)removeDropData;
- (void)addDropData:(id <NSDraggingInfo>)sender;
- (void)setSupportedActions:(NSDragOperation)actions;
@@ -105,6 +103,7 @@ Q_GUI_EXPORT
- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation;
- (BOOL)isComposing;
- (QWidget *)qt_qwidget;
+- (void) qt_clearQWidget;
- (BOOL)qt_leftButtonIsRightButton;
- (void)qt_setLeftButtonIsRightButton:(BOOL)isSwapped;
+ (DnDParams*)currentMouseEvent;
diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm
index a644dfebfe..f1b642b50c 100644
--- a/src/gui/kernel/qcocoawindow_mac.mm
+++ b/src/gui/kernel/qcocoawindow_mac.mm
@@ -46,6 +46,7 @@
#import <private/qcocoaview_mac_p.h>
#import <private/qt_cocoa_helpers_mac_p.h>
#import <private/qcocoawindowcustomthemeframe_mac_p.h>
+#import <private/qcocoaapplication_mac_p.h>
#include <QtGui/QWidget>
diff --git a/src/gui/kernel/qcocoawindow_mac_p.h b/src/gui/kernel/qcocoawindow_mac_p.h
index 04748822ce..21f82df078 100644
--- a/src/gui/kernel/qcocoawindow_mac_p.h
+++ b/src/gui/kernel/qcocoawindow_mac_p.h
@@ -73,9 +73,12 @@ QT_FORWARD_DECLARE_CLASS(QStringList);
@interface QT_MANGLE_NAMESPACE(QCocoaWindow) : NSWindow {
bool leftButtonIsRightButton;
+ QStringList *currentCustomDragTypes;
}
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
+- (void)registerDragTypes;
+
@end
#endif
diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm
index db8749190a..24498f8cc0 100644
--- a/src/gui/kernel/qcocoawindowdelegate_mac.mm
+++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm
@@ -269,9 +269,6 @@ static void cleanupCocoaWindowDelegate()
{
QWidget *qwidget = m_windowHash->value([notification object]);
Q_ASSERT(qwidget);
- if (qwidget->isActiveWindow())
- return; // Widget is already active, no need to go through re-activation.
-
onApplicationWindowChangedActivation(qwidget, true);
}
@@ -288,10 +285,6 @@ static void cleanupCocoaWindowDelegate()
{
QWidget *qwidget = m_windowHash->value([notification object]);
Q_ASSERT(qwidget);
- if (qwidget->isActiveWindow())
- return; // Widget is already active, no need to go through re-activation
-
-
onApplicationWindowChangedActivation(qwidget, true);
}
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index 6b21d56b5f..ae1f60d756 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -141,6 +141,12 @@ QT_BEGIN_NAMESPACE
\o Qt::WhatsThisCursor \o \c whats_this
\o \inlineimage cursor-closedhand.png
\o Qt::ClosedHandCursor \o \c closedhand
+ \row \o
+ \o Qt::DragMoveCursor \o \c dnd-move or \c move
+ \o
+ \o Qt::DragCopyCursor \o \c dnd-copy or \c copy
+ \row \o
+ \o Qt::DragLinkCursor \o \c dnd-link or \c link
\endtable
\sa QWidget, {fowler}{GUI Design Handbook: Cursors}
diff --git a/src/gui/kernel/qcursor_mac.mm b/src/gui/kernel/qcursor_mac.mm
index 48bb9cc709..c3d6c54c9b 100644
--- a/src/gui/kernel/qcursor_mac.mm
+++ b/src/gui/kernel/qcursor_mac.mm
@@ -114,27 +114,18 @@ void qt_mac_set_cursor(const QCursor *c, const QPoint &)
}
c->handle(); //force the cursor to get loaded, if it's not
- if(1 || currentCursor != c->d) {
- if(currentCursor && currentCursor->type == QCursorData::TYPE_ThemeCursor
- && currentCursor->curs.tc.anim)
- currentCursor->curs.tc.anim->stop();
- QMacCocoaAutoReleasePool pool;
- if(c->d->type == QCursorData::TYPE_ImageCursor) {
- [static_cast<NSCursor *>(c->d->curs.cp.nscursor) set];
- } else if(c->d->type == QCursorData::TYPE_ThemeCursor) {
-#ifdef QT_MAC_USE_COCOA
- if (c->d->curs.cp.nscursor == 0)
- [[NSCursor arrowCursor] set];
- [static_cast<NSCursor *>(c->d->curs.cp.nscursor) set];
-#else
- if(SetAnimatedThemeCursor(c->d->curs.tc.curs, 0) == themeBadCursorIndexErr) {
- SetThemeCursor(c->d->curs.tc.curs);
- } else {
- if(!c->d->curs.tc.anim)
- c->d->curs.tc.anim = new QMacAnimateCursor;
- c->d->curs.tc.anim->start(c->d->curs.tc.curs);
- }
-#endif
+ if(currentCursor && currentCursor->type == QCursorData::TYPE_ThemeCursor
+ && currentCursor->curs.tc.anim)
+ currentCursor->curs.tc.anim->stop();
+ if(c->d->type == QCursorData::TYPE_ImageCursor) {
+ [static_cast<NSCursor *>(c->d->curs.cp.nscursor) set];
+ } else if(c->d->type == QCursorData::TYPE_ThemeCursor) {
+ if(SetAnimatedThemeCursor(c->d->curs.tc.curs, 0) == themeBadCursorIndexErr) {
+ SetThemeCursor(c->d->curs.tc.curs);
+ } else {
+ if(!c->d->curs.tc.anim)
+ c->d->curs.tc.anim = new QMacAnimateCursor;
+ c->d->curs.tc.anim->start(c->d->curs.tc.curs);
}
}
currentCursor = c->d;
@@ -233,6 +224,15 @@ QPoint QCursor::pos()
void QCursor::setPos(int x, int y)
{
+#ifdef QT_MAC_USE_COCOA
+ CGPoint pos;
+ pos.x = x;
+ pos.y = y;
+
+ CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0);
+ CGEventPost(kCGHIDEventTap, e);
+ CFRelease(e);
+#else
CGWarpMouseCursorPosition(CGPointMake(x, y));
/* I'm not too keen on doing this, but this makes it a lot easier, so I just
@@ -249,6 +249,7 @@ void QCursor::setPos(int x, int y)
QApplication::mouseButtons(), QApplication::keyboardModifiers());
qt_sendSpontaneousEvent(widget, &me);
}
+#endif
}
void QCursorData::initCursorFromBitmap()
@@ -424,6 +425,18 @@ void QCursorData::update()
type = QCursorData::TYPE_ThemeCursor;
curs.cp.nscursor = [NSCursor closedHandCursor];
break;
+ case Qt::DragCopyCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor dragCopyCursor];
+ break;
+ case Qt::DragMoveCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor arrowCursor];
+ break;
+ case Qt::DragLinkCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor dragLinkCursor];
+ break;
#define QT_USE_APPROXIMATE_CURSORS
#ifdef QT_USE_APPROXIMATE_CURSORS
case Qt::SizeVerCursor:
@@ -519,6 +532,18 @@ void QCursorData::update()
type = QCursorData::TYPE_ThemeCursor;
curs.tc.curs = kThemeClosedHandCursor;
break;
+ case Qt::DragMoveCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeArrowCursor;
+ break;
+ case Qt::DragCopyCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeCopyArrowCursor;
+ break;
+ case Qt::DragLinkCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeAliasArrowCursor;
+ break;
#define QT_USE_APPROXIMATE_CURSORS
#ifdef QT_USE_APPROXIMATE_CURSORS
case Qt::SizeVerCursor:
diff --git a/src/gui/kernel/qcursor_s60.cpp b/src/gui/kernel/qcursor_s60.cpp
index 54a91760f5..68e079ee5c 100644
--- a/src/gui/kernel/qcursor_s60.cpp
+++ b/src/gui/kernel/qcursor_s60.cpp
@@ -44,7 +44,7 @@
#include <private/qapplication_p.h>
#include <coecntrl.h>
#include <qcursor.h>
-#include <qt_s60_p.h>
+#include <private/qt_s60_p.h>
#include <qbitmap.h>
#include <w32std.h>
#include <qapplication.h>
diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp
index 6f651d4fab..ae1c004e39 100644
--- a/src/gui/kernel/qcursor_win.cpp
+++ b/src/gui/kernel/qcursor_win.cpp
@@ -47,6 +47,7 @@
#include <qimage.h>
#include <qt_windows.h>
+#include <private/qapplication_p.h>
QT_BEGIN_NAMESPACE
@@ -470,6 +471,12 @@ void QCursorData::update()
#endif
return;
}
+ case Qt::DragCopyCursor:
+ case Qt::DragMoveCursor:
+ case Qt::DragLinkCursor: {
+ QPixmap pixmap = QApplicationPrivate::instance()->getPixmapCursor(cshape);
+ hcurs = create32BitCursor(pixmap, hx, hy);
+ }
default:
qWarning("QCursor::update: Invalid cursor shape %d", cshape);
return;
diff --git a/src/gui/kernel/qcursor_x11.cpp b/src/gui/kernel/qcursor_x11.cpp
index 3e833638a2..8e486289aa 100644
--- a/src/gui/kernel/qcursor_x11.cpp
+++ b/src/gui/kernel/qcursor_x11.cpp
@@ -39,9 +39,11 @@
**
****************************************************************************/
+#include <qdebug.h>
#include <qdatastream.h>
#include <private/qcursor_p.h>
#include <private/qt_x11_p.h>
+#include <private/qapplication_p.h>
#include <qbitmap.h>
#include <qcursor.h>
#include <X11/cursorfont.h>
@@ -57,6 +59,7 @@
#endif // QT_NO_XFIXES
#include "qx11info_x11.h"
+#include <private/qpixmap_x11_p.h>
QT_BEGIN_NAMESPACE
@@ -262,17 +265,36 @@ void QCursorData::update()
"whats_this",
"left_ptr_watch",
"openhand",
- "closedhand"
+ "closedhand",
+ "copy",
+ "move",
+ "link"
};
#ifndef QT_NO_XCURSOR
- if (X11->ptrXcursorLibraryLoadCursor)
- hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+ if (X11->ptrXcursorLibraryLoadCursor) {
+ // special case for non-standard dnd-* cursors
+ switch (cshape) {
+ case Qt::DragCopyCursor:
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
+ break;
+ case Qt::DragMoveCursor:
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
+ break;
+ case Qt::DragLinkCursor:
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
+ break;
+ default:
+ break;
+ }
+ if (!hcurs)
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+ }
if (hcurs)
return;
#endif // QT_NO_XCURSOR
- static const char cur_blank_bits[] = {
+ static const uchar cur_blank_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -280,44 +302,44 @@ void QCursorData::update()
// Non-standard X11 cursors are created from bitmaps
#ifndef QT_USE_APPROXIMATE_CURSORS
- static const char cur_ver_bits[] = {
+ static const uchar cur_ver_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f,
0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 };
- static const char mcur_ver_bits[] = {
+ static const uchar mcur_ver_bits[] = {
0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f,
0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f,
0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 };
- static const char cur_hor_bits[] = {
+ static const uchar cur_hor_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18,
0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char mcur_hor_bits[] = {
+ static const uchar mcur_hor_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c,
0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c,
0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 };
- static const char cur_bdiag_bits[] = {
+ static const uchar cur_bdiag_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e,
0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00,
0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char mcur_bdiag_bits[] = {
+ static const uchar mcur_bdiag_bits[] = {
0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f,
0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01,
0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 };
- static const char cur_fdiag_bits[] = {
+ static const uchar cur_fdiag_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00,
0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c,
0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 };
- static const char mcur_fdiag_bits[] = {
+ static const uchar mcur_fdiag_bits[] = {
0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00,
0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e,
0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 };
- static const char *cursor_bits16[] = {
+ static const uchar *cursor_bits16[] = {
cur_ver_bits, mcur_ver_bits, cur_hor_bits, mcur_hor_bits,
cur_bdiag_bits, mcur_bdiag_bits, cur_fdiag_bits, mcur_fdiag_bits,
0, 0, cur_blank_bits, cur_blank_bits };
- static const char vsplit_bits[] = {
+ static const uchar vsplit_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
@@ -329,7 +351,7 @@ void QCursorData::update()
0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char vsplitm_bits[] = {
+ static const uchar vsplitm_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
@@ -341,7 +363,7 @@ void QCursorData::update()
0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char hsplit_bits[] = {
+ static const uchar hsplit_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
@@ -353,7 +375,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char hsplitm_bits[] = {
+ static const uchar hsplitm_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
@@ -365,7 +387,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char whatsthis_bits[] = {
+ static const uchar whatsthis_bits[] = {
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00,
0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00,
0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00,
@@ -377,7 +399,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
- static const char whatsthism_bits[] = {
+ static const uchar whatsthism_bits[] = {
0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00,
0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00,
0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00,
@@ -389,7 +411,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
- static const char busy_bits[] = {
+ static const uchar busy_bits[] = {
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00,
@@ -401,7 +423,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- static const char busym_bits[] = {
+ static const uchar busym_bits[] = {
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00,
@@ -414,41 +436,41 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- static const char * const cursor_bits32[] = {
+ static const uchar * const cursor_bits32[] = {
vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits,
0, 0, 0, 0, whatsthis_bits, whatsthism_bits, busy_bits, busym_bits
};
- static const char forbidden_bits[] = {
+ static const uchar forbidden_bits[] = {
0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01,
0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06,
0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03,
0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 };
- static const char forbiddenm_bits[] = {
+ static const uchar forbiddenm_bits[] = {
0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03,
0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f,
0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07,
0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00};
- static const char openhand_bits[] = {
+ static const uchar openhand_bits[] = {
0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92,
0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20,
0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00};
- static const char openhandm_bits[] = {
+ static const uchar openhandm_bits[] = {
0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff,
0xf6,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f,
0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00};
- static const char closedhand_bits[] = {
+ static const uchar closedhand_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50,
0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10,
0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00};
- static const char closedhandm_bits[] = {
+ static const uchar closedhandm_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f,
0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
- static const char * const cursor_bits20[] = {
+ static const uchar * const cursor_bits20[] = {
forbidden_bits, forbiddenm_bits
};
@@ -462,8 +484,8 @@ void QCursorData::update()
fg.green = 0;
fg.blue = 0;
int i = (cshape - Qt::SizeVerCursor) * 2;
- pm = XCreateBitmapFromData(dpy, rootwin, cursor_bits16[i], 16, 16);
- pmm = XCreateBitmapFromData(dpy, rootwin, cursor_bits16[i + 1], 16, 16);
+ pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char*>(cursor_bits16[i]), 16, 16);
+ pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char*>(cursor_bits16[i + 1]), 16, 16);
hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
} else if ((cshape >= Qt::SplitVCursor && cshape <= Qt::SplitHCursor)
|| cshape == Qt::WhatsThisCursor || cshape == Qt::BusyCursor) {
@@ -475,8 +497,8 @@ void QCursorData::update()
fg.green = 0;
fg.blue = 0;
int i = (cshape - Qt::SplitVCursor) * 2;
- pm = XCreateBitmapFromData(dpy, rootwin, cursor_bits32[i], 32, 32);
- pmm = XCreateBitmapFromData(dpy, rootwin, cursor_bits32[i + 1], 32, 32);
+ pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits32[i]), 32, 32);
+ pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits32[i + 1]), 32, 32);
int hs = (cshape == Qt::PointingHandCursor || cshape == Qt::WhatsThisCursor
|| cshape == Qt::BusyCursor) ? 0 : 16;
hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, hs, hs);
@@ -489,8 +511,8 @@ void QCursorData::update()
fg.green = 0;
fg.blue = 0;
int i = (cshape - Qt::ForbiddenCursor) * 2;
- pm = XCreateBitmapFromData(dpy, rootwin, cursor_bits20[i], 20, 20);
- pmm = XCreateBitmapFromData(dpy, rootwin, cursor_bits20[i + 1], 20, 20);
+ pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits20[i]), 20, 20);
+ pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits20[i + 1]), 20, 20);
hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 10, 10);
} else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
XColor bg, fg;
@@ -501,8 +523,21 @@ void QCursorData::update()
fg.green = 0;
fg.blue = 0;
bool open = cshape == Qt::OpenHandCursor;
- pm = XCreateBitmapFromData(dpy, rootwin, open ? openhand_bits : closedhand_bits, 16, 16);
- pmm = XCreateBitmapFromData(dpy, rootwin, open ? openhandm_bits : closedhandm_bits, 16, 16);
+ pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(open ? openhand_bits : closedhand_bits), 16, 16);
+ pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(open ? openhandm_bits : closedhandm_bits), 16, 16);
+ hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
+ } else if (cshape == Qt::DragCopyCursor || cshape == Qt::DragMoveCursor
+ || cshape == Qt::DragLinkCursor) {
+ XColor bg, fg;
+ bg.red = 255 << 8;
+ bg.green = 255 << 8;
+ bg.blue = 255 << 8;
+ fg.red = 0;
+ fg.green = 0;
+ fg.blue = 0;
+ QImage image = QApplicationPrivate::instance()->getPixmapCursor(cshape).toImage();
+ pm = QX11PixmapData::createBitmapFromImage(image);
+ pmm = QX11PixmapData::createBitmapFromImage(image.createAlphaMask().convertToFormat(QImage::Format_MonoLSB));
hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
}
@@ -577,6 +612,15 @@ void QCursorData::update()
case Qt::BusyCursor:
sh = XC_watch;
break;
+ case Qt::DragCopyCursor:
+ sh = XC_tcross;
+ break;
+ case Qt::DragLinkCursor:
+ sh = XC_center_ptr;
+ break;
+ case Qt::DragMoveCursor:
+ sh = XC_top_left_arrow;
+ break;
#endif /* QT_USE_APPROXIMATE_CURSORS */
default:
qWarning("QCursor::update: Invalid cursor shape %d", cshape);
diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp
index 1fea8d64d3..07dbc24b91 100644
--- a/src/gui/kernel/qdesktopwidget_win.cpp
+++ b/src/gui/kernel/qdesktopwidget_win.cpp
@@ -76,7 +76,7 @@ public:
};
typedef BOOL (WINAPI *InfoFunc)(HMONITOR, MONITORINFO*);
- typedef BOOL (CALLBACK *EnumProc)(HMONITOR, HDC, LPRECT, LPARAM);
+ typedef BOOL (QT_WIN_CALLBACK *EnumProc)(HMONITOR, HDC, LPRECT, LPARAM);
typedef BOOL (WINAPI *EnumFunc)(HDC, LPCRECT, EnumProc, LPARAM);
static EnumFunc enumDisplayMonitors;
@@ -107,7 +107,7 @@ static inline void qt_get_sip_info(QRect &rect)
#endif
-BOOL CALLBACK enumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM)
+BOOL QT_WIN_CALLBACK enumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM)
{
QDesktopWidgetPrivate::screenCount++;
QDesktopWidgetPrivate::rects->resize(QDesktopWidgetPrivate::screenCount);
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
index 21438a8b8a..2b3a3d08c1 100644
--- a/src/gui/kernel/qdnd.cpp
+++ b/src/gui/kernel/qdnd.cpp
@@ -60,204 +60,12 @@
#include "qdebug.h"
#include <ctype.h>
+#include <private/qapplication_p.h>
+
#ifndef QT_NO_DRAGANDDROP
QT_BEGIN_NAMESPACE
-// These pixmaps approximate the images in the Windows User Interface Guidelines.
-
-// XPM
-
-static const char * const move_xpm[] = {
-"11 20 3 1",
-". c None",
-#if defined(Q_WS_WIN)
-"a c #000000",
-"X c #FFFFFF", // Windows cursor is traditionally white
-#else
-"a c #FFFFFF",
-"X c #000000", // X11 cursor is traditionally black
-#endif
-"aa.........",
-"aXa........",
-"aXXa.......",
-"aXXXa......",
-"aXXXXa.....",
-"aXXXXXa....",
-"aXXXXXXa...",
-"aXXXXXXXa..",
-"aXXXXXXXXa.",
-"aXXXXXXXXXa",
-"aXXXXXXaaaa",
-"aXXXaXXa...",
-"aXXaaXXa...",
-"aXa..aXXa..",
-"aa...aXXa..",
-"a.....aXXa.",
-"......aXXa.",
-".......aXXa",
-".......aXXa",
-"........aa."};
-
-#ifdef Q_WS_WIN
-/* XPM */
-static const char * const ignore_xpm[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa.....XXXX.....",
-".......aXXa..XXaaaaXX...",
-".......aXXa.XaaaaaaaaX..",
-"........aa.XaaaXXXXaaaX.",
-"...........XaaaaX..XaaX.",
-"..........XaaXaaaX..XaaX",
-"..........XaaXXaaaX.XaaX",
-"..........XaaX.XaaaXXaaX",
-"..........XaaX..XaaaXaaX",
-"...........XaaX..XaaaaX.",
-"...........XaaaXXXXaaaX.",
-"............XaaaaaaaaX..",
-".............XXaaaaXX...",
-"...............XXXX....."};
-#endif
-
-/* XPM */
-static const char * const copy_xpm[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-#if defined(Q_WS_WIN) // Windows cursor is traditionally white
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa..............",
-".......aXXa.............",
-".......aXXa.............",
-"........aa...aaaaaaaaaaa",
-#else
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-#endif
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXaaaaaXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
-/* XPM */
-static const char * const link_xpm[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-#if defined(Q_WS_WIN) // Windows cursor is traditionally white
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa..............",
-".......aXXa.............",
-".......aXXa.............",
-"........aa...aaaaaaaaaaa",
-#else
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-#endif
-".............aXXXXXXXXXa",
-".............aXXXaaaaXXa",
-".............aXXXXaaaXXa",
-".............aXXXaaaaXXa",
-".............aXXaaaXaXXa",
-".............aXXaaXXXXXa",
-".............aXXaXXXXXXa",
-".............aXXXaXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
#ifndef QT_NO_DRAGANDDROP
//#define QDND_DEBUG
@@ -326,22 +134,9 @@ QDragManager::QDragManager()
{
Q_ASSERT(!instance);
-#ifdef Q_WS_WIN
- n_cursor = 4;
-#else
- n_cursor = 3;
-#endif
-
#ifdef Q_WS_QWS
currentActionForOverrideCursor = Qt::IgnoreAction;
#endif
- pm_cursor = new QPixmap[n_cursor];
- pm_cursor[0] = QPixmap((const char **)move_xpm);
- pm_cursor[1] = QPixmap((const char **)copy_xpm);
- pm_cursor[2] = QPixmap((const char **)link_xpm);
-#ifdef Q_WS_WIN
- pm_cursor[3] = QPixmap((const char **)ignore_xpm);
-#endif
object = 0;
beingCancelled = false;
restoreCursor = false;
@@ -362,7 +157,6 @@ QDragManager::~QDragManager()
QApplication::restoreOverrideCursor();
#endif
instance = 0;
- delete [] pm_cursor;
delete dropData;
}
@@ -379,14 +173,14 @@ QPixmap QDragManager::dragCursor(Qt::DropAction action) const
if (d && d->customCursors.contains(action))
return d->customCursors[action];
else if (action == Qt::MoveAction)
- return pm_cursor[0];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::DragMoveCursor);
else if (action == Qt::CopyAction)
- return pm_cursor[1];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::DragCopyCursor);
else if (action == Qt::LinkAction)
- return pm_cursor[2];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::DragLinkCursor);
#ifdef Q_WS_WIN
else if (action == Qt::IgnoreAction)
- return pm_cursor[3];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::ForbiddenCursor);
#endif
return QPixmap();
}
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index d70b983c30..033e6a6702 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -261,8 +261,6 @@ public:
#endif
private:
- QPixmap *pm_cursor;
- int n_cursor;
#ifdef Q_WS_QWS
Qt::DropAction currentActionForOverrideCursor;
#endif
diff --git a/src/gui/kernel/qdnd_win.cpp b/src/gui/kernel/qdnd_win.cpp
index 0742a937d0..a164c2af3e 100644
--- a/src/gui/kernel/qdnd_win.cpp
+++ b/src/gui/kernel/qdnd_win.cpp
@@ -524,18 +524,14 @@ QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
if (fEscapePressed) {
return ResultFromScode(DRAGDROP_S_CANCEL);
- } else if (!(grfKeyState & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))) {
+ } else if ((GetAsyncKeyState(VK_LBUTTON) == 0)
+ && (GetAsyncKeyState(VK_MBUTTON) == 0)
+ && (GetAsyncKeyState(VK_RBUTTON) == 0)) {
+ // grfKeyState is broken on CE & some Windows XP versions,
+ // therefore we need to check the state manually
return ResultFromScode(DRAGDROP_S_DROP);
} else {
-#if defined(Q_OS_WINCE)
- // grfKeyState is broken on CE, therefore need to check
- // the state manually
- if ((GetAsyncKeyState(VK_LBUTTON) == 0) &&
- (GetAsyncKeyState(VK_MBUTTON) == 0) &&
- (GetAsyncKeyState(VK_RBUTTON) == 0)) {
- return ResultFromScode(DRAGDROP_S_DROP);
- }
-#else
+#if !defined(Q_OS_WINCE)
if (currentButtons == Qt::NoButton) {
currentButtons = keystate_to_mousebutton(grfKeyState);
} else {
diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp
index 33968bd9fc..0a05d8e625 100644
--- a/src/gui/kernel/qdnd_x11.cpp
+++ b/src/gui/kernel/qdnd_x11.cpp
@@ -51,10 +51,10 @@
#include "qbitmap.h"
#include "qdesktopwidget.h"
#include "qevent.h"
-#include "qdatetime.h"
#include "qiodevice.h"
#include "qpointer.h"
#include "qcursor.h"
+#include "qelapsedtimer.h"
#include "qvariant.h"
#include "qvector.h"
#include "qurl.h"
@@ -1340,9 +1340,9 @@ void QDragManager::updateCursor()
if (!noDropCursor) {
#ifndef QT_NO_CURSOR
noDropCursor = new QCursor(Qt::ForbiddenCursor);
- moveCursor = new QCursor(dragCursor(Qt::MoveAction), 0,0);
- copyCursor = new QCursor(dragCursor(Qt::CopyAction), 0,0);
- linkCursor = new QCursor(dragCursor(Qt::LinkAction), 0,0);
+ moveCursor = new QCursor(Qt::DragMoveCursor);
+ copyCursor = new QCursor(Qt::DragCopyCursor);
+ linkCursor = new QCursor(Qt::DragLinkCursor);
#endif
}
@@ -1911,23 +1911,19 @@ Qt::DropAction QDragManager::drag(QDrag * o)
// then we could still have problems, but this is highly unlikely
QApplication::flush();
- QTime started = QTime::currentTime();
- QTime now = started;
+ QElapsedTimer timer;
+ timer.start();
do {
XEvent event;
if (XCheckTypedEvent(X11->display, ClientMessage, &event))
qApp->x11ProcessEvent(&event);
- now = QTime::currentTime();
- if (started > now) // crossed midnight
- started = now;
-
// sleep 50 ms, so we don't use up CPU cycles all the time.
struct timeval usleep_tv;
usleep_tv.tv_sec = 0;
usleep_tv.tv_usec = 50000;
select(0, 0, 0, 0, &usleep_tv);
- } while (object && started.msecsTo(now) < 1000);
+ } while (object && timer.hasExpired(1000));
}
object = o;
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
index df09185ea7..0d93b9ffa1 100644
--- a/src/gui/kernel/qeventdispatcher_mac.mm
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -90,11 +90,11 @@
#ifndef QT_NO_THREAD
# include "qmutex.h"
+#endif
QT_BEGIN_NAMESPACE
QT_USE_NAMESPACE
-#endif
/*****************************************************************************
Externals
@@ -548,6 +548,12 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherMac);
d->interrupt = false;
+
+#ifdef QT_MAC_USE_COCOA
+ bool interruptLater = false;
+ QtMacInterruptDispatcherHelp::cancelInterruptLater();
+#endif
+
// In case we end up recursing while we now process events, make sure
// that we send remaining posted Qt events before this call returns:
wakeUp();
@@ -562,25 +568,37 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
QMacCocoaAutoReleasePool pool;
NSEvent* event = 0;
- // 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;
+ // First, send all previously excluded input events, if any:
+ if (!(flags & QEventLoop::ExcludeUserInputEvents)) {
+ while (!d->queuedUserInputEvents.isEmpty()) {
+ event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
+ if (!filterEvent(event)) {
+ qt_mac_send_event(flags, event, 0);
+ retVal = true;
+ }
+ [event release];
+ }
+ }
+
+ // If Qt is used as a plugin, or as an extension in a native cocoa
+ // application, we should not run or stop NSApplication; This will be
+ // done from the application itself. And if processEvents is called
+ // manually (rather than from a QEventLoop), we cannot enter a tight
+ // loop and block this call, but instead we need to return after one flush:
+ const bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning];
+ const 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.
+ // interrupted. This is mostly an optimization, but it allow us to use
+ // [NSApp run], which is the normal code path for cocoa applications.
if (NSModalSession session = d->currentModalSession()) {
QBoolBlocker execGuard(d->currentExecIsNSAppRun, false);
while ([NSApp runModalSession:session] == NSRunContinuesResponse && !d->interrupt)
qt_mac_waitForMoreModalSessionEvents();
+
if (!d->interrupt && session == d->currentModalSessionCached) {
- // INVARIANT: Someone called e.g. [NSApp stopModal:] from outside the event
+ // Someone called [NSApp stopModal:] from outside the event
// dispatcher (e.g to stop a native dialog). But that call wrongly stopped
// 'session' as well. As a result, we need to restart all internal sessions:
d->temporarilyStopAllModalSessions();
@@ -591,54 +609,47 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
[NSApp run];
}
retVal = true;
- } else do {
- // INVARIANT: We cannot block the thread (and run in a tight loop).
+ } else {
+ // 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
- mustRelease = true;
- event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
- } else {
- if (NSModalSession session = d->currentModalSession()) {
- if (flags & QEventLoop::WaitForMoreEvents)
- qt_mac_waitForMoreModalSessionEvents();
- NSInteger status = [NSApp runModalSession:session];
- if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) {
- // INVARIANT: Someone called e.g. [NSApp stopModal:] from outside the event
- // dispatcher (e.g to stop a native dialog). But that call wrongly stopped
- // 'session' as well. As a result, we need to restart all internal sessions:
- d->temporarilyStopAllModalSessions();
- }
- retVal = true;
- break;
- } else {
- event = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:nil
- inMode:NSDefaultRunLoopMode
- dequeue: YES];
-
- if (event != nil) {
- if (flags & QEventLoop::ExcludeUserInputEvents) {
- if (IsMouseOrKeyEvent(event)) {
- // retain event here?
- [event retain];
- d->queuedUserInputEvents.append(event);
- continue;
- }
+ d->ensureNSAppInitialized();
+ if (NSModalSession session = d->currentModalSession()) {
+ if (flags & QEventLoop::WaitForMoreEvents)
+ qt_mac_waitForMoreModalSessionEvents();
+ NSInteger status = [NSApp runModalSession:session];
+ if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) {
+ // INVARIANT: Someone called [NSApp stopModal:] from outside the event
+ // dispatcher (e.g to stop a native dialog). But that call wrongly stopped
+ // 'session' as well. As a result, we need to restart all internal sessions:
+ d->temporarilyStopAllModalSessions();
+ }
+ retVal = true;
+ } else do {
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:nil
+ inMode:NSDefaultRunLoopMode
+ dequeue: YES];
+
+ if (event) {
+ if (flags & QEventLoop::ExcludeUserInputEvents) {
+ if (IsMouseOrKeyEvent(event)) {
+ [event retain];
+ d->queuedUserInputEvents.append(event);
+ continue;
}
}
+ if (!filterEvent(event) && qt_mac_send_event(flags, event, 0))
+ retVal = true;
}
- }
- if (event) {
- if (!filterEvent(event) && qt_mac_send_event(flags, event, 0))
- retVal = true;
- if (mustRelease)
- [event release];
- }
- } while(!d->interrupt && event != nil);
-
+ } while (!d->interrupt && event != nil);
+
+ // Since the window that holds modality might have changed while processing
+ // events, we we need to interrupt when we return back the previous process
+ // event recursion to ensure that we spin the correct modal session.
+ // We do the interruptLater at the end of the function to ensure that we don't
+ // disturb the 'wait for more events' below (as deleteLater will post an event):
+ interruptLater = true;
+ }
#else
do {
EventRef event;
@@ -690,25 +701,19 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
}
}
+ // If we're interrupted, we need to interrupt the _current_
+ // recursion as well to check if it is still supposed to be
+ // executing. This way we wind down the stack until we land
+ // on a recursion that again calls processEvents (typically
+ // from QEventLoop), and set interrupt to false:
+ if (d->interrupt)
+ interrupt();
+
#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();
+ if (interruptLater)
+ QtMacInterruptDispatcherHelp::interruptLater();
#endif
- 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;
}
@@ -737,31 +742,46 @@ void QEventDispatcherMac::flush()
*****************************************************************************/
MacTimerHash QEventDispatcherMacPrivate::macTimerHash;
bool QEventDispatcherMacPrivate::blockSendPostedEvents = false;
+bool QEventDispatcherMacPrivate::interrupt = false;
#ifdef QT_MAC_USE_COCOA
QStack<QCocoaModalSessionInfo> QEventDispatcherMacPrivate::cocoaModalSessionStack;
bool QEventDispatcherMacPrivate::currentExecIsNSAppRun = false;
bool QEventDispatcherMacPrivate::nsAppRunCalledByQt = false;
+bool QEventDispatcherMacPrivate::cleanupModalSessionsNeeded = false;
NSModalSession QEventDispatcherMacPrivate::currentModalSessionCached = 0;
-int QEventDispatcherMacPrivate::activeModalSessionCount()
+void QEventDispatcherMacPrivate::ensureNSAppInitialized()
{
- // 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;
+ // Some elements in Cocoa require NSApplication to be running before
+ // they get fully initialized, in particular the menu bar. This
+ // function is intended for cases where a dialog is told to execute before
+ // QApplication::exec is called, or the application spins the events loop
+ // manually rather than calling QApplication:exec.
+ // The function makes sure that NSApplication starts running, but stops
+ // it again as soon as the send posted events callback is called. That way
+ // we let Cocoa finish the initialization it seems to need. We'll only
+ // apply this trick at most once for any application, and we avoid doing it
+ // for the common case where main just starts QApplication::exec.
+ if (nsAppRunCalledByQt || [NSApp isRunning])
+ return;
+ nsAppRunCalledByQt = true;
+ QBoolBlocker block1(interrupt, true);
+ QBoolBlocker block2(currentExecIsNSAppRun, true);
+ [NSApp run];
}
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:
+ // Flush, and Stop, all created modal session, and as
+ // such, make them pending again. The next call to
+ // currentModalSession will recreate them again. The
+ // reason to stop all session like this is that otherwise
+ // a call [NSApp stop] would not stop NSApp, but rather
+ // the current modal session. So if we need to stop NSApp
+ // we need to stop all the modal session first. To avoid changing
+ // the stacking order of the windows while doing so, we put
+ // up a block that is used in QCocoaWindow and QCocoaPanel:
int stackSize = cocoaModalSessionStack.size();
for (int i=stackSize-1; i>=0; --i) {
QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
@@ -783,23 +803,6 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession()
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:0
- 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];
@@ -812,11 +815,20 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession()
NSWindow *window = qt_mac_window_for(info.widget);
if (!window)
continue;
+
+ ensureNSAppInitialized();
+ QBoolBlocker block1(blockSendPostedEvents, true);
+ info.nswindow = window;
+ [(NSWindow*) info.nswindow retain];
+ // When creating a modal session cocoa will rearrange the windows.
+ // In order to avoid windows to be put behind another we need to
+ // keep the window level.
+ int level = [window level];
info.session = [NSApp beginModalSessionForWindow:window];
+ [window setLevel:level];
}
currentModalSessionCached = info.session;
}
-
return currentModalSessionCached;
}
@@ -852,6 +864,36 @@ void QEventDispatcherMacPrivate::updateChildrenWorksWhenModal()
}
}
+void QEventDispatcherMacPrivate::cleanupModalSessions()
+{
+ // Go through the list of modal sessions, and end those
+ // that no longer has a widget assosiated; no widget means
+ // the the session has logically ended. The reason we wait like
+ // this to actually end the sessions for real (rather than at the
+ // point they were marked as stopped), is that ending a session
+ // when no other session runs below it on the stack will make cocoa
+ // drop some events on the floor.
+ QMacCocoaAutoReleasePool pool;
+ int stackSize = cocoaModalSessionStack.size();
+
+ for (int i=stackSize-1; i>=0; --i) {
+ QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
+ if (info.widget) {
+ currentModalSessionCached = info.session;
+ break;
+ }
+ cocoaModalSessionStack.remove(i);
+ currentModalSessionCached = 0;
+ if (info.session) {
+ [NSApp endModalSession:info.session];
+ [(NSWindow *)info.nswindow release];
+ }
+ }
+
+ updateChildrenWorksWhenModal();
+ cleanupModalSessionsNeeded = false;
+}
+
void QEventDispatcherMacPrivate::beginModalSession(QWidget *widget)
{
// Add a new, empty (null), NSModalSession to the stack.
@@ -860,8 +902,8 @@ void QEventDispatcherMacPrivate::beginModalSession(QWidget *widget)
// 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};
+ // stopped in cleanupModalSessions()).
+ QCocoaModalSessionInfo info = {widget, 0, 0};
cocoaModalSessionStack.push(info);
updateChildrenWorksWhenModal();
currentModalSessionCached = 0;
@@ -877,38 +919,21 @@ void QEventDispatcherMacPrivate::endModalSession(QWidget *widget)
int stackSize = cocoaModalSessionStack.size();
for (int i=stackSize-1; i>=0; --i) {
QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
- if (info.widget == widget)
+ if (info.widget == widget) {
info.widget = 0;
- }
-
- // 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=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];
- needToInterruptEventDispatcher = true;
+ if (i == stackSize-1) {
+ // The top sessions ended. Interrupt the event dispatcher
+ // to start spinning the correct session immidiatly:
+ cleanupModalSessionsNeeded = true;
+ QEventDispatcherMac::instance()->interrupt();
+ }
}
}
-
- if (needToUpdateChildrenWorksWhenModal)
- updateChildrenWorksWhenModal();
- if (needToInterruptEventDispatcher)
- QEventDispatcherMac::instance()->interrupt();
}
#endif
QEventDispatcherMacPrivate::QEventDispatcherMacPrivate()
- : interrupt(false)
{
}
@@ -967,13 +992,39 @@ Boolean QEventDispatcherMacPrivate::postedEventSourceEqualCallback(const void *i
inline static void processPostedEvents(QEventDispatcherMacPrivate *const d, const bool blockSendPostedEvents)
{
- if (blockSendPostedEvents || d->interrupt) {
+ if (blockSendPostedEvents) {
+ // We're told to not send posted events (because the event dispatcher
+ // is currently working on setting up the correct session to run). But
+ // we still need to make sure that we don't fall asleep until pending events
+ // are sendt, so we just signal this need, and return:
CFRunLoopSourceSignal(d->postedEventsSource);
- } else {
- if (!d->threadData->canWait || (d->serialNumber != d->lastSerial)) {
- d->lastSerial = d->serialNumber;
- QApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ return;
+ }
+
+#ifdef QT_MAC_USE_COCOA
+ if (d->cleanupModalSessionsNeeded)
+ d->cleanupModalSessions();
+#endif
+
+ if (d->interrupt) {
+#ifdef QT_MAC_USE_COCOA
+ if (d->currentExecIsNSAppRun) {
+ // The event dispatcher has been interrupted. But since
+ // [NSApplication run] is running the event loop, we
+ // delayed stopping it until now (to let cocoa process
+ // pending cocoa events first).
+ if (d->currentModalSessionCached)
+ d->temporarilyStopAllModalSessions();
+ [NSApp stop:NSApp];
+ d->cancelWaitForMoreEvents();
}
+#endif
+ return;
+ }
+
+ if (!d->threadData->canWait || (d->serialNumber != d->lastSerial)) {
+ d->lastSerial = d->serialNumber;
+ QApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
}
}
@@ -983,6 +1034,9 @@ void QEventDispatcherMacPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
{
Q_UNUSED(ref);
Q_UNUSED(activity);
+#ifdef QT_MAC_USE_COCOA
+ QApplicationPrivate::qt_initAfterNSAppStarted();
+#endif
processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents);
}
@@ -991,6 +1045,18 @@ void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info)
processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents);
}
+#ifdef QT_MAC_USE_COCOA
+void QEventDispatcherMacPrivate::cancelWaitForMoreEvents()
+{
+ // In case the event dispatcher is waiting for more
+ // events somewhere, we post a dummy event to wake it up:
+ QMacCocoaAutoReleasePool pool;
+ [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
+ modifierFlags:0 timestamp:0. windowNumber:0 context:0
+ subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO];
+}
+#endif
+
void QEventDispatcherMac::interrupt()
{
Q_D(QEventDispatcherMac);
@@ -1000,20 +1066,14 @@ void QEventDispatcherMac::interrupt()
#ifndef QT_MAC_USE_COCOA
CFRunLoopStop(mainRunLoop());
#else
- 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];
- }
+ // We do nothing more here than setting d->interrupt = true, and
+ // poke the event loop if it is sleeping. Actually stopping
+ // NSApp, or the current modal session, is done inside the send
+ // posted events callback. We do this to ensure that all current pending
+ // cocoa events gets delivered before we stop. Otherwise, if we now stop
+ // the last event loop recursion, cocoa will just drop pending posted
+ // events on the floor before we get a chance to reestablish a new session.
+ d->cancelWaitForMoreEvents();
#endif
}
@@ -1054,17 +1114,18 @@ QEventDispatcherMac::~QEventDispatcherMac()
CFRelease(d->firstTimeObserver);
}
-/////////////////////////////////////////////////////////////////////////////
-
#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:
+ // The whole point of this class is that we enable a way to interrupt
+ // the event dispatcher when returning back to a lower recursion level
+ // than where interruptLater was called. This is needed to detect if
+ // [NSApp run] should still be running at the recursion level it is at.
+ // Since the interrupt is canceled if processEvents is called before
+ // this object gets deleted, we also avoid interrupting unnecessary.
deleteLater();
}
@@ -1072,34 +1133,26 @@ 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;
- }
+void QtMacInterruptDispatcherHelp::cancelInterruptLater()
+{
+ if (!instance)
+ return;
+ instance->cancelled = true;
+ delete instance;
+ instance = 0;
+}
+
+void QtMacInterruptDispatcherHelp::interruptLater()
+{
+ cancelInterruptLater();
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 a335f162fd..a0afb84179 100644
--- a/src/gui/kernel/qeventdispatcher_mac_p.h
+++ b/src/gui/kernel/qeventdispatcher_mac_p.h
@@ -100,6 +100,7 @@ typedef struct _NSModalSession *NSModalSession;
typedef struct _QCocoaModalSessionInfo {
QPointer<QWidget> widget;
NSModalSession session;
+ void *nswindow;
} QCocoaModalSessionInfo;
#endif
@@ -174,13 +175,16 @@ public:
static QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
static bool currentExecIsNSAppRun;
static bool nsAppRunCalledByQt;
+ static bool cleanupModalSessionsNeeded;
static NSModalSession currentModalSessionCached;
- static void updateChildrenWorksWhenModal();
static NSModalSession currentModalSession();
- static int activeModalSessionCount();
+ static void updateChildrenWorksWhenModal();
static void temporarilyStopAllModalSessions();
static void beginModalSession(QWidget *widget);
static void endModalSession(QWidget *widget);
+ static void cancelWaitForMoreEvents();
+ static void cleanupModalSessions();
+ static void ensureNSAppInitialized();
#endif
MacSocketHash macSockets;
@@ -190,7 +194,7 @@ public:
CFRunLoopObserverRef firstTimeObserver;
QAtomicInt serialNumber;
int lastSerial;
- bool interrupt;
+ static bool interrupt;
private:
static Boolean postedEventSourceEqualCallback(const void *info1, const void *info2);
static void postedEventsSourcePerformCallback(void *info);
@@ -211,6 +215,7 @@ class QtMacInterruptDispatcherHelp : public QObject
public:
static void interruptLater();
+ static void cancelInterruptLater();
};
#endif
diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h
index dee5592094..bf60f97861 100644
--- a/src/gui/kernel/qgesture_p.h
+++ b/src/gui/kernel/qgesture_p.h
@@ -55,8 +55,8 @@
#include "qrect.h"
#include "qpoint.h"
-#include "qdatetime.h"
#include "qgesture.h"
+#include "qelapsedtimer.h"
#include "private/qobject_p.h"
QT_BEGIN_NAMESPACE
@@ -69,13 +69,13 @@ public:
QGesturePrivate()
: gestureType(Qt::CustomGesture), state(Qt::NoGesture),
isHotSpotSet(false), gestureCancelPolicy(0)
-
{
}
Qt::GestureType gestureType;
Qt::GestureState state;
QPointF hotSpot;
+ QPointF sceneHotSpot;
uint isHotSpotSet : 1;
uint gestureCancelPolicy : 2;
};
@@ -148,7 +148,7 @@ public:
QPoint lastPositions[3];
bool started;
qreal speed;
- QTime time;
+ QElapsedTimer time;
};
class QTapGesturePrivate : public QGesturePrivate
diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp
index 8735d272c0..9dcca175bc 100644
--- a/src/gui/kernel/qgesturerecognizer.cpp
+++ b/src/gui/kernel/qgesturerecognizer.cpp
@@ -161,6 +161,8 @@ QGestureRecognizer::~QGestureRecognizer()
Reimplement this function to create a custom QGesture-derived gesture
object if necessary.
+
+ The application takes ownership of the created gesture object.
*/
QGesture *QGestureRecognizer::create(QObject *target)
{
@@ -181,6 +183,7 @@ void QGestureRecognizer::reset(QGesture *gesture)
QGesturePrivate *d = gesture->d_func();
d->state = Qt::NoGesture;
d->hotSpot = QPointF();
+ d->sceneHotSpot = QPointF();
d->isHotSpotSet = false;
}
}
diff --git a/src/gui/kernel/qguieventdispatcher_glib.cpp b/src/gui/kernel/qguieventdispatcher_glib.cpp
index 7b30741e86..ac2b5f787c 100644
--- a/src/gui/kernel/qguieventdispatcher_glib.cpp
+++ b/src/gui/kernel/qguieventdispatcher_glib.cpp
@@ -216,4 +216,9 @@ void QGuiEventDispatcherGlib::startingUp()
g_source_add_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
}
+void QGuiEventDispatcherGlib::flush()
+{
+ XFlush(X11->display);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qguieventdispatcher_glib_p.h b/src/gui/kernel/qguieventdispatcher_glib_p.h
index ff778cc744..758650b434 100644
--- a/src/gui/kernel/qguieventdispatcher_glib_p.h
+++ b/src/gui/kernel/qguieventdispatcher_glib_p.h
@@ -71,6 +71,7 @@ public:
bool processEvents(QEventLoop::ProcessEventsFlags flags);
void startingUp();
+ void flush();
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp
index a31480dcd8..a7145d4f2f 100644
--- a/src/gui/kernel/qkeymapper_mac.cpp
+++ b/src/gui/kernel/qkeymapper_mac.cpp
@@ -323,6 +323,32 @@ static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes
{ 0, QT_MAC_MAP_ENUM(0) }
};
+static qt_mac_enum_mapper qt_mac_private_unicode[] = {
+ { 0xF700, QT_MAC_MAP_ENUM(Qt::Key_Up) }, //NSUpArrowFunctionKey
+ { 0xF701, QT_MAC_MAP_ENUM(Qt::Key_Down) }, //NSDownArrowFunctionKey
+ { 0xF702, QT_MAC_MAP_ENUM(Qt::Key_Left) }, //NSLeftArrowFunctionKey
+ { 0xF703, QT_MAC_MAP_ENUM(Qt::Key_Right) }, //NSRightArrowFunctionKey
+ { 0xF727, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertFunctionKey
+ { 0xF728, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteFunctionKey
+ { 0xF729, QT_MAC_MAP_ENUM(Qt::Key_Home) }, //NSHomeFunctionKey
+ { 0xF72B, QT_MAC_MAP_ENUM(Qt::Key_End) }, //NSEndFunctionKey
+ { 0xF72C, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, //NSPageUpFunctionKey
+ { 0xF72D, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, //NSPageDownFunctionKey
+ { 0xF72F, QT_MAC_MAP_ENUM(Qt::Key_ScrollLock) }, //NSScrollLockFunctionKey
+ { 0xF730, QT_MAC_MAP_ENUM(Qt::Key_Pause) }, //NSPauseFunctionKey
+ { 0xF731, QT_MAC_MAP_ENUM(Qt::Key_SysReq) }, //NSSysReqFunctionKey
+ { 0xF735, QT_MAC_MAP_ENUM(Qt::Key_Menu) }, //NSMenuFunctionKey
+ { 0xF738, QT_MAC_MAP_ENUM(Qt::Key_Print) }, //NSPrintFunctionKey
+ { 0xF73A, QT_MAC_MAP_ENUM(Qt::Key_Clear) }, //NSClearDisplayFunctionKey
+ { 0xF73D, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertCharFunctionKey
+ { 0xF73E, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteCharFunctionKey
+ { 0xF741, QT_MAC_MAP_ENUM(Qt::Key_Select) }, //NSSelectFunctionKey
+ { 0xF742, QT_MAC_MAP_ENUM(Qt::Key_Execute) }, //NSExecuteFunctionKey
+ { 0xF746, QT_MAC_MAP_ENUM(Qt::Key_Help) }, //NSHelpFunctionKey
+ { 0xF747, QT_MAC_MAP_ENUM(Qt::Key_Mode_switch) }, //NSModeSwitchFunctionKey
+ { 0, QT_MAC_MAP_ENUM(0) }
+};
+
static int qt_mac_get_key(int modif, const QChar &key, int virtualKey)
{
#ifdef DEBUG_KEY_BINDINGS
@@ -379,6 +405,19 @@ static int qt_mac_get_key(int modif, const QChar &key, int virtualKey)
}
}
+ // check if they belong to key codes in private unicode range
+ if (key >= 0xf700 && key <= 0xf747) {
+ if (key >= 0xf704 && key <= 0xf726) {
+ return Qt::Key_F1 + (key.unicode() - 0xf704) ;
+ }
+ for (int i = 0; qt_mac_private_unicode[i].qt_code; i++) {
+ if (qt_mac_private_unicode[i].mac_code == key) {
+ return qt_mac_private_unicode[i].qt_code;
+ }
+ }
+
+ }
+
//oh well
#ifdef DEBUG_KEY_BINDINGS
qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey);
@@ -717,14 +756,23 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e
return true;
}
- if (qApp->inputContext() && qApp->inputContext()->isComposing()) {
+ QInputContext *currentContext = qApp->inputContext();
+ if (currentContext && currentContext->isComposing()) {
if (ekind == kEventRawKeyDown) {
- QMacInputContext *context = qobject_cast<QMacInputContext*>(qApp->inputContext());
+ QMacInputContext *context = qobject_cast<QMacInputContext*>(currentContext);
if (context)
context->setLastKeydownEvent(event);
}
return false;
}
+ // Once we process the key down , we dont need to send the saved event again from
+ // kEventTextInputUnicodeForKeyEvent, so clear it.
+ if (currentContext && ekind == kEventRawKeyDown) {
+ QMacInputContext *context = qobject_cast<QMacInputContext*>(currentContext);
+ if (context)
+ context->setLastKeydownEvent(0);
+ }
+
//get modifiers
Qt::KeyboardModifiers modifiers;
int qtKey;
@@ -847,7 +895,11 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e
}
void
-QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *)
+QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *
+#if defined(QT_MAC_USE_COCOA)
+ unicodeKey // unicode character from NSEvent (modifiers applied)
+#endif
+ )
{
UInt32 macVirtualKey = 0;
GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey);
@@ -875,6 +927,15 @@ QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *)
qtkey = unicode.unicode();
keyLayout[macVirtualKey]->qtKey[i] = qtkey;
}
+#ifndef Q_WS_MAC32
+ else {
+ const QChar unicode(*((UniChar *)unicodeKey));
+ int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey);
+ if (qtkey == Qt::Key_unknown)
+ qtkey = unicode.unicode();
+ keyLayout[macVirtualKey]->qtKey[i] = qtkey;
+ }
+#endif
#ifdef Q_WS_MAC32
} else {
const UInt32 keyModifier = (qt_mac_get_mac_modifiers(ModsTbl[i]));
diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h
index 3e42d6e4bf..38f141ee92 100644
--- a/src/gui/kernel/qkeymapper_p.h
+++ b/src/gui/kernel/qkeymapper_p.h
@@ -183,7 +183,7 @@ public:
const XEvent *,
bool grab);
- bool useXKB;
+ int xkb_currentGroup;
QXCoreDesc coreDesc;
#elif defined(Q_WS_MAC)
diff --git a/src/gui/kernel/qkeymapper_s60.cpp b/src/gui/kernel/qkeymapper_s60.cpp
index fd263ef2c3..d019c0f1da 100644
--- a/src/gui/kernel/qkeymapper_s60.cpp
+++ b/src/gui/kernel/qkeymapper_s60.cpp
@@ -144,7 +144,7 @@ static const KeyMapping keyMapping[] = {
{EKeyDevice0, EStdKeyDevice0, Key_Context1}, // Found by manual testing.
{EKeyDevice1, EStdKeyDevice1, Key_Context2}, // Found by manual testing.
{EKeyDevice3, EStdKeyDevice3, Key_Select},
-// {EKeyDevice7, EStdKeyDevice7, Key_Camera}, //not supported by qt yet
+ {EKeyDevice7, EStdKeyDevice7, Key_Camera},
{EKeyApplication0, EStdKeyApplication0, Key_Menu}, // Found by manual testing.
{EKeyApplication1, EStdKeyApplication1, Key_Launch1}, // Found by manual testing.
{EKeyApplication2, EStdKeyApplication2, Key_MediaPlay}, // Found by manual testing.
@@ -161,7 +161,7 @@ static const KeyMapping keyMapping[] = {
{EKeyApplicationD, EStdKeyApplicationD, Key_LaunchD},
{EKeyApplicationE, EStdKeyApplicationE, Key_LaunchE},
{EKeyApplicationF, EStdKeyApplicationF, Key_LaunchF},
-// {EKeyApplication19, EStdKeyApplication19, Key_CameraFocus}, //not supported by qt yet
+ {EKeyApplication19, EStdKeyApplication19, Key_CameraFocus},
{EKeyYes, EStdKeyYes, Key_Yes},
{EKeyNo, EStdKeyNo, Key_No},
{TKeyCode(0), TStdScanCode(0), Qt::Key(0)}
diff --git a/src/gui/kernel/qkeymapper_win.cpp b/src/gui/kernel/qkeymapper_win.cpp
index 578f32a0ad..f84b902498 100644
--- a/src/gui/kernel/qkeymapper_win.cpp
+++ b/src/gui/kernel/qkeymapper_win.cpp
@@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE
//#define DEBUG_KEYMAPPER
// Implemented elsewhere
-extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
extern Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id);
#ifndef LANG_PASHTO
@@ -619,7 +619,7 @@ void QKeyMapperPrivate::clearMappings()
/* MAKELCID()'s first argument is a WORD, and GetKeyboardLayout()
* returns a DWORD. */
- LCID newLCID = MAKELCID((DWORD)GetKeyboardLayout(0), SORT_DEFAULT);
+ LCID newLCID = MAKELCID((quintptr)GetKeyboardLayout(0), SORT_DEFAULT);
// keyboardInputLocale = qt_localeFromLCID(newLCID);
bool bidi = false;
diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp
index b32b62672d..807959cf6d 100644
--- a/src/gui/kernel/qkeymapper_x11.cpp
+++ b/src/gui/kernel/qkeymapper_x11.cpp
@@ -80,7 +80,7 @@ QT_BEGIN_NAMESPACE
(((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF))
#endif
-static void getLocaleAndDirection(QLocale *locale,
+void q_getLocaleAndDirection(QLocale *locale,
Qt::LayoutDirection *direction,
const QByteArray &layoutName,
const QByteArray &variantName)
@@ -248,22 +248,17 @@ qt_XTranslateKey(register QXCoreDesc *dpy,
QKeyMapperPrivate::QKeyMapperPrivate()
- : keyboardInputDirection(Qt::LeftToRight), useXKB(false)
+ : keyboardInputDirection(Qt::LeftToRight), xkb_currentGroup(0)
{
memset(&coreDesc, 0, sizeof(coreDesc));
#ifndef QT_NO_XKB
- int opcode = -1;
- int xkbEventBase = -1;
- int xkbErrorBase = -1;
- int xkblibMajor = XkbMajorVersion;
- int xkblibMinor = XkbMinorVersion;
- if (XkbQueryExtension(X11->display, &opcode, &xkbEventBase, &xkbErrorBase, &xkblibMajor, &xkblibMinor))
- useXKB = true;
-#endif
-
-#if 0
- qDebug() << "useXKB =" << useXKB;
+ if (X11->use_xkb) {
+ // get the current group
+ XkbStateRec xkbState;
+ if (XkbGetState(X11->display, XkbUseCoreKbd, &xkbState) == Success)
+ xkb_currentGroup = xkbState.group;
+ }
#endif
}
@@ -276,7 +271,7 @@ QKeyMapperPrivate::~QKeyMapperPrivate()
QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *event)
{
#ifndef QT_NO_XKB
- if (useXKB)
+ if (X11->use_xkb)
return possibleKeysXKB(event);
#endif
return possibleKeysCore(event);
@@ -486,7 +481,7 @@ enum {
void QKeyMapperPrivate::clearMappings()
{
#ifndef QT_NO_XKB
- if (useXKB) {
+ if (X11->use_xkb) {
// try to determine the layout name and input direction by reading the _XKB_RULES_NAMES property off
// the root window
QByteArray layoutName;
@@ -515,15 +510,20 @@ void QKeyMapperPrivate::clearMappings()
p += qstrlen(p) + 1;
} while (p < end);
- layoutName = QByteArray::fromRawData(names[2], qstrlen(names[2]));
- variantName = QByteArray::fromRawData(names[3], qstrlen(names[3]));
+ // the layout names and variants are saved in the _XKB_RULES_NAMES property as a comma separated list
+ QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(',');
+ if (uint(xkb_currentGroup) < uint(layoutNames.count()))
+ layoutName = layoutNames.at(xkb_currentGroup);
+ QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(',');
+ if (uint(xkb_currentGroup) < uint(variantNames.count()))
+ variantName = variantNames.at(xkb_currentGroup);
}
// ### ???
// if (keyboardLayoutName.isEmpty())
// qWarning("Qt: unable to determine keyboard layout, please talk to qt-bugs@trolltech.com"); ?
- getLocaleAndDirection(&keyboardInputLocale,
+ q_getLocaleAndDirection(&keyboardInputLocale,
&keyboardInputDirection,
layoutName,
variantName);
@@ -534,7 +534,6 @@ void QKeyMapperPrivate::clearMappings()
<< "direction ="
<< keyboardInputDirection;
#endif
-
if (data)
XFree(data);
} else
@@ -574,7 +573,7 @@ void QKeyMapperPrivate::clearMappings()
// look at the modifier mapping, and get the correct masks for alt, meta, super, hyper, and mode_switch
#ifndef QT_NO_XKB
- if (useXKB) {
+ if (X11->use_xkb) {
XkbDescPtr xkbDesc = XkbGetMap(X11->display, XkbAllClientInfoMask, XkbUseCoreKbd);
for (int i = xkbDesc->min_key_code; i < xkbDesc->max_key_code; ++i) {
const uint mask = xkbDesc->map->modmap ? xkbDesc->map->modmap[i] : 0;
@@ -1186,6 +1185,8 @@ static const unsigned int KeyTbl[] = {
XF86XK_LaunchB, Qt::Key_LaunchD,
XF86XK_LaunchC, Qt::Key_LaunchE,
XF86XK_LaunchD, Qt::Key_LaunchF,
+ XF86XK_LaunchE, Qt::Key_LaunchG,
+ XF86XK_LaunchF, Qt::Key_LaunchH,
// Qtopia keys
QTOPIAXK_Select, Qt::Key_Select,
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 2a13546061..931bc33747 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -390,6 +390,9 @@ static const struct {
int key;
const char* name;
} keyname[] = {
+ //: This and all following "incomprehensible" strings in QShortcut context
+ //: are key names. Please use the localized names appearing on actual
+ //: keyboards or whatever is commonly used.
{ Qt::Key_Space, QT_TRANSLATE_NOOP("QShortcut", "Space") },
{ Qt::Key_Escape, QT_TRANSLATE_NOOP("QShortcut", "Esc") },
{ Qt::Key_Tab, QT_TRANSLATE_NOOP("QShortcut", "Tab") },
@@ -580,6 +583,41 @@ static const struct {
{ Qt::Key_Hangup, QT_TRANSLATE_NOOP("QShortcut", "Hangup") },
{ Qt::Key_Flip, QT_TRANSLATE_NOOP("QShortcut", "Flip") },
+ // --------------------------------------------------------------
+ // Japanese keyboard support
+ { Qt::Key_Kanji, QT_TRANSLATE_NOOP("QShortcut", "Kanji") },
+ { Qt::Key_Muhenkan, QT_TRANSLATE_NOOP("QShortcut", "Muhenkan") },
+ { Qt::Key_Henkan, QT_TRANSLATE_NOOP("QShortcut", "Henkan") },
+ { Qt::Key_Romaji, QT_TRANSLATE_NOOP("QShortcut", "Romaji") },
+ { Qt::Key_Hiragana, QT_TRANSLATE_NOOP("QShortcut", "Hiragana") },
+ { Qt::Key_Katakana, QT_TRANSLATE_NOOP("QShortcut", "Katakana") },
+ { Qt::Key_Hiragana_Katakana,QT_TRANSLATE_NOOP("QShortcut", "Hiragana Katakana") },
+ { Qt::Key_Zenkaku, QT_TRANSLATE_NOOP("QShortcut", "Zenkaku") },
+ { Qt::Key_Hankaku, QT_TRANSLATE_NOOP("QShortcut", "Hankaku") },
+ { Qt::Key_Zenkaku_Hankaku, QT_TRANSLATE_NOOP("QShortcut", "Zenkaku Hankaku") },
+ { Qt::Key_Touroku, QT_TRANSLATE_NOOP("QShortcut", "Touroku") },
+ { Qt::Key_Massyo, QT_TRANSLATE_NOOP("QShortcut", "Massyo") },
+ { Qt::Key_Kana_Lock, QT_TRANSLATE_NOOP("QShortcut", "Kana Lock") },
+ { Qt::Key_Kana_Shift, QT_TRANSLATE_NOOP("QShortcut", "Kana Shift") },
+ { Qt::Key_Eisu_Shift, QT_TRANSLATE_NOOP("QShortcut", "Eisu Shift") },
+ { Qt::Key_Eisu_toggle, QT_TRANSLATE_NOOP("QShortcut", "Eisu toggle") },
+ { Qt::Key_Codeinput, QT_TRANSLATE_NOOP("QShortcut", "Code input") },
+ { Qt::Key_MultipleCandidate,QT_TRANSLATE_NOOP("QShortcut", "Multiple Candidate") },
+ { Qt::Key_PreviousCandidate,QT_TRANSLATE_NOOP("QShortcut", "Previous Candidate") },
+
+ // --------------------------------------------------------------
+ // Korean keyboard support
+ { Qt::Key_Hangul, QT_TRANSLATE_NOOP("QShortcut", "Hangul") },
+ { Qt::Key_Hangul_Start, QT_TRANSLATE_NOOP("QShortcut", "Hangul Start") },
+ { Qt::Key_Hangul_End, QT_TRANSLATE_NOOP("QShortcut", "Hangul End") },
+ { Qt::Key_Hangul_Hanja, QT_TRANSLATE_NOOP("QShortcut", "Hangul Hanja") },
+ { Qt::Key_Hangul_Jamo, QT_TRANSLATE_NOOP("QShortcut", "Hangul Jamo") },
+ { Qt::Key_Hangul_Romaja, QT_TRANSLATE_NOOP("QShortcut", "Hangul Romaja") },
+ { Qt::Key_Hangul_Jeonja, QT_TRANSLATE_NOOP("QShortcut", "Hangul Jeonja") },
+ { Qt::Key_Hangul_Banja, QT_TRANSLATE_NOOP("QShortcut", "Hangul Banja") },
+ { Qt::Key_Hangul_PreHanja, QT_TRANSLATE_NOOP("QShortcut", "Hangul PreHanja") },
+ { Qt::Key_Hangul_PostHanja,QT_TRANSLATE_NOOP("QShortcut", "Hangul PostHanja") },
+ { Qt::Key_Hangul_Special, QT_TRANSLATE_NOOP("QShortcut", "Hangul Special") },
{ 0, 0 }
};
@@ -696,6 +734,7 @@ 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::Paste, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Insert, 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},
@@ -861,6 +900,8 @@ QKeySequence::QKeySequence()
Up to four key codes may be entered by separating them with
commas, e.g. "Alt+X,Ctrl+S,Q".
+ \a key should be in NativeText format.
+
This constructor is typically used with \link QObject::tr() tr
\endlink(), so that shortcut keys can be replaced in
translations:
@@ -877,6 +918,16 @@ QKeySequence::QKeySequence(const QString &key)
}
/*!
+ \since 4.x
+ Creates a key sequence from the \a key string based on \a format.
+*/
+QKeySequence::QKeySequence(const QString &key, QKeySequence::SequenceFormat format)
+{
+ d = new QKeySequencePrivate();
+ assign(key, format);
+}
+
+/*!
Constructs a key sequence with up to 4 keys \a k1, \a k2,
\a k3 and \a k4.
@@ -1055,9 +1106,24 @@ QKeySequence QKeySequence::mnemonic(const QString &text)
contain up to four key codes, provided they are separated by a
comma; for example, "Alt+X,Ctrl+S,Z". The return value is the
number of key codes added.
+ \a keys should be in NativeText format.
*/
int QKeySequence::assign(const QString &ks)
{
+ return assign(ks, NativeText);
+}
+
+/*!
+ \fn int QKeySequence::assign(const QString &keys, QKeySequence::SequenceFormat format)
+ \since 4.x
+
+ Adds the given \a keys to the key sequence (based on \a format).
+ \a keys may contain up to four key codes, provided they are
+ separated by a comma; for example, "Alt+X,Ctrl+S,Z". The return
+ value is the number of key codes added.
+*/
+int QKeySequence::assign(const QString &ks, QKeySequence::SequenceFormat format)
+{
QString keyseq = ks;
QString part;
int n = 0;
@@ -1086,7 +1152,7 @@ int QKeySequence::assign(const QString &ks)
}
part = keyseq.left(-1 == p ? keyseq.length() : p - diff);
keyseq = keyseq.right(-1 == p ? 0 : keyseq.length() - (p + 1));
- d->key[n] = decodeString(part);
+ d->key[n] = QKeySequencePrivate::decodeString(part, format);
++n;
}
return n;
@@ -1557,12 +1623,7 @@ QString QKeySequence::toString(SequenceFormat format) const
*/
QKeySequence QKeySequence::fromString(const QString &str, SequenceFormat format)
{
- QStringList sl = str.split(QLatin1String(", "));
- int keys[4] = {0, 0, 0, 0};
- int total = qMin(sl.count(), 4);
- for (int i = 0; i < total; ++i)
- keys[i] = QKeySequencePrivate::decodeString(sl[i], format);
- return QKeySequence(keys[0], keys[1], keys[2], keys[3]);
+ return QKeySequence(str, format);
}
/*****************************************************************************
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index 1409e28f3b..5a973e398c 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -141,8 +141,14 @@ public:
Quit
};
+ enum SequenceFormat {
+ NativeText,
+ PortableText
+ };
+
QKeySequence();
QKeySequence(const QString &key);
+ QKeySequence(const QString &key, SequenceFormat format);
QKeySequence(int k1, int k2 = 0, int k3 = 0, int k4 = 0);
QKeySequence(const QKeySequence &ks);
QKeySequence(StandardKey key);
@@ -160,11 +166,6 @@ public:
#endif
};
- enum SequenceFormat {
- NativeText,
- PortableText
- };
-
QString toString(SequenceFormat format = PortableText) const;
static QKeySequence fromString(const QString &str, SequenceFormat format = PortableText);
@@ -194,6 +195,7 @@ private:
static int decodeString(const QString &ks);
static QString encodeString(int key);
int assign(const QString &str);
+ int assign(const QString &str, SequenceFormat format);
void setKey(int key, int index);
QKeySequencePrivate *d;
diff --git a/src/gui/kernel/qmime_mac.cpp b/src/gui/kernel/qmime_mac.cpp
index 071f80df1f..c6fd184447 100644
--- a/src/gui/kernel/qmime_mac.cpp
+++ b/src/gui/kernel/qmime_mac.cpp
@@ -154,6 +154,7 @@ CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker");
\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 public.vcard - converts to "text/plain"
\i com.apple.traditional-mac-plain-text - converts to "text/plain"
\i com.apple.pict - converts to "application/x-qt-image"
\endlist
@@ -909,6 +910,61 @@ QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QV
return ret;
}
+class QMacPasteboardMimeVCard : public QMacPasteboardMime
+{
+public:
+ QMacPasteboardMimeVCard() : 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 QMacPasteboardMimeVCard::convertorName()
+{
+ return QString("VCard");
+}
+
+bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav)
+{
+ return mimeFor(flav) == mime;
+}
+
+QString QMacPasteboardMimeVCard::flavorFor(const QString &mime)
+{
+ if(mime.startsWith(QLatin1String("text/plain")))
+ return QLatin1String("public.vcard");
+ return QString();
+}
+
+QString QMacPasteboardMimeVCard::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.vcard"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList<QByteArray> data, QString)
+{
+ QByteArray cards;
+ if (mime == QLatin1String("text/plain")) {
+ for (int i=0; i<data.size(); ++i)
+ cards += data[i];
+ }
+ return QVariant(cards);
+}
+
+QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString)
+{
+ QList<QByteArray> ret;
+ if (mime == QLatin1String("text/plain"))
+ ret.append(data.toString().toUtf8());
+ return ret;
+}
+
#ifdef QT3_SUPPORT
class QMacPasteboardMimeQt3Any : public QMacPasteboardMime {
private:
@@ -1116,6 +1172,7 @@ void QMacPasteboardMime::initialize()
new QMacPasteboardMimeFileUri;
new QMacPasteboardMimeUrl;
new QMacPasteboardMimeTypeName;
+ new QMacPasteboardMimeVCard;
//make sure our "non-standard" types are always last! --Sam
new QMacPasteboardMimeAny;
#ifdef QT3_SUPPORT
diff --git a/src/gui/kernel/qmime_win.cpp b/src/gui/kernel/qmime_win.cpp
index 39633bf7c0..2840843c07 100644
--- a/src/gui/kernel/qmime_win.cpp
+++ b/src/gui/kernel/qmime_win.cpp
@@ -952,6 +952,8 @@ bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeD
QDataStream s(&ba, QIODevice::WriteOnly);
s.setByteOrder(QDataStream::LittleEndian);// Intel byte order ####
if (cf == CF_DIB) {
+ if (img.format() > QImage::Format_ARGB32)
+ img = img.convertToFormat(QImage::Format_RGB32);
if (qt_write_dib(s, img))
return setData(ba, pmedium);
} else {
diff --git a/src/gui/kernel/qnsthemeframe_mac_p.h b/src/gui/kernel/qnsthemeframe_mac_p.h
index 77a6963f10..d061b1bfbe 100644
--- a/src/gui/kernel/qnsthemeframe_mac_p.h
+++ b/src/gui/kernel/qnsthemeframe_mac_p.h
@@ -157,7 +157,7 @@
- (void)resetCursorRects;
- (char)shouldBeTreatedAsInkEvent:fp8;
- (char)_shouldBeTreatedAsInkEventInInactiveWindow:fp8;
-- hitTest:(struct _NSPoint)fp8;
+//- hitTest:(struct _NSPoint)fp8; // collides with hittest in qcocoasharedwindowmethods_mac_p.h
- (NSRect)_leftGroupRect;
- (NSRect)_rightGroupRect;
- (void)_updateWidgets;
diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp
index 23f14814e2..04e4685825 100644
--- a/src/gui/kernel/qsoftkeymanager.cpp
+++ b/src/gui/kernel/qsoftkeymanager.cpp
@@ -43,7 +43,7 @@
#include "qevent.h"
#include "qbitmap.h"
#include "private/qsoftkeymanager_p.h"
-#include "private/qobject_p.h"
+#include "private/qaction_p.h"
#include "private/qsoftkeymanager_common_p.h"
#ifdef Q_WS_S60
@@ -104,7 +104,7 @@ QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *act
QAction::SoftKeyRole softKeyRole = QAction::NoSoftKey;
switch (standardKey) {
case MenuSoftKey: // FALL-THROUGH
- action->setProperty(MENU_ACTION_PROPERTY, QVariant(true)); // TODO: can be refactored away to use _q_action_menubar
+ QActionPrivate::get(action)->menuActionSoftkeys = true;
case OkSoftKey:
case SelectSoftKey:
case DoneSoftKey:
@@ -255,16 +255,12 @@ bool QSoftKeyManager::handleUpdateSoftKeys()
void QSoftKeyManager::setForceEnabledInSoftkeys(QAction *action)
{
- action->setProperty(FORCE_ENABLED_PROPERTY, QVariant(true));
+ QActionPrivate::get(action)->forceEnabledInSoftkeys = true;
}
bool QSoftKeyManager::isForceEnabledInSofkeys(QAction *action)
{
- bool ret = false;
- QVariant property = action->property(FORCE_ENABLED_PROPERTY);
- if (property.isValid() && property.toBool())
- ret = true;
- return ret;
+ return QActionPrivate::get(action)->forceEnabledInSoftkeys;
}
bool QSoftKeyManager::event(QEvent *e)
diff --git a/src/gui/kernel/qsoftkeymanager_p.h b/src/gui/kernel/qsoftkeymanager_p.h
index a5b258b255..6eedfa8825 100644
--- a/src/gui/kernel/qsoftkeymanager_p.h
+++ b/src/gui/kernel/qsoftkeymanager_p.h
@@ -63,9 +63,6 @@ QT_BEGIN_NAMESPACE
class QSoftKeyManagerPrivate;
-const char MENU_ACTION_PROPERTY[] = "_q_menuAction";
-const char FORCE_ENABLED_PROPERTY[] = "_q_forceEnabledInSoftkeys";
-
class Q_AUTOTEST_EXPORT QSoftKeyManager : public QObject
{
Q_OBJECT
diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp
index f656e883ff..6325d9502c 100644
--- a/src/gui/kernel/qsoftkeymanager_s60.cpp
+++ b/src/gui/kernel/qsoftkeymanager_s60.cpp
@@ -46,6 +46,7 @@
#include "qmenubar.h"
#include "private/qt_s60_p.h"
#include "private/qmenu_p.h"
+#include "private/qaction_p.h"
#include "private/qsoftkeymanager_p.h"
#include "private/qsoftkeymanager_s60_p.h"
#include "private/qobject_p.h"
@@ -384,8 +385,8 @@ bool QSoftKeyManagerPrivateS60::handleCommand(int command)
{
QAction *action = realSoftKeyActions.value(command);
if (action) {
- QVariant property = action->property(MENU_ACTION_PROPERTY);
- if (property.isValid() && property.toBool()) {
+ bool property = QActionPrivate::get(action)->menuActionSoftkeys;
+ if (property) {
QT_TRAP_THROWING(tryDisplayMenuBarL());
} else if (action->menu()) {
// TODO: This is hack, in order to use exising QMenuBar implementation for Symbian
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp
index 86bf1b2eb6..a575717471 100644
--- a/src/gui/kernel/qstandardgestures.cpp
+++ b/src/gui/kernel/qstandardgestures.cpp
@@ -301,7 +301,7 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
switch (event->type()) {
case QEvent::TouchBegin: {
d->speed = 1;
- d->time = QTime::currentTime();
+ d->time.start();
d->started = true;
result = QGestureRecognizer::MayBeGesture;
break;
@@ -338,11 +338,10 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
p3.screenPos().y() - d->lastPositions[2].y()) / 3;
const int distance = xDistance >= yDistance ? xDistance : yDistance;
- int elapsedTime = d->time.msecsTo(QTime::currentTime());
+ int elapsedTime = d->time.restart();
if (!elapsedTime)
elapsedTime = 1;
d->speed = 0.9 * d->speed + distance / elapsedTime;
- d->time = QTime::currentTime();
d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle();
static const int MoveThreshold = 50;
@@ -405,7 +404,7 @@ void QSwipeGestureRecognizer::reset(QGesture *state)
d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint();
d->started = false;
d->speed = 0;
- d->time = QTime();
+ d->time.invalidate();
QGestureRecognizer::reset(state);
}
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index ce1e3c58fc..8cef03c4c8 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -83,6 +83,7 @@
#include <private/qt_cocoa_helpers_mac_p.h>
#include <private/qt_mac_p.h>
#include <private/qapplication_p.h>
+#include <private/qcocoaapplication_mac_p.h>
#include <private/qcocoawindow_mac_p.h>
#include <private/qcocoaview_mac_p.h>
#include <private/qkeymapper_p.h>
@@ -137,9 +138,8 @@ void QMacWindowFader::performFade()
}
extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp;
-extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
extern QWidget * mac_mouse_grabber;
-extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+extern QWidget *qt_button_down; //qapplication_mac.cpp
void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds)
{
@@ -369,6 +369,16 @@ QMacTabletHash *qt_mac_tablet_hash()
}
#ifdef QT_MAC_USE_COCOA
+
+// Clears the QWidget pointer that each QCocoaView holds.
+void qt_mac_clearCocoaViewQWidgetPointers(QWidget *widget)
+{
+ QT_MANGLE_NAMESPACE(QCocoaView) *cocoaView = reinterpret_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(qt_mac_nativeview_for(widget));
+ if (cocoaView && [cocoaView respondsToSelector:@selector(qt_qwidget)]) {
+ [cocoaView qt_clearQWidget];
+ }
+}
+
void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent)
{
NSEvent *proximityEvent = static_cast<NSEvent *>(tabletEvent);
@@ -642,11 +652,25 @@ bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widge
UInt32 macScanCode = 1;
QKeyEventEx ke(cocoaEvent2QtEvent([event type]), qtKey, keyMods, text, [event isARepeat], qMax(1, keyLength),
macScanCode, [event keyCode], [event modifierFlags]);
- qt_sendSpontaneousEvent(widgetToGetEvent, &ke);
- return ke.isAccepted();
+ return qt_sendSpontaneousEvent(widgetToGetEvent, &ke) && ke.isAccepted();
}
#endif
+Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
+{
+ if (buttonNum == 0)
+ return Qt::LeftButton;
+ if (buttonNum == 1)
+ return Qt::RightButton;
+ if (buttonNum == 2)
+ return Qt::MidButton;
+ if (buttonNum == 3)
+ return Qt::XButton1;
+ if (buttonNum == 4)
+ return Qt::XButton2;
+ return Qt::NoButton;
+}
+
// Helper to share code between QCocoaWindow and QCocoaView
bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent)
{
@@ -659,8 +683,16 @@ bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEve
EventRef key_event = static_cast<EventRef>(const_cast<void *>([event eventRef]));
Q_ASSERT(key_event);
if ([event type] == NSKeyDown) {
- qt_keymapper_private()->updateKeyMap(0, key_event, 0);
+ NSString *characters = [event characters];
+ unichar value = [characters characterAtIndex:0];
+ qt_keymapper_private()->updateKeyMap(0, key_event, (void *)&value);
}
+
+ // Redirect keys to alien widgets.
+ if (widgetToGetEvent->testAttribute(Qt::WA_NativeWindow) == false) {
+ widgetToGetEvent = qApp->focusWidget();
+ }
+
if (widgetToGetEvent == 0)
return false;
@@ -670,8 +702,8 @@ bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEve
if (mustUseCocoaKeyEvent())
return qt_dispatchKeyEventWithCocoa(keyEvent, widgetToGetEvent);
bool isAccepted;
- qt_keymapper_private()->translateKeyEvent(widgetToGetEvent, 0, key_event, &isAccepted, true);
- return isAccepted;
+ bool consumed = qt_keymapper_private()->translateKeyEvent(widgetToGetEvent, 0, key_event, &isAccepted, true);
+ return consumed && isAccepted;
#endif
}
@@ -850,7 +882,15 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /*
}
}
- QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, button, keyMods);
+ Qt::MouseButtons buttons = 0;
+ {
+ UInt32 mac_buttons;
+ if (GetEventParameter((EventRef)[event eventRef], kEventParamMouseChord, typeUInt32, 0,
+ sizeof(mac_buttons), 0, &mac_buttons) == noErr)
+ buttons = qt_mac_get_buttons(mac_buttons);
+ }
+
+ QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, buttons, keyMods);
qt_sendSpontaneousEvent(widgetToGetEvent, &qme);
// We don't need to set the implicit grab widget here because we won't
@@ -915,7 +955,7 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev
[static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(tmpView) qt_qwidget];
}
} else {
- extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+ extern QWidget * qt_button_down; //qapplication_mac.cpp
QPoint pos;
widgetToGetMouse = QApplicationPrivate::pickMouseReceiver(qwidget, qglobalPoint,
pos, eventType,
@@ -927,7 +967,20 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev
return false;
NSPoint localPoint = [tmpView convertPoint:windowPoint fromView:nil];
- QPoint qlocalPoint(localPoint.x, localPoint.y);
+ QPoint qlocalPoint = QPoint(localPoint.x, localPoint.y);
+
+ // Search for alien child widgets (either on this qwidget or on the popup)
+ if (widgetToGetMouse->testAttribute(Qt::WA_NativeWindow) == false || qt_widget_private(widgetToGetMouse)->hasAlienChildren) {
+ QPoint qScreenPoint = flipPoint(globalPoint).toPoint();
+#ifdef ALIEN_DEBUG
+ qDebug() << "alien mouse event" << qScreenPoint << possibleAlien;
+#endif
+ QWidget *possibleAlien = widgetToGetMouse->childAt(qlocalPoint);
+ if (possibleAlien) {
+ qlocalPoint = possibleAlien->mapFromGlobal(widgetToGetMouse->mapToGlobal(qlocalPoint));
+ widgetToGetMouse = possibleAlien;
+ }
+ }
EventRef carbonEvent = static_cast<EventRef>(const_cast<void *>([theEvent eventRef]));
if (qt_mac_sendMacEventToWidget(widgetToGetMouse, carbonEvent))
@@ -955,7 +1008,7 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev
#ifndef QT_NAMESPACE
Q_ASSERT(clickCount > 0);
#endif
- if (clickCount % 2 == 0)
+ if (clickCount % 2 == 0 && buttons == button)
eventType = QEvent::MouseButtonDblClick;
if (button == Qt::LeftButton && (keyMods & Qt::MetaModifier)) {
button = Qt::RightButton;
@@ -967,11 +1020,24 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev
button = Qt::RightButton;
[theView qt_setLeftButtonIsRightButton: false];
}
+ qt_button_down = 0;
break;
}
[QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->localPoint = localPoint;
QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, buttons, keyMods);
- qt_sendSpontaneousEvent(widgetToGetMouse, &qme);
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "sending mouse event to" << widgetToGetMouse;
+#endif
+ extern QWidget *qt_button_down;
+ extern QPointer<QWidget> qt_last_mouse_receiver;
+
+ if (qwidget->testAttribute(Qt::WA_NativeWindow) && qt_widget_private(qwidget)->hasAlienChildren == false)
+ qt_sendSpontaneousEvent(widgetToGetMouse, &qme);
+ else
+ QApplicationPrivate::sendMouseEvent(widgetToGetMouse, &qme, widgetToGetMouse, qwidget, &qt_button_down,
+ qt_last_mouse_receiver);
+
if (eventType == QEvent::MouseButtonPress && button == Qt::RightButton) {
QContextMenuEvent qcme(QContextMenuEvent::Mouse, qlocalPoint, qglobalPoint, keyMods);
qt_sendSpontaneousEvent(widgetToGetMouse, &qcme);
@@ -1097,15 +1163,81 @@ void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::H
#endif
}
+#if QT_MAC_USE_COCOA
+void qt_mac_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widget)
+{
+ QMacCocoaAutoReleasePool pool;
+ OSWindowRef theWindow = static_cast<OSWindowRef>(window);
+ if(!theWindow)
+ return;
+ id theClass = [[[theWindow contentView] superview] class];
+ // What we do here is basically to add a new selector to NSThemeFrame called
+ // "drawRectOriginal:" which will contain the original implementation of
+ // "drawRect:". After that we get the new implementation from QCocoaWindow
+ // and exchange them. The new implementation is called drawRectSpecial.
+ // We cannot just add the method because it might have been added before and since
+ // we cannot remove a method once it has been added we need to ask QCocoaWindow if
+ // we did the swap or not.
+ if(!widget->drawRectOriginalAdded) {
+ Method m2 = class_getInstanceMethod(theClass, @selector(drawRect:));
+ if(!m2) {
+ // This case is pretty extreme, no drawRect means no drawing!
+ return;
+ }
+ class_addMethod(theClass, @selector(drawRectOriginal:), method_getImplementation(m2), method_getTypeEncoding(m2));
+ widget->drawRectOriginalAdded = true;
+ }
+ if(widget->originalDrawMethod) {
+ Method m0 = class_getInstanceMethod([theWindow class], @selector(drawRectSpecial:));
+ if(!m0) {
+ // Ok, this means the methods were never swapped. Just ignore
+ return;
+ }
+ Method m1 = class_getInstanceMethod(theClass, @selector(drawRect:));
+ if(!m1) {
+ // Ok, this means the methods were never swapped. Just ignore
+ return;
+ }
+ // We have the original method here. Proceed and swap the methods.
+ method_exchangeImplementations(m1, m0);
+ widget->originalDrawMethod = false;
+ [window display];
+ }
+}
+
+void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivate *widget)
+{
+ QMacCocoaAutoReleasePool pool;
+ OSWindowRef theWindow = static_cast<OSWindowRef>(window);
+ id theClass = [[[theWindow contentView] superview] class];
+ // Now we need to revert the methods to their original state.
+ // We cannot remove the method, so we just keep track of it in QCocoaWindow.
+ Method m0 = class_getInstanceMethod([theWindow class], @selector(drawRectSpecial:));
+ if(!m0) {
+ // Ok, this means the methods were never swapped. Just ignore
+ return;
+ }
+ Method m1 = class_getInstanceMethod(theClass, @selector(drawRect:));
+ if(!m1) {
+ // Ok, this means the methods were never swapped. Just ignore
+ return;
+ }
+ method_exchangeImplementations(m1, m0);
+ widget->originalDrawMethod = true;
+ [window display];
+}
+#endif // QT_MAC_USE_COCOA
+
void qt_mac_showBaseLineSeparator(void * /*OSWindowRef */window, bool show)
{
+ if(!window)
+ return;
#if QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
OSWindowRef theWindow = static_cast<OSWindowRef>(window);
NSToolbar *macToolbar = [theWindow toolbar];
- if (macToolbar)
- [macToolbar setShowsBaselineSeparator: show];
-#endif
+ [macToolbar setShowsBaselineSeparator:show];
+#endif // QT_MAC_USE_COCOA
}
QStringList qt_mac_NSArrayToQStringList(void *nsarray)
@@ -1290,6 +1422,41 @@ void qt_cocoaChangeOverrideCursor(const QCursor &cursor)
QMacCocoaAutoReleasePool pool;
[static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set];
}
+
+// WARNING: If Qt did not create NSApplication (e.g. in case it is
+// used as a plugin), and at the same time, there is no window on
+// screen (or the window that the event is sendt to becomes hidden etc
+// before the event gets delivered), the message will not be performed.
+bool qt_cocoaPostMessage(id target, SEL selector)
+{
+ if (!target)
+ return false;
+
+ NSInteger windowNumber = 0;
+ if (![NSApp isMemberOfClass:[QNSApplication class]]) {
+ // INVARIANT: Cocoa is not using our NSApplication subclass. That means
+ // we don't control the main event handler either. So target the event
+ // for one of the windows on screen:
+ NSWindow *nswin = [NSApp mainWindow];
+ if (!nswin) {
+ nswin = [NSApp keyWindow];
+ if (!nswin)
+ return false;
+ }
+ windowNumber = [nswin windowNumber];
+ }
+
+ // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5!
+ // That is why we need to split the address in two parts:
+ QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector);
+ quint32 lower = quintptr(args);
+ quint32 upper = quintptr(args) >> 32;
+ NSEvent *e = [NSEvent otherEventWithType:NSApplicationDefined
+ location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:windowNumber
+ context:nil subtype:QtCocoaEventSubTypePostMessage data1:lower data2:upper];
+ [NSApp postEvent:e atStart:NO];
+ return true;
+}
#endif
QMacCocoaAutoReleasePool::QMacCocoaAutoReleasePool()
@@ -1305,4 +1472,60 @@ QMacCocoaAutoReleasePool::~QMacCocoaAutoReleasePool()
[(NSAutoreleasePool*)pool release];
}
+void qt_mac_post_retranslateAppMenu()
+{
+#ifdef QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ qt_cocoaPostMessage([NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)], @selector(qtTranslateApplicationMenu));
+#endif
+}
+
+#ifdef QT_MAC_USE_COCOA
+// This method implements the magic for the drawRectSpecial method.
+// We draw a line at the upper edge of the content view in order to
+// override the title baseline.
+void macDrawRectOnTop(void * /*OSWindowRef */window)
+{
+ OSWindowRef theWindow = static_cast<OSWindowRef>(window);
+ NSView *contentView = [theWindow contentView];
+ if(!contentView)
+ return;
+ // Get coordinates of the content view
+ NSRect contentRect = [contentView frame];
+ // Draw a line on top of the already drawn line.
+ // We need to check if we are active or not to use the proper color.
+ if([window isKeyWindow] || [window isMainWindow]) {
+ [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set];
+ } else {
+ [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set];
+ }
+ NSPoint origin = NSMakePoint(0, contentRect.size.height);
+ NSPoint end = NSMakePoint(contentRect.size.width, contentRect.size.height);
+ [NSBezierPath strokeLineFromPoint:origin toPoint:end];
+}
+
+// This method will (or at least should) get called only once.
+// Its mission is to find out if we are active or not. If we are active
+// we assume that we were launched via finder, otherwise we assume
+// we were called from the command line. The distinction is important,
+// since in the first case we don't need to trigger a paintEvent, while
+// in the second case we do.
+void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window)
+{
+ OSWindowRef theWindow = static_cast<OSWindowRef>(window);
+ NSApplication *application = [NSApplication sharedApplication];
+ NSToolbar *toolbar = [window toolbar];
+ if([application isActive]) {
+ // Launched from finder
+ [toolbar setShowsBaselineSeparator:NO];
+ } else {
+ // Launched from commandline
+ [toolbar setVisible:false];
+ [toolbar setShowsBaselineSeparator:NO];
+ [toolbar setVisible:true];
+ [theWindow display];
+ }
+}
+#endif // QT_MAC_USE_COCOA
+
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 6f0c4ce1e3..5db121af23 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h
+++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
@@ -114,6 +114,12 @@ typedef struct CGPoint NSPoint;
#endif
QT_BEGIN_NAMESPACE
+
+enum {
+ QtCocoaEventSubTypeWakeup = SHRT_MAX,
+ QtCocoaEventSubTypePostMessage = SHRT_MAX-1
+};
+
Qt::MouseButtons qt_mac_get_buttons(int buttons);
Qt::MouseButton qt_mac_get_button(EventMouseButton button);
void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0.15);
@@ -125,6 +131,8 @@ 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_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widget);
+void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivate *widget);
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);
@@ -134,6 +142,9 @@ 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);
+// These methods exists only for supporting unified mode.
+void macDrawRectOnTop(void * /*OSWindowRef */ window);
+void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window);
#endif
void qt_mac_menu_collapseSeparators(void * /*NSMenu */ menu, bool collapse);
bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent);
@@ -181,6 +192,27 @@ inline QString qt_mac_NSStringToQString(const NSString *nsstr)
inline NSString *qt_mac_QStringToNSString(const QString &qstr)
{ return [reinterpret_cast<const NSString *>(QCFString::toCFStringRef(qstr)) autorelease]; }
+
+#ifdef QT_MAC_USE_COCOA
+class QCocoaPostMessageArgs {
+public:
+ id target;
+ SEL selector;
+ QCocoaPostMessageArgs(id target, SEL selector) : target(target), selector(selector)
+ {
+ [target retain];
+ }
+
+ ~QCocoaPostMessageArgs()
+ {
+ [target release];
+ }
+};
+bool qt_cocoaPostMessage(id target, SEL selector);
#endif
+#endif
+
+void qt_mac_post_retranslateAppMenu();
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h
index 7bfb257e8b..3341ce1688 100644
--- a/src/gui/kernel/qt_mac_p.h
+++ b/src/gui/kernel/qt_mac_p.h
@@ -57,6 +57,7 @@
#ifdef __OBJC__
#include <Cocoa/Cocoa.h>
+#include <objc/runtime.h>
#endif
#include <CoreServices/CoreServices.h>
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
index 14e04bbeee..73833823de 100644
--- a/src/gui/kernel/qt_x11_p.h
+++ b/src/gui/kernel/qt_x11_p.h
@@ -331,7 +331,7 @@ struct QXdndDropTransaction
class QMimeData;
struct QX11Data;
-extern QX11Data *qt_x11Data;
+extern Q_GUI_EXPORT QX11Data *qt_x11Data;
enum DesktopEnvironment {
DE_UNKNOWN,
@@ -439,6 +439,12 @@ struct QX11Data
int xinput_eventbase;
int xinput_errorbase;
+ // for XKEYBOARD support
+ bool use_xkb;
+ int xkb_major;
+ int xkb_eventbase;
+ int xkb_errorbase;
+
QList<QWidget *> deferred_map;
struct ScrollInProgress {
long id;
@@ -564,11 +570,8 @@ struct QX11Data
_MOTIF_WM_HINTS,
DTWM_IS_RUNNING,
- KDE_FULL_SESSION,
- KWIN_RUNNING,
- KWM_RUNNING,
- GNOME_BACKGROUND_PROPERTIES,
ENLIGHTENMENT_DESKTOP,
+ _DT_SAVE_MODE,
_SGI_DESKS_MANAGER,
// EWMH (aka NETWM)
@@ -629,6 +632,8 @@ struct QX11Data
_NET_SYSTEM_TRAY_VISUAL,
+ _NET_ACTIVE_WINDOW,
+
// Property formats
COMPOUND_TEXT,
TEXT,
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index e180001291..20d1d300c4 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -205,6 +205,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
, nativeGesturePanEnabled(0)
#elif defined(Q_WS_MAC)
, needWindowChange(0)
+ , hasAlienChildren(0)
, window_event(0)
, qd_hd(0)
#endif
@@ -219,6 +220,11 @@ QWidgetPrivate::QWidgetPrivate(int version)
isWidget = true;
memset(high_attributes, 0, sizeof(high_attributes));
+#if QT_MAC_USE_COCOA
+ drawRectOriginalAdded = false;
+ originalDrawMethod = true;
+ changeMethods = false;
+#endif // QT_MAC_USE_COCOA
#ifdef QWIDGET_EXTRA_DEBUG
static int count = 0;
qDebug() << "widgets" << ++count;
@@ -1121,7 +1127,8 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
qFatal("QWidget: Cannot create a QWidget when no GUI is being used");
Q_ASSERT(allWidgets);
- allWidgets->insert(q);
+ if (allWidgets)
+ allWidgets->insert(q);
QWidget *desktopWidget = 0;
if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
@@ -1168,6 +1175,10 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
if (f & Qt::MSWindowsOwnDC)
q->setAttribute(Qt::WA_NativeWindow);
+#ifdef Q_WS_MAC
+ q->setAttribute(Qt::WA_NativeWindow);
+#endif
+
q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
adjustQuitOnCloseAttribute();
@@ -1263,6 +1274,10 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
}
if (QWidget *parent = parentWidget()) {
+#ifdef Q_WS_MAC
+ if (testAttribute(Qt::WA_NativeWindow) == false)
+ parent->d_func()->hasAlienChildren = true;
+#endif
if (type & Qt::Window) {
if (!parent->testAttribute(Qt::WA_WState_Created))
parent->createWinId();
@@ -1433,7 +1448,7 @@ QWidget::~QWidget()
}
}
-#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_WS_MAC)
else if (!internalWinId() && isVisible()) {
qApp->d_func()->sendSyntheticEnterLeave(this);
#ifdef Q_WS_QWS
@@ -1468,10 +1483,19 @@ QWidget::~QWidget()
QObjectPrivate::clearGuards(this);
if (d->declarativeData) {
- d->declarativeData->destroyed(this);
+ QAbstractDeclarativeData::destroyed(d->declarativeData, this);
d->declarativeData = 0; // don't activate again in ~QObject
}
+#ifdef QT_MAC_USE_COCOA
+ // QCocoaView holds a pointer back to this widget. Clear it now
+ // to make sure it's not followed later on. The lifetime of the
+ // QCocoaView might exceed the lifetime of this widget in cases
+ // where Cocoa itself holds references to it.
+ extern void qt_mac_clearCocoaViewQWidgetPointers(QWidget *);
+ qt_mac_clearCocoaViewQWidgetPointers(this);
+#endif
+
if (!d->children.isEmpty())
d->deleteChildren();
@@ -2301,6 +2325,9 @@ QWidget *QWidget::find(WId id)
WId QWidget::winId() const
{
if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidget::winId: creating native window for" << this;
+#endif
QWidget *that = const_cast<QWidget*>(this);
that->setAttribute(Qt::WA_NativeWindow);
that->d_func()->createWinId();
@@ -2313,6 +2340,10 @@ WId QWidget::winId() const
void QWidgetPrivate::createWinId(WId winid)
{
Q_Q(QWidget);
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidgetPrivate::createWinId for" << q << winid;
+#endif
const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
if (!q->isWindow()) {
@@ -2355,6 +2386,9 @@ Ensures that the widget has a window system identifier, i.e. that it is known to
void QWidget::createWinId()
{
Q_D(QWidget);
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidget::createWinId" << this;
+#endif
// qWarning("QWidget::createWinId is obsolete, please fix your code.");
d->createWinId();
}
@@ -4884,90 +4918,7 @@ void QWidget::unsetCursor()
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
const QRegion &sourceRegion, RenderFlags renderFlags)
{
- Q_D(QWidget);
- if (!target) {
- qWarning("QWidget::render: null pointer to paint device");
- return;
- }
-
- const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
- QRegion paintRegion = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
- : sourceRegion;
- if (paintRegion.isEmpty())
- return;
-
-#ifndef Q_WS_MAC
- QPainter *oldSharedPainter = inRenderWithPainter ? d->sharedPainter() : 0;
-
- // Use the target's shared painter if set (typically set when doing
- // "other->render(widget);" in the widget's paintEvent.
- if (target->devType() == QInternal::Widget) {
- QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
- if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
- QPainter *targetPainter = targetPrivate->sharedPainter();
- if (targetPainter && targetPainter->isActive())
- d->setSharedPainter(targetPainter);
- }
- }
-#endif
-
- // Use the target's redirected device if set and adjust offset and paint
- // region accordingly. This is typically the case when people call render
- // from the paintEvent.
- QPoint offset = targetOffset;
- offset -= paintRegion.boundingRect().topLeft();
- QPoint redirectionOffset;
- QPaintDevice *redirected = 0;
-
- if (target->devType() == QInternal::Widget)
- redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
- if (!redirected)
- redirected = QPainter::redirected(target, &redirectionOffset);
-
- if (redirected) {
- target = redirected;
- offset -= redirectionOffset;
- }
-
- if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
- if (QPaintEngine *targetEngine = target->paintEngine()) {
- const QRegion targetSystemClip = targetEngine->systemClip();
- if (!targetSystemClip.isEmpty())
- paintRegion &= targetSystemClip.translated(-offset);
- }
- }
-
- // Set backingstore flags.
- int flags = QWidgetPrivate::DrawPaintOnScreen | QWidgetPrivate::DrawInvisible;
- if (renderFlags & DrawWindowBackground)
- flags |= QWidgetPrivate::DrawAsRoot;
-
- if (renderFlags & DrawChildren)
- flags |= QWidgetPrivate::DrawRecursive;
- else
- flags |= QWidgetPrivate::DontSubtractOpaqueChildren;
-
-#ifdef Q_WS_QWS
- flags |= QWidgetPrivate::DontSetCompositionMode;
-#endif
-
- if (target->devType() == QInternal::Printer) {
- QPainter p(target);
- d->render_helper(&p, targetOffset, paintRegion, renderFlags);
- return;
- }
-
-#ifndef Q_WS_MAC
- // Render via backingstore.
- d->drawWidget(target, paintRegion, offset, flags, d->sharedPainter());
-
- // Restore shared painter.
- if (oldSharedPainter)
- d->setSharedPainter(oldSharedPainter);
-#else
- // Render via backingstore (no shared painter).
- d->drawWidget(target, paintRegion, offset, flags, 0);
-#endif
+ d_func()->render(target, targetOffset, sourceRegion, renderFlags, false);
}
/*!
@@ -5327,7 +5278,15 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QPaintEngine *paintEngine = pdev->paintEngine();
if (paintEngine) {
setRedirected(pdev, -offset);
+#ifdef Q_WS_MAC
+ // (Alien support) Special case for Mac when redirecting: If the paint device
+ // is of the Widget type we need to set WA_WState_InPaintEvent since painting
+ // outside the paint event is not supported on QWidgets. The attributeis
+ // restored further down.
+ if (pdev->devType() == QInternal::Widget)
+ static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent);
+#endif
if (sharedPainter)
paintEngine->d_func()->systemClip = toBePainted;
else
@@ -5368,6 +5327,10 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
//restore
if (paintEngine) {
+#ifdef Q_WS_MAC
+ if (pdev->devType() == QInternal::Widget)
+ static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent, false);
+#endif
restoreRedirected();
if (!sharedPainter)
paintEngine->d_func()->systemRect = QRect();
@@ -5413,6 +5376,96 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
}
+void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
+ const QRegion &sourceRegion, QWidget::RenderFlags renderFlags,
+ bool readyToRender)
+{
+ if (!target) {
+ qWarning("QWidget::render: null pointer to paint device");
+ return;
+ }
+
+ const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
+ QRegion paintRegion = !inRenderWithPainter && !readyToRender
+ ? prepareToRender(sourceRegion, renderFlags)
+ : sourceRegion;
+ if (paintRegion.isEmpty())
+ return;
+
+#ifndef Q_WS_MAC
+ QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : 0;
+
+ // Use the target's shared painter if set (typically set when doing
+ // "other->render(widget);" in the widget's paintEvent.
+ if (target->devType() == QInternal::Widget) {
+ QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
+ if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
+ QPainter *targetPainter = targetPrivate->sharedPainter();
+ if (targetPainter && targetPainter->isActive())
+ setSharedPainter(targetPainter);
+ }
+ }
+#endif
+
+ // Use the target's redirected device if set and adjust offset and paint
+ // region accordingly. This is typically the case when people call render
+ // from the paintEvent.
+ QPoint offset = targetOffset;
+ offset -= paintRegion.boundingRect().topLeft();
+ QPoint redirectionOffset;
+ QPaintDevice *redirected = 0;
+
+ if (target->devType() == QInternal::Widget)
+ redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
+ if (!redirected)
+ redirected = QPainter::redirected(target, &redirectionOffset);
+
+ if (redirected) {
+ target = redirected;
+ offset -= redirectionOffset;
+ }
+
+ if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
+ if (QPaintEngine *targetEngine = target->paintEngine()) {
+ const QRegion targetSystemClip = targetEngine->systemClip();
+ if (!targetSystemClip.isEmpty())
+ paintRegion &= targetSystemClip.translated(-offset);
+ }
+ }
+
+ // Set backingstore flags.
+ int flags = DrawPaintOnScreen | DrawInvisible;
+ if (renderFlags & QWidget::DrawWindowBackground)
+ flags |= DrawAsRoot;
+
+ if (renderFlags & QWidget::DrawChildren)
+ flags |= DrawRecursive;
+ else
+ flags |= DontSubtractOpaqueChildren;
+
+#ifdef Q_WS_QWS
+ flags |= DontSetCompositionMode;
+#endif
+
+ if (target->devType() == QInternal::Printer) {
+ QPainter p(target);
+ render_helper(&p, targetOffset, paintRegion, renderFlags);
+ return;
+ }
+
+#ifndef Q_WS_MAC
+ // Render via backingstore.
+ drawWidget(target, paintRegion, offset, flags, sharedPainter());
+
+ // Restore shared painter.
+ if (oldSharedPainter)
+ setSharedPainter(oldSharedPainter);
+#else
+ // Render via backingstore (no shared painter).
+ drawWidget(target, paintRegion, offset, flags, 0);
+#endif
+}
+
void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
const QPoint &offset, int flags
#ifdef Q_BACKINGSTORE_SUBSURFACES
@@ -6458,7 +6511,7 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
// QWidget *fp = first->d_func()->focus_prev;
QWidget *fn = first->d_func()->focus_next;
- if (fn == second)
+ if (fn == second || first == second)
return;
QWidget *sp = second->d_func()->focus_prev;
@@ -7274,7 +7327,7 @@ void QWidgetPrivate::hide_helper()
bool isEmbedded = false;
#if !defined QT_NO_GRAPHICSVIEW
- isEmbedded = q->isWindow() && nearestGraphicsProxyWidget(q->parentWidget()) != 0;
+ isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != 0;
#else
Q_UNUSED(isEmbedded);
#endif
@@ -7311,7 +7364,7 @@ void QWidgetPrivate::hide_helper()
// next bit tries to move the focus if the focus widget is now
// hidden.
if (wasVisible) {
-#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_WS_MAC)
qApp->d_func()->sendSyntheticEnterLeave(q);
#endif
@@ -7443,7 +7496,7 @@ void QWidget::setVisible(bool visible)
d->show_helper();
-#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_WS_MAC)
qApp->d_func()->sendSyntheticEnterLeave(this);
#endif
}
@@ -7575,7 +7628,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous)
widget->d_func()->hide_sys();
}
}
-#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_WS_MAC)
qApp->d_func()->sendSyntheticEnterLeave(widget);
#endif
#ifndef QT_NO_ACCESSIBILITY
@@ -7619,23 +7672,21 @@ bool QWidgetPrivate::close_helper(CloseMode mode)
if (isMain)
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
- quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible() || parentWidget->testAttribute(Qt::WA_DontShowOnScreen));
+ // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
+ quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible());
if (quitOnClose) {
- // If there is no non-withdrawn primary window left (except
- // the ones without QuitOnClose or with WA_DontShowOnScreen),
- // we emit the lastWindowClosed signal
+ /* if there is no non-withdrawn primary window left (except
+ the ones without QuitOnClose), we emit the lastWindowClosed
+ signal */
QWidgetList list = QApplication::topLevelWidgets();
bool lastWindowClosed = true;
for (int i = 0; i < list.size(); ++i) {
QWidget *w = list.at(i);
- if ((w->isVisible() && !w->testAttribute(Qt::WA_DontShowOnScreen))
- && !w->parentWidget() && w->testAttribute(Qt::WA_QuitOnClose)) {
- lastWindowClosed = false;
- break;
- }
+ if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose))
+ continue;
+ lastWindowClosed = false;
+ break;
}
if (lastWindowClosed)
QApplicationPrivate::emitLastWindowClosed();
@@ -9798,7 +9849,7 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
desktopWidget = parent;
bool newParent = (parent != parentWidget()) || !wasCreated || desktopWidget;
-#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_MAC)
if (newParent && parent && !desktopWidget) {
if (testAttribute(Qt::WA_NativeWindow) && !qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
parent->d_func()->enforceNativeChildren();
@@ -10273,6 +10324,29 @@ const QPixmap *QWidget::icon() const
#endif // QT3_SUPPORT
+ /*!
+ \internal
+
+ This just sets the corresponding attribute bit to 1 or 0
+ */
+static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
+ QWidgetPrivate *d)
+{
+ if (attribute < int(8*sizeof(uint))) {
+ if (on)
+ data->widget_attributes |= (1<<attribute);
+ else
+ data->widget_attributes &= ~(1<<attribute);
+ } else {
+ const int x = attribute - 8*sizeof(uint);
+ const int int_off = x / (8*sizeof(uint));
+ if (on)
+ d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
+ else
+ d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
+ }
+}
+
/*!
Sets the attribute \a attribute on this widget if \a on is true;
otherwise clears the attribute.
@@ -10299,19 +10373,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
}
#endif
- if (attribute < int(8*sizeof(uint))) {
- if (on)
- data->widget_attributes |= (1<<attribute);
- else
- data->widget_attributes &= ~(1<<attribute);
- } else {
- const int x = attribute - 8*sizeof(uint);
- const int int_off = x / (8*sizeof(uint));
- if (on)
- d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
- else
- d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
- }
+ setAttribute_internal(attribute, on, data, d);
switch (attribute) {
@@ -10370,14 +10432,11 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
#ifdef Q_WS_MAC
{
// We can only have one of these set at a time
- static const int MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
- Qt::WA_MacMiniSize, 0 };
- for (int i = 0; MacSizes[i] != 0; ++i) {
- if (MacSizes[i] == attribute)
- continue;
- int macsize_x = MacSizes[i] - 8*sizeof(uint);
- int macsize_int_off = macsize_x / (8*sizeof(uint));
- d->high_attributes[macsize_int_off] &= ~(1<<(macsize_x-(macsize_int_off*8*sizeof(uint))));
+ const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
+ Qt::WA_MacMiniSize };
+ for (int i = 0; i < 3; ++i) {
+ if (MacSizes[i] != attribute)
+ setAttribute_internal(MacSizes[i], false, data, d);
}
d->macUpdateSizeAttribute();
}
@@ -10444,7 +10503,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
}
case Qt::WA_PaintOnScreen:
d->updateIsOpaque();
-#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC)
// Recreate the widget if it's already created as an alien widget and
// WA_PaintOnScreen is enabled. Paint on screen widgets must have win id.
// So must their children.
@@ -10500,6 +10559,10 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
case Qt::WA_X11OpenGLOverlay:
d->updateIsOpaque();
break;
+ case Qt::WA_X11DoNotAcceptFocus:
+ if (testAttribute(Qt::WA_WState_Created))
+ d->updateX11AcceptFocus();
+ break;
#endif
case Qt::WA_DontShowOnScreen: {
if (on && isVisible()) {
@@ -12234,6 +12297,28 @@ void QWidgetPrivate::_q_delayedDestroy(WId winId)
}
#endif
+#if QT_MAC_USE_COCOA
+void QWidgetPrivate::syncUnifiedMode() {
+ // The whole purpose of this method is to keep the unifiedToolbar in sync.
+ // That means making sure we either exchange the drawing methods or we let
+ // the toolbar know that it does not require to draw the baseline.
+ Q_Q(QWidget);
+ // This function makes sense only if this is a top level
+ if(!q->isWindow())
+ return;
+ OSWindowRef window = qt_mac_window_for(q);
+ if(changeMethods) {
+ // Ok, we are in documentMode.
+ if(originalDrawMethod)
+ qt_mac_replaceDrawRect(window, this);
+ } else {
+ if(!originalDrawMethod)
+ qt_mac_replaceDrawRectOriginal(window, this);
+ }
+}
+
+#endif // QT_MAC_USE_COCOA
+
QT_END_NAMESPACE
#include "moc_qwidget.cpp"
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 0d7475e993..e12148b97f 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -773,6 +773,7 @@ private:
#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);
+ friend void qt_set_winid_on_widget(QWidget*, Qt::HANDLE);
#endif
friend Q_GUI_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget);
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index bee93b5555..d7cd2eb525 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -460,7 +460,13 @@ static bool qt_isGenuineQWidget(OSViewRef ref)
bool qt_isGenuineQWidget(const QWidget *window)
{
- return window && qt_isGenuineQWidget(OSViewRef(window->winId()));
+ if (!window)
+ return false;
+
+ if (!window->internalWinId())
+ return true; //alien
+
+ return qt_isGenuineQWidget(OSViewRef(window->internalWinId()));
}
Q_GUI_EXPORT OSWindowRef qt_mac_window_for(const QWidget *w)
@@ -1912,13 +1918,15 @@ void QWidgetPrivate::determineWindowClass()
wclass = kDocumentWindowClass;
else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen))
wclass = kModalWindowClass;
- else if(q->testAttribute(Qt::WA_ShowModal) || type == Qt::Dialog)
+ else if(type == Qt::Dialog)
wclass = kMovableModalWindowClass;
else if(type == Qt::ToolTip)
wclass = kHelpWindowClass;
else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5
&& type == Qt::SplashScreen))
wclass = kFloatingWindowClass;
+ else if(q->testAttribute(Qt::WA_ShowModal))
+ wclass = kMovableModalWindowClass;
else
wclass = kDocumentWindowClass;
@@ -2022,8 +2030,6 @@ void QWidgetPrivate::determineWindowClass()
for(int i = 0; tmp_wattr && known_attribs[i].name; i++) {
if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) {
tmp_wattr ^= known_attribs[i].tag;
- qDebug("Qt: internal: * %s %s", known_attribs[i].name,
- (GetAvailableWindowAttributes(wclass) & known_attribs[i].tag) ? "" : "(*)");
}
}
if(tmp_wattr)
@@ -2218,6 +2224,41 @@ void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef)
applyMaxAndMinSizeOnWindow();
}
#else // QT_MAC_USE_COCOA
+
+void QWidgetPrivate::setWindowLevel()
+{
+ Q_Q(QWidget);
+ const QWidget * const windowParent = q->window()->parentWidget();
+ const QWidget * const primaryWindow = windowParent ? windowParent->window() : 0;
+ NSInteger winLevel = -1;
+
+ if (q->windowType() == Qt::Popup) {
+ winLevel = NSPopUpMenuWindowLevel;
+ // Popup should be in at least the same level as its parent.
+ if (primaryWindow) {
+ OSWindowRef parentRef = qt_mac_window_for(primaryWindow);
+ winLevel = qMax([parentRef level], winLevel);
+ }
+ } else if (q->windowType() == Qt::Tool) {
+ winLevel = NSFloatingWindowLevel;
+ } else if (q->windowType() == Qt::Dialog) {
+ // Correct modality level (NSModalPanelWindowLevel) will be
+ // set by cocoa when creating a modal session later.
+ winLevel = NSNormalWindowLevel;
+ }
+
+ // StayOnTop window should appear above Tool windows.
+ if (data.window_flags & Qt::WindowStaysOnTopHint)
+ winLevel = NSPopUpMenuWindowLevel;
+ // Tooltips should appear above StayOnTop windows.
+ if (q->windowType() == Qt::ToolTip)
+ winLevel = NSScreenSaverWindowLevel;
+ // All other types are Normal level.
+ if (winLevel == -1)
+ winLevel = NSNormalWindowLevel;
+ [qt_mac_window_for(q) setLevel:winLevel];
+}
+
void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWindowRef)
{
Q_Q(QWidget);
@@ -2290,6 +2331,10 @@ void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWin
q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
}
+ if (qApp->overrideCursor())
+ [windowRef disableCursorRects];
+
+ setWindowLevel();
macUpdateHideOnSuspend();
macUpdateOpaqueSizeGrip();
macUpdateIgnoreMouseEvents();
@@ -2564,7 +2609,16 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
} else {
data.fstrut_dirty = false; // non-toplevel widgets don't have a frame, so no need to update the strut
- if(OSViewRef osview = qt_mac_create_widget(q, this, qt_mac_nativeview_for(parentWidget))) {
+
+#ifdef QT_MAC_USE_COCOA
+ if (q->testAttribute(Qt::WA_NativeWindow) == false ||
+ q->internalWinId() != 0) {
+#ifdef ALIEN_DEBUG
+ qDebug() << "Skipping native widget creation for" << this;
+#endif
+ } else
+#endif
+ if (OSViewRef osview = qt_mac_create_widget(q, this, qt_mac_nativeview_for(parentWidget))) {
#ifndef QT_MAC_USE_COCOA
HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height());
HIViewSetFrame(osview, &bounds);
@@ -2720,6 +2774,35 @@ void QWidgetPrivate::transferChildren()
}
}
+#ifdef QT_MAC_USE_COCOA
+void QWidgetPrivate::setSubWindowStacking(bool set)
+{
+ Q_Q(QWidget);
+ if (!q->isWindow() || !q->testAttribute(Qt::WA_WState_Created))
+ return;
+
+ if (QWidget *parent = q->parentWidget()) {
+ if (parent->testAttribute(Qt::WA_WState_Created)) {
+ if (set)
+ [qt_mac_window_for(parent) addChildWindow:qt_mac_window_for(q) ordered:NSWindowAbove];
+ else
+ [qt_mac_window_for(parent) removeChildWindow:qt_mac_window_for(q)];
+ }
+ }
+
+ QList<QWidget *> widgets = q->findChildren<QWidget *>();
+ for (int i=0; i<widgets.size(); ++i) {
+ QWidget *child = widgets.at(i);
+ if (child->isWindow() && child->testAttribute(Qt::WA_WState_Created)) {
+ if (set)
+ [qt_mac_window_for(q) addChildWindow:qt_mac_window_for(child) ordered:NSWindowAbove];
+ else
+ [qt_mac_window_for(q) removeChildWindow:qt_mac_window_for(child)];
+ }
+ }
+}
+#endif
+
void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
{
Q_Q(QWidget);
@@ -2780,13 +2863,14 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
//recreate and setup flags
QObjectPrivate::setParent_helper(parent);
- QPoint pt = q->pos();
bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
if (wasCreated && !qt_isGenuineQWidget(q))
return;
- if ((data.window_flags & Qt::Sheet) && topData && topData->opacity == 242)
+ if (!q->testAttribute(Qt::WA_WState_WindowOpacitySet)) {
q->setWindowOpacity(1.0f);
+ q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
+ }
setWinId(0); //do after the above because they may want the id
@@ -2795,9 +2879,12 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
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))) {
+ // 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,
+ // unless this is an alien widget. )
+ const bool nonWindowWithCreatedParent = !q->isWindow() && parent->testAttribute(Qt::WA_WState_Created);
+ const bool nativeWidget = q->internalWinId() != 0;
+ if (wasCreated || nativeWidget && nonWindowWithCreatedParent) {
createWinId();
if (q->isWindow()) {
#ifndef QT_MAC_USE_COCOA
@@ -2874,7 +2961,6 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
current = current->parentWidget();
}
}
-
invalidateBuffer(q->rect());
qt_event_request_window_change(q);
}
@@ -2882,7 +2968,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
QPoint QWidget::mapToGlobal(const QPoint &pos) const
{
Q_D(const QWidget);
- if (!testAttribute(Qt::WA_WState_Created)) {
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
QPoint p = pos + data->crect.topLeft();
return isWindow() ? p : parentWidget()->mapToGlobal(p);
}
@@ -2909,7 +2995,7 @@ QPoint QWidget::mapToGlobal(const QPoint &pos) const
QPoint QWidget::mapFromGlobal(const QPoint &pos) const
{
Q_D(const QWidget);
- if (!testAttribute(Qt::WA_WState_Created)) {
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
QPoint p = isWindow() ? pos : parentWidget()->mapFromGlobal(pos);
return p - data->crect.topLeft();
}
@@ -3180,10 +3266,10 @@ void QWidget::activateWindow()
|| windowActive) {
#ifndef QT_MAC_USE_COCOA
ActivateWindow(win, true);
+ qApp->setActiveWindow(tlw);
#else
[win makeKeyWindow];
#endif
- qApp->setActiveWindow(tlw);
} else if(!isMinimized()) {
#ifndef QT_MAC_USE_COCOA
SelectWindow(win);
@@ -3208,7 +3294,7 @@ void QWidgetPrivate::update_sys(const QRect &r)
#ifndef QT_MAC_USE_COCOA
HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true);
#else
- [qt_mac_nativeview_for(q) setNeedsDisplay:YES];
+ qt_mac_set_needs_display(q, QRegion());
#endif
return;
}
@@ -3246,11 +3332,24 @@ void QWidgetPrivate::update_sys(const QRegion &rgn)
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();
- [qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(boundingRect.x(),
- boundingRect.y(), boundingRect.width(),
- boundingRect.height())];
+ // Alien support: get the first native ancestor widget (will be q itself in the non-alien case),
+ // map the coordinates from q space to NSView space and invalidate the rect.
+ QWidget *nativeParent = q->internalWinId() ? q : q->nativeParentWidget();
+ if (nativeParent == 0)
+ return;
+
+ QVector<QRect> rects = rgn.rects();
+ for (int i = 0; i < rects.count(); ++i) {
+ const QRect &rect = rects.at(i);
+
+ const QRect nativeBoundingRect = QRect(
+ QPoint(q->mapTo(nativeParent, rect.topLeft())),
+ QSize(rect.size()));
+
+ [qt_mac_nativeview_for(nativeParent) setNeedsDisplayInRect:NSMakeRect(nativeBoundingRect.x(),
+ nativeBoundingRect.y(), nativeBoundingRect.width(),
+ nativeBoundingRect.height())];
+ }
#endif
}
@@ -3274,38 +3373,20 @@ void QWidgetPrivate::show_sys()
return;
bool realWindow = isRealWindow();
+#ifndef QT_MAC_USE_COCOA
if (realWindow && !q->testAttribute(Qt::WA_Moved)) {
+ if (qt_mac_is_macsheet(q))
+ recreateMacWindow();
q->createWinId();
if (QWidget *p = q->parentWidget()) {
p->createWinId();
-#ifndef QT_MAC_USE_COCOA
RepositionWindow(qt_mac_window_for(q), qt_mac_window_for(p), kWindowCenterOnParentWindow);
-#else
- CGRect parentFrame = NSRectToCGRect([qt_mac_window_for(p) frame]);
- OSWindowRef windowRef = qt_mac_window_for(q);
- NSRect windowFrame = [windowRef frame];
- NSPoint parentCenter = NSMakePoint(CGRectGetMidX(parentFrame), CGRectGetMidY(parentFrame));
- [windowRef setFrameTopLeftPoint:NSMakePoint(parentCenter.x - (windowFrame.size.width / 2),
- (parentCenter.y + (windowFrame.size.height / 2)))];
-#endif
} else {
-#ifndef QT_MAC_USE_COCOA
RepositionWindow(qt_mac_window_for(q), 0, kWindowCenterOnMainScreen);
-#else
- // Ideally we would do a "center" here, but NSWindow's center is more equivalent to
- // kWindowAlertPositionOnMainScreen instead of kWindowCenterOnMainScreen.
- QRect availGeo = QApplication::desktop()->availableGeometry(q);
- // Center the content only.
- data.crect.moveCenter(availGeo.center());
- QRect fStrut = frameStrut();
- QRect frameRect(data.crect.x() - fStrut.left(), data.crect.y() - fStrut.top(),
- fStrut.left() + fStrut.right() + data.crect.width(),
- fStrut.top() + fStrut.bottom() + data.crect.height());
- NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1), frameRect.width(), frameRect.height());
- [qt_mac_window_for(q) setFrame:cocoaFrameRect display:NO];
-#endif
}
}
+#endif
+
data.fstrut_dirty = true;
if (realWindow) {
// Delegates can change window state, so record some things earlier.
@@ -3336,13 +3417,25 @@ 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)
- QEventDispatcherMac::instance()->interrupt();
+ setSubWindowStacking(true);
+
+ QWidget *top = 0;
+ if (QApplicationPrivate::tryModalHelper(q, &top)) {
+ [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)
+ QEventDispatcherMac::instance()->interrupt();
+ } else {
+ // The window is modally shaddowed, so we need to make
+ // sure that we don't pop in front of the modal window:
+ [window orderFront:window];
+ if (!top->testAttribute(Qt::WA_DontShowOnScreen)) {
+ if (NSWindow *modalWin = qt_mac_window_for(top))
+ [modalWin orderFront:window];
+ }
+ }
#endif
if (q->windowType() == Qt::Popup) {
if (q->focusWidget())
@@ -3361,8 +3454,6 @@ void QWidgetPrivate::show_sys()
} else if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) {
#ifndef QT_MAC_USE_COCOA
qt_event_request_activate(q);
-#else
- [qt_mac_window_for(q) makeKeyWindow];
#endif
}
} else if(topData()->embedded || !q->parentWidget() || q->parentWidget()->isVisible()) {
@@ -3404,6 +3495,9 @@ void QWidgetPrivate::hide_sys()
return;
QMacCocoaAutoReleasePool pool;
if(q->isWindow()) {
+#ifdef QT_MAC_USE_COCOA
+ setSubWindowStacking(false);
+#endif
OSWindowRef window = qt_mac_window_for(q);
if(qt_mac_is_macsheet(q)) {
#ifndef QT_MAC_USE_COCOA
@@ -3469,12 +3563,15 @@ void QWidgetPrivate::hide_sys()
}
#endif
}
- if(q->isActiveWindow() && !(q->windowType() == Qt::Popup)) {
+#ifndef QT_MAC_USE_COCOA
+ // If the window we now hide was the active window, we need
+ // to find, and activate another window on screen. NB: Cocoa takes care of this
+ // logic for us (and distinquishes between main windows and key windows)
+ if (q->isActiveWindow() && !(q->windowType() == Qt::Popup)) {
QWidget *w = 0;
if(q->parentWidget())
w = q->parentWidget()->window();
if(!w || (!w->isVisible() && !w->isMinimized())) {
-#ifndef QT_MAC_USE_COCOA
for (WindowPtr wp = GetFrontWindowOfClass(kMovableModalWindowClass, true);
wp; wp = GetNextWindowOfClass(wp, kMovableModalWindowClass, true)) {
if((w = qt_mac_find_window(wp)))
@@ -3494,24 +3591,12 @@ void QWidgetPrivate::hide_sys()
break;
}
}
-#else
- NSArray *windows = [NSApp windows];
- NSUInteger totalWindows = [windows count];
- for (NSUInteger i = 0; i < totalWindows; ++i) {
- OSWindowRef wp = [windows objectAtIndex:i];
- if ((w = qt_mac_find_window(wp)))
- break;
- }
-#endif
}
if(w && w->isVisible() && !w->isMinimized()) {
-#ifndef QT_MAC_USE_COCOA
- qt_event_request_activate(w);
-#else
- [qt_mac_window_for(w) makeKeyWindow];
-#endif
+ qt_event_request_activate(w);
}
}
+#endif
} else {
invalidateBuffer(q->rect());
#ifndef QT_MAC_USE_COCOA
@@ -3848,7 +3933,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget *w)
widget, either by scrolling its contents or repainting, depending on the WA_StaticContents
flag
*/
-static void qt_mac_update_widget_posisiton(QWidget *q, QRect oldRect, QRect newRect)
+static void qt_mac_update_widget_position(QWidget *q, QRect oldRect, QRect newRect)
{
#ifndef QT_MAC_USE_COCOA
HIRect bounds = CGRectMake(newRect.x(), newRect.y(),
@@ -3945,7 +4030,7 @@ static void qt_mac_update_widget_posisiton(QWidget *q, QRect oldRect, QRect newR
#else
Q_UNUSED(oldRect);
NSRect bounds = NSMakeRect(newRect.x(), newRect.y(),
- newRect.width(), newRect.height());
+ newRect.width(), newRect.height());
[qt_mac_nativeview_for(q) setFrame:bounds];
#endif
}
@@ -3982,7 +4067,8 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
QRect xrect = data.crect;
QRect parentWRect;
- if (q->isWindow() && topData()->embedded) {
+ bool isEmbeddedWindow = (q->isWindow() && topData()->embedded);
+ if (isEmbeddedWindow) {
#ifndef QT_MAC_USE_COCOA
HIViewRef parentView = HIViewGetSuperview(qt_mac_nativeview_for(q));
#else
@@ -4007,7 +4093,7 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
if (parentWRect.isValid()) {
// parent is clipped, and we have to clip to the same limit as parent
- if (!parentWRect.contains(xrect)) {
+ if (!parentWRect.contains(xrect) && !isEmbeddedWindow) {
xrect &= parentWRect;
wrect = xrect;
//translate from parent's to my Qt coord sys
@@ -4109,7 +4195,7 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
}
}
- qt_mac_update_widget_posisiton(q, oldRect, xrect);
+ qt_mac_update_widget_position(q, oldRect, xrect);
if (jump)
q->update();
@@ -4181,6 +4267,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
QMacCocoaAutoReleasePool pool;
bool realWindow = isRealWindow();
+ BOOL needDisplay = realWindow ? YES : NO;
if (realWindow && !q->testAttribute(Qt::WA_DontShowOnScreen)){
adjustWithinMaxAndMinSize(w, h);
@@ -4195,6 +4282,22 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
setGeometry_sys_helper(x, y, w, h, isMove);
}
#else
+ if (!isMove && !q->testAttribute(Qt::WA_Moved) && !q->isVisible()) {
+ // INVARIANT: The location of the window has not yet been set. The default will
+ // instead be to center it on the desktop, or over the parent, if any. Since we now
+ // resize the window, we need to adjust the top left position to keep the window
+ // centeralized. And we need to to this now (and before show) in case the positioning
+ // of other windows (e.g. sub-windows) depend on this position:
+ if (QWidget *p = q->parentWidget()) {
+ x = p->geometry().center().x() - (w / 2);
+ y = p->geometry().center().y() - (h / 2);
+ } else {
+ QRect availGeo = QApplication::desktop()->availableGeometry(q);
+ x = availGeo.center().x() - (w / 2);
+ y = availGeo.center().y() - (h / 2);
+ }
+ }
+
QSize olds = q->size();
const bool isResize = (olds != QSize(w, h));
NSWindow *window = qt_mac_window_for(q);
@@ -4212,7 +4315,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
if (currTopLeft.x() == x && currTopLeft.y() == y
&& cocoaFrameRect.size.width != 0
&& cocoaFrameRect.size.height != 0) {
- [window setFrame:cocoaFrameRect display:NO];
+ [window setFrame:cocoaFrameRect display:needDisplay];
} else {
// The window is moved and resized (or resized to zero).
// Since Cocoa usually only sends us a resize callback after
@@ -4221,7 +4324,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
// would have the same origin as the setFrame call) we shift the
// window back and forth inbetween.
cocoaFrameRect.origin.y += 1;
- [window setFrame:cocoaFrameRect display:NO];
+ [window setFrame:cocoaFrameRect display:needDisplay];
cocoaFrameRect.origin.y -= 1;
[window setFrameOrigin:cocoaFrameRect.origin];
}
@@ -4611,9 +4714,12 @@ void QWidgetPrivate::registerDropSite(bool on)
#ifndef QT_MAC_USE_COCOA
SetControlDragTrackingEnabled(qt_mac_nativeview_for(q), on);
#else
- NSView *view = qt_mac_nativeview_for(q);
- if (on && [view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) {
- [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view) registerDragTypes];
+ NSWindow *win = qt_mac_window_for(q);
+ if (on) {
+ if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaWindow) class]])
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaWindow) *>(win) registerDragTypes];
+ else if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaPanel) class]])
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaPanel) *>(win) registerDragTypes];
}
#endif
}
@@ -4729,7 +4835,7 @@ void QWidgetPrivate::finishCocoaMaskSetup()
[window setOpaque:(extra->imageMask == 0)];
[window invalidateShadow];
}
- [qt_mac_nativeview_for(q) setNeedsDisplay:YES];
+ qt_mac_set_needs_display(q, QRegion());
}
#endif
@@ -4769,7 +4875,7 @@ void QWidgetPrivate::setModal_sys()
bool alreadySheet = [windowRef styleMask] & NSDocModalWindowMask;
if (windowParent && q->windowModality() == Qt::WindowModal){
- // Window should be window-modal, which implies a sheet.
+ // INVARIANT: Window should be window-modal (which implies a sheet).
if (!alreadySheet) {
// NB: the following call will call setModal_sys recursivly:
recreateMacWindow();
@@ -4786,47 +4892,19 @@ void QWidgetPrivate::setModal_sys()
[static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES];
}
} else {
- // Window shold not be window-modal, and as such, not a sheet.
+ // INVARIANT: Window shold _not_ be window-modal (and as such, not a sheet).
if (alreadySheet){
// NB: the following call will call setModal_sys recursivly:
recreateMacWindow();
windowRef = qt_mac_window_for(q);
}
- if (q->windowModality() == Qt::ApplicationModal) {
- [windowRef setLevel:NSModalPanelWindowLevel];
- } else if (primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) {
- // INVARIANT: Our window is a dialog that has a dialog parent that is
- // application modal, or . This means that q is supposed to be on top of this
- // dialog and not be modally shaddowed:
- [windowRef setLevel:NSModalPanelWindowLevel];
+ if (q->windowModality() == Qt::NonModal
+ && primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) {
+ // INVARIANT: Our window has a parent that is application modal.
+ // This means that q is supposed to be on top of this window and
+ // not be modally shaddowed:
if ([windowRef isKindOfClass:[NSPanel class]])
[static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES];
- } else {
- // INVARIANT: q should not be modal.
- NSInteger winLevel = -1;
- if (q->windowType() == Qt::Popup) {
- winLevel = NSPopUpMenuWindowLevel;
- // Popup should be in at least the same level as its parent.
- if (primaryWindow) {
- OSWindowRef parentRef = qt_mac_window_for(primaryWindow);
- winLevel = qMax([parentRef level], winLevel);
- }
- } else if (q->windowType() == Qt::Tool) {
- winLevel = NSFloatingWindowLevel;
- } else if (q->windowType() == Qt::Dialog) {
- winLevel = NSModalPanelWindowLevel;
- }
-
- // StayOnTop window should appear above Tool windows.
- if (data.window_flags & Qt::WindowStaysOnTopHint)
- winLevel = NSPopUpMenuWindowLevel;
- // Tooltips should appear above StayOnTop windows.
- if (q->windowType() == Qt::ToolTip)
- winLevel = NSScreenSaverWindowLevel;
- // All other types are Normal level.
- if (winLevel == -1)
- winLevel = NSNormalWindowLevel;
- [windowRef setLevel:winLevel];
}
}
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 555647c1df..cad60b5ff9 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -158,6 +158,7 @@ struct QTLWExtra {
quint32 newCounterValueLo;
#endif
#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
+ uint hotkeyRegistered: 1; // Hot key from the STARTUPINFO has been registered.
HICON winIconBig; // internal big Windows icon
HICON winIconSmall; // internal small Windows icon
#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
@@ -385,6 +386,8 @@ public:
QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);
void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion,
QWidget::RenderFlags renderFlags);
+ void render(QPaintDevice *target, const QPoint &targetOffset, const QRegion &sourceRegion,
+ QWidget::RenderFlags renderFlags, bool readyToRender);
void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,
QPainter *sharedPainter = 0, QWidgetBackingStore *backingStore = 0);
@@ -677,7 +680,7 @@ public:
QMap<Qt::GestureType, Qt::GestureFlags> gestureContext;
// Bit fields.
- uint high_attributes[3]; // the low ones are in QWidget::widget_attributes
+ uint high_attributes[4]; // the low ones are in QWidget::widget_attributes
QPalette::ColorRole fg_role : 8;
QPalette::ColorRole bg_role : 8;
uint dirtyOpaqueChildren : 1;
@@ -700,6 +703,7 @@ public:
void setNetWmWindowTypes();
void x11UpdateIsOpaque();
bool isBackgroundInherited() const;
+ void updateX11AcceptFocus();
#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
uint nativeGesturePanEnabled : 1;
@@ -717,6 +721,7 @@ public:
#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
// This is new stuff
uint needWindowChange : 1;
+ uint hasAlienChildren : 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
@@ -763,9 +768,18 @@ public:
void initWindowPtr();
void finishCreateWindow_sys_Carbon(OSWindowRef windowRef);
#else
+ void setSubWindowStacking(bool set);
+ void setWindowLevel();
void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef);
void syncCocoaMask();
void finishCocoaMaskSetup();
+ void syncUnifiedMode();
+ // Did we add the drawRectOriginal method?
+ bool drawRectOriginalAdded;
+ // Is the original drawRect method available?
+ bool originalDrawMethod;
+ // Do we need to change the methods?
+ bool changeMethods;
#endif
void determineWindowClass();
void transferChildren();
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index 9acfb70409..7d647b79ee 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -243,7 +243,7 @@ static QCursor *mouseGrbCur = 0;
static QWidget *keyboardGrb = 0;
static HHOOK journalRec = 0;
-extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
#define XCOORD_MAX 16383
#define WRECT_MAX 16383
@@ -825,7 +825,7 @@ QCursor *qt_grab_cursor()
// The procedure does nothing, but is required for mousegrabbing to work
#ifndef Q_WS_WINCE
-LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
+LRESULT QT_WIN_CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(journalRec, nCode, wParam, lParam);
}
@@ -1094,6 +1094,21 @@ void QWidgetPrivate::show_sys()
return;
}
+ if (data.window_flags & Qt::Window) {
+ QTLWExtra *extra = topData();
+ if (!extra->hotkeyRegistered) {
+ // Try to set the hotkey using information from STARTUPINFO
+ STARTUPINFO startupInfo;
+ GetStartupInfo(&startupInfo);
+ // If STARTF_USEHOTKEY is set, hStdInput is the virtual keycode
+ if (startupInfo.dwFlags & 0x00000200) {
+ WPARAM hotKey = (WPARAM)startupInfo.hStdInput;
+ SendMessage(data.winid, WM_SETHOTKEY, hotKey, 0);
+ }
+ extra->hotkeyRegistered = 1;
+ }
+ }
+
int sm = SW_SHOWNORMAL;
bool fakedMaximize = false;
if (q->isWindow()) {
@@ -1141,6 +1156,11 @@ void QWidgetPrivate::show_sys()
data.window_state |= Qt::WindowMinimized;
if (IsZoomed(q->internalWinId()))
data.window_state |= Qt::WindowMaximized;
+ // This is to resolve the problem where popups are opened from the
+ // system tray and not being implicitly activated
+ if (q->windowType() == Qt::Popup &&
+ (!q->parentWidget() || !q->parentWidget()->isActiveWindow()))
+ q->activateWindow();
}
winSetupGestures();
@@ -1687,6 +1707,7 @@ void QWidgetPrivate::deleteSysExtra()
void QWidgetPrivate::createTLSysExtra()
{
+ extra->topextra->hotkeyRegistered = 0;
extra->topextra->savedFlags = 0;
extra->topextra->winIconBig = 0;
extra->topextra->winIconSmall = 0;
diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp
index fa9470325b..509847b6d8 100644
--- a/src/gui/kernel/qwidget_wince.cpp
+++ b/src/gui/kernel/qwidget_wince.cpp
@@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
const QString qt_reg_winclass(QWidget *w); // defined in qapplication_win.cpp
-extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
//#define TABLET_DEBUG
#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \
@@ -586,7 +586,7 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) {
}
// The procedure does nothing, but is required for mousegrabbing to work
-LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam) {
+LRESULT QT_WIN_CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam) {
Q_UNUSED(nCode);
Q_UNUSED(wParam);
Q_UNUSED(lParam);
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index 9660de5819..37ac6bff10 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -49,7 +49,7 @@
#include "qbitmap.h"
#include "qlayout.h"
#include "qtextcodec.h"
-#include "qdatetime.h"
+#include "qelapsedtimer.h"
#include "qcursor.h"
#include "qstack.h"
#include "qcolormap.h"
@@ -352,7 +352,7 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
return;
QApplication::flush();
XEvent ev;
- QTime t;
+ QElapsedTimer t;
t.start();
static const int maximumWaitTime = 2000;
if (!w->testAttribute(Qt::WA_WState_Created))
@@ -780,7 +780,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
XWMHints wm_hints; // window manager hints
memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
wm_hints.flags = InputHint | StateHint | WindowGroupHint;
- wm_hints.input = True;
+ wm_hints.input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
wm_hints.initial_state = NormalState;
wm_hints.window_group = X11->wm_client_leader;
@@ -1166,7 +1166,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
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)))
+ if (wasCreated)
createWinId();
if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
q->setAttribute(Qt::WA_WState_Hidden);
@@ -1641,7 +1641,29 @@ void QWidget::activateWindow()
if (X11->userTime == 0)
X11->userTime = X11->time;
qt_net_update_user_time(tlw, X11->userTime);
- XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
+
+ if (X11->isSupportedByWM(ATOM(_NET_ACTIVE_WINDOW))
+ && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)) {
+ XEvent e;
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = ATOM(_NET_ACTIVE_WINDOW);
+ e.xclient.display = X11->display;
+ e.xclient.window = tlw->internalWinId();
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = 1; // 1 == application
+ e.xclient.data.l[1] = X11->userTime;
+ if (QWidget *aw = QApplication::activeWindow())
+ e.xclient.data.l[2] = aw->internalWinId();
+ else
+ e.xclient.data.l[2] = XNone;
+ e.xclient.data.l[3] = 0;
+ e.xclient.data.l[4] = 0;
+ XSendEvent(X11->display, RootWindow(X11->display, tlw->x11Info().screen()),
+ false, SubstructureNotifyMask | SubstructureRedirectMask, &e);
+ } else {
+ if (!qt_widget_private(tlw)->topData()->waitingForMapNotify)
+ XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
+ }
}
}
@@ -3030,4 +3052,24 @@ void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &at
xinfo->setX11Data(xd);
}
+void QWidgetPrivate::updateX11AcceptFocus()
+{
+ Q_Q(QWidget);
+ if (!q->isWindow() || !q->internalWinId())
+ return;
+
+ 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;
+ }
+ h->flags |= InputHint;
+ h->input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
+
+ XSetWMHints(X11->display, q->internalWinId(), h);
+ if (h != &wm_hints)
+ XFree((char *)h);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp
index 35850db3f7..b527e72ed6 100644
--- a/src/gui/kernel/qx11embed_x11.cpp
+++ b/src/gui/kernel/qx11embed_x11.cpp
@@ -47,7 +47,7 @@
#include <qlayout.h>
#include <qstyle.h>
#include <qstyleoption.h>
-#include <qdatetime.h>
+#include <qelapsedtimer.h>
#include <qpointer.h>
#include <qdebug.h>
#include <qx11info_x11.h>
@@ -1231,7 +1231,7 @@ void QX11EmbedContainer::embedClient(WId id)
For safety, we will not wait more than 500 ms, so that we can
preemptively workaround buggy window managers.
*/
- QTime t;
+ QElapsedTimer t;
t.start();
functorData data;
diff --git a/src/gui/mac/qt_menu.nib/classes.nib b/src/gui/mac/qt_menu.nib/classes.nib
index fed50a386c..0031e0e4e5 100644
--- a/src/gui/mac/qt_menu.nib/classes.nib
+++ b/src/gui/mac/qt_menu.nib/classes.nib
@@ -5,14 +5,6 @@
<key>IBClasses</key>
<array>
<dict>
- <key>CLASS</key>
- <string>FirstResponder</string>
- <key>LANGUAGE</key>
- <string>ObjC</string>
- <key>SUPERCLASS</key>
- <string>NSObject</string>
- </dict>
- <dict>
<key>ACTIONS</key>
<dict>
<key>hide</key>
@@ -52,6 +44,14 @@
<key>SUPERCLASS</key>
<string>NSResponder</string>
</dict>
+ <dict>
+ <key>CLASS</key>
+ <string>FirstResponder</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSObject</string>
+ </dict>
</array>
<key>IBVersion</key>
<string>1</string>
diff --git a/src/gui/mac/qt_menu.nib/info.nib b/src/gui/mac/qt_menu.nib/info.nib
index 768cb8b9f1..02e5cca562 100644
--- a/src/gui/mac/qt_menu.nib/info.nib
+++ b/src/gui/mac/qt_menu.nib/info.nib
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>IBFramework Version</key>
- <string>670</string>
+ <string>672</string>
<key>IBOldestOS</key>
<integer>5</integer>
<key>IBOpenObjects</key>
@@ -11,7 +11,7 @@
<integer>57</integer>
</array>
<key>IBSystem Version</key>
- <string>9G55</string>
+ <string>9L31a</string>
<key>targetFramework</key>
<string>IBCocoaFramework</string>
</dict>
diff --git a/src/gui/mac/qt_menu.nib/keyedobjects.nib b/src/gui/mac/qt_menu.nib/keyedobjects.nib
index 18a66488f5..3edb0ed2eb 100644
--- a/src/gui/mac/qt_menu.nib/keyedobjects.nib
+++ b/src/gui/mac/qt_menu.nib/keyedobjects.nib
Binary files differ
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
index f9902d7083..0671fa8829 100644
--- a/src/gui/math3d/qmatrix4x4.h
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -208,6 +208,8 @@ private:
friend class QGraphicsRotation;
};
+Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE);
+
inline QMatrix4x4::QMatrix4x4
(qreal m11, qreal m12, qreal m13, qreal m14,
qreal m21, qreal m22, qreal m23, qreal m24,
diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h
index a446f28af3..16aa5d0774 100644
--- a/src/gui/math3d/qquaternion.h
+++ b/src/gui/math3d/qquaternion.h
@@ -136,6 +136,8 @@ private:
qreal wp, xp, yp, zp;
};
+Q_DECLARE_TYPEINFO(QQuaternion, Q_MOVABLE_TYPE);
+
inline QQuaternion::QQuaternion() : wp(1.0f), xp(0.0f), yp(0.0f), zp(0.0f) {}
inline QQuaternion::QQuaternion(qreal aScalar, qreal xpos, qreal ypos, qreal zpos) : wp(aScalar), xp(xpos), yp(ypos), zp(zpos) {}
diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h
index d76f35ac57..c92c5e0153 100644
--- a/src/gui/math3d/qvector2d.h
+++ b/src/gui/math3d/qvector2d.h
@@ -126,6 +126,8 @@ private:
friend class QVector4D;
};
+Q_DECLARE_TYPEINFO(QVector2D, Q_MOVABLE_TYPE);
+
inline QVector2D::QVector2D() : xp(0.0f), yp(0.0f) {}
inline QVector2D::QVector2D(float xpos, float ypos, int) : xp(xpos), yp(ypos) {}
diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h
index 80c71526e0..2fdd1d3d41 100644
--- a/src/gui/math3d/qvector3d.h
+++ b/src/gui/math3d/qvector3d.h
@@ -141,6 +141,8 @@ private:
#endif
};
+Q_DECLARE_TYPEINFO(QVector3D, Q_MOVABLE_TYPE);
+
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) {}
diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h
index 4af2961715..a383fbb16f 100644
--- a/src/gui/math3d/qvector4d.h
+++ b/src/gui/math3d/qvector4d.h
@@ -138,6 +138,8 @@ private:
#endif
};
+Q_DECLARE_TYPEINFO(QVector4D, Q_MOVABLE_TYPE);
+
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) {}
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index a6cc9c7ec9..ed8ee762d2 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -91,6 +91,8 @@ SOURCES += \
HEADERS += \
painting/qpaintengine_raster_p.h \
+ painting/qdrawhelper_p.h \
+ painting/qblendfunctions_p.h \
painting/qrasterdefs_p.h \
painting/qgrayraster_p.h
@@ -379,11 +381,23 @@ symbian {
QMAKE_CXXFLAGS.ARMCC *= -O3
}
-neon {
+neon:*-g++* {
DEFINES += QT_HAVE_NEON
HEADERS += painting/qdrawhelper_neon_p.h
SOURCES += painting/qdrawhelper_neon.cpp
QMAKE_CXXFLAGS *= -mfpu=neon
+
+ DRAWHELPER_NEON_ASM_FILES = ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
+
+ neon_compiler.commands = $$QMAKE_CXX -c
+ neon_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
+ neon_compiler.dependency_type = TYPE_C
+ neon_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
+ neon_compiler.input = DRAWHELPER_NEON_ASM_FILES
+ neon_compiler.variable_out = OBJECTS
+ neon_compiler.name = compiling[neon] ${QMAKE_FILE_IN}
+ silent:neon_compiler.commands = @echo compiling[neon] ${QMAKE_FILE_IN} && $$neon_compiler.commands
+ QMAKE_EXTRA_COMPILERS += neon_compiler
}
contains(QT_CONFIG, zlib) {
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 8de9eaa5c8..f9cd59b001 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -263,7 +263,7 @@ bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *wi
{
const QPoint pos(tlwOffset + widget->mapTo(tlw, rect.topLeft()));
const QRect tlwRect(QRect(pos, rect.size()));
- if (dirty.intersects(tlwRect))
+ if (fullUpdatePending || dirty.intersects(tlwRect))
return false; // We don't want to scroll junk.
return windowSurface->scroll(tlwRect, dx, dy);
}
@@ -402,7 +402,7 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const
const bool widgetDirty = widget && widget != tlw;
const QRect tlwRect(topLevelRect());
const QRect surfaceGeometry(windowSurface->geometry());
- if (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size()) {
+ if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) {
if (widgetDirty) {
const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size());
const QPoint offset(widget->mapTo(tlw, QPoint()));
@@ -555,6 +555,18 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
return;
}
+ if (fullUpdatePending) {
+ if (updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ if (!windowSurface->hasPartialUpdateSupport()) {
+ fullUpdatePending = true;
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
const QPoint offset = widget->mapTo(tlw, QPoint());
const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
@@ -638,6 +650,18 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd
return;
}
+ if (fullUpdatePending) {
+ if (updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+ if (!windowSurface->hasPartialUpdateSupport()) {
+ fullUpdatePending = true;
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
if (qt_region_strictContains(dirty, translatedRect)) {
@@ -833,6 +857,7 @@ void QWidgetBackingStore::updateLists(QWidget *cur)
QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
: tlw(topLevel), dirtyOnScreenWidgets(0), hasDirtyFromPreviousSync(false)
+ , fullUpdatePending(0)
{
windowSurface = tlw->windowSurface();
if (!windowSurface)
@@ -1122,6 +1147,7 @@ void QWidgetBackingStore::sync()
for (int i = 0; i < dirtyWidgets.size(); ++i)
resetWidget(dirtyWidgets.at(i));
dirtyWidgets.clear();
+ fullUpdatePending = false;
}
return;
}
@@ -1132,28 +1158,28 @@ void QWidgetBackingStore::sync()
const QRect surfaceGeometry(windowSurface->geometry());
bool repaintAllWidgets = false;
- if (inTopLevelResize || surfaceGeometry != tlwRect) {
- if ((inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
- if (hasStaticContents()) {
- // Repaint existing dirty area and newly visible area.
- const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
- const QRegion staticRegion(staticContents(0, clipRect));
- QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height());
- newVisible -= staticRegion;
- dirty += newVisible;
- windowSurface->setStaticContents(staticRegion);
- } else {
- // Repaint everything.
- dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height());
- for (int i = 0; i < dirtyWidgets.size(); ++i)
- resetWidget(dirtyWidgets.at(i));
- dirtyWidgets.clear();
- repaintAllWidgets = true;
- }
+ if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
+ if (hasStaticContents()) {
+ // Repaint existing dirty area and newly visible area.
+ const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
+ const QRegion staticRegion(staticContents(0, clipRect));
+ QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height());
+ newVisible -= staticRegion;
+ dirty += newVisible;
+ windowSurface->setStaticContents(staticRegion);
+ } else {
+ // Repaint everything.
+ dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height());
+ for (int i = 0; i < dirtyWidgets.size(); ++i)
+ resetWidget(dirtyWidgets.at(i));
+ dirtyWidgets.clear();
+ repaintAllWidgets = true;
}
- windowSurface->setGeometry(tlwRect);
}
+ if (inTopLevelResize || surfaceGeometry != tlwRect)
+ windowSurface->setGeometry(tlwRect);
+
if (updatesDisabled)
return;
@@ -1212,6 +1238,8 @@ void QWidgetBackingStore::sync()
}
dirtyWidgets.clear();
+ fullUpdatePending = false;
+
if (toClean.isEmpty()) {
// Nothing to repaint. However, we might have newly exposed areas on the
// screen if this function was called from sync(QWidget *, QRegion)), so
diff --git a/src/gui/painting/qbackingstore_p.h b/src/gui/painting/qbackingstore_p.h
index 02c0f7cc2b..6510b579b8 100644
--- a/src/gui/painting/qbackingstore_p.h
+++ b/src/gui/painting/qbackingstore_p.h
@@ -91,6 +91,7 @@ public:
inline bool isDirty() const
{
return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && !hasDirtyFromPreviousSync
+ && !fullUpdatePending
#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
&& !hasDirtyWindowDecoration()
#endif
@@ -115,7 +116,8 @@ private:
#ifdef Q_BACKINGSTORE_SUBSURFACES
QList<QWindowSurface*> subSurfaces;
#endif
- bool hasDirtyFromPreviousSync;
+ uint hasDirtyFromPreviousSync : 1;
+ uint fullUpdatePending : 1;
QPoint tlwOffset;
diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp
index bbffda14ee..7ff2a37a58 100644
--- a/src/gui/painting/qbezier.cpp
+++ b/src/gui/painting/qbezier.cpp
@@ -112,8 +112,13 @@ QPolygonF QBezier::toPolygon() const
return polygon;
}
-//0.5 is really low
-static const qreal flatness = 0.5;
+QBezier QBezier::mapBy(const QTransform &transform) const
+{
+ return QBezier::fromPoints(transform.map(pt1()), transform.map(pt2()), transform.map(pt3()), transform.map(pt4()));
+}
+
+//0.05 is really low, but required for scaled-up beziers...
+static const qreal flatness = 0.05;
//based on "Fast, precise flattening of cubic Bezier path and offset curves"
// by T. F. Hain, A. L. Ahmad, S. V. R. Racherla and D. D. Langan
@@ -140,6 +145,25 @@ static inline void flattenBezierWithoutInflections(QBezier &bez,
}
}
+QBezier QBezier::getSubRange(qreal t0, qreal t1) const
+{
+ QBezier result;
+ QBezier temp;
+
+ // cut at t1
+ if (qFuzzyIsNull(t1 - qreal(1.))) {
+ result = *this;
+ } else {
+ temp = *this;
+ temp.parameterSplitLeft(t1, &result);
+ }
+
+ // cut at t0
+ if (!qFuzzyIsNull(t0))
+ result.parameterSplitLeft(t0 / t1, &temp);
+
+ return result;
+}
static inline int quadraticRoots(qreal a, qreal b, qreal c,
qreal *x1, qreal *x2)
@@ -588,88 +612,6 @@ give_up:
return o - curveSegments;
}
-#if 0
-static inline bool IntersectBB(const QBezier &a, const QBezier &b)
-{
- return a.bounds().intersects(b.bounds());
-}
-#else
-static int IntersectBB(const QBezier &a, const QBezier &b)
-{
- // Compute bounding box for a
- qreal minax, maxax, minay, maxay;
- if (a.x1 > a.x4) // These are the most likely to be extremal
- minax = a.x4, maxax = a.x1;
- else
- minax = a.x1, maxax = a.x4;
-
- if (a.x3 < minax)
- minax = a.x3;
- else if (a.x3 > maxax)
- maxax = a.x3;
-
- if (a.x2 < minax)
- minax = a.x2;
- else if (a.x2 > maxax)
- maxax = a.x2;
-
- if (a.y1 > a.y4)
- minay = a.y4, maxay = a.y1;
- else
- minay = a.y1, maxay = a.y4;
-
- if (a.y3 < minay)
- minay = a.y3;
- else if (a.y3 > maxay)
- maxay = a.y3;
-
- if (a.y2 < minay)
- minay = a.y2;
- else if (a.y2 > maxay)
- maxay = a.y2;
-
- // Compute bounding box for b
- qreal minbx, maxbx, minby, maxby;
- if (b.x1 > b.x4)
- minbx = b.x4, maxbx = b.x1;
- else
- minbx = b.x1, maxbx = b.x4;
-
- if (b.x3 < minbx)
- minbx = b.x3;
- else if (b.x3 > maxbx)
- maxbx = b.x3;
-
- if (b.x2 < minbx)
- minbx = b.x2;
- else if (b.x2 > maxbx)
- maxbx = b.x2;
-
- if (b.y1 > b.y4)
- minby = b.y4, maxby = b.y1;
- else
- minby = b.y1, maxby = b.y4;
-
- if (b.y3 < minby)
- minby = b.y3;
- else if (b.y3 > maxby)
- maxby = b.y3;
-
- if (b.y2 < minby)
- minby = b.y2;
- else if (b.y2 > maxby)
- maxby = b.y2;
-
- // Test bounding box of b against bounding box of a
- if ((minax > maxbx) || (minay > maxby) // Not >= : need boundary case
- || (minbx > maxax) || (minby > maxay))
- return 0; // they don't intersect
- else
- return 1; // they intersect
-}
-#endif
-
-
#ifdef QDEBUG_BEZIER
static QDebug operator<<(QDebug dbg, const QBezier &bz)
{
@@ -681,193 +623,6 @@ static QDebug operator<<(QDebug dbg, const QBezier &bz)
}
#endif
-static bool RecursivelyIntersect(const QBezier &a, qreal t0, qreal t1, int deptha,
- const QBezier &b, qreal u0, qreal u1, int depthb,
- QVector<QPair<qreal, qreal> > *t)
-{
-#ifdef QDEBUG_BEZIER
- static int I = 0;
- int currentD = I;
- fprintf(stderr, "%d) t0 = %lf, t1 = %lf, deptha = %d\n"
- "u0 = %lf, u1 = %lf, depthb = %d\n", I++, t0, t1, deptha,
- u0, u1, depthb);
-#endif
- if (deptha > 0) {
- QBezier A[2];
- a.split(&A[0], &A[1]);
- qreal tmid = (t0+t1)*0.5;
- //qDebug()<<"\t1)"<<A[0];
- //qDebug()<<"\t2)"<<A[1];
- deptha--;
- if (depthb > 0) {
- QBezier B[2];
- b.split(&B[0], &B[1]);
- //qDebug()<<"\t3)"<<B[0];
- //qDebug()<<"\t4)"<<B[1];
- qreal umid = (u0+u1)*0.5;
- depthb--;
- if (IntersectBB(A[0], B[0])) {
- //fprintf(stderr, "\t 1 from %d\n", currentD);
- if (RecursivelyIntersect(A[0], t0, tmid, deptha,
- B[0], u0, umid, depthb,
- t) && !t)
- return true;
- }
- if (IntersectBB(A[1], B[0])) {
- //fprintf(stderr, "\t 2 from %d\n", currentD);
- if (RecursivelyIntersect(A[1], tmid, t1, deptha,
- B[0], u0, umid, depthb,
- t) && !t)
- return true;
- }
- if (IntersectBB(A[0], B[1])) {
- //fprintf(stderr, "\t 3 from %d\n", currentD);
- if (RecursivelyIntersect(A[0], t0, tmid, deptha,
- B[1], umid, u1, depthb,
- t) && !t)
- return true;
- }
- if (IntersectBB(A[1], B[1])) {
- //fprintf(stderr, "\t 4 from %d\n", currentD);
- if (RecursivelyIntersect(A[1], tmid, t1, deptha,
- B[1], umid, u1, depthb,
- t) && !t)
- return true;
- }
- return t ? !t->isEmpty() : false;
- } else {
- if (IntersectBB(A[0], b)) {
- //fprintf(stderr, "\t 5 from %d\n", currentD);
- if (RecursivelyIntersect(A[0], t0, tmid, deptha,
- b, u0, u1, depthb,
- t) && !t)
- return true;
- }
- if (IntersectBB(A[1], b)) {
- //fprintf(stderr, "\t 6 from %d\n", currentD);
- if (RecursivelyIntersect(A[1], tmid, t1, deptha,
- b, u0, u1, depthb,
- t) && !t)
- return true;
- }
- return t ? !t->isEmpty() : false;
- }
- } else {
- if (depthb > 0) {
- QBezier B[2];
- b.split(&B[0], &B[1]);
- qreal umid = (u0 + u1)*0.5;
- depthb--;
- if (IntersectBB(a, B[0])) {
- //fprintf(stderr, "\t 7 from %d\n", currentD);
- if (RecursivelyIntersect(a, t0, t1, deptha,
- B[0], u0, umid, depthb,
- t) && !t)
- return true;
- }
- if (IntersectBB(a, B[1])) {
- //fprintf(stderr, "\t 8 from %d\n", currentD);
- if (RecursivelyIntersect(a, t0, t1, deptha,
- B[1], umid, u1, depthb,
- t) && !t)
- return true;
- }
- return t ? !t->isEmpty() : false;
- }
- else {
- // Both segments are fully subdivided; now do line segments
- qreal xlk = a.x4 - a.x1;
- qreal ylk = a.y4 - a.y1;
- qreal xnm = b.x4 - b.x1;
- qreal ynm = b.y4 - b.y1;
- qreal xmk = b.x1 - a.x1;
- qreal ymk = b.y1 - a.y1;
- qreal det = xnm * ylk - ynm * xlk;
- if (1.0 + det == 1.0) {
- return false;
- } else {
- qreal detinv = 1.0 / det;
- qreal rs = (xnm * ymk - ynm *xmk) * detinv;
- qreal rt = (xlk * ymk - ylk * xmk) * detinv;
- if ((rs < 0.0) || (rs > 1.0) || (rt < 0.0) || (rt > 1.0))
- return false;
-
- if (t) {
- const qreal alpha_a = t0 + rs * (t1 - t0);
- const qreal alpha_b = u0 + rt * (u1 - u0);
-
- *t << qMakePair(alpha_a, alpha_b);
- }
-
- return true;
- }
- }
- }
-}
-
-QVector< QPair<qreal, qreal> > QBezier::findIntersections(const QBezier &a, const QBezier &b)
-{
- QVector< QPair<qreal, qreal> > v(2);
- findIntersections(a, b, &v);
- return v;
-}
-
-bool QBezier::findIntersections(const QBezier &a, const QBezier &b,
- QVector<QPair<qreal, qreal> > *t)
-{
- if (IntersectBB(a, b)) {
- QPointF la1(qFabs((a.x3 - a.x2) - (a.x2 - a.x1)),
- qFabs((a.y3 - a.y2) - (a.y2 - a.y1)));
- QPointF la2(qFabs((a.x4 - a.x3) - (a.x3 - a.x2)),
- qFabs((a.y4 - a.y3) - (a.y3 - a.y2)));
- QPointF la;
- if (la1.x() > la2.x()) la.setX(la1.x()); else la.setX(la2.x());
- if (la1.y() > la2.y()) la.setY(la1.y()); else la.setY(la2.y());
- QPointF lb1(qFabs((b.x3 - b.x2) - (b.x2 - b.x1)),
- qFabs((b.y3 - b.y2) - (b.y2 - b.y1)));
- QPointF lb2(qFabs((b.x4 - b.x3) - (b.x3 - b.x2)),
- qFabs((b.y4 - b.y3) - (b.y3 - b.y2)));
- QPointF lb;
- if (lb1.x() > lb2.x()) lb.setX(lb1.x()); else lb.setX(lb2.x());
- if (lb1.y() > lb2.y()) lb.setY(lb1.y()); else lb.setY(lb2.y());
- qreal l0;
- if (la.x() > la.y())
- l0 = la.x();
- else
- l0 = la.y();
- int ra;
- if (l0 * 0.75 * M_SQRT2 + 1.0 == 1.0)
- ra = 0;
- else
- ra = qCeil(log4(M_SQRT2 * 6.0 / 8.0 * INV_EPS * l0));
- if (lb.x() > lb.y())
- l0 = lb.x();
- else
- l0 = lb.y();
- int rb;
- if (l0 * 0.75 * M_SQRT2 + 1.0 == 1.0)
- rb = 0;
- else
- rb = qCeil(log4(M_SQRT2 * 6.0 / 8.0 * INV_EPS * l0));
-
- // if qreal is float then halve the number of subdivisions
- if (sizeof(qreal) == 4) {
- ra /= 2;
- rb /= 2;
- }
-
- return RecursivelyIntersect(a, 0., 1., ra, b, 0., 1., rb, t);
- }
-
- //Don't sort here because it breaks the orders of corresponding
- // intersections points. this way t's at the same locations correspond
- // to the same intersection point.
- //qSort(parameters[0].begin(), parameters[0].end(), qLess<qreal>());
- //qSort(parameters[1].begin(), parameters[1].end(), qLess<qreal>());
-
- return false;
-}
-
static inline void splitBezierAt(const QBezier &bez, qreal t,
QBezier *left, QBezier *right)
{
@@ -896,42 +651,6 @@ static inline void splitBezierAt(const QBezier &bez, qreal t,
right->y4 = bez.y4;
}
-QVector< QList<QBezier> > QBezier::splitAtIntersections(QBezier &b)
-{
- QVector< QList<QBezier> > curves(2);
-
- QVector< QPair<qreal, qreal> > allInters = findIntersections(*this, b);
-
- QList<qreal> inters1;
- QList<qreal> inters2;
-
- for (int i = 0; i < allInters.size(); ++i) {
- inters1 << allInters[i].first;
- inters2 << allInters[i].second;
- }
-
- qSort(inters1.begin(), inters1.end(), qLess<qreal>());
- qSort(inters2.begin(), inters2.end(), qLess<qreal>());
-
- Q_ASSERT(inters1.count() == inters2.count());
-
- int i;
- for (i = 0; i < inters1.count(); ++i) {
- qreal t1 = inters1.at(i);
- qreal t2 = inters2.at(i);
-
- QBezier curve1, curve2;
- parameterSplitLeft(t1, &curve1);
- b.parameterSplitLeft(t2, &curve2);
- curves[0].append(curve1);
- curves[0].append(curve2);
- }
- curves[0].append(*this);
- curves[1].append(b);
-
- return curves;
-}
-
qreal QBezier::length(qreal error) const
{
qreal length = 0.0;
@@ -1018,13 +737,19 @@ int QBezier::stationaryYPoints(qreal &t0, qreal &t1) const
const qreal b = 2 * y1 - 4 * y2 + 2 * y3;
const qreal c = -y1 + y2;
- qreal reciprocal = b * b - 4 * a * c;
+ if (qFuzzyIsNull(a)) {
+ if (qFuzzyIsNull(b))
+ return 0;
- QList<qreal> result;
+ t0 = -c / b;
+ return t0 > 0 && t0 < 1;
+ }
+
+ qreal reciprocal = b * b - 4 * a * c;
if (qFuzzyIsNull(reciprocal)) {
t0 = -b / (2 * a);
- return 1;
+ return t0 > 0 && t0 < 1;
} else if (reciprocal > 0) {
qreal temp = qSqrt(reciprocal);
diff --git a/src/gui/painting/qbezier_p.h b/src/gui/painting/qbezier_p.h
index 3409bc7994..846635fbe0 100644
--- a/src/gui/painting/qbezier_p.h
+++ b/src/gui/painting/qbezier_p.h
@@ -59,6 +59,7 @@
#include "QtCore/qvector.h"
#include "QtCore/qlist.h"
#include "QtCore/qpair.h"
+#include "QtGui/qtransform.h"
QT_BEGIN_NAMESPACE
@@ -96,6 +97,8 @@ public:
QPointF pt3() const { return QPointF(x3, y3); }
QPointF pt4() const { return QPointF(x4, y4); }
+ QBezier mapBy(const QTransform &transform) const;
+
inline QPointF midPoint() const;
inline QLineF midTangent() const;
@@ -104,18 +107,12 @@ public:
inline void parameterSplitLeft(qreal t, QBezier *left);
inline void split(QBezier *firstHalf, QBezier *secondHalf) const;
+
int shifted(QBezier *curveSegments, int maxSegmets,
qreal offset, float threshold) const;
- QVector< QList<QBezier> > splitAtIntersections(QBezier &a);
-
QBezier bezierOnInterval(qreal t0, qreal t1) const;
-
- static QVector< QPair<qreal, qreal> > findIntersections(const QBezier &a,
- const QBezier &b);
-
- static bool findIntersections(const QBezier &a, const QBezier &b,
- QVector<QPair<qreal, qreal> > *t);
+ QBezier getSubRange(qreal t0, qreal t1) const;
qreal x1, y1, x2, y2, x3, y3, x4, y4;
};
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index dc33896434..24908cec0d 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include <qmath.h>
-#include "qdrawhelper_p.h"
+#include "qblendfunctions_p.h"
QT_BEGIN_NAMESPACE
@@ -88,6 +88,8 @@ static inline quint16 convert_argb32_to_rgb16(quint32 spix)
struct Blend_RGB16_on_RGB16_NoAlpha {
inline void write(quint16 *dst, quint16 src) { *dst = src; }
+
+ inline void flush(void *) {}
};
struct Blend_RGB16_on_RGB16_ConstAlpha {
@@ -100,6 +102,8 @@ struct Blend_RGB16_on_RGB16_ConstAlpha {
*dst = BYTE_MUL_RGB16(src, m_alpha) + BYTE_MUL_RGB16(*dst, m_ialpha);
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
quint32 m_ialpha;
};
@@ -114,6 +118,8 @@ struct Blend_ARGB24_on_RGB16_SourceAlpha {
*dst = s;
}
}
+
+ inline void flush(void *) {}
};
struct Blend_ARGB24_on_RGB16_SourceAndConstAlpha {
@@ -132,6 +138,8 @@ struct Blend_ARGB24_on_RGB16_SourceAndConstAlpha {
}
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
};
@@ -145,6 +153,8 @@ struct Blend_ARGB32_on_RGB16_SourceAlpha {
*dst = s;
}
}
+
+ inline void flush(void *) {}
};
struct Blend_ARGB32_on_RGB16_SourceAndConstAlpha {
@@ -163,99 +173,11 @@ struct Blend_ARGB32_on_RGB16_SourceAndConstAlpha {
}
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
};
-template <typename SRC, typename T>
-void qt_scale_image_16bit(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- const QRectF &targetRect,
- const QRectF &srcRect,
- const QRect &clip,
- T blender)
-{
- qreal sx = targetRect.width() / (qreal) srcRect.width();
- qreal sy = targetRect.height() / (qreal) srcRect.height();
-
- int ix = 0x00010000 / sx;
- int iy = 0x00010000 / sy;
-
-// qDebug() << "scale:" << endl
-// << " - target" << targetRect << endl
-// << " - source" << srcRect << endl
-// << " - clip" << clip << endl
-// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
-
- int cx1 = clip.x();
- int cx2 = clip.x() + clip.width();
- int cy1 = clip.top();
- int cy2 = clip.y() + clip.height();
-
- int tx1 = qRound(targetRect.left());
- int tx2 = qRound(targetRect.right());
- int ty1 = qRound(targetRect.top());
- int ty2 = qRound(targetRect.bottom());
-
- if (tx2 < tx1)
- qSwap(tx2, tx1);
-
- if (ty2 < ty1)
- qSwap(ty2, ty1);
-
- if (tx1 < cx1)
- tx1 = cx1;
-
- if (tx2 >= cx2)
- tx2 = cx2;
-
- if (tx1 >= tx2)
- return;
-
- if (ty1 < cy1)
- ty1 = cy1;
-
- if (ty2 >= cy2)
- ty2 = cy2;
-
- if (ty1 >= ty2)
- return;
-
- int h = ty2 - ty1;
- int w = tx2 - tx1;
-
-
- quint32 basex;
- quint32 srcy;
-
- if (sx < 0) {
- int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
- basex = quint32(srcRect.right() * 65536) + dstx;
- } else {
- int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
- basex = quint32(srcRect.left() * 65536) + dstx;
- }
- if (sy < 0) {
- int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
- srcy = quint32(srcRect.bottom() * 65536) + dsty;
- } else {
- int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
- srcy = quint32(srcRect.top() * 65536) + dsty;
- }
-
- quint16 *dst = ((quint16 *) (destPixels + ty1 * dbpl)) + tx1;
-
- while (h--) {
- const SRC *src = (const SRC *) (srcPixels + (srcy >> 16) * sbpl);
- int srcx = basex;
- for (int x=0; x<w; ++x) {
- blender.write(&dst[x], src[srcx >> 16]);
- srcx += ix;
- }
- dst = (quint16 *)(((uchar *) dst) + dbpl);
- srcy += iy;
- }
-}
-
void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
const QRectF &targetRect,
@@ -447,10 +369,10 @@ static void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl,
-static void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha)
+void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
{
quint16 *dst = (quint16 *) destPixels;
const quint32 *src = (const quint32 *) srcPixels;
@@ -643,6 +565,8 @@ void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
struct Blend_RGB32_on_RGB32_NoAlpha {
inline void write(quint32 *dst, quint32 src) { *dst = src; }
+
+ inline void flush(void *) {}
};
struct Blend_RGB32_on_RGB32_ConstAlpha {
@@ -655,6 +579,8 @@ struct Blend_RGB32_on_RGB32_ConstAlpha {
*dst = BYTE_MUL(src, m_alpha) + BYTE_MUL(*dst, m_ialpha);
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
quint32 m_ialpha;
};
@@ -663,6 +589,8 @@ struct Blend_ARGB32_on_ARGB32_SourceAlpha {
inline void write(quint32 *dst, quint32 src) {
*dst = src + BYTE_MUL(*dst, qAlpha(~src));
}
+
+ inline void flush(void *) {}
};
struct Blend_ARGB32_on_ARGB32_SourceAndConstAlpha {
@@ -676,98 +604,12 @@ struct Blend_ARGB32_on_ARGB32_SourceAndConstAlpha {
*dst = src + BYTE_MUL(*dst, qAlpha(~src));
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
quint32 m_ialpha;
};
-template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- const QRectF &targetRect,
- const QRectF &srcRect,
- const QRect &clip,
- T blender)
-{
- qreal sx = targetRect.width() / (qreal) srcRect.width();
- qreal sy = targetRect.height() / (qreal) srcRect.height();
-
- int ix = 0x00010000 / sx;
- int iy = 0x00010000 / sy;
-
-// qDebug() << "scale:" << endl
-// << " - target" << targetRect << endl
-// << " - source" << srcRect << endl
-// << " - clip" << clip << endl
-// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
-
- int cx1 = clip.x();
- int cx2 = clip.x() + clip.width();
- int cy1 = clip.top();
- int cy2 = clip.y() + clip.height();
-
- int tx1 = qRound(targetRect.left());
- int tx2 = qRound(targetRect.right());
- int ty1 = qRound(targetRect.top());
- int ty2 = qRound(targetRect.bottom());
-
- if (tx2 < tx1)
- qSwap(tx2, tx1);
-
- if (ty2 < ty1)
- qSwap(ty2, ty1);
-
- if (tx1 < cx1)
- tx1 = cx1;
-
- if (tx2 >= cx2)
- tx2 = cx2;
-
- if (tx1 >= tx2)
- return;
-
- if (ty1 < cy1)
- ty1 = cy1;
-
- if (ty2 >= cy2)
- ty2 = cy2;
-
- if (ty1 >= ty2)
- return;
-
- int h = ty2 - ty1;
- int w = tx2 - tx1;
-
- quint32 basex;
- quint32 srcy;
-
- if (sx < 0) {
- int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
- basex = quint32(srcRect.right() * 65536) + dstx;
- } else {
- int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
- basex = quint32(srcRect.left() * 65536) + dstx;
- }
- if (sy < 0) {
- int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
- srcy = quint32(srcRect.bottom() * 65536) + dsty;
- } else {
- int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
- srcy = quint32(srcRect.top() * 65536) + dsty;
- }
-
- quint32 *dst = ((quint32 *) (destPixels + ty1 * dbpl)) + tx1;
-
- while (h--) {
- const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl);
- int srcx = basex;
- for (int x=0; x<w; ++x) {
- blender.write(&dst[x], src[srcx >> 16]);
- srcx += ix;
- }
- dst = (quint32 *)(((uchar *) dst) + dbpl);
- srcy += iy;
- }
-}
-
void qt_scale_image_rgb32_on_rgb32(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
const QRectF &targetRect,
@@ -818,244 +660,6 @@ 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,
diff --git a/src/gui/painting/qblendfunctions_p.h b/src/gui/painting/qblendfunctions_p.h
new file mode 100644
index 0000000000..ad754b0e8c
--- /dev/null
+++ b/src/gui/painting/qblendfunctions_p.h
@@ -0,0 +1,497 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** 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 QBLENDFUNCTIONS_P_H
+#define QBLENDFUNCTIONS_P_H
+
+#include <qmath.h>
+#include "qdrawhelper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+//
+// 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.
+//
+
+template <typename SRC, typename T>
+void qt_scale_image_16bit(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &srcRect,
+ const QRect &clip,
+ T blender)
+{
+ qreal sx = targetRect.width() / (qreal) srcRect.width();
+ qreal sy = targetRect.height() / (qreal) srcRect.height();
+
+ int ix = 0x00010000 / sx;
+ int iy = 0x00010000 / sy;
+
+// qDebug() << "scale:" << endl
+// << " - target" << targetRect << endl
+// << " - source" << srcRect << endl
+// << " - clip" << clip << endl
+// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
+
+ int cx1 = clip.x();
+ int cx2 = clip.x() + clip.width();
+ int cy1 = clip.top();
+ int cy2 = clip.y() + clip.height();
+
+ int tx1 = qRound(targetRect.left());
+ int tx2 = qRound(targetRect.right());
+ int ty1 = qRound(targetRect.top());
+ int ty2 = qRound(targetRect.bottom());
+
+ if (tx2 < tx1)
+ qSwap(tx2, tx1);
+
+ if (ty2 < ty1)
+ qSwap(ty2, ty1);
+
+ if (tx1 < cx1)
+ tx1 = cx1;
+
+ if (tx2 >= cx2)
+ tx2 = cx2;
+
+ if (tx1 >= tx2)
+ return;
+
+ if (ty1 < cy1)
+ ty1 = cy1;
+
+ if (ty2 >= cy2)
+ ty2 = cy2;
+
+ if (ty1 >= ty2)
+ return;
+
+ int h = ty2 - ty1;
+ int w = tx2 - tx1;
+
+
+ quint32 basex;
+ quint32 srcy;
+
+ if (sx < 0) {
+ int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
+ basex = quint32(srcRect.right() * 65536) + dstx;
+ } else {
+ int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
+ basex = quint32(srcRect.left() * 65536) + dstx;
+ }
+ if (sy < 0) {
+ int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
+ srcy = quint32(srcRect.bottom() * 65536) + dsty;
+ } else {
+ int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
+ srcy = quint32(srcRect.top() * 65536) + dsty;
+ }
+
+ quint16 *dst = ((quint16 *) (destPixels + ty1 * dbpl)) + tx1;
+
+ while (h--) {
+ const SRC *src = (const SRC *) (srcPixels + (srcy >> 16) * sbpl);
+ int srcx = basex;
+ int x = 0;
+ for (; x<w-7; x+=8) {
+ blender.write(&dst[x], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+1], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+2], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+3], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+4], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+5], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+6], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+7], src[srcx >> 16]); srcx += ix;
+ }
+ for (; x<w; ++x) {
+ blender.write(&dst[x], src[srcx >> 16]);
+ srcx += ix;
+ }
+ blender.flush(&dst[x]);
+ dst = (quint16 *)(((uchar *) dst) + dbpl);
+ srcy += iy;
+ }
+}
+
+template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &srcRect,
+ const QRect &clip,
+ T blender)
+{
+ qreal sx = targetRect.width() / (qreal) srcRect.width();
+ qreal sy = targetRect.height() / (qreal) srcRect.height();
+
+ int ix = 0x00010000 / sx;
+ int iy = 0x00010000 / sy;
+
+// qDebug() << "scale:" << endl
+// << " - target" << targetRect << endl
+// << " - source" << srcRect << endl
+// << " - clip" << clip << endl
+// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
+
+ int cx1 = clip.x();
+ int cx2 = clip.x() + clip.width();
+ int cy1 = clip.top();
+ int cy2 = clip.y() + clip.height();
+
+ int tx1 = qRound(targetRect.left());
+ int tx2 = qRound(targetRect.right());
+ int ty1 = qRound(targetRect.top());
+ int ty2 = qRound(targetRect.bottom());
+
+ if (tx2 < tx1)
+ qSwap(tx2, tx1);
+
+ if (ty2 < ty1)
+ qSwap(ty2, ty1);
+
+ if (tx1 < cx1)
+ tx1 = cx1;
+
+ if (tx2 >= cx2)
+ tx2 = cx2;
+
+ if (tx1 >= tx2)
+ return;
+
+ if (ty1 < cy1)
+ ty1 = cy1;
+
+ if (ty2 >= cy2)
+ ty2 = cy2;
+
+ if (ty1 >= ty2)
+ return;
+
+ int h = ty2 - ty1;
+ int w = tx2 - tx1;
+
+ quint32 basex;
+ quint32 srcy;
+
+ if (sx < 0) {
+ int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
+ basex = quint32(srcRect.right() * 65536) + dstx;
+ } else {
+ int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
+ basex = quint32(srcRect.left() * 65536) + dstx;
+ }
+ if (sy < 0) {
+ int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
+ srcy = quint32(srcRect.bottom() * 65536) + dsty;
+ } else {
+ int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
+ srcy = quint32(srcRect.top() * 65536) + dsty;
+ }
+
+ quint32 *dst = ((quint32 *) (destPixels + ty1 * dbpl)) + tx1;
+
+ while (h--) {
+ const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl);
+ int srcx = basex;
+ int x = 0;
+ for (; x<w; ++x) {
+ blender.write(&dst[x], src[srcx >> 16]);
+ srcx += ix;
+ }
+ blender.flush(&dst[x]);
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ srcy += iy;
+ }
+}
+
+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;
+ }
+
+ blender.flush(line);
+ }
+ 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);
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QBLENDFUNCTIONS_P_H
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index c0c73a21f2..96d547b291 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -911,7 +911,7 @@ void QBrush::setTransform(const QTransform &matrix)
otherwise returns false.
Two brushes are different if they have different styles, colors or
- pixmaps.
+ transforms or different pixmaps or gradients depending on the style.
\sa operator==()
*/
@@ -923,7 +923,7 @@ void QBrush::setTransform(const QTransform &matrix)
otherwise returns false.
Two brushes are equal if they have equal styles, colors and
- pixmaps.
+ transforms and equal pixmaps or gradients depending on the style.
\sa operator!=()
*/
@@ -932,26 +932,26 @@ bool QBrush::operator==(const QBrush &b) const
{
if (b.d == d)
return true;
- if (b.d->style == d->style && b.d->color == d->color) {
- switch (d->style) {
- case Qt::TexturePattern: {
- QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
- QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
+ if (b.d->style != d->style || b.d->color != d->color || b.d->transform != d->transform)
+ return false;
+ switch (d->style) {
+ case Qt::TexturePattern:
+ {
+ const QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
+ const 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.data());
- QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
- return d1->gradient == d2->gradient;
- }
- default:
- return true;
+ case Qt::LinearGradientPattern:
+ case Qt::RadialGradientPattern:
+ case Qt::ConicalGradientPattern:
+ {
+ const QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
+ const QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
+ return d1->gradient == d2->gradient;
}
+ default:
+ return true;
}
- return false;
}
/*!
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index d6d288ef95..08d5572b0a 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -532,25 +532,49 @@ QString QColor::name() const
void QColor::setNamedColor(const QString &name)
{
+ if (!setColorFromString(name))
+ qWarning("QColor::setNamedColor: Unknown color name '%s'", name.toLatin1().constData());
+}
+
+/*!
+ \since 4.7
+
+ Returns true if the \a name is a valid color name and can
+ be used to construct a valid QColor object, otherwise returns
+ false.
+
+ It uses the same algorithm used in setNamedColor().
+
+ \sa setNamedColor()
+*/
+bool QColor::isValidColor(const QString &name)
+{
+ return !name.isEmpty() && QColor().setColorFromString(name);
+}
+
+bool QColor::setColorFromString(const QString &name)
+{
if (name.isEmpty()) {
invalidate();
- return;
+ return true;
}
if (name.startsWith(QLatin1Char('#'))) {
QRgb rgb;
if (qt_get_hex_rgb(name.constData(), name.length(), &rgb)) {
setRgb(rgb);
+ return true;
} else {
invalidate();
+ return false;
}
- return;
}
#ifndef QT_NO_COLORNAMES
QRgb rgb;
if (qt_get_named_rgb(name.constData(), name.length(), &rgb)) {
setRgba(rgb);
+ return true;
} else
#endif
{
@@ -561,11 +585,12 @@ void QColor::setNamedColor(const QString &name)
&& QX11Info::display()
&& XParseColor(QX11Info::display(), QX11Info::appColormap(), name.toLatin1().constData(), &result)) {
setRgb(result.red >> 8, result.green >> 8, result.blue >> 8);
+ return true;
} else
#endif
{
- qWarning("QColor::setNamedColor: Unknown color name '%s'", name.toLatin1().constData());
invalidate();
+ return false;
}
}
}
@@ -2692,12 +2717,4 @@ QDataStream &operator>>(QDataStream &stream, QColor &color)
\sa QColor::rgb(), QColor::rgba()
*/
-/*! \fn void QColormap::initialize()
- \internal
-*/
-
-/*! \fn void QColormap::cleanup()
- \internal
-*/
-
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h
index 332dc25beb..0ac828d91a 100644
--- a/src/gui/painting/qcolor.h
+++ b/src/gui/painting/qcolor.h
@@ -225,6 +225,8 @@ public:
QT3_SUPPORT uint pixel(int screen = -1) const;
#endif
+ static bool isValidColor(const QString &name);
+
private:
#ifndef QT3_SUPPORT
// do not allow a spec to be used as an alpha value
@@ -232,6 +234,7 @@ private:
#endif
void invalidate();
+ bool setColorFromString(const QString &name);
Spec cspec;
union {
diff --git a/src/gui/painting/qcolormap.qdoc b/src/gui/painting/qcolormap.qdoc
index 56fabf78bc..22a73fdd71 100644
--- a/src/gui/painting/qcolormap.qdoc
+++ b/src/gui/painting/qcolormap.qdoc
@@ -150,3 +150,13 @@
Assigns the given \a colormap to \e this color map and returns
a reference to \e this color map.
*/
+
+/*!
+ \fn void QColormap::initialize()
+ \internal
+*/
+
+/*!
+ \fn void QColormap::cleanup()
+ \internal
+*/
diff --git a/src/gui/painting/qcups.cpp b/src/gui/painting/qcups.cpp
index ac41692e74..1ea1670591 100644
--- a/src/gui/painting/qcups.cpp
+++ b/src/gui/painting/qcups.cpp
@@ -343,7 +343,8 @@ bool QCUPSSupport::printerHasPPD(const char *printerName)
if (!isAvailable())
return false;
const char *ppdFile = _cupsGetPPD(printerName);
- unlink(ppdFile);
+ if (ppdFile)
+ unlink(ppdFile);
return (ppdFile != 0);
}
diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h
index a7834ea03c..bc5f1efcf7 100644
--- a/src/gui/painting/qdatabuffer_p.h
+++ b/src/gui/painting/qdatabuffer_p.h
@@ -81,7 +81,9 @@ public:
inline Type &at(int i) { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
inline const Type &at(int i) const { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
+ inline Type &last() { Q_ASSERT(!isEmpty()); return buffer[siz-1]; }
inline const Type &last() const { Q_ASSERT(!isEmpty()); return buffer[siz-1]; }
+ inline Type &first() { Q_ASSERT(!isEmpty()); return buffer[0]; }
inline const Type &first() const { Q_ASSERT(!isEmpty()); return buffer[0]; }
inline void add(const Type &t) {
@@ -90,6 +92,11 @@ public:
++siz;
}
+ inline void pop_back() {
+ Q_ASSERT(siz > 0);
+ --siz;
+ }
+
inline void resize(int size) {
reserve(size);
siz = size;
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 2724d7f87a..bfa11368d4 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -46,6 +46,7 @@
#include <private/qdrawhelper_armv6_p.h>
#include <private/qdrawhelper_neon_p.h>
#include <private/qmath_p.h>
+#include <private/qsimd_p.h>
#include <qmath.h>
QT_BEGIN_NAMESPACE
@@ -69,8 +70,10 @@ static uint gccBug(uint value)
constants and structures
*/
-static const int fixed_scale = 1 << 16;
-static const int half_point = 1 << 15;
+enum {
+ fixed_scale = 1 << 16,
+ half_point = 1 << 15
+};
static const int buffer_size = 2048;
struct LinearGradientValues
@@ -174,7 +177,7 @@ Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuf
# define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg>
-static const DestFetchProc destFetchProc[QImage::NImageFormats] =
+static DestFetchProc destFetchProc[QImage::NImageFormats] =
{
0, // Format_Invalid
destFetchMono, // Format_Mono,
@@ -322,7 +325,7 @@ Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffe
# define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST>
-static const DestStoreProc destStoreProc[QImage::NImageFormats] =
+static DestStoreProc destStoreProc[QImage::NImageFormats] =
{
0, // Format_Invalid
destStoreMono, // Format_Mono,
@@ -671,6 +674,11 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *
int image_width = data->texture.width;
int image_height = data->texture.height;
+ int image_x1 = data->texture.x1;
+ int image_y1 = data->texture.y1;
+ int image_x2 = data->texture.x2;
+ int image_y2 = data->texture.y2;
+
const qreal cx = x + 0.5;
const qreal cy = y + 0.5;
@@ -690,37 +698,42 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *
fy -= half_point;
while (b < end) {
int x1 = (fx >> 16);
- int x2 = x1 + 1;
+ int x2;
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;
+ int y2;
if (blendType == BlendTransformedBilinearTiled) {
x1 %= image_width;
+ if (x1 < 0) x1 += image_width;
+ x2 = x1 + 1;
x2 %= image_width;
- y1 %= image_height;
- y2 %= image_height;
- if (x1 < 0) x1 += image_width;
- if (x2 < 0) x2 += image_width;
+ y1 %= image_height;
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);
+ y2 = y1 + 1;
+ 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);
+ if (x1 < image_x1) {
+ x2 = x1 = image_x1;
+ } else if (x1 >= image_x2 - 1) {
+ x2 = x1 = image_x2 - 1;
+ } else {
+ x2 = x1 + 1;
+ }
+ if (y1 < image_y1) {
+ y2 = y1 = image_y1;
+ } else if (y1 >= image_y2 - 1) {
+ y2 = y1 = image_y2 - 1;
+ } else {
+ y2 = y1 + 1;
+ }
}
+ 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);
@@ -729,6 +742,11 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *
uint bl = fetch(s2, x1, data->texture.colorTable);
uint br = fetch(s2, x2, data->texture.colorTable);
+ int distx = (fx & 0x0000ffff) >> 8;
+ int disty = (fy & 0x0000ffff) >> 8;
+ int idistx = 256 - distx;
+ int idisty = 256 - disty;
+
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);
@@ -752,9 +770,9 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *
const qreal py = fy * iw - 0.5;
int x1 = int(px) - (px < 0);
- int x2 = x1 + 1;
+ int x2;
int y1 = int(py) - (py < 0);
- int y2 = y1 + 1;
+ int y2;
int distx = int((px - x1) * 256);
int disty = int((py - y1) * 256);
@@ -763,26 +781,36 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *
if (blendType == BlendTransformedBilinearTiled) {
x1 %= image_width;
+ if (x1 < 0) x1 += image_width;
+ x2 = x1 + 1;
x2 %= image_width;
- y1 %= image_height;
- y2 %= image_height;
- if (x1 < 0) x1 += image_width;
- if (x2 < 0) x2 += image_width;
+ y1 %= image_height;
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);
+ y2 = y1 + 1;
+ 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);
+ if (x1 < 0) {
+ x2 = x1 = 0;
+ } else if (x1 >= image_width - 1) {
+ x2 = x1 = image_width - 1;
+ } else {
+ x2 = x1 + 1;
+ }
+ if (y1 < 0) {
+ y2 = y1 = 0;
+ } else if (y1 >= image_height - 1) {
+ y2 = y1 = image_height - 1;
+ } else {
+ y2 = y1 + 1;
+ }
}
+ 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);
@@ -2826,7 +2854,7 @@ static void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest,
}
}
-static const CompositionFunctionSolid functionForModeSolid_C[] = {
+static CompositionFunctionSolid functionForModeSolid_C[] = {
comp_func_solid_SourceOver,
comp_func_solid_DestinationOver,
comp_func_solid_Clear,
@@ -2864,7 +2892,7 @@ static const CompositionFunctionSolid functionForModeSolid_C[] = {
static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C;
-static const CompositionFunction functionForMode_C[] = {
+static CompositionFunction functionForMode_C[] = {
comp_func_SourceOver,
comp_func_DestinationOver,
comp_func_Clear,
@@ -3700,7 +3728,7 @@ template <>
Q_STATIC_TEMPLATE_SPECIALIZATION
inline quint32 alpha_4(const qargb8555 *src)
{
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint8 *src8 = reinterpret_cast<const quint8*>(src);
return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9];
}
@@ -3883,8 +3911,8 @@ inline void interpolate_pixel_unaligned_2(DST *dest, const SRC *src,
template <class DST, class SRC>
inline void interpolate_pixel_2(DST *dest, const SRC *src, quint16 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint16 a = eff_alpha_2(alpha, dest);
const quint16 ia = eff_ialpha_2(alpha, dest);
@@ -3957,8 +3985,8 @@ template <class DST, class SRC>
inline void interpolate_pixel_2(DST *dest, quint8 a,
const SRC *src, quint8 b)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
Q_ASSERT(!SRC::hasAlpha());
@@ -4006,8 +4034,8 @@ inline void interpolate_pixel_2(qrgb444 *dest, quint8 a,
template <class DST, class SRC>
inline void interpolate_pixel_4(DST *dest, const SRC *src, quint32 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = eff_alpha_4(alpha, dest);
const quint32 ia = eff_ialpha_4(alpha, dest);
@@ -4026,8 +4054,8 @@ template <>
inline void interpolate_pixel_4(qargb8565 *dest, const qargb8565 *src,
quint32 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = eff_alpha_4(alpha, dest);
const quint32 ia = eff_ialpha_4(alpha, dest);
@@ -4122,8 +4150,8 @@ template <>
inline void interpolate_pixel_4(qargb8555 *dest, const qargb8555 *src,
quint32 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = eff_alpha_4(alpha, dest);
@@ -4218,8 +4246,8 @@ template <>
inline void interpolate_pixel_4(qrgb888 *dest, const qrgb888 *src,
quint32 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = eff_alpha_4(alpha, dest);
const quint32 ia = eff_ialpha_4(alpha, dest);
@@ -4291,8 +4319,8 @@ template <class DST, class SRC>
inline void interpolate_pixel_4(DST *dest, quint8 a,
const SRC *src, quint8 b)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b);
dest[1] = dest[1].byte_mul(a) + DST(src[1]).byte_mul(b);
@@ -4303,8 +4331,8 @@ inline void interpolate_pixel_4(DST *dest, quint8 a,
template <class DST, class SRC>
inline void blend_sourceOver_4(DST *dest, const SRC *src)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = alpha_4(src);
if (a == 0xffffffff) {
@@ -4319,8 +4347,8 @@ inline void blend_sourceOver_4(DST *dest, const SRC *src)
template <>
inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = alpha_4(src);
if (a == 0xffffffff) {
@@ -4333,8 +4361,8 @@ inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src)
template <>
inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = alpha_4(src);
if (a == 0xffffffff) {
@@ -4347,8 +4375,8 @@ inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src)
template <>
inline void blend_sourceOver_4(qargb6666 *dest, const qargb6666 *src)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = alpha_4(src);
if (a == 0xffffffff) {
@@ -4410,7 +4438,7 @@ void QT_FASTCALL blendUntransformed_dest16(DST *dest, const SRC *src,
{
Q_ASSERT(sizeof(DST) == 2);
Q_ASSERT(sizeof(SRC) == 2);
- Q_ASSERT((long(dest) & 0x3) == (long(src) & 0x3));
+ Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3));
Q_ASSERT(coverage > 0);
const int align = quintptr(dest) & 0x3;
@@ -4478,8 +4506,8 @@ void QT_FASTCALL blendUntransformed_dest16(DST *dest, const SRC *src,
}
while (length >= 2) {
- Q_ASSERT((long(dest) & 3) == 0);
- Q_ASSERT((long(src) & 3) == 0);
+ Q_ASSERT((quintptr(dest) & 3) == 0);
+ Q_ASSERT((quintptr(src) & 3) == 0);
const quint16 a = alpha_2(src);
if (a == 0xffff) {
@@ -4510,7 +4538,7 @@ template <class DST, class SRC>
void QT_FASTCALL blendUntransformed_dest24(DST *dest, const SRC *src,
quint8 coverage, int length)
{
- Q_ASSERT((long(dest) & 0x3) == (long(src) & 0x3));
+ Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3));
Q_ASSERT(sizeof(DST) == 3);
Q_ASSERT(coverage > 0);
@@ -4733,7 +4761,7 @@ static void blend_untransformed_argb8565(int count, const QSpan *spans,
static void blend_untransformed_rgb565(int count, const QSpan *spans,
void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
@@ -5071,7 +5099,7 @@ static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData)
static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
@@ -5140,7 +5168,7 @@ static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData)
}
-template <SpanMethod spanMethod>
+template <SpanMethod spanMethod, TextureBlendType blendType> /* blendType must be either BlendTransformedBilinear or BlendTransformedBilinearTiled */
Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -5153,10 +5181,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const
CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode];
uint buffer[buffer_size];
- int image_x1 = data->texture.x1;
- int image_y1 = data->texture.y1;
- int image_x2 = data->texture.x2;
- int image_y2 = data->texture.y2;
+ const int image_x1 = data->texture.x1;
+ const int image_y1 = data->texture.y1;
+ const int image_x2 = data->texture.x2;
+ const int image_y2 = data->texture.y2;
+ const int image_width = data->texture.width;
+ const int image_height = data->texture.height;
const int scanline_offset = data->texture.bytesPerLine / 4;
if (data->fast_matrix) {
@@ -5186,19 +5216,41 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const
uint *b = buffer;
while (b < end) {
int x1 = (x >> 16);
- int x2 = x1 + 1;
+ int x2;
int y1 = (y >> 16);
- int y2 = y1 + 1;
-
- int distx = ((x - (x1 << 16)) >> 8);
- int disty = ((y - (y1 << 16)) >> 8);
- int idistx = 256 - distx;
- int idisty = 256 - disty;
-
- x1 = qBound(image_x1, x1, image_x2 - 1);
- x2 = qBound(image_x1, x2, image_x2 - 1);
- y1 = qBound(image_y1, y1, image_y2 - 1);
- y2 = qBound(image_y1, y2, image_y2 - 1);
+ int y2;
+
+ if (blendType == BlendTransformedBilinearTiled) {
+ x1 %= image_width;
+ if (x1 < 0) x1 += image_width;
+ x2 = x1 + 1;
+ x2 %= image_width;
+
+ y1 %= image_height;
+ if (y1 < 0) y1 += image_height;
+ y2 = y1 + 1;
+ 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 {
+ if (x1 < image_x1) {
+ x2 = x1 = image_x1;
+ } else if (x1 >= image_x2 - 1) {
+ x2 = x1 = image_x2 - 1;
+ } else {
+ x2 = x1 + 1;
+ }
+ if (y1 < image_y1) {
+ y2 = y1 = image_y1;
+ } else if (y1 >= image_y2 - 1) {
+ y2 = y1 = image_y2 - 1;
+ } else {
+ y2 = y1 + 1;
+ }
+ }
int y1_offset = y1 * scanline_offset;
int y2_offset = y2 * scanline_offset;
@@ -5215,6 +5267,11 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const
uint br = image_bits[y2_offset + x2];
#endif
+ int distx = (x & 0x0000ffff) >> 8;
+ int disty = (y & 0x0000ffff) >> 8;
+ int idistx = 256 - distx;
+ int idisty = 256 - disty;
+
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);
@@ -5264,19 +5321,46 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const
const qreal py = y * iw - 0.5;
int x1 = int(px) - (px < 0);
- int x2 = x1 + 1;
+ int x2;
int y1 = int(py) - (py < 0);
- int y2 = y1 + 1;
+ int y2;
int distx = int((px - x1) * 256);
int disty = int((py - y1) * 256);
int idistx = 256 - distx;
int idisty = 256 - disty;
- x1 = qBound(image_x1, x1, image_x2 - 1);
- x2 = qBound(image_x1, x2, image_x2 - 1);
- y1 = qBound(image_y1, y1, image_y2 - 1);
- y2 = qBound(image_y1, y2, image_y2 - 1);
+ if (blendType == BlendTransformedBilinearTiled) {
+ x1 %= image_width;
+ if (x1 < 0) x1 += image_width;
+ x2 = x1 + 1;
+ x2 %= image_width;
+
+ y1 %= image_height;
+ if (y1 < 0) y1 += image_height;
+ y2 = y1 + 1;
+ 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 {
+ if (x1 < image_x1) {
+ x2 = x1 = image_x1;
+ } else if (x1 >= image_x2 - 1) {
+ x2 = x1 = image_x2 - 1;
+ } else {
+ x2 = x1 + 1;
+ }
+ if (y1 < image_y1) {
+ y2 = y1 = image_y1;
+ } else if (y1 >= image_y2 - 1) {
+ y2 = y1 = image_y2 - 1;
+ } else {
+ y2 = y1 + 1;
+ }
+ }
int y1_offset = y1 * scanline_offset;
int y2_offset = y2 * scanline_offset;
@@ -5365,17 +5449,27 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan
SRC *b = buffer;
while (b < end) {
int x1 = (x >> 16);
- int x2 = x1 + 1;
+ int x2;
int y1 = (y >> 16);
- int y2 = y1 + 1;
+ int y2;
- const int distx = ((x - (x1 << 16)) >> 8);
- const int disty = ((y - (y1 << 16)) >> 8);
- x1 = qBound(src_minx, x1, src_maxx);
- x2 = qBound(src_minx, x2, src_maxx);
- y1 = qBound(src_miny, y1, src_maxy);
- y2 = qBound(src_miny, y2, src_maxy);
+ const int distx = (x & 0x0000ffff) >> 8;
+ const int disty = (y & 0x0000ffff) >> 8;
+ if (x1 < src_minx) {
+ x2 = x1 = src_minx;
+ } else if (x1 >= src_maxx) {
+ x2 = x1 = src_maxx;
+ } else {
+ x2 = x1 + 1;
+ }
+ if (y1 < src_miny) {
+ y2 = y1 = src_miny;
+ } else if (y1 >= src_maxy) {
+ y2 = y1 = src_maxy;
+ } else {
+ y2 = y1 + 1;
+ }
#if 0
if (x1 == x2) {
if (y1 == y2) {
@@ -5466,17 +5560,27 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan
const qreal py = y * iw - qreal(0.5);
int x1 = int(px) - (px < 0);
- int x2 = x1 + 1;
+ int x2;
int y1 = int(py) - (py < 0);
- int y2 = y1 + 1;
+ int y2;
const int distx = int((px - x1) * 256);
const int disty = int((py - y1) * 256);
- x1 = qBound(src_minx, x1, src_maxx);
- x2 = qBound(src_minx, x2, src_maxx);
- y1 = qBound(src_miny, y1, src_maxy);
- y2 = qBound(src_miny, y2, src_maxy);
+ if (x1 < src_minx) {
+ x2 = x1 = src_minx;
+ } else if (x1 >= src_maxx) {
+ x2 = x1 = src_maxx;
+ } else {
+ x2 = x1 + 1;
+ }
+ if (y1 < src_miny) {
+ y2 = y1 = src_miny;
+ } else if (y1 >= src_maxy) {
+ y2 = y1 = src_maxy;
+ } else {
+ y2 = y1 + 1;
+ }
const SRC *src1 = (SRC*)data->texture.scanLine(y1);
const SRC *src2 = (SRC*)data->texture.scanLine(y2);
@@ -5576,7 +5680,7 @@ static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, v
static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans,
void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_RGB16)
@@ -5645,197 +5749,6 @@ static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, voi
}
template <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);
- return;
- }
-
- CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode];
- uint buffer[buffer_size];
-
- int image_width = data->texture.width;
- int image_height = data->texture.height;
- const int scanline_offset = data->texture.bytesPerLine / 4;
-
- 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);
-
- while (count--) {
- void *t = data->rasterBuffer->scanLine(spans->y);
-
- uint *target = ((uint *)t) + spans->x;
- uint *image_bits = (uint *)data->texture.imageData;
-
- const qreal cx = spans->x + 0.5;
- const qreal cy = spans->y + 0.5;
-
- int x = int((data->m21 * cy
- + data->m11 * cx + data->dx) * fixed_scale) - half_point;
- int y = int((data->m22 * cy
- + data->m12 * cx + data->dy) * fixed_scale) - half_point;
-
- int length = spans->len;
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(length, buffer_size);
- const uint *end = buffer + l;
- uint *b = buffer;
- while (b < end) {
- int x1 = (x >> 16);
- int x2 = (x1 + 1);
- int y1 = (y >> 16);
- int y2 = (y1 + 1);
-
- int distx = ((x - (x1 << 16)) >> 8);
- int disty = ((y - (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);
-
- int y1_offset = y1 * scanline_offset;
- int y2_offset = y2 * scanline_offset;
-
-#if defined(Q_IRIX_GCC3_3_WORKAROUND)
- uint tl = gccBug(image_bits[y1_offset + x1]);
- uint tr = gccBug(image_bits[y1_offset + x2]);
- uint bl = gccBug(image_bits[y2_offset + x1]);
- uint br = gccBug(image_bits[y2_offset + x2]);
-#else
- uint tl = image_bits[y1_offset + x1];
- uint tr = image_bits[y1_offset + x2];
- uint bl = image_bits[y2_offset + x1];
- uint br = image_bits[y2_offset + x2];
-#endif
-
- 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);
- ++b;
- x += fdx;
- y += fdy;
- }
- if (spanMethod == RegularSpans)
- func(target, buffer, l, coverage);
- else
- drawBufferSpan(data, buffer, buffer_size,
- spans->x + spans->len - length,
- spans->y, l, coverage);
- target += l;
- length -= l;
- }
- ++spans;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
- while (count--) {
- void *t = data->rasterBuffer->scanLine(spans->y);
-
- uint *target = ((uint *)t) + spans->x;
- uint *image_bits = (uint *)data->texture.imageData;
-
- const qreal cx = spans->x + 0.5;
- const qreal cy = spans->y + 0.5;
-
- qreal x = data->m21 * cy + data->m11 * cx + data->dx;
- qreal y = data->m22 * cy + data->m12 * cx + data->dy;
- qreal w = data->m23 * cy + data->m13 * cx + data->m33;
-
- int length = spans->len;
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(length, buffer_size);
- const uint *end = buffer + l;
- uint *b = buffer;
- while (b < end) {
- const qreal iw = w == 0 ? 1 : 1 / w;
- const qreal px = x * iw - 0.5;
- const qreal py = y * 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 %= 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);
-
- int y1_offset = y1 * scanline_offset;
- int y2_offset = y2 * scanline_offset;
-
-#if defined(Q_IRIX_GCC3_3_WORKAROUND)
- uint tl = gccBug(image_bits[y1_offset + x1]);
- uint tr = gccBug(image_bits[y1_offset + x2]);
- uint bl = gccBug(image_bits[y2_offset + x1]);
- uint br = gccBug(image_bits[y2_offset + x2]);
-#else
- uint tl = image_bits[y1_offset + x1];
- uint tr = image_bits[y1_offset + x2];
- uint bl = image_bits[y2_offset + x1];
- uint br = image_bits[y2_offset + x2];
-#endif
-
- 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);
- ++b;
- x += fdx;
- y += fdy;
- w += fdw;
- }
- if (spanMethod == RegularSpans)
- func(target, buffer, l, coverage);
- else
- drawBufferSpan(data, buffer, buffer_size,
- spans->x + spans->len - length,
- spans->y, l, coverage);
- target += l;
- length -= l;
- }
- ++spans;
- }
- }
-}
-
-template <SpanMethod spanMethod>
Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -6163,7 +6076,7 @@ static void blend_transformed_argb8565(int count, const QSpan *spans,
static void blend_transformed_rgb565(int count, const QSpan *spans,
void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
@@ -6576,7 +6489,7 @@ static void blend_transformed_tiled_argb8565(int count, const QSpan *spans,
static void blend_transformed_tiled_rgb565(int count, const QSpan *spans,
void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
@@ -6737,7 +6650,7 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8
SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32
SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32
- SPANFUNC_POINTER(blend_transformed_bilinear_argb, RegularSpans), // ARGB32_Premultiplied
+ blend_transformed_bilinear_argb<RegularSpans, BlendTransformedBilinear>, // ARGB32_Premultiplied
blend_transformed_bilinear_rgb565,
blend_transformed_bilinear_argb8565,
blend_transformed_bilinear_rgb666,
@@ -6756,7 +6669,7 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8
SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32
SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32
- SPANFUNC_POINTER(blend_transformed_bilinear_tiled_argb, RegularSpans), // ARGB32_Premultiplied
+ blend_transformed_bilinear_argb<RegularSpans, BlendTransformedBilinearTiled>, // ARGB32_Premultiplied
SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB16
SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8565_Premultiplied
SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB666
@@ -6855,7 +6768,7 @@ static const ProcessSpans processTextureSpansCallback[NBlendTypes][QImage::NImag
blend_src_generic<CallbackSpans>, // Indexed8
blend_src_generic<CallbackSpans>, // RGB32
blend_src_generic<CallbackSpans>, // ARGB32
- blend_transformed_bilinear_argb<CallbackSpans>, // ARGB32_Premultiplied
+ blend_transformed_bilinear_argb<CallbackSpans, BlendTransformedBilinear>, // ARGB32_Premultiplied
blend_src_generic<CallbackSpans>, // RGB16
blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied
blend_src_generic<CallbackSpans>, // RGB666
@@ -6874,7 +6787,7 @@ static const ProcessSpans processTextureSpansCallback[NBlendTypes][QImage::NImag
blend_src_generic<CallbackSpans>, // Indexed8
blend_src_generic<CallbackSpans>, // RGB32
blend_src_generic<CallbackSpans>, // ARGB32
- blend_transformed_bilinear_tiled_argb<CallbackSpans>, // ARGB32_Premultiplied
+ blend_transformed_bilinear_argb<CallbackSpans, BlendTransformedBilinearTiled>, // ARGB32_Premultiplied
blend_src_generic<CallbackSpans>, // RGB16
blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied
blend_src_generic<CallbackSpans>, // RGB666
@@ -7134,6 +7047,11 @@ void qt_build_pow_tables() {
int winSmooth;
if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0))
smoothing = winSmooth / 1000.0;
+
+ // Safeguard ourselves against corrupt registry values...
+ if (smoothing > 5 || smoothing < 1)
+ smoothing = 1.4;
+
#endif
#ifdef Q_WS_X11
@@ -7720,199 +7638,6 @@ static void qt_memfill16_setup(quint16 *dest, quint16 value, int count);
qt_memfill32_func qt_memfill32 = qt_memfill32_setup;
qt_memfill16_func qt_memfill16 = qt_memfill16_setup;
-enum CPUFeatures {
- None = 0,
- MMX = 0x1,
- MMXEXT = 0x2,
- MMX3DNOW = 0x4,
- MMX3DNOWEXT = 0x8,
- SSE = 0x10,
- SSE2 = 0x20,
- CMOV = 0x40,
- IWMMXT = 0x80,
- NEON = 0x100
-};
-
-static uint detectCPUFeatures()
-{
-#if defined (Q_OS_WINCE)
-#if defined (ARM)
- if (IsProcessorFeaturePresent(PF_ARM_INTEL_WMMX))
- return IWMMXT;
-#elif defined(_X86_)
- uint features = 0;
-#if defined QT_HAVE_MMX
- if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
- features |= MMX;
-#endif
-#if defined QT_HAVE_3DNOW
- if (IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE))
- features |= MMX3DNOW;
-#endif
- return features;
-#endif
- return 0;
-#elif defined(QT_HAVE_IWMMXT)
- // runtime detection only available when running as a previlegied process
- static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt();
- return doIWMMXT ? IWMMXT : 0;
-#elif defined(QT_HAVE_NEON)
- static const bool doNEON = !qgetenv("QT_NO_NEON").toInt();
- return doNEON ? NEON : 0;
-#else
- uint features = 0;
-#if defined(__x86_64__) || defined(Q_OS_WIN64)
- features = MMX|SSE|SSE2|CMOV;
-#elif defined(__ia64__)
- features = MMX|SSE|SSE2;
-#elif defined(__i386__) || defined(_M_IX86)
- unsigned int extended_result = 0;
- uint result = 0;
- /* see p. 118 of amd64 instruction set manual Vol3 */
-#if defined(Q_CC_GNU)
- asm ("push %%ebx\n"
- "pushf\n"
- "pop %%eax\n"
- "mov %%eax, %%ebx\n"
- "xor $0x00200000, %%eax\n"
- "push %%eax\n"
- "popf\n"
- "pushf\n"
- "pop %%eax\n"
- "xor %%edx, %%edx\n"
- "xor %%ebx, %%eax\n"
- "jz 1f\n"
-
- "mov $0x00000001, %%eax\n"
- "cpuid\n"
- "1:\n"
- "pop %%ebx\n"
- "mov %%edx, %0\n"
- : "=r" (result)
- :
- : "%eax", "%ecx", "%edx"
- );
-
- asm ("push %%ebx\n"
- "pushf\n"
- "pop %%eax\n"
- "mov %%eax, %%ebx\n"
- "xor $0x00200000, %%eax\n"
- "push %%eax\n"
- "popf\n"
- "pushf\n"
- "pop %%eax\n"
- "xor %%edx, %%edx\n"
- "xor %%ebx, %%eax\n"
- "jz 2f\n"
-
- "mov $0x80000000, %%eax\n"
- "cpuid\n"
- "cmp $0x80000000, %%eax\n"
- "jbe 2f\n"
- "mov $0x80000001, %%eax\n"
- "cpuid\n"
- "2:\n"
- "pop %%ebx\n"
- "mov %%edx, %0\n"
- : "=r" (extended_result)
- :
- : "%eax", "%ecx", "%edx"
- );
-#elif defined (Q_OS_WIN)
- _asm {
- push eax
- push ebx
- push ecx
- push edx
- pushfd
- pop eax
- mov ebx, eax
- xor eax, 00200000h
- push eax
- popfd
- pushfd
- pop eax
- mov edx, 0
- xor eax, ebx
- jz skip
-
- mov eax, 1
- cpuid
- mov result, edx
- skip:
- pop edx
- pop ecx
- pop ebx
- pop eax
- }
-
- _asm {
- push eax
- push ebx
- push ecx
- push edx
- pushfd
- pop eax
- mov ebx, eax
- xor eax, 00200000h
- push eax
- popfd
- pushfd
- pop eax
- mov edx, 0
- xor eax, ebx
- jz skip2
-
- mov eax, 80000000h
- cpuid
- cmp eax, 80000000h
- jbe skip2
- mov eax, 80000001h
- cpuid
- mov extended_result, edx
- skip2:
- pop edx
- pop ecx
- pop ebx
- pop eax
- }
-#endif
-
- // result now contains the standard feature bits
- if (result & (1u << 15))
- features |= CMOV;
- if (result & (1u << 23))
- features |= MMX;
- if (extended_result & (1u << 22))
- features |= MMXEXT;
- if (extended_result & (1u << 31))
- features |= MMX3DNOW;
- if (extended_result & (1u << 30))
- features |= MMX3DNOWEXT;
- if (result & (1u << 25))
- features |= SSE;
- if (result & (1u << 26))
- features |= SSE2;
-#endif // i386
-
- if (qgetenv("QT_NO_MMX").toInt())
- features ^= MMX;
- if (qgetenv("QT_NO_MMXEXT").toInt())
- features ^= MMXEXT;
- if (qgetenv("QT_NO_3DNOW").toInt())
- features ^= MMX3DNOW;
- if (qgetenv("QT_NO_3DNOWEXT").toInt())
- features ^= MMX3DNOWEXT;
- if (qgetenv("QT_NO_SSE").toInt())
- features ^= SSE;
- if (qgetenv("QT_NO_SSE2").toInt())
- features ^= SSE2;
-
- return features;
-#endif
-}
-
#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
// Move these to qdrawhelper_arm.c when all
// functions are implemented using arm assembly.
@@ -8005,10 +7730,6 @@ static void qt_blend_color_argb_armv6(int count, const QSpan *spans, void *userD
void qInitDrawhelperAsm()
{
- static uint features = 0xffffffff;
- if (features != 0xffffffff)
- return;
- features = detectCPUFeatures();
qt_memfill32 = qt_memfill_template<quint32, quint32>;
qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16, quint16>;
@@ -8016,7 +7737,7 @@ void qInitDrawhelperAsm()
CompositionFunction *functionForModeAsm = 0;
CompositionFunctionSolid *functionForModeSolidAsm = 0;
-#ifdef QT_NO_DEBUG
+ const uint features = qDetectCPUFeatures();
if (false) {
#ifdef QT_HAVE_SSE2
} else if (features & SSE2) {
@@ -8139,8 +7860,6 @@ void qInitDrawhelperAsm()
}
#endif // IWMMXT
-#endif // QT_NO_DEBUG
-
#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
functionForModeAsm = qt_functionForMode_ARMv6;
functionForModeSolidAsm = qt_functionForModeSolid_ARMv6;
@@ -8159,6 +7878,20 @@ void qInitDrawhelperAsm()
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
+
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16_neon;
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16_neon;
+
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16_neon;
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16_neon;
+
+ qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon;
+
+ functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon;
+ destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon;
+ destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon;
}
#endif
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 77c52022f8..ee5f24a1db 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -40,10 +40,13 @@
****************************************************************************/
#include <private/qdrawhelper_p.h>
+#include <private/qblendfunctions_p.h>
+#include <private/qmath_p.h>
#ifdef QT_HAVE_NEON
#include <private/qdrawhelper_neon_p.h>
+#include <private/qpaintengine_raster_p.h>
#include <arm_neon.h>
QT_BEGIN_NAMESPACE
@@ -87,60 +90,142 @@ static inline uint16x8_t qvsource_over_u16(uint16x8_t src16, uint16x8_t dst16, u
return vaddq_u16(src16, qvbyte_mul_u16(dst16, alpha16, half));
}
-void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha)
+extern "C" void
+pixman_composite_over_8888_0565_asm_neon (int32_t w,
+ int32_t h,
+ uint16_t *dst,
+ int32_t dst_stride,
+ uint32_t *src,
+ int32_t src_stride);
+
+extern "C" void
+pixman_composite_over_8888_8888_asm_neon (int32_t w,
+ int32_t h,
+ uint32_t *dst,
+ int32_t dst_stride,
+ uint32_t *src,
+ int32_t src_stride);
+
+extern "C" void
+pixman_composite_src_0565_8888_asm_neon (int32_t w,
+ int32_t h,
+ uint32_t *dst,
+ int32_t dst_stride,
+ uint16_t *src,
+ int32_t src_stride);
+
+extern "C" void
+pixman_composite_over_n_8_0565_asm_neon (int32_t w,
+ int32_t h,
+ uint16_t *dst,
+ int32_t dst_stride,
+ uint32_t src,
+ int32_t unused,
+ uint8_t *mask,
+ int32_t mask_stride);
+
+extern "C" void
+pixman_composite_scanline_over_asm_neon (int32_t w,
+ const uint32_t *dst,
+ const uint32_t *src);
+
+// qblendfunctions.cpp
+void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
{
- const uint *src = (const uint *) srcPixels;
- uint *dst = (uint *) destPixels;
- uint16x8_t half = vdupq_n_u16(0x80);
- uint16x8_t full = vdupq_n_u16(0xff);
- if (const_alpha == 256) {
- for (int y = 0; y < h; ++y) {
- int x = 0;
- for (; x < w-3; x += 4) {
- uint32x4_t src32 = vld1q_u32((uint32_t *)&src[x]);
- if ((src[x] & src[x+1] & src[x+2] & src[x+3]) >= 0xff000000) {
- // all opaque
- vst1q_u32((uint32_t *)&dst[x], src32);
- } else if (src[x] | src[x+1] | src[x+2] | src[x+3]) {
- uint32x4_t dst32 = vld1q_u32((uint32_t *)&dst[x]);
+ dbpl /= 4;
+ sbpl /= 2;
- const uint8x16_t src8 = vreinterpretq_u8_u32(src32);
- const uint8x16_t dst8 = vreinterpretq_u8_u32(dst32);
+ quint32 *dst = (quint32 *) destPixels;
+ quint16 *src = (quint16 *) srcPixels;
- const uint8x8_t src8_low = vget_low_u8(src8);
- const uint8x8_t dst8_low = vget_low_u8(dst8);
+ if (const_alpha != 256) {
+ quint8 a = (255 * const_alpha) >> 8;
+ quint8 ia = 255 - a;
+
+ while (h--) {
+ for (int x=0; x<w; ++x)
+ dst[x] = INTERPOLATE_PIXEL_255(qt_colorConvert(src[x], dst[x]), a, dst[x], ia);
+ dst += dbpl;
+ src += sbpl;
+ }
+ return;
+ }
- const uint8x8_t src8_high = vget_high_u8(src8);
- const uint8x8_t dst8_high = vget_high_u8(dst8);
+ pixman_composite_src_0565_8888_asm_neon(w, h, dst, dbpl, src, sbpl);
+}
- const uint16x8_t src16_low = vmovl_u8(src8_low);
- const uint16x8_t dst16_low = vmovl_u8(dst8_low);
+extern "C" void blend_8_pixels_argb32_on_rgb16_neon(quint16 *dst, const quint32 *src, int const_alpha);
- const uint16x8_t src16_high = vmovl_u8(src8_high);
- const uint16x8_t dst16_high = vmovl_u8(dst8_high);
+void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+ quint16 *dst = (quint16 *) destPixels;
+ quint32 *src = (quint32 *) srcPixels;
- const uint16x8_t result16_low = qvsource_over_u16(src16_low, dst16_low, half, full);
- const uint16x8_t result16_high = qvsource_over_u16(src16_high, dst16_high, half, full);
+ if (const_alpha != 256) {
+ for (int y=0; y<h; ++y) {
+ int i = 0;
+ for (; i < w-7; i += 8)
+ blend_8_pixels_argb32_on_rgb16_neon(&dst[i], &src[i], const_alpha);
- const uint32x2_t result32_low = vreinterpret_u32_u8(vmovn_u16(result16_low));
- const uint32x2_t result32_high = vreinterpret_u32_u8(vmovn_u16(result16_high));
+ if (i < w) {
+ int tail = w - i;
- vst1q_u32((uint32_t *)&dst[x], vcombine_u32(result32_low, result32_high));
+ quint16 dstBuffer[8];
+ quint32 srcBuffer[8];
+
+ for (int j = 0; j < tail; ++j) {
+ dstBuffer[j] = dst[i + j];
+ srcBuffer[j] = src[i + j];
+ }
+
+ blend_8_pixels_argb32_on_rgb16_neon(dstBuffer, srcBuffer, const_alpha);
+
+ for (int j = 0; j < tail; ++j) {
+ dst[i + j] = dstBuffer[j];
+ src[i + j] = srcBuffer[j];
}
}
- for (; x<w; ++x) {
- uint s = src[x];
- if (s >= 0xff000000)
- dst[x] = s;
- 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);
+
+ dst = (quint16 *)(((uchar *) dst) + dbpl);
+ src = (quint32 *)(((uchar *) src) + sbpl);
}
+ return;
+ }
+
+ pixman_composite_over_8888_0565_asm_neon(w, h, dst, dbpl / 2, src, sbpl / 4);
+}
+
+void qt_blend_argb32_on_argb32_scanline_neon(uint *dest, const uint *src, int length, uint const_alpha)
+{
+ if (const_alpha == 255) {
+ pixman_composite_scanline_over_asm_neon(length, dest, src);
+ } else {
+ qt_blend_argb32_on_argb32_neon((uchar *)dest, 4 * length, (uchar *)src, 4 * length, length, 1, (const_alpha * 256) / 255);
+ }
+}
+
+void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+ const uint *src = (const uint *) srcPixels;
+ uint *dst = (uint *) destPixels;
+ uint16x8_t half = vdupq_n_u16(0x80);
+ uint16x8_t full = vdupq_n_u16(0xff);
+ if (const_alpha == 256) {
+ pixman_composite_over_8888_8888_asm_neon(w, h, (uint32_t *)destPixels, dbpl / 4, (uint32_t *)srcPixels, sbpl / 4);
} else if (const_alpha != 0) {
const_alpha = (const_alpha * 255) >> 8;
uint16x8_t const_alpha16 = vdupq_n_u16(const_alpha);
@@ -254,6 +339,246 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
}
}
+void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
+ int x, int y, quint32 color,
+ const uchar *bitmap,
+ int mapWidth, int mapHeight, int mapStride,
+ const QClipData *)
+{
+ quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
+ const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
+
+ uchar *mask = const_cast<uchar *>(bitmap);
+
+ pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, color, 0, mask, mapStride);
+}
+
+extern "C" void blend_8_pixels_rgb16_on_rgb16_neon(quint16 *dst, const quint16 *src, int const_alpha);
+
+template <typename SRC, typename BlendFunc>
+struct Blend_on_RGB16_SourceAndConstAlpha_Neon {
+ Blend_on_RGB16_SourceAndConstAlpha_Neon(BlendFunc blender, int const_alpha)
+ : m_index(0)
+ , m_blender(blender)
+ , m_const_alpha(const_alpha)
+ {
+ }
+
+ inline void write(quint16 *dst, quint32 src)
+ {
+ srcBuffer[m_index++] = src;
+
+ if (m_index == 8) {
+ m_blender(dst - 7, srcBuffer, m_const_alpha);
+ m_index = 0;
+ }
+ }
+
+ inline void flush(quint16 *dst)
+ {
+ if (m_index > 0) {
+ quint16 dstBuffer[8];
+ for (int i = 0; i < m_index; ++i)
+ dstBuffer[i] = dst[i - m_index];
+
+ m_blender(dstBuffer, srcBuffer, m_const_alpha);
+
+ for (int i = 0; i < m_index; ++i)
+ dst[i - m_index] = dstBuffer[i];
+
+ m_index = 0;
+ }
+ }
+
+ SRC srcBuffer[8];
+
+ int m_index;
+ BlendFunc m_blender;
+ int m_const_alpha;
+};
+
+template <typename SRC, typename BlendFunc>
+Blend_on_RGB16_SourceAndConstAlpha_Neon<SRC, BlendFunc>
+Blend_on_RGB16_SourceAndConstAlpha_Neon_create(BlendFunc blender, int const_alpha)
+{
+ return Blend_on_RGB16_SourceAndConstAlpha_Neon<SRC, BlendFunc>(blender, const_alpha);
+}
+
+void qt_scale_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha)
+{
+ if (const_alpha == 0)
+ return;
+
+ qt_scale_image_16bit<quint32>(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip,
+ Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint32>(blend_8_pixels_argb32_on_rgb16_neon, const_alpha));
+}
+
+void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha);
+
+void qt_scale_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha)
+{
+ if (const_alpha == 0)
+ return;
+
+ if (const_alpha == 256) {
+ qt_scale_image_rgb16_on_rgb16(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip, const_alpha);
+ return;
+ }
+
+ qt_scale_image_16bit<quint16>(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip,
+ Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint16>(blend_8_pixels_rgb16_on_rgb16_neon, const_alpha));
+}
+
+extern 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);
+
+void qt_transform_image_rgb16_on_rgb16_neon(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 == 0)
+ return;
+
+ if (const_alpha == 256) {
+ qt_transform_image_rgb16_on_rgb16(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip, targetRectTransform, const_alpha);
+ return;
+ }
+
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const quint16 *>(srcPixels), sbpl, targetRect, sourceRect, clip, targetRectTransform,
+ Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint16>(blend_8_pixels_rgb16_on_rgb16_neon, const_alpha));
+}
+
+void qt_transform_image_argb32_on_rgb16_neon(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 == 0)
+ return;
+
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const quint32 *>(srcPixels), sbpl, targetRect, sourceRect, clip, targetRectTransform,
+ Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint32>(blend_8_pixels_argb32_on_rgb16_neon, const_alpha));
+}
+
+static inline void convert_8_pixels_rgb16_to_argb32(quint32 *dst, const quint16 *src)
+{
+ asm volatile (
+ "vld1.16 { d0, d1 }, [%[SRC]]\n\t"
+
+ /* convert 8 r5g6b5 pixel data from {d0, d1} to planar 8-bit format
+ and put data into d4 - red, d3 - green, d2 - blue */
+ "vshrn.u16 d4, q0, #8\n\t"
+ "vshrn.u16 d3, q0, #3\n\t"
+ "vsli.u16 q0, q0, #5\n\t"
+ "vsri.u8 d4, d4, #5\n\t"
+ "vsri.u8 d3, d3, #6\n\t"
+ "vshrn.u16 d2, q0, #2\n\t"
+
+ /* fill d5 - alpha with 0xff */
+ "mov r2, #255\n\t"
+ "vdup.8 d5, r2\n\t"
+
+ "vst4.8 { d2, d3, d4, d5 }, [%[DST]]"
+ : : [DST]"r" (dst), [SRC]"r" (src)
+ : "memory", "r2", "d0", "d1", "d2", "d3", "d4", "d5"
+ );
+}
+
+uint * QT_FASTCALL qt_destFetchRGB16_neon(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+{
+ const ushort *data = (const ushort *)rasterBuffer->scanLine(y) + x;
+
+ int i = 0;
+ for (; i < length - 7; i += 8)
+ convert_8_pixels_rgb16_to_argb32(&buffer[i], &data[i]);
+
+ if (i < length) {
+ quint16 srcBuffer[8];
+ quint32 dstBuffer[8];
+
+ int tail = length - i;
+ for (int j = 0; j < tail; ++j)
+ srcBuffer[j] = data[i + j];
+
+ convert_8_pixels_rgb16_to_argb32(dstBuffer, srcBuffer);
+
+ for (int j = 0; j < tail; ++j)
+ buffer[i + j] = dstBuffer[j];
+ }
+
+ return buffer;
+}
+
+static inline void convert_8_pixels_argb32_to_rgb16(quint16 *dst, const quint32 *src)
+{
+ asm volatile (
+ "vld4.8 { d0, d1, d2, d3 }, [%[SRC]]\n\t"
+
+ /* convert to r5g6b5 and store it into {d28, d29} */
+ "vshll.u8 q14, d2, #8\n\t"
+ "vshll.u8 q8, d1, #8\n\t"
+ "vshll.u8 q9, d0, #8\n\t"
+ "vsri.u16 q14, q8, #5\n\t"
+ "vsri.u16 q14, q9, #11\n\t"
+
+ "vst1.16 { d28, d29 }, [%[DST]]"
+ : : [DST]"r" (dst), [SRC]"r" (src)
+ : "memory", "d0", "d1", "d2", "d3", "d16", "d17", "d18", "d19", "d28", "d29"
+ );
+}
+
+void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length)
+{
+ quint16 *data = (quint16*)rasterBuffer->scanLine(y) + x;
+
+ int i = 0;
+ for (; i < length - 7; i += 8)
+ convert_8_pixels_argb32_to_rgb16(&data[i], &buffer[i]);
+
+ if (i < length) {
+ quint32 srcBuffer[8];
+ quint16 dstBuffer[8];
+
+ int tail = length - i;
+ for (int j = 0; j < tail; ++j)
+ srcBuffer[j] = buffer[i + j];
+
+ convert_8_pixels_argb32_to_rgb16(dstBuffer, srcBuffer);
+
+ for (int j = 0; j < tail; ++j)
+ data[i + j] = dstBuffer[j];
+ }
+}
+
QT_END_NAMESPACE
#endif // QT_HAVE_NEON
diff --git a/src/gui/painting/qdrawhelper_neon_asm.S b/src/gui/painting/qdrawhelper_neon_asm.S
new file mode 100644
index 0000000000..9992817fec
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_neon_asm.S
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** 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$
+**
+****************************************************************************/
+
+/* Prevent the stack from becoming executable for no reason... */
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+.text
+.fpu neon
+.arch armv7a
+.altmacro
+
+/* void blend_8_pixels_argb32_on_rgb16_neon(quint16 *dst, const quint32 *src, int const_alpha) */
+
+ .func blend_8_pixels_argb32_on_rgb16_neon
+ .global blend_8_pixels_argb32_on_rgb16_neon
+ /* For ELF format also set function visibility to hidden */
+#ifdef __ELF__
+ .hidden blend_8_pixels_argb32_on_rgb16_neon
+ .type blend_8_pixels_argb32_on_rgb16_neon, %function
+#endif
+blend_8_pixels_argb32_on_rgb16_neon:
+ vld4.8 { d0, d1, d2, d3 }, [r1]
+ vld1.16 { d4, d5 }, [r0]
+
+ cmp r2, #256
+ beq .blend_32_inner
+
+ vdup.8 d6, r2
+
+ /* multiply by const_alpha */
+ vmull.u8 q8, d6, d0
+ vmull.u8 q9, d6, d1
+ vmull.u8 q10, d6, d2
+ vmull.u8 q11, d6, d3
+
+ vshrn.u16 d0, q8, #8
+ vshrn.u16 d1, q9, #8
+ vshrn.u16 d2, q10, #8
+ vshrn.u16 d3, q11, #8
+
+.blend_32_inner:
+ /* convert 8 r5g6b5 pixel data from {d4, d5} to planar 8-bit format
+ and put data into d6 - red, d7 - green, d30 - blue */
+ vshrn.u16 d6, q2, #8
+ vshrn.u16 d7, q2, #3
+ vsli.u16 q2, q2, #5
+ vsri.u8 d6, d6, #5
+ vmvn.8 d3, d3
+ vsri.u8 d7, d7, #6
+ vshrn.u16 d30, q2, #2
+
+ pld [r0, #128]
+
+ /* now do alpha blending, storing results in 8-bit planar format
+ into d16 - red, d19 - green, d18 - blue */
+ vmull.u8 q10, d3, d6
+ vmull.u8 q11, d3, d7
+ vmull.u8 q12, d3, d30
+ vrshr.u16 q13, q10, #8
+ vrshr.u16 q3, q11, #8
+ vrshr.u16 q15, q12, #8
+ vraddhn.u16 d20, q10, q13
+ vraddhn.u16 d23, q11, q3
+ vraddhn.u16 d22, q12, q15
+ vqadd.u8 d16, d2, d20
+ vqadd.u8 q9, q0, q11
+ /* convert the result to r5g6b5 and store it into {d28, d29} */
+ vshll.u8 q14, d16, #8
+ vshll.u8 q8, d19, #8
+ vshll.u8 q9, d18, #8
+ vsri.u16 q14, q8, #5
+ vsri.u16 q14, q9, #11
+
+ vst1.16 { d28, d29 }, [r0]
+
+ bx lr
+
+ .endfunc
+
+/* void blend_8_pixels_rgb16_on_rgb16_neon(quint16 *dst, const quint16 *src, int const_alpha) */
+
+ .func blend_8_pixels_rgb16_on_rgb16_neon
+ .global blend_8_pixels_rgb16_on_rgb16_neon
+ /* For ELF format also set function visibility to hidden */
+#ifdef __ELF__
+ .hidden blend_8_pixels_rgb16_on_rgb16_neon
+ .type blend_8_pixels_rgb16_on_rgb16_neon, %function
+#endif
+blend_8_pixels_rgb16_on_rgb16_neon:
+ vld1.16 { d0, d1 }, [r0]
+ vld1.16 { d2, d3 }, [r1]
+
+ rsb r3, r2, #256
+ vdup.8 d4, r2
+ vdup.8 d5, r3
+
+ /* convert 8 r5g6b5 pixel data from {d0, d1} to planar 8-bit format
+ and put data into d6 - red, d7 - green, d30 - blue */
+ vshrn.u16 d6, q0, #8
+ vshrn.u16 d7, q0, #3
+ vsli.u16 q0, q0, #5
+ vsri.u8 d6, d6, #5
+ vsri.u8 d7, d7, #6
+ vshrn.u16 d30, q0, #2
+
+ /* same from {d2, d3} into {d26, d27, d28} */
+ vshrn.u16 d26, q1, #8
+ vshrn.u16 d27, q1, #3
+ vsli.u16 q1, q1, #5
+ vsri.u8 d26, d26, #5
+ vsri.u8 d27, d27, #6
+ vshrn.u16 d28, q1, #2
+
+ /* multiply dst by inv const_alpha */
+ vmull.u8 q10, d5, d6
+ vmull.u8 q11, d5, d7
+ vmull.u8 q12, d5, d30
+
+ vshrn.u16 d6, q10, #8
+ vshrn.u16 d7, q11, #8
+ vshrn.u16 d30, q12, #8
+
+ /* multiply src by const_alpha */
+ vmull.u8 q10, d4, d26
+ vmull.u8 q11, d4, d27
+ vmull.u8 q12, d4, d28
+
+ vshrn.u16 d26, q10, #8
+ vshrn.u16 d27, q11, #8
+ vshrn.u16 d28, q12, #8
+
+ /* preload dst + 128 */
+ pld [r0, #128]
+
+ /* add components, storing results in 8-bit planar format
+ into d16 - red, d19 - green, d18 - blue */
+ vadd.u8 d16, d26, d6
+ vadd.u8 d19, d27, d7
+ vadd.u8 d18, d28, d30
+
+ /* convert the result to r5g6b5 and store it into {d28, d29} */
+ vshll.u8 q14, d16, #8
+ vshll.u8 q8, d19, #8
+ vshll.u8 q9, d18, #8
+ vsri.u16 q14, q8, #5
+ vsri.u16 q14, q9, #11
+
+ vst1.16 { d28, d29 }, [r0]
+
+ bx lr
+
+ .endfunc
diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
index 1994441b65..d6a4509075 100644
--- a/src/gui/painting/qdrawhelper_neon_p.h
+++ b/src/gui/painting/qdrawhelper_neon_p.h
@@ -69,6 +69,64 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
int w, int h,
int const_alpha);
+void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+void qt_blend_argb32_on_argb32_scanline_neon(uint *dest,
+ const uint *src,
+ int length,
+ uint const_alpha);
+
+void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
+ int x, int y, quint32 color,
+ const uchar *bitmap,
+ int mapWidth, int mapHeight, int mapStride,
+ const QClipData *clip);
+
+void qt_scale_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha);
+
+void qt_scale_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha);
+
+void qt_transform_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha);
+
+void qt_transform_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha);
+
+uint * QT_FASTCALL qt_destFetchRGB16_neon(uint *buffer,
+ QRasterBuffer *rasterBuffer,
+ int x, int y, int length);
+
+void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer,
+ int x, int y, const uint *buffer, int length);
+
#endif // QT_HAVE_NEON
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index cb0db4fdb3..acf765c5f2 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -67,17 +67,15 @@
#include "QtGui/qscreen_qws.h"
#endif
-// Disable MMX and SSE on Mac/PPC builds, or if the compiler
-// does not support -Xarch argument passing
-#if defined(QT_NO_MAC_XARCH) || (defined(Q_OS_DARWIN) && (defined(__ppc__) || defined(__ppc64__)))
-#undef QT_HAVE_SSE2
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_MAC) && (defined(__ppc__) || defined(__ppc64__))
+#undef QT_HAVE_MMX
#undef QT_HAVE_SSE
+#undef QT_HAVE_SSE2
#undef QT_HAVE_3DNOW
-#undef QT_HAVE_MMX
#endif
-QT_BEGIN_NAMESPACE
-
#if defined(Q_CC_MSVC) && _MSCVER <= 1300 && !defined(Q_CC_INTEL)
#define Q_STATIC_TEMPLATE_SPECIALIZATION static
#else
@@ -1649,7 +1647,7 @@ inline void qt_memconvert(qrgb666 *dest, const quint32 *src, int count)
return;
}
- const int align = (long(dest) & 3);
+ const int align = (quintptr(dest) & 3);
switch (align) {
case 1: *dest++ = qrgb666(*src++); --count;
case 2: *dest++ = qrgb666(*src++); --count;
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index 35bf2bfd24..a62f06bde9 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1081,7 +1081,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
according to the \a margins structure.
*/
-typedef QVarLengthArray<QDrawPixmaps::Data, 16> QDrawPixmapsDataArray;
+typedef QVarLengthArray<QPainter::PixmapFragment, 16> QPixmapFragmentsArray;
/*!
\since 4.6
@@ -1102,12 +1102,12 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
{
- QDrawPixmaps::Data d;
+ QPainter::PixmapFragment d;
d.opacity = 1.0;
d.rotation = 0.0;
- QDrawPixmapsDataArray opaqueData;
- QDrawPixmapsDataArray translucentData;
+ QPixmapFragmentsArray opaqueData;
+ QPixmapFragmentsArray translucentData;
// source center
const int sourceCenterTop = sourceRect.top() + sourceMargins.top();
@@ -1182,44 +1182,56 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
// corners
if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
- d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
- d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
- d.source = QRectF(sourceRect.left(), sourceRect.top(), sourceMargins.left(), sourceMargins.top());
- d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
- d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
+ d.x = (0.5 * (xTarget[1] + xTarget[0]));
+ d.y = (0.5 * (yTarget[1] + yTarget[0]));
+ d.sourceLeft = sourceRect.left();
+ d.sourceTop = sourceRect.top();
+ d.width = sourceMargins.left();
+ d.height = sourceMargins.top();
+ d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
+ d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
if (hints & QDrawBorderPixmap::OpaqueTopLeft)
opaqueData.append(d);
else
translucentData.append(d);
}
if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
- d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
- d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
- d.source = QRectF(sourceCenterRight, sourceRect.top(), sourceMargins.right(), sourceMargins.top());
- d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
- d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
+ d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
+ d.y = (0.5 * (yTarget[1] + yTarget[0]));
+ d.sourceLeft = sourceCenterRight;
+ d.sourceTop = sourceRect.top();
+ d.width = sourceMargins.right();
+ d.height = sourceMargins.top();
+ d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
+ d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
if (hints & QDrawBorderPixmap::OpaqueTopRight)
opaqueData.append(d);
else
translucentData.append(d);
}
if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
- d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
- d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
- d.source = QRectF(sourceRect.left(), sourceCenterBottom, sourceMargins.left(), sourceMargins.bottom());
- d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
- d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
+ d.x = (0.5 * (xTarget[1] + xTarget[0]));
+ d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1]));
+ d.sourceLeft = sourceRect.left();
+ d.sourceTop = sourceCenterBottom;
+ d.width = sourceMargins.left();
+ d.height = sourceMargins.bottom();
+ d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
+ d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
if (hints & QDrawBorderPixmap::OpaqueBottomLeft)
opaqueData.append(d);
else
translucentData.append(d);
}
if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
- d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
- d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
- d.source = QRectF(sourceCenterRight, sourceCenterBottom, sourceMargins.right(), sourceMargins.bottom());
- d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
- d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
+ d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
+ d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
+ d.sourceLeft = sourceCenterRight;
+ d.sourceTop = sourceCenterBottom;
+ d.width = sourceMargins.right();
+ d.height = sourceMargins.bottom();
+ d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
+ d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
if (hints & QDrawBorderPixmap::OpaqueBottomRight)
opaqueData.append(d);
else
@@ -1229,158 +1241,107 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
// horizontal edges
if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
- d.source = QRectF(sourceCenterLeft, sourceRect.top(), sourceCenterWidth, sourceMargins.top());
- d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
- d.scaleX = dx / d.source.width();
- d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
+ d.sourceLeft = sourceCenterLeft;
+ d.sourceTop = sourceRect.top();
+ d.width = sourceCenterWidth;
+ d.height = sourceMargins.top();
+ d.y = (0.5 * (yTarget[1] + yTarget[0]));
+ d.scaleX = dx / d.width;
+ d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
for (int i = 1; i < columns - 1; ++i) {
- d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
+ d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
data.append(d);
}
if (rules.horizontal == Qt::RepeatTile)
- data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
+ data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
}
if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
- d.source = QRectF(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom());;
- d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
- d.scaleX = dx / d.source.width();
- d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
+ d.sourceLeft = sourceCenterLeft;
+ d.sourceTop = sourceCenterBottom;
+ d.width = sourceCenterWidth;
+ d.height = sourceMargins.bottom();
+ d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
+ d.scaleX = dx / d.width;
+ d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
for (int i = 1; i < columns - 1; ++i) {
- d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
+ d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
data.append(d);
}
if (rules.horizontal == Qt::RepeatTile)
- data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
+ data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
}
}
// vertical edges
if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
- d.source = QRectF(sourceRect.left(), sourceCenterTop, sourceMargins.left(), sourceCenterHeight);
- d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
- d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
- d.scaleY = dy / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
+ d.sourceLeft = sourceRect.left();
+ d.sourceTop = sourceCenterTop;
+ d.width = sourceMargins.left();
+ d.height = sourceCenterHeight;
+ d.x = (0.5 * (xTarget[1] + xTarget[0]));
+ d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
+ d.scaleY = dy / d.height;
for (int i = 1; i < rows - 1; ++i) {
- d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
+ d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
data.append(d);
}
if (rules.vertical == Qt::RepeatTile)
- data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
+ data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
}
if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
- d.source = QRectF(sourceCenterRight, sourceCenterTop, sourceMargins.right(), sourceCenterHeight);
- d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
- d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
- d.scaleY = dy / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
+ d.sourceLeft = sourceCenterRight;
+ d.sourceTop = sourceCenterTop;
+ d.width = sourceMargins.right();
+ d.height = sourceCenterHeight;
+ d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
+ d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
+ d.scaleY = dy / d.height;
for (int i = 1; i < rows - 1; ++i) {
- d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
+ d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
data.append(d);
}
if (rules.vertical == Qt::RepeatTile)
- data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
+ data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
}
}
// center
if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
- d.source = QRectF(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
- d.scaleX = dx / d.source.width();
- d.scaleY = dy / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
+ d.sourceLeft = sourceCenterLeft;
+ d.sourceTop = sourceCenterTop;
+ d.width = sourceCenterWidth;
+ d.height = sourceCenterHeight;
+ d.scaleX = dx / d.width;
+ d.scaleY = dy / d.height;
qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY;
for (int j = 1; j < rows - 1; ++j) {
- d.point.setY(0.5 * (yTarget[j + 1] + yTarget[j]));
+ d.y = (0.5 * (yTarget[j + 1] + yTarget[j]));
for (int i = 1; i < columns - 1; ++i) {
- d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
+ d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
data.append(d);
}
if (rules.horizontal == Qt::RepeatTile)
- data[data.size() - 1].source.setWidth(repeatWidth);
+ data[data.size() - 1].width = repeatWidth;
}
if (rules.vertical == Qt::RepeatTile) {
for (int i = 1; i < columns - 1; ++i)
- data[data.size() - i].source.setHeight(repeatHeight);
+ data[data.size() - i].height = repeatHeight;
}
}
if (opaqueData.size())
- qDrawPixmaps(painter, opaqueData.data(), opaqueData.size(), pixmap, QDrawPixmaps::OpaqueHint);
+ painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint);
if (translucentData.size())
- qDrawPixmaps(painter, translucentData.data(), translucentData.size(), pixmap);
-}
-
-/*!
- \class QDrawPixmaps::Data
- \since 4.6
- \internal
-
- This structure is used with the qDrawPixmaps() function.
-
- QPointF point: Specifies the center of the target rectangle.
- QRectF source: Specifies the source rectangle in the pixmap passed into the qDrawPixmaps() call.
- qreal scaleX: Specifies the horizontal scale of the target rectangle.
- qreal scaleY: Specifies the vertical scale of the target rectangle.
- qreal rotation: Specifies the rotation of the target rectangle in degrees.
- The target rectangle is rotated after scaling.
- qreal opacity: Specifies the opacity of the rectangle.
-*/
-
-/*!
- \enum QDrawPixmaps::DrawingHint
- \internal
-*/
-
-/*!
- \internal
- \since 4.6
-
- This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap, at multiple positions
- with different scale, rotation and opacity on \a painter. \a drawingData is an array of \a
- dataCount elements specifying the parameters used to draw each pixmap instance.
- This can be used for example to implement a particle system.
-*/
-void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
-{
- QPaintEngine *engine = painter->paintEngine();
- if (!engine)
- return;
-
- if (engine->isExtended()) {
- static_cast<QPaintEngineEx *>(engine)->drawPixmaps(drawingData, dataCount, pixmap, hints);
- } else {
- qreal oldOpacity = painter->opacity();
- QTransform oldTransform = painter->transform();
-
- for (int i = 0; i < dataCount; ++i) {
- QTransform transform = oldTransform;
- qreal xOffset = 0;
- qreal yOffset = 0;
- if (drawingData[i].rotation == 0) {
- xOffset = drawingData[i].point.x();
- yOffset = drawingData[i].point.y();
- } else {
- transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
- transform.rotate(drawingData[i].rotation);
- }
- painter->setTransform(transform);
- painter->setOpacity(oldOpacity * drawingData[i].opacity);
-
- qreal w = drawingData[i].scaleX * drawingData[i].source.width();
- qreal h = drawingData[i].scaleY * drawingData[i].source.height();
- painter->drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, drawingData[i].source);
- }
-
- painter->setOpacity(oldOpacity);
- painter->setTransform(oldTransform);
- }
+ painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap);
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawutil.h b/src/gui/painting/qdrawutil.h
index 2801b2fbb3..31e352f6f5 100644
--- a/src/gui/painting/qdrawutil.h
+++ b/src/gui/painting/qdrawutil.h
@@ -188,31 +188,6 @@ inline void qDrawBorderPixmap(QPainter *painter,
qDrawBorderPixmap(painter, target, margins, pixmap, pixmap.rect(), margins);
}
-// For internal use only.
-namespace QDrawPixmaps
-{
- struct Data
- {
- QPointF point;
- QRectF source;
- qreal scaleX;
- qreal scaleY;
- qreal rotation;
- qreal opacity;
- };
-
- enum DrawingHint
- {
- OpaqueHint = 0x01
- };
-
- Q_DECLARE_FLAGS(DrawingHints, DrawingHint)
-}
-
-// This function is private and may change without notice. Do not use outside Qt!!!
-Q_GUI_EXPORT void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData,
- int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints = 0);
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp
index f2f0c73035..0510b103a7 100644
--- a/src/gui/painting/qemulationpaintengine.cpp
+++ b/src/gui/painting/qemulationpaintengine.cpp
@@ -172,9 +172,44 @@ void QEmulationPaintEngine::drawTextItem(const QPointF &p, const QTextItem &text
QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
fillBGRect(rect);
}
+
+ QPainterState *s = state();
+ Qt::BrushStyle style = qbrush_style(s->pen.brush());
+ if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern)
+ {
+ QPen savedPen = s->pen;
+ QGradient g = *s->pen.brush().gradient();
+
+ if (g.coordinateMode() > QGradient::LogicalMode) {
+ QTransform mat = s->pen.brush().transform();
+ if (g.coordinateMode() == QGradient::StretchToDeviceMode) {
+ mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height());
+ } else if (g.coordinateMode() == QGradient::ObjectBoundingMode) {
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+ QRectF r(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
+ mat.translate(r.x(), r.y());
+ mat.scale(r.width(), r.height());
+ }
+ g.setCoordinateMode(QGradient::LogicalMode);
+ QBrush brush(g);
+ brush.setTransform(mat);
+ s->pen.setBrush(brush);
+ penChanged();
+ real_engine->drawTextItem(p, textItem);
+ s->pen = savedPen;
+ penChanged();
+ return;
+ }
+ }
+
real_engine->drawTextItem(p, textItem);
}
+void QEmulationPaintEngine::drawStaticTextItem(QStaticTextItem *item)
+{
+ real_engine->drawStaticTextItem(item);
+}
+
void QEmulationPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
{
if (state()->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
diff --git a/src/gui/painting/qemulationpaintengine_p.h b/src/gui/painting/qemulationpaintengine_p.h
index 0ed641b250..5835f10afb 100644
--- a/src/gui/painting/qemulationpaintengine_p.h
+++ b/src/gui/painting/qemulationpaintengine_p.h
@@ -78,6 +78,7 @@ public:
virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
+ virtual void drawStaticTextItem(QStaticTextItem *item);
virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags);
diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h
index 8df0520f03..2911860d3b 100644
--- a/src/gui/painting/qmemrotate_p.h
+++ b/src/gui/painting/qmemrotate_p.h
@@ -82,8 +82,9 @@ QT_BEGIN_NAMESPACE
void Q_GUI_QWS_EXPORT qt_memrotate270(const srctype*, int, int, int, desttype*, int)
void Q_GUI_EXPORT qt_memrotate90(const quint32*, int, int, int, quint32*, int);
+void Q_GUI_QWS_EXPORT qt_memrotate180(const quint32*, int, int, int, quint32*, int);
+void Q_GUI_QWS_EXPORT qt_memrotate270(const quint32*, int, int, int, quint32*, int);
-QT_DECL_MEMROTATE(quint32, quint32);
QT_DECL_MEMROTATE(quint32, quint16);
QT_DECL_MEMROTATE(quint16, quint32);
QT_DECL_MEMROTATE(quint16, quint16);
diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp
index 9fdb96cdb5..3a4c94ce1c 100644
--- a/src/gui/painting/qpaintbuffer.cpp
+++ b/src/gui/painting/qpaintbuffer.cpp
@@ -45,6 +45,8 @@
#include <private/qfontengine_p.h>
#include <private/qemulationpaintengine_p.h>
#include <private/qimage_p.h>
+#include <qstatictext.h>
+#include <private/qstatictext_p.h>
#include <QDebug>
@@ -267,24 +269,302 @@ void QPaintBuffer::draw(QPainter *painter, int frame) const
printf("\n");
#endif
- if (painter && !painter->isActive())
- return;
+ processCommands(painter, frameStartIndex(frame), frameEndIndex(frame));
+
+#ifdef QPAINTBUFFER_DEBUG_DRAW
+ qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
+#endif
+}
+
+int QPaintBuffer::frameStartIndex(int frame) const
+{
+ return (frame == 0) ? 0 : d_ptr->frames.at(frame - 1);
+}
+
+int QPaintBuffer::frameEndIndex(int frame) const
+{
+ return (frame == d_ptr->frames.size()) ? d_ptr->commands.size() : d_ptr->frames.at(frame);
+}
+
+int QPaintBuffer::processCommands(QPainter *painter, int begin, int end) const
+{
+ if (!painter || !painter->isActive())
+ return 0;
QPaintEngineEx *xengine = painter->paintEngine()->isExtended()
? (QPaintEngineEx *) painter->paintEngine() : 0;
if (xengine) {
QPaintEngineExReplayer player;
- player.draw(*this, painter, frame);
+ player.processCommands(*this, painter, begin, end);
} else {
QPainterReplayer player;
- player.draw(*this, painter, frame);
+ player.processCommands(*this, painter, begin, end);
}
-#ifdef QPAINTBUFFER_DEBUG_DRAW
- qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
-#endif
+ int depth = 0;
+ for (int i = begin; i < end; ++i) {
+ const QPaintBufferCommand &cmd = d_ptr->commands.at(i);
+ if (cmd.id == QPaintBufferPrivate::Cmd_Save)
+ ++depth;
+ else if (cmd.id == QPaintBufferPrivate::Cmd_Restore)
+ --depth;
+ }
+ return depth;
}
+#ifndef QT_NO_DEBUG_STREAM
+QString QPaintBuffer::commandDescription(int command) const
+{
+ QString desc;
+ QDebug debug(&desc);
+
+ const QPaintBufferCommand &cmd = d_ptr->commands.at(command);
+
+ switch (cmd.id) {
+ case QPaintBufferPrivate::Cmd_Save: {
+ debug << "Cmd_Save";
+ break; }
+
+ case QPaintBufferPrivate::Cmd_Restore: {
+ debug << "Cmd_Restore";
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetBrush: {
+ QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.offset));
+ debug << "Cmd_SetBrush: " << brush;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
+ debug << "Cmd_SetBrushOrigin: " << d_ptr->variants.at(cmd.offset).toPointF();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetCompositionMode: {
+ QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
+ debug << "ExCmd_SetCompositionMode, mode: " << mode;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetOpacity: {
+ debug << "ExCmd_SetOpacity: " << d_ptr->variants.at(cmd.offset).toDouble();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawVectorPath: {
+ debug << "ExCmd_DrawVectorPath: size: " << cmd.size
+// << ", hints:" << d->ints[cmd.offset2+cmd.size]
+ << "pts/elms:" << cmd.offset << cmd.offset2;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
+ QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.extra));
+ debug << "ExCmd_StrokeVectorPath: size: " << cmd.size
+// << ", hints:" << d->ints[cmd.offset2+cmd.size]
+ << "pts/elms:" << cmd.offset << cmd.offset2 << pen;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_FillVectorPath: {
+ QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
+ debug << "ExCmd_FillVectorPath: size: " << cmd.size
+// << ", hints:" << d->ints[cmd.offset2+cmd.size]
+ << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_FillRectBrush: {
+ QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
+ QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
+ debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_FillRectColor: {
+ QColor color = qVariantValue<QColor>(d_ptr->variants.at(cmd.extra));
+ QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
+ debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPolygonF: {
+ debug << "ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
+ << " mode: " << cmd.extra
+ << d_ptr->floats.at(cmd.offset)
+ << d_ptr->floats.at(cmd.offset+1);
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPolygonI: {
+ debug << "ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
+ << " mode: " << cmd.extra
+ << d_ptr->ints.at(cmd.offset)
+ << d_ptr->ints.at(cmd.offset+1);
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawEllipseF: {
+ debug << "ExCmd_DrawEllipseF, offset: " << cmd.offset;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawLineF: {
+ debug << "ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawLineI: {
+ debug << "ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPointsF: {
+ debug << "ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPointsI: {
+ debug << "ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPolylineF: {
+ debug << "ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPolylineI: {
+ debug << "ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawRectF: {
+ debug << "ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawRectI: {
+ debug << "ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetClipEnabled: {
+ bool clipEnabled = d_ptr->variants.at(cmd.offset).toBool();
+ debug << "ExCmd_SetClipEnabled:" << clipEnabled;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_ClipVectorPath: {
+ QVectorPathCmd path(d_ptr, cmd);
+ debug << "ExCmd_ClipVectorPath:" << path().elementCount();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_ClipRect: {
+ QRect rect(QPoint(d_ptr->ints.at(cmd.offset), d_ptr->ints.at(cmd.offset + 1)),
+ QPoint(d_ptr->ints.at(cmd.offset + 2), d_ptr->ints.at(cmd.offset + 3)));
+ debug << "ExCmd_ClipRect:" << rect << cmd.extra;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_ClipRegion: {
+ QRegion region(d_ptr->variants.at(cmd.offset).value<QRegion>());
+ debug << "ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetPen: {
+ QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.offset));
+ debug << "Cmd_SetPen: " << pen;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetTransform: {
+ QTransform xform = qVariantValue<QTransform>(d_ptr->variants.at(cmd.offset));
+ debug << "Cmd_SetTransform, offset: " << cmd.offset << xform;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetRenderHints: {
+ debug << "Cmd_SetRenderHints, hints: " << cmd.extra;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
+ debug << "Cmd_SetBackgroundMode: " << cmd.extra;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
+ debug << "Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
+ debug << "Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawEllipseI: {
+ debug << "Cmd_DrawEllipseI, offset: " << cmd.offset;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
+ QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
+ QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
+ d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
+
+ QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
+ d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
+ debug << "Cmd_DrawPixmapRect:" << r << sr << pm.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
+ QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
+ QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ debug << "Cmd_DrawPixmapPos:" << pos << pm.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
+ QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
+ QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
+ d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
+
+ QPointF offset(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5));
+ debug << "Cmd_DrawTiledPixmap:" << r << offset << pm.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawImageRect: {
+ QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
+ QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
+ d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
+ QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
+ d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
+ debug << "Cmd_DrawImageRect:" << r << sr << image.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawImagePos: {
+ QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
+ QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ debug << "Cmd_DrawImagePos:" << pos << image.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawText: {
+ QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ QList<QVariant> variants(d_ptr->variants.at(cmd.offset).value<QList<QVariant> >());
+
+ QFont font(variants.at(0).value<QFont>());
+ QString text(variants.at(1).value<QString>());
+
+ debug << "Cmd_DrawText:" << pos << text << font.family();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawTextItem: {
+ QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d_ptr->variants.at(cmd.offset)));
+ QTextItemInt &ti = (*tiCopy)();
+ QString text(ti.text());
+
+ QFont font(ti.font());
+ font.setUnderline(false);
+ font.setStrikeOut(false);
+ font.setOverline(false);
+
+ const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
+ qreal justificationWidth = 0;
+ if (si.justified)
+ justificationWidth = si.width.toReal();
+
+ debug << "Cmd_DrawTextItem:" << pos << " " << text;
+ break; }
+ case QPaintBufferPrivate::Cmd_SystemStateChanged: {
+ QRegion systemClip(d_ptr->variants.at(cmd.offset).value<QRegion>());
+
+ debug << "Cmd_SystemStateChanged:" << systemClip;
+ break; }
+ case QPaintBufferPrivate::Cmd_Translate: {
+ QPointF delta(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ debug << "Cmd_Translate:" << delta;
+ break; }
+ case QPaintBufferPrivate::Cmd_DrawStaticText: {
+ debug << "Cmd_DrawStaticText";
+ break; }
+ }
+
+ return desc;
+}
+#endif
QRectF QPaintBuffer::boundingRect() const
{
@@ -306,6 +586,8 @@ public:
Q_Q(QPaintBufferEngine);
q->buffer->addCommand(QPaintBufferPrivate::Cmd_SystemStateChanged, QVariant(systemClip));
}
+
+ QTransform last;
};
@@ -492,6 +774,32 @@ void QPaintBufferEngine::renderHintsChanged()
void QPaintBufferEngine::transformChanged()
{
+ Q_D(QPaintBufferEngine);
+ const QTransform &transform = state()->matrix;
+
+ QTransform delta;
+
+ bool invertible = false;
+ if (transform.type() <= QTransform::TxScale && transform.type() == d->last.type())
+ delta = transform * d->last.inverted(&invertible);
+
+ d->last = transform;
+
+ if (invertible && delta.type() == QTransform::TxNone)
+ return;
+
+ if (invertible && delta.type() == QTransform::TxTranslate) {
+#ifdef QPAINTBUFFER_DEBUG_DRAW
+ qDebug() << "QPaintBufferEngine: transformChanged (translate only) " << state()->matrix;
+#endif
+ QPaintBufferCommand *cmd =
+ buffer->addCommand(QPaintBufferPrivate::Cmd_Translate);
+
+ qreal data[] = { delta.dx(), delta.dy() };
+ cmd->extra = buffer->addData((qreal *) data, 2);
+ return;
+ }
+
// ### accumulate, like in QBrush case...
if (!buffer->commands.isEmpty()
&& buffer->commands.last().id == QPaintBufferPrivate::Cmd_SetTransform) {
@@ -960,6 +1268,19 @@ void QPaintBufferEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, con
buffer->updateBoundingRect(r);
}
+void QPaintBufferEngine::drawStaticTextItem(QStaticTextItem *staticTextItem)
+{
+ QVariantList variants;
+
+ variants << QVariant(staticTextItem->font);
+ for (int i=0; i<staticTextItem->numGlyphs; ++i) {
+ variants.append(staticTextItem->glyphs[i]);
+ variants.append(staticTextItem->glyphPositions[i].toPointF());
+ }
+
+ buffer->addCommand(QPaintBufferPrivate::Cmd_DrawStaticText, QVariant(variants));
+}
+
void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
{
#ifdef QPAINTBUFFER_DEBUG_DRAW
@@ -999,6 +1320,7 @@ void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
void QPaintBufferEngine::setState(QPainterState *s)
{
+ Q_D(QPaintBufferEngine);
if (m_begin_detected) {
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << "QPaintBufferEngine: setState: begin, ignoring.";
@@ -1017,6 +1339,8 @@ void QPaintBufferEngine::setState(QPainterState *s)
buffer->addCommand(QPaintBufferPrivate::Cmd_Restore);
}
+ d->last = s->matrix;
+
QPaintEngineEx::setState(s);
}
@@ -1065,15 +1389,12 @@ void QPainterReplayer::setupTransform(QPainter *_painter)
painter->setTransform(m_world_matrix);
}
-void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter, int frame)
+void QPainterReplayer::processCommands(const QPaintBuffer &buffer, QPainter *p, int begin, int end)
{
d = buffer.d_ptr;
- setupTransform(_painter);
+ painter = p;
- int frameStart = (frame == 0) ? 0 : d->frames.at(frame-1);
- int frameEnd = (frame == d->frames.size()) ? d->commands.size() : d->frames.at(frame);
-
- for (int cmdIndex=frameStart; cmdIndex<frameEnd; ++cmdIndex) {
+ for (int cmdIndex = begin; cmdIndex < end; ++cmdIndex) {
const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
process(cmd);
}
@@ -1138,6 +1459,15 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
painter->setTransform(xform * m_world_matrix);
break; }
+ case QPaintBufferPrivate::Cmd_Translate: {
+ QPointF delta(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
+#ifdef QPAINTBUFFER_DEBUG_DRAW
+ qDebug() << " -> Cmd_Translate, offset: " << cmd.offset << delta;
+#endif
+ painter->translate(delta.x(), delta.y());
+ return;
+ }
+
case QPaintBufferPrivate::Cmd_SetCompositionMode: {
QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
#ifdef QPAINTBUFFER_DEBUG_DRAW
@@ -1425,6 +1755,27 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
#endif
painter->setClipRegion(region, Qt::ClipOperation(cmd.extra));
break; }
+
+ case QPaintBufferPrivate::Cmd_DrawStaticText: {
+
+ QVariantList variants(d->variants.at(cmd.offset).value<QVariantList>());
+
+ QFont font = variants.at(0).value<QFont>();
+
+ QVector<quint32> glyphs;
+ QVector<QPointF> positions;
+
+ for (int i=0; i<(variants.size() - 1) / 2; ++i) {
+ glyphs.append(variants.at(i*2 + 1).toUInt());
+ positions.append(variants.at(i*2 + 2).toPointF());
+ }
+
+ painter->setFont(font);
+
+ qt_draw_glyphs(painter, glyphs.constData(), positions.constData(), glyphs.size());
+
+ break;
+ }
case QPaintBufferPrivate::Cmd_DrawText: {
QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
@@ -1770,8 +2121,28 @@ struct QPaintBufferCacheEntry
QVariant::Type type;
quint64 cacheKey;
};
+
+struct QPaintBufferCacheEntryV2
+{
+ enum Type {
+ ImageKey,
+ PixmapKey
+ };
+
+ struct Flags {
+ uint type : 8;
+ uint key : 24;
+ };
+
+ union {
+ Flags flags;
+ uint bits;
+ };
+};
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QPaintBufferCacheEntry)
+Q_DECLARE_METATYPE(QPaintBufferCacheEntryV2)
QT_BEGIN_NAMESPACE
QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry)
@@ -1784,10 +2155,22 @@ QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntry &entry)
return stream >> entry.type >> entry.cacheKey;
}
+QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntryV2 &entry)
+{
+ return stream << entry.bits;
+}
+
+QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntryV2 &entry)
+{
+ return stream >> entry.bits;
+}
+
static int qRegisterPaintBufferMetaTypes()
{
qRegisterMetaType<QPaintBufferCacheEntry>();
qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntry>("QPaintBufferCacheEntry");
+ qRegisterMetaType<QPaintBufferCacheEntryV2>();
+ qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntryV2>("QPaintBufferCacheEntryV2");
return 0; // something
}
@@ -1796,6 +2179,9 @@ Q_CONSTRUCTOR_FUNCTION(qRegisterPaintBufferMetaTypes)
QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
{
+ QHash<qint64, uint> pixmapKeys;
+ QHash<qint64, uint> imageKeys;
+
QHash<qint64, QPixmap> pixmaps;
QHash<qint64, QImage> images;
@@ -1804,19 +2190,33 @@ QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
const QVariant &v = variants.at(i);
if (v.type() == QVariant::Image) {
const QImage image(v.value<QImage>());
- images[image.cacheKey()] = image;
- QPaintBufferCacheEntry entry;
- entry.type = QVariant::Image;
- entry.cacheKey = image.cacheKey();
+ QPaintBufferCacheEntryV2 entry;
+ entry.flags.type = QPaintBufferCacheEntryV2::ImageKey;
+
+ QHash<qint64, uint>::iterator it = imageKeys.find(image.cacheKey());
+ if (it != imageKeys.end()) {
+ entry.flags.key = *it;
+ } else {
+ imageKeys[image.cacheKey()] = entry.flags.key = images.size();
+ images[images.size()] = image;
+ }
+
variants[i] = QVariant::fromValue(entry);
} else if (v.type() == QVariant::Pixmap) {
const QPixmap pixmap(v.value<QPixmap>());
- pixmaps[pixmap.cacheKey()] = pixmap;
- QPaintBufferCacheEntry entry;
- entry.type = QVariant::Pixmap;
- entry.cacheKey = pixmap.cacheKey();
+ QPaintBufferCacheEntryV2 entry;
+ entry.flags.type = QPaintBufferCacheEntryV2::PixmapKey;
+
+ QHash<qint64, uint>::iterator it = pixmapKeys.find(pixmap.cacheKey());
+ if (it != pixmapKeys.end()) {
+ entry.flags.key = *it;
+ } else {
+ pixmapKeys[pixmap.cacheKey()] = entry.flags.key = pixmaps.size();
+ pixmaps[pixmaps.size()] = pixmap;
+ }
+
variants[i] = QVariant::fromValue(entry);
}
}
@@ -1858,6 +2258,15 @@ QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer)
variants[i] = QVariant(images.value(entry.cacheKey));
else
variants[i] = QVariant(pixmaps.value(entry.cacheKey));
+ } else if (v.canConvert<QPaintBufferCacheEntryV2>()) {
+ QPaintBufferCacheEntryV2 entry = v.value<QPaintBufferCacheEntryV2>();
+
+ if (entry.flags.type == QPaintBufferCacheEntryV2::ImageKey)
+ variants[i] = QVariant(images.value(entry.flags.key));
+ else if (entry.flags.type == QPaintBufferCacheEntryV2::PixmapKey)
+ variants[i] = QVariant(pixmaps.value(entry.flags.key));
+ else
+ qWarning() << "operator<<(QDataStream &stream, QPaintBuffer &buffer): unrecognized cache entry type:" << entry.flags.type;
}
}
diff --git a/src/gui/painting/qpaintbuffer_p.h b/src/gui/painting/qpaintbuffer_p.h
index 79d7b35713..e4fe4bf1b3 100644
--- a/src/gui/painting/qpaintbuffer_p.h
+++ b/src/gui/painting/qpaintbuffer_p.h
@@ -78,6 +78,14 @@ public:
int numFrames() const;
void draw(QPainter *painter, int frame = 0) const;
+
+ int frameStartIndex(int frame) const;
+ int frameEndIndex(int frame) const;
+ int processCommands(QPainter *painter, int begin, int end) const;
+#ifndef QT_NO_DEBUG_STREAM
+ QString commandDescription(int command) const;
+#endif
+
void setBoundingRect(const QRectF &rect);
QRectF boundingRect() const;
@@ -183,6 +191,10 @@ public:
Cmd_DrawTiledPixmap,
Cmd_SystemStateChanged,
+ Cmd_Translate,
+ Cmd_DrawStaticText,
+
+ // new commands must be added above this line
Cmd_LastCommand
};
@@ -313,7 +325,7 @@ public:
void setupTransform(QPainter *painter);
virtual void process(const QPaintBufferCommand &cmd);
- void draw(const QPaintBuffer &buffer, QPainter *painter, int frame);
+ void processCommands(const QPaintBuffer &buffer, QPainter *painter, int begin, int end);
protected:
QPaintBufferPrivate *d;
@@ -394,6 +406,7 @@ public:
virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
virtual void drawTextItem(const QPointF &pos, const QTextItem &ti);
+ virtual void drawStaticTextItem(QStaticTextItem *staticTextItem);
virtual void setState(QPainterState *s);
virtual uint flags() const {return QPaintEngineEx::DoNotEmulate;}
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 975ebb0afa..9148ac23ab 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -67,6 +67,7 @@
// #include <private/qpolygonclipper_p.h>
// #include <private/qrasterizer_p.h>
#include <private/qimage_p.h>
+#include <private/qstatictext_p.h>
#include "qpaintengine_raster_p.h"
// #include "qbezier_p.h"
@@ -1724,9 +1725,10 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
if (patternLength > 0) {
int n = qFloor(dashOffset / patternLength);
dashOffset -= n * patternLength;
- while (dashOffset > pattern.at(dashIndex)) {
+ while (dashOffset >= pattern.at(dashIndex)) {
dashOffset -= pattern.at(dashIndex);
- dashIndex = (dashIndex + 1) % pattern.size();
+ if (++dashIndex >= pattern.size())
+ dashIndex = 0;
inDash = !inDash;
}
}
@@ -1737,7 +1739,6 @@ 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) {
- dashOffset = s->lastPen.dashOffset();
if (lines[i].p1() == lines[i].p2()) {
if (s->lastPen.capStyle() != Qt::FlatCap) {
QPointF p = lines[i].p1();
@@ -2551,7 +2552,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
int sr_t = qFloor(sr.top());
int sr_b = qCeil(sr.bottom()) - 1;
- if (!s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) {
+ if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && 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;
@@ -3002,27 +3003,22 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
blend(current, spans, &s->penData);
}
-void QRasterPaintEngine::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
+void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
+ const QFixedPoint *positions, QFontEngine *fontEngine)
{
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
- QVarLengthArray<QFixedPoint> positions;
- QVarLengthArray<glyph_t> glyphs;
- QTransform matrix = s->matrix;
- matrix.translate(p.x(), p.y());
- ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
-
- QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat) : d->glyphCacheType;
+ QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(fontEngine->glyphFormat) : d->glyphCacheType;
QImageTextureGlyphCache *cache =
- (QImageTextureGlyphCache *) ti.fontEngine->glyphCache(0, glyphType, s->matrix);
+ static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphType, s->matrix));
if (!cache) {
cache = new QImageTextureGlyphCache(glyphType, s->matrix);
- ti.fontEngine->setGlyphCache(0, cache);
+ fontEngine->setGlyphCache(0, cache);
}
- cache->populate(ti, glyphs, positions);
+ cache->populate(fontEngine, numGlyphs, glyphs, positions);
const QImage &image = cache->image();
int bpl = image.bytesPerLine();
@@ -3040,7 +3036,7 @@ void QRasterPaintEngine::drawCachedGlyphs(const QPointF &p, const QTextItemInt &
const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta);
const uchar *bits = image.bits();
- for (int i=0; i<glyphs.size(); ++i) {
+ for (int i=0; i<numGlyphs; ++i) {
const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]);
int x = qFloor(positions[i].x + offs) + c.baseLineX - margin;
int y = qFloor(positions[i].y + offs) - c.baseLineY - margin;
@@ -3218,6 +3214,18 @@ QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect,
}
/*!
+ \reimp
+*/
+void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
+{
+ ensurePen();
+ ensureState();
+
+ drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
+ textItem->fontEngine);
+}
+
+/*!
\reimp
*/
void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
@@ -3265,7 +3273,17 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
drawCached = false;
#endif
if (drawCached) {
- drawCachedGlyphs(p, ti);
+ QRasterPaintEngineState *s = state();
+
+ QVarLengthArray<QFixedPoint> positions;
+ QVarLengthArray<glyph_t> glyphs;
+
+ QTransform matrix = s->matrix;
+ matrix.translate(p.x(), p.y());
+
+ ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+
+ drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), ti.fontEngine);
return;
}
@@ -3372,7 +3390,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
};
for(int i = 0; i < glyphs.size(); i++) {
- QFontEngineFT::Glyph *glyph = gset->glyph_data.value(glyphs[i]);
+ QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i]);
if (!glyph || glyph->format != neededFormat) {
if (!lockedFace)
@@ -3608,13 +3626,14 @@ void QRasterPaintEnginePrivate::rasterizeLine_dashed(QLineF line,
} else {
*dashOffset = 0;
*inDash = !(*inDash);
- *dashIndex = (*dashIndex + 1) % pattern.size();
+ if (++*dashIndex >= pattern.size())
+ *dashIndex = 0;
length -= dash;
l.setLength(dash);
line.setP1(l.p2());
}
- if (rasterize && dash != 0)
+ if (rasterize && dash > 0)
rasterizer->rasterizeLine(l.p1(), l.p2(), width / dash, squareCap);
}
}
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index a1c73ccdc2..55eb82ee50 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -203,6 +203,8 @@ public:
void clip(const QRect &rect, Qt::ClipOperation op);
void clip(const QRegion &region, Qt::ClipOperation op);
+ void drawStaticTextItem(QStaticTextItem *textItem);
+
enum ClipType {
RectClip,
ComplexClip
@@ -257,7 +259,8 @@ private:
void fillRect(const QRectF &rect, QSpanData *data);
void drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fill);
- void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
+ void drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions,
+ QFontEngine *fontEngine);
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
void drawGlyphsS60(const QPointF &p, const QTextItemInt &ti);
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index d54c1edbcf..a78cafb394 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -607,11 +607,11 @@ void QPaintEngineEx::clip(const QRect &r, Qt::ClipOperation op)
{
qreal right = r.x() + r.width();
qreal bottom = r.y() + r.height();
- qreal pts[] = { r.x(), r.y(),
- right, r.y(),
+ qreal pts[] = { qreal(r.x()), qreal(r.y()),
+ right, qreal(r.y()),
right, bottom,
- r.x(), bottom,
- r.x(), r.y() };
+ qreal(r.x()), bottom,
+ qreal(r.x()), qreal(r.y()) };
QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
clip(vp, op);
}
@@ -711,11 +711,11 @@ void QPaintEngineEx::drawRects(const QRect *rects, int rectCount)
// ### Is there a one off here?
qreal right = r.x() + r.width();
qreal bottom = r.y() + r.height();
- qreal pts[] = { r.x(), r.y(),
- right, r.y(),
+ qreal pts[] = { qreal(r.x()), qreal(r.y()),
+ right, qreal(r.y()),
right, bottom,
- r.x(), bottom,
- r.x(), r.y() };
+ qreal(r.x()), bottom,
+ qreal(r.x()), qreal(r.y()) };
QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
draw(vp);
}
@@ -893,7 +893,7 @@ void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount)
for (int i=0; i<count; ++i) {
pts[++oset] = points[i].x();
pts[++oset] = points[i].y();
- pts[++oset] = points[i].x() + 1/63;
+ pts[++oset] = points[i].x() + 1/63.;
pts[++oset] = points[i].y();
}
QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::LinesHint);
@@ -903,7 +903,8 @@ void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount)
}
} else {
for (int i=0; i<pointCount; ++i) {
- qreal pts[] = { points[i].x(), points[i].y(), points[i].x() +1/63., points[i].y() };
+ qreal pts[] = { qreal(points[i].x()), qreal(points[i].y()),
+ qreal(points[i].x() +1/63.), qreal(points[i].y()) };
QVectorPath path(pts, 2, 0);
stroke(path, pen);
}
@@ -970,23 +971,29 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con
fill(path, brush);
}
-void QPaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints /*hints*/)
+void QPaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount,
+ const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/)
{
+ if (pixmap.isNull())
+ return;
+
qreal oldOpacity = state()->opacity;
QTransform oldTransform = state()->matrix;
- for (int i = 0; i < dataCount; ++i) {
+ for (int i = 0; i < fragmentCount; ++i) {
QTransform transform = oldTransform;
- transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
- transform.rotate(drawingData[i].rotation);
- state()->opacity = oldOpacity * drawingData[i].opacity;
+ transform.translate(fragments[i].x, fragments[i].y);
+ transform.rotate(fragments[i].rotation);
+ state()->opacity = oldOpacity * fragments[i].opacity;
state()->matrix = transform;
opacityChanged();
transformChanged();
- qreal w = drawingData[i].scaleX * drawingData[i].source.width();
- qreal h = drawingData[i].scaleY * drawingData[i].source.height();
- drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, drawingData[i].source);
+ qreal w = fragments[i].scaleX * fragments[i].width;
+ qreal h = fragments[i].scaleY * fragments[i].height;
+ QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
+ fragments[i].width, fragments[i].height);
+ drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, sourceRect);
}
state()->opacity = oldOpacity;
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index fccd1dcdc2..6c654bd85c 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -70,6 +70,7 @@ QT_MODULE(Gui)
class QPainterState;
class QPaintEngineExPrivate;
+class QStaticTextItem;
struct StrokeHandler;
struct QIntRect {
@@ -196,10 +197,13 @@ public:
virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
- virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QFlags<QDrawPixmaps::DrawingHint> hints);
+ virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
+ QFlags<QPainter::PixmapFragmentHint> hints);
virtual void updateState(const QPaintEngineState &state);
+ virtual void drawStaticTextItem(QStaticTextItem *) = 0;
+
virtual void setState(QPainterState *s);
inline QPainterState *state() { return static_cast<QPainterState *>(QPaintEngine::state); }
inline const QPainterState *state() const { return static_cast<const QPainterState *>(QPaintEngine::state); }
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 075c457e3b..898a996e15 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -38,6 +38,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
// QtCore
#include <qdebug.h>
#include <qmath.h>
@@ -69,6 +70,8 @@
#include <private/qwidget_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qmath_p.h>
+#include <qstatictext.h>
+#include <private/qstatictext_p.h>
QT_BEGIN_NAMESPACE
@@ -5411,10 +5414,15 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
scale(w / sw, h / sh);
setBackgroundMode(Qt::TransparentMode);
setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
- QBrush brush(d->state->pen.color(), pm);
+ QBrush brush;
+
+ if (sw == pm.width() && sh == pm.height())
+ brush = QBrush(d->state->pen.color(), pm);
+ else
+ brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
+
setBrush(brush);
setPen(Qt::NoPen);
- setBrushOrigin(QPointF(-sx, -sy));
drawRect(QRectF(0, 0, sw, sh));
restore();
@@ -5697,6 +5705,93 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
}
+
+void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray,
+ int glyphCount)
+{
+ QPainterPrivate *painter_d = QPainterPrivate::get(painter);
+ painter_d->drawGlyphs(glyphArray, positionArray, glyphCount);
+}
+
+void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray,
+ int glyphCount)
+{
+ updateState(state);
+
+ QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common);
+
+ while (fontEngine->type() == QFontEngine::Multi) {
+ // Pick engine based on first glyph in array if we are using a multi engine.
+ // (all glyphs must be for same font)
+ int engineIdx = 0;
+ if (glyphCount > 0)
+ engineIdx = glyphArray[0] >> 24;
+
+ fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
+ }
+
+ QVarLengthArray<QFixedPoint, 128> positions;
+ for (int i=0; i<glyphCount; ++i) {
+ QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]);
+ positions.append(fp);
+ }
+
+ if (extended != 0) {
+ QStaticTextItem staticTextItem;
+ staticTextItem.color = state->pen.color();
+ staticTextItem.font = state->font;
+ staticTextItem.fontEngine = fontEngine;
+ staticTextItem.numGlyphs = glyphCount;
+ staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
+ staticTextItem.glyphPositions = positions.data();
+
+ extended->drawStaticTextItem(&staticTextItem);
+ } else {
+ QTextItemInt textItem;
+ textItem.f = &state->font;
+ textItem.fontEngine = fontEngine;
+
+ QVarLengthArray<QFixed, 128> advances(glyphCount);
+ QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
+ QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
+ qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
+ qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
+ qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
+
+ textItem.glyphs.numGlyphs = glyphCount;
+ textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
+ textItem.glyphs.offsets = positions.data();
+ textItem.glyphs.advances_x = advances.data();
+ textItem.glyphs.advances_y = advances.data();
+ textItem.glyphs.justifications = glyphJustifications.data();
+ textItem.glyphs.attributes = glyphAttributes.data();
+
+ engine->drawTextItem(QPointF(0, 0), textItem);
+ }
+}
+
+/*!
+
+ \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
+ \since 4.7
+ \overload
+
+ Draws the \a staticText at the \a topLeftPosition.
+
+ \note The y-position is used as the top of the font.
+
+*/
+
+/*!
+ \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
+ \since 4.7
+ \overload
+
+ Draws the \a staticText at coordinates \a left and \a top.
+
+ \note The y-position is used as the top of the font.
+*/
+
/*!
\fn void QPainter::drawText(const QPointF &position, const QString &text)
@@ -5720,6 +5815,115 @@ void QPainter::drawText(const QPointF &p, const QString &str)
}
/*!
+ \since 4.7
+
+ Draws the given \a staticText at the given \a topLeftPosition.
+
+ The text will be drawn using the font and the transformation set on the painter. If the
+ font and/or transformation set on the painter are different from the ones used to initialize
+ the layout of the QStaticText, then the layout will have to be recalculated. Use
+ QStaticText::prepare() to initialize \a staticText with the font and transformation with which
+ it will later be drawn.
+
+ If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
+ last drawn, then there will be a slight overhead when translating the text to its new position.
+
+ \note If the painter's transformation is not affine, then \a staticText will be drawn using
+ regular calls to drawText(), losing any potential for performance improvement.
+
+ \note The y-position is used as the top of the font.
+
+ \sa QStaticText
+*/
+void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
+{
+ Q_D(QPainter);
+ if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
+ return;
+
+ QStaticTextPrivate *staticText_d =
+ const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
+
+ if (font() != staticText_d->font) {
+ staticText_d->font = font();
+ staticText_d->needsRelayout = true;
+ }
+
+ // If we don't have an extended paint engine, or if the painter is projected,
+ // we go through standard code path
+ if (d->extended == 0 || !d->state->matrix.isAffine()) {
+ staticText_d->paintText(topLeftPosition, this);
+ return;
+ }
+
+ // Don't recalculate entire layout because of translation, rather add the dx and dy
+ // into the position to move each text item the correct distance.
+ QPointF transformedPosition = topLeftPosition * d->state->matrix;
+ QTransform matrix = d->state->matrix;
+
+ // The translation has been applied to transformedPosition. Remove translation
+ // component from matrix.
+ if (d->state->matrix.isTranslating()) {
+ qreal m11 = d->state->matrix.m11();
+ qreal m12 = d->state->matrix.m12();
+ qreal m13 = d->state->matrix.m13();
+ qreal m21 = d->state->matrix.m21();
+ qreal m22 = d->state->matrix.m22();
+ qreal m23 = d->state->matrix.m23();
+ qreal m33 = d->state->matrix.m33();
+
+ d->state->matrix.setMatrix(m11, m12, m13,
+ m21, m22, m23,
+ 0.0, 0.0, m33);
+ }
+
+ // If the transform is not identical to the text transform,
+ // we have to relayout the text (for other transformations than plain translation)
+ bool staticTextNeedsReinit = staticText_d->needsRelayout;
+ if (staticText_d->matrix != d->state->matrix) {
+ staticText_d->matrix = d->state->matrix;
+ staticTextNeedsReinit = true;
+ }
+
+ // Recreate the layout of the static text because the matrix or font has changed
+ if (staticTextNeedsReinit)
+ staticText_d->init();
+
+ if (transformedPosition != staticText_d->position) { // Translate to actual position
+ QFixed fx = QFixed::fromReal(transformedPosition.x());
+ QFixed fy = QFixed::fromReal(transformedPosition.y());
+ QFixed oldX = QFixed::fromReal(staticText_d->position.x());
+ QFixed oldY = QFixed::fromReal(staticText_d->position.y());
+ for (int item=0; item<staticText_d->itemCount;++item) {
+ QStaticTextItem *textItem = staticText_d->items + item;
+ for (int i=0; i<textItem->numGlyphs; ++i) {
+ textItem->glyphPositions[i].x += fx - oldX;
+ textItem->glyphPositions[i].y += fy - oldY;
+ }
+ textItem->userDataNeedsUpdate = true;
+ }
+
+ staticText_d->position = transformedPosition;
+ }
+
+ QPen oldPen = d->state->pen;
+ QColor currentColor = oldPen.color();
+ for (int i=0; i<staticText_d->itemCount; ++i) {
+ QStaticTextItem *item = staticText_d->items + i;
+ if (item->color.isValid() && currentColor != item->color) {
+ setPen(item->color);
+ currentColor = item->color;
+ }
+ d->extended->drawStaticTextItem(item);
+ }
+ if (currentColor != oldPen.color())
+ setPen(oldPen);
+
+ if (matrix.isTranslating())
+ d->state->matrix = matrix;
+}
+
+/*!
\internal
*/
void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
@@ -7801,10 +8005,11 @@ start_lengthVariant:
for (int i = 0; i < textLayout.lineCount(); i++) {
QTextLine line = textLayout.lineAt(i);
+ qreal advance = line.horizontalAdvance();
if (tf & Qt::AlignRight)
- xoff = r.width() - line.naturalTextWidth();
+ xoff = r.width() - advance;
else if (tf & Qt::AlignHCenter)
- xoff = (r.width() - line.naturalTextWidth())/2;
+ xoff = (r.width() - advance)/2;
line.draw(painter, QPointF(r.x() + xoff + line.x(), r.y() + yoff));
}
@@ -8709,6 +8914,167 @@ QTransform QPainter::combinedTransform() const
return d->state->worldMatrix * d->viewTransform();
}
+/*!
+ \since 4.7
+
+ This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
+ at multiple positions with different scale, rotation and opacity. \a
+ fragments is an array of \a fragmentCount elements specifying the
+ parameters used to draw each pixmap fragment. The \a hints
+ parameter can be used to pass in drawing hints.
+
+ This function is potentially faster than multiple calls to drawPixmap(),
+ since the backend can optimize state changes.
+
+ \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
+*/
+
+void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
+ const QPixmap &pixmap, PixmapFragmentHints hints)
+{
+ Q_D(QPainter);
+
+ if (!d->engine)
+ return;
+
+ if (d->engine->isExtended()) {
+ d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
+ } else {
+ qreal oldOpacity = opacity();
+ QTransform oldTransform = transform();
+
+ for (int i = 0; i < fragmentCount; ++i) {
+ QTransform transform = oldTransform;
+ qreal xOffset = 0;
+ qreal yOffset = 0;
+ if (fragments[i].rotation == 0) {
+ xOffset = fragments[i].x;
+ yOffset = fragments[i].y;
+ } else {
+ transform.translate(fragments[i].x, fragments[i].y);
+ transform.rotate(fragments[i].rotation);
+ }
+ setOpacity(oldOpacity * fragments[i].opacity);
+ setTransform(transform);
+
+ qreal w = fragments[i].scaleX * fragments[i].width;
+ qreal h = fragments[i].scaleY * fragments[i].height;
+ QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
+ fragments[i].width, fragments[i].height);
+ drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
+ }
+
+ setOpacity(oldOpacity);
+ setTransform(oldTransform);
+ }
+}
+
+/*!
+ \since 4.7
+ \class QPainter::PixmapFragment
+
+ \brief This class is used in conjunction with the
+ QPainter::drawPixmapFragments() function to specify how a pixmap, or
+ sub-rect of a pixmap, is drawn.
+
+ The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
+ as a source rectangle within the pixmap passed into the
+ QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
+ width and \a height are used to calculate the target rectangle that is
+ drawn. \a x and \a y denotes the center of the target rectangle. The \a
+ width and \a heigth in the target rectangle is scaled by the \a scaleX and
+ \a scaleY values. The resulting target rectangle is then rotated \a
+ rotation degrees around the \a x, \a y center point.
+
+ \sa QPainter::drawPixmapFragments()
+*/
+
+/*!
+ \since 4.7
+
+ This is a convenience function that returns a QPainter::PixmapFragment that is
+ initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
+ rotation, \a opacity parameters.
+*/
+
+QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
+ qreal scaleX, qreal scaleY, qreal rotation,
+ qreal opacity)
+{
+ PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
+ sourceRect.height(), scaleX, scaleY, rotation, opacity};
+ return fragment;
+}
+
+/*!
+ \variable QPainter::PixmapFragment::x
+ \brief the x coordinate of center point in the target rectangle.
+*/
+
+/*!
+ \variable QPainter::PixmapFragment::y
+ \brief the y coordinate of the center point in the target rectangle.
+*/
+
+/*!
+ \variable QPainter::PixmapFragment::sourceLeft
+ \brief the left coordinate of the source rectangle.
+*/
+
+/*!
+ \variable QPainter::PixmapFragment::sourceTop
+ \brief the top coordinate of the source rectangle.
+*/
+
+/*!
+ \variable QPainter::PixmapFragment::width
+
+ \brief the width of the source rectangle and is used to calculate the width
+ of the target rectangle.
+*/
+
+/*!
+ \variable QPainter::PixmapFragment::height
+
+ \brief the height of the source rectangle and is used to calculate the
+ height of the target rectangle.
+*/
+
+/*!
+ \variable QPainter::PixmapFragment::scaleX
+ \brief the horizontal scale of the target rectangle.
+*/
+
+/*!
+ \variable QPainter::PixmapFragment::scaleY
+ \brief the vertical scale of the target rectangle.
+*/
+
+/*!
+ \variable QPainter::PixmapFragment::rotation
+
+ \brief the rotation of the target rectangle in degrees. The target
+ rectangle is rotated after it has been scaled.
+*/
+
+/*!
+ \variable QPainter::PixmapFragment::opacity
+
+ \brief the opacity of the target rectangle, where 0.0 is fully transparent
+ and 1.0 is fully opaque.
+*/
+
+/*!
+ \since 4.7
+
+ \enum QPainter::PixmapFragmentHint
+
+ \value OpaqueHint Indicates that the pixmap fragments to be drawn are
+ opaque. Opaque fragments are potentially faster to draw.
+
+ \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
+*/
+
void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
{
p->draw_helper(path, operation);
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index ffddcbad23..edfb67ecb1 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -78,6 +78,7 @@ class QPolygon;
class QTextItem;
class QMatrix;
class QTransform;
+class QStaticText;
class QPainterPrivateDeleter;
@@ -98,6 +99,29 @@ public:
Q_DECLARE_FLAGS(RenderHints, RenderHint)
+ class PixmapFragment {
+ public:
+ qreal x;
+ qreal y;
+ qreal sourceLeft;
+ qreal sourceTop;
+ qreal width;
+ qreal height;
+ qreal scaleX;
+ qreal scaleY;
+ qreal rotation;
+ qreal opacity;
+ static PixmapFragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect,
+ qreal scaleX = 1, qreal scaleY = 1,
+ qreal rotation = 0, qreal opacity = 1);
+ };
+
+ enum PixmapFragmentHint {
+ OpaqueHint = 0x01
+ };
+
+ Q_DECLARE_FLAGS(PixmapFragmentHints, PixmapFragmentHint)
+
QPainter();
explicit QPainter(QPaintDevice *);
~QPainter();
@@ -351,6 +375,9 @@ public:
inline void drawPixmap(const QRect &r, const QPixmap &pm);
inline void drawPixmap(int x, int y, int w, int h, const QPixmap &pm);
+ void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
+ const QPixmap &pixmap, PixmapFragmentHints hints = 0);
+
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
Qt::ImageConversionFlags flags = Qt::AutoColor);
inline void drawImage(const QRect &targetRect, const QImage &image, const QRect &sourceRect,
@@ -369,6 +396,10 @@ public:
void setLayoutDirection(Qt::LayoutDirection direction);
Qt::LayoutDirection layoutDirection() const;
+ void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText);
+ inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText);
+ inline void drawStaticText(int left, int top, const QStaticText &staticText);
+
void drawText(const QPointF &p, const QString &s);
inline void drawText(const QPoint &p, const QString &s);
inline void drawText(int x, int y, const QString &s);
@@ -896,6 +927,16 @@ inline void QPainter::drawImage(int x, int y, const QImage &image, int sx, int s
drawImage(QRectF(x, y, -1, -1), image, QRectF(sx, sy, sw, sh), flags);
}
+inline void QPainter::drawStaticText(const QPoint &p, const QStaticText &staticText)
+{
+ drawStaticText(QPointF(p), staticText);
+}
+
+inline void QPainter::drawStaticText(int x, int y, const QStaticText &staticText)
+{
+ drawStaticText(QPointF(x, y), staticText);
+}
+
inline void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
{
drawTextItem(QPointF(p), ti);
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 02a91aa27d..9362dbe80c 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -228,6 +228,7 @@ public:
void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw);
void drawStretchedGradient(const QPainterPath &path, DrawOperation operation);
void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation);
+ void drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, int glyphCount);
void updateMatrix();
void updateInvMatrix();
@@ -238,6 +239,11 @@ public:
void checkEmulation();
+ static QPainterPrivate *get(QPainter *painter)
+ {
+ return painter->d_ptr.data();
+ }
+
QTransform viewTransform() const;
static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev);
void detachPainterPrivate(QPainter *q);
@@ -252,6 +258,8 @@ public:
};
Q_GUI_EXPORT void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation);
+Q_GUI_EXPORT void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray,
+ const QPointF *positionArray, int glyphCount);
QString qt_generate_brush_key(const QBrush &brush);
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index fba3595b92..f5a698e71f 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1257,6 +1257,8 @@ Qt::FillRule QPainterPath::fillRule() const
void QPainterPath::setFillRule(Qt::FillRule fillRule)
{
ensureData();
+ if (d_func()->fillRule == fillRule)
+ return;
detach();
d_func()->fillRule = fillRule;
@@ -1912,7 +1914,7 @@ static bool qt_painterpath_check_crossing(const QPainterPath *path, const QRectF
case QPainterPath::MoveToElement:
if (i > 0
- && qFuzzyCompare(last_pt.x(), last_start.y())
+ && qFuzzyCompare(last_pt.x(), last_start.x())
&& qFuzzyCompare(last_pt.y(), last_start.y())
&& qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(),
last_start.x(), last_start.y(), rect))
@@ -3165,6 +3167,8 @@ 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.
+ Bezier curves may be flattened to line segments due to numerical instability of
+ doing bezier curve intersections.
\sa intersected(), subtracted()
*/
@@ -3180,6 +3184,8 @@ QPainterPath QPainterPath::united(const QPainterPath &p) const
\since 4.3
Returns a path which is the intersection of this path's fill area and \a p's fill area.
+ Bezier curves may be flattened to line segments due to numerical instability of
+ doing bezier curve intersections.
*/
QPainterPath QPainterPath::intersected(const QPainterPath &p) const
{
@@ -3196,7 +3202,8 @@ QPainterPath QPainterPath::intersected(const QPainterPath &p) const
Set operations on paths will treat the paths as areas. Non-closed
paths will be treated as implicitly closed.
-
+ Bezier curves may be flattened to line segments due to numerical instability of
+ doing bezier curve intersections.
*/
QPainterPath QPainterPath::subtracted(const QPainterPath &p) const
{
@@ -3225,6 +3232,8 @@ QPainterPath QPainterPath::subtractedInverted(const QPainterPath &p) const
Returns a simplified version of this path. This implies merging all subpaths that intersect,
and returning a path containing no intersecting edges. Consecutive parallel lines will also
be merged. The simplified path will always use the default fill rule, Qt::OddEvenFill.
+ Bezier curves may be flattened to line segments due to numerical instability of
+ doing bezier curve intersections.
*/
QPainterPath QPainterPath::simplified() const
{
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index 296ce33841..15d83b8bbb 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -288,6 +288,8 @@ public:
QPainterPath createStroke(const QPainterPath &path) const;
private:
+ Q_DISABLE_COPY(QPainterPathStroker)
+
friend class QX11PaintEngine;
QScopedPointer<QPainterPathStrokerPrivate> d_ptr;
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index bc81514067..c910024679 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -43,6 +43,7 @@
#include <private/qbezier_p.h>
#include <private/qdatabuffer_p.h>
+#include <private/qnumeric_p.h>
#include <qmath.h>
/**
@@ -105,22 +106,9 @@ public:
bool hasIntersections(const QPathSegments &a, const QPathSegments &b) const;
private:
- void intersectBeziers(const QBezier &one, const QBezier &two, QVector<QPair<qreal, qreal> > &t, QDataBuffer<QIntersection> &intersections);
- void intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections);
-
- bool beziersIntersect(const QBezier &one, const QBezier &two) const;
bool linesIntersect(const QLineF &a, const QLineF &b) const;
};
-bool QIntersectionFinder::beziersIntersect(const QBezier &one, const QBezier &two) const
-{
- return (comparePoints(one.pt1(), two.pt1()) && comparePoints(one.pt2(), two.pt2())
- && comparePoints(one.pt3(), two.pt3()) && comparePoints(one.pt4(), two.pt4()))
- || (comparePoints(one.pt1(), two.pt4()) && comparePoints(one.pt2(), two.pt3())
- && comparePoints(one.pt3(), two.pt2()) && comparePoints(one.pt4(), two.pt1()))
- || QBezier::findIntersections(one, two, 0);
-}
-
bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const
{
const QPointF p1 = a.p1();
@@ -174,11 +162,6 @@ bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const
return false;
}
- // if the lines are not parallel and share a common end point, then they
- // don't intersect
- if (p1_equals_q1 || p1_equals_q2 || p2_equals_q1 || p2_equals_q2)
- return false;
-
const qreal invPar = 1 / par;
const qreal tp = (qDelta.y() * (q1.x() - p1.x()) -
@@ -193,49 +176,223 @@ bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const
return tq >= 0 && tq <= 1;
}
-void QIntersectionFinder::intersectBeziers(const QBezier &one, const QBezier &two, QVector<QPair<qreal, qreal> > &t, QDataBuffer<QIntersection> &intersections)
+bool QIntersectionFinder::hasIntersections(const QPathSegments &a, const QPathSegments &b) const
{
- if ((comparePoints(one.pt1(), two.pt1()) && comparePoints(one.pt2(), two.pt2())
- && comparePoints(one.pt3(), two.pt3()) && comparePoints(one.pt4(), two.pt4()))
- || (comparePoints(one.pt1(), two.pt4()) && comparePoints(one.pt2(), two.pt3())
- && comparePoints(one.pt3(), two.pt2()) && comparePoints(one.pt4(), two.pt1()))) {
+ if (a.segments() == 0 || b.segments() == 0)
+ return false;
- return;
+ const QRectF &rb0 = b.elementBounds(0);
+
+ qreal minX = rb0.left();
+ qreal minY = rb0.top();
+ qreal maxX = rb0.right();
+ qreal maxY = rb0.bottom();
+
+ for (int i = 1; i < b.segments(); ++i) {
+ const QRectF &r = b.elementBounds(i);
+ minX = qMin(minX, r.left());
+ minY = qMin(minY, r.top());
+ maxX = qMax(maxX, r.right());
+ maxY = qMax(maxY, r.bottom());
}
- t.clear();
+ QRectF rb(minX, minY, maxX - minX, maxY - minY);
- if (!QBezier::findIntersections(one, two, &t))
- return;
+ for (int i = 0; i < a.segments(); ++i) {
+ const QRectF &r1 = a.elementBounds(i);
- int count = t.size();
-
- for (int i = 0; i < count; ++i) {
- qreal alpha_p = t.at(i).first;
- qreal alpha_q = t.at(i).second;
-
- QPointF pt;
- if (qFuzzyIsNull(alpha_p)) {
- pt = one.pt1();
- } else if (qFuzzyIsNull(alpha_p - 1)) {
- pt = one.pt4();
- } else if (qFuzzyIsNull(alpha_q)) {
- pt = two.pt1();
- } else if (qFuzzyIsNull(alpha_q - 1)) {
- pt = two.pt4();
- } else {
- pt = one.pointAt(alpha_p);
+ if (r1.left() > rb.right() || rb.left() > r1.right())
+ continue;
+ if (r1.top() > rb.bottom() || rb.top() > r1.bottom())
+ continue;
+
+ for (int j = 0; j < b.segments(); ++j) {
+ const QRectF &r2 = b.elementBounds(j);
+
+ if (r1.left() > r2.right() || r2.left() > r1.right())
+ continue;
+ if (r1.top() > r2.bottom() || r2.top() > r1.bottom())
+ continue;
+
+ if (linesIntersect(a.lineAt(i), b.lineAt(j)))
+ return true;
}
+ }
+
+ return false;
+}
+
+namespace {
+struct TreeNode
+{
+ qreal splitLeft;
+ qreal splitRight;
+ bool leaf;
+
+ int lowestLeftIndex;
+ int lowestRightIndex;
+
+ union {
+ struct {
+ int first;
+ int last;
+ } interval;
+ struct {
+ int left;
+ int right;
+ } children;
+ } index;
+};
+
+struct RectF
+{
+ qreal x1;
+ qreal y1;
+ qreal x2;
+ qreal y2;
+};
- QIntersection intersection;
- intersection.alphaA = alpha_p;
- intersection.alphaB = alpha_q;
- intersection.pos = pt;
- intersections.add(intersection);
+class SegmentTree
+{
+public:
+ SegmentTree(QPathSegments &segments);
+
+ QRectF boundingRect() const;
+
+ void produceIntersections(int segment);
+
+private:
+ TreeNode buildTree(int first, int last, int depth, const RectF &bounds);
+
+ void produceIntersectionsLeaf(const TreeNode &node, int segment);
+ void produceIntersections(const TreeNode &node, int segment, const RectF &segmentBounds, const RectF &nodeBounds, int axis);
+ void intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections);
+
+ QPathSegments &m_segments;
+ QVector<int> m_index;
+
+ RectF m_bounds;
+
+ QVector<TreeNode> m_tree;
+ QDataBuffer<QIntersection> m_intersections;
+};
+
+SegmentTree::SegmentTree(QPathSegments &segments)
+ : m_segments(segments)
+{
+ m_bounds.x1 = qt_inf();
+ m_bounds.y1 = qt_inf();
+ m_bounds.x2 = -qt_inf();
+ m_bounds.y2 = -qt_inf();
+
+ m_index.resize(m_segments.segments());
+
+ for (int i = 0; i < m_index.size(); ++i) {
+ m_index[i] = i;
+
+ const QRectF &segmentBounds = m_segments.elementBounds(i);
+
+ if (segmentBounds.left() < m_bounds.x1)
+ m_bounds.x1 = segmentBounds.left();
+ if (segmentBounds.top() < m_bounds.y1)
+ m_bounds.y1 = segmentBounds.top();
+ if (segmentBounds.right() > m_bounds.x2)
+ m_bounds.x2 = segmentBounds.right();
+ if (segmentBounds.bottom() > m_bounds.y2)
+ m_bounds.y2 = segmentBounds.bottom();
+ }
+
+ m_tree.resize(1);
+
+ TreeNode root = buildTree(0, m_index.size(), 0, m_bounds);
+ m_tree[0] = root;
+}
+
+QRectF SegmentTree::boundingRect() const
+{
+ return QRectF(QPointF(m_bounds.x1, m_bounds.y1),
+ QPointF(m_bounds.x2, m_bounds.y2));
+}
+
+static inline qreal coordinate(const QPointF &pos, int axis)
+{
+ return axis == 0 ? pos.x() : pos.y();
+}
+
+TreeNode SegmentTree::buildTree(int first, int last, int depth, const RectF &bounds)
+{
+ if (depth >= 24 || (last - first) <= 10) {
+ TreeNode node;
+ node.leaf = true;
+ node.index.interval.first = first;
+ node.index.interval.last = last;
+
+ return node;
+ }
+
+ int splitAxis = (depth & 1);
+
+ TreeNode node;
+ node.leaf = false;
+
+ qreal split = 0.5f * ((&bounds.x1)[splitAxis] + (&bounds.x2)[splitAxis]);
+
+ node.splitLeft = (&bounds.x1)[splitAxis];
+ node.splitRight = (&bounds.x2)[splitAxis];
+
+ node.lowestLeftIndex = INT_MAX;
+ node.lowestRightIndex = INT_MAX;
+
+ const int treeSize = m_tree.size();
+
+ node.index.children.left = treeSize;
+ node.index.children.right = treeSize + 1;
+
+ m_tree.resize(treeSize + 2);
+
+ int l = first;
+ int r = last - 1;
+
+ // partition into left and right sets
+ while (l <= r) {
+ const int index = m_index.at(l);
+ const QRectF &segmentBounds = m_segments.elementBounds(index);
+
+ qreal lowCoordinate = coordinate(segmentBounds.topLeft(), splitAxis);
+
+ if (coordinate(segmentBounds.center(), splitAxis) < split) {
+ qreal highCoordinate = coordinate(segmentBounds.bottomRight(), splitAxis);
+ if (highCoordinate > node.splitLeft)
+ node.splitLeft = highCoordinate;
+ if (index < node.lowestLeftIndex)
+ node.lowestLeftIndex = index;
+ ++l;
+ } else {
+ if (lowCoordinate < node.splitRight)
+ node.splitRight = lowCoordinate;
+ if (index < node.lowestRightIndex)
+ node.lowestRightIndex = index;
+ qSwap(m_index[l], m_index[r]);
+ --r;
+ }
}
+
+ RectF lbounds = bounds;
+ (&lbounds.x2)[splitAxis] = node.splitLeft;
+
+ RectF rbounds = bounds;
+ (&rbounds.x1)[splitAxis] = node.splitRight;
+
+ TreeNode left = buildTree(first, l, depth + 1, lbounds);
+ m_tree[node.index.children.left] = left;
+
+ TreeNode right = buildTree(l, last, depth + 1, rbounds);
+ m_tree[node.index.children.right] = right;
+
+ return node;
}
-void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections)
+void SegmentTree::intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections)
{
const QPointF p1 = a.p1();
const QPointF p2 = a.p2();
@@ -357,149 +514,86 @@ void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QData
intersections.add(intersection);
}
-static const QBezier bezierFromLine(const QLineF &line)
+void SegmentTree::produceIntersections(int segment)
{
- const QPointF p1 = line.p1();
- const QPointF p2 = line.p2();
- const QPointF delta = (p2 - p1) / 3;
- return QBezier::fromPoints(p1, p1 + delta, p1 + 2 * delta, p2);
-}
+ const QRectF &segmentBounds = m_segments.elementBounds(segment);
-bool QIntersectionFinder::hasIntersections(const QPathSegments &a, const QPathSegments &b) const
-{
- QBezier tempA;
- QBezier tempB;
-
- if (a.segments() == 0 || b.segments() == 0)
- return false;
-
- const QRectF &rb0 = b.elementBounds(0);
+ RectF sbounds;
+ sbounds.x1 = segmentBounds.left();
+ sbounds.y1 = segmentBounds.top();
+ sbounds.x2 = segmentBounds.right();
+ sbounds.y2 = segmentBounds.bottom();
- qreal minX = rb0.left();
- qreal minY = rb0.top();
- qreal maxX = rb0.right();
- qreal maxY = rb0.bottom();
-
- for (int i = 1; i < b.segments(); ++i) {
- const QRectF &r = b.elementBounds(i);
- minX = qMin(minX, r.left());
- minY = qMin(minY, r.top());
- maxX = qMax(maxX, r.right());
- maxY = qMax(maxY, r.bottom());
- }
+ produceIntersections(m_tree.at(0), segment, sbounds, m_bounds, 0);
+}
- QRectF rb(minX, minY, maxX - minX, maxY - minY);
+void SegmentTree::produceIntersectionsLeaf(const TreeNode &node, int segment)
+{
+ const QRectF &r1 = m_segments.elementBounds(segment);
+ const QLineF lineA = m_segments.lineAt(segment);
- for (int i = 0; i < a.segments(); ++i) {
- const QBezier *bezierA = a.bezierAt(i);
- bool isBezierA = bezierA != 0;
+ for (int i = node.index.interval.first; i < node.index.interval.last; ++i) {
+ const int other = m_index.at(i);
+ if (other >= segment)
+ continue;
- const QRectF &r1 = a.elementBounds(i);
+ const QRectF &r2 = m_segments.elementBounds(other);
- if (r1.left() > rb.right() || rb.left() > r1.right())
+ if (r1.left() > r2.right() || r2.left() > r1.right())
continue;
- if (r1.top() > rb.bottom() || rb.top() > r1.bottom())
+ if (r1.top() > r2.bottom() || r2.top() > r1.bottom())
continue;
- for (int j = 0; j < b.segments(); ++j) {
- const QRectF &r2 = b.elementBounds(j);
+ m_intersections.reset();
- if (r1.left() > r2.right() || r2.left() > r1.right())
- continue;
- if (r1.top() > r2.bottom() || r2.top() > r1.bottom())
- continue;
+ const QLineF lineB = m_segments.lineAt(other);
- bool isBezierB = b.bezierAt(j) != 0;
+ intersectLines(lineA, lineB, m_intersections);
- if (isBezierA || isBezierB) {
- const QBezier *bezierB;
- if (isBezierB) {
- bezierB = b.bezierAt(j);
- } else {
- tempB = bezierFromLine(b.lineAt(j));
- bezierB = &tempB;
- }
+ for (int k = 0; k < m_intersections.size(); ++k) {
+ QPathSegments::Intersection i_isect, j_isect;
+ i_isect.vertex = j_isect.vertex = m_segments.addPoint(m_intersections.at(k).pos);
- if (!bezierA) {
- tempA = bezierFromLine(a.lineAt(i));
- bezierA = &tempA;
- }
+ i_isect.t = m_intersections.at(k).alphaA;
+ j_isect.t = m_intersections.at(k).alphaB;
- if (beziersIntersect(*bezierA, *bezierB))
- return true;
- } else {
- if (linesIntersect(a.lineAt(i), b.lineAt(j)))
- return true;
- }
+ i_isect.next = 0;
+ j_isect.next = 0;
+
+ m_segments.addIntersection(segment, i_isect);
+ m_segments.addIntersection(other, j_isect);
}
}
-
- return false;
}
-void QIntersectionFinder::produceIntersections(QPathSegments &segments)
+void SegmentTree::produceIntersections(const TreeNode &node, int segment, const RectF &segmentBounds, const RectF &nodeBounds, int axis)
{
- QBezier tempA;
- QBezier tempB;
-
- QVector<QPair<qreal, qreal> > t;
- QDataBuffer<QIntersection> intersections;
-
- for (int i = 0; i < segments.segments(); ++i) {
- const QBezier *bezierA = segments.bezierAt(i);
- bool isBezierA = bezierA != 0;
-
- const QRectF &r1 = segments.elementBounds(i);
-
- for (int j = 0; j < i; ++j) {
- const QRectF &r2 = segments.elementBounds(j);
-
- if (r1.left() > r2.right() || r2.left() > r1.right())
- continue;
- if (r1.top() > r2.bottom() || r2.top() > r1.bottom())
- continue;
-
- intersections.reset();
-
- bool isBezierB = segments.bezierAt(j) != 0;
-
- if (isBezierA || isBezierB) {
- const QBezier *bezierB;
- if (isBezierB) {
- bezierB = segments.bezierAt(j);
- } else {
- tempB = bezierFromLine(segments.lineAt(j));
- bezierB = &tempB;
- }
+ if (node.leaf) {
+ produceIntersectionsLeaf(node, segment);
+ return;
+ }
- if (!bezierA) {
- tempA = bezierFromLine(segments.lineAt(i));
- bezierA = &tempA;
- }
+ RectF lbounds = nodeBounds;
+ (&lbounds.x2)[axis] = node.splitLeft;
- intersectBeziers(*bezierA, *bezierB, t, intersections);
- } else {
- const QLineF lineA = segments.lineAt(i);
- const QLineF lineB = segments.lineAt(j);
+ RectF rbounds = nodeBounds;
+ (&rbounds.x1)[axis] = node.splitRight;
- intersectLines(lineA, lineB, intersections);
- }
+ if (segment > node.lowestLeftIndex && (&segmentBounds.x1)[axis] <= node.splitLeft)
+ produceIntersections(m_tree.at(node.index.children.left), segment, segmentBounds, lbounds, !axis);
- for (int k = 0; k < intersections.size(); ++k) {
- QPathSegments::Intersection i_isect, j_isect;
- i_isect.vertex = j_isect.vertex = segments.addPoint(intersections.at(k).pos);
+ if (segment > node.lowestRightIndex && (&segmentBounds.x2)[axis] >= node.splitRight)
+ produceIntersections(m_tree.at(node.index.children.right), segment, segmentBounds, rbounds, !axis);
+}
- i_isect.t = intersections.at(k).alphaA;
- j_isect.t = intersections.at(k).alphaB;
+}
- i_isect.next = 0;
- j_isect.next = 0;
+void QIntersectionFinder::produceIntersections(QPathSegments &segments)
+{
+ SegmentTree tree(segments);
- segments.addIntersection(i, i_isect);
- segments.addIntersection(j, j_isect);
- }
- }
- }
+ for (int i = 0; i < segments.segments(); ++i)
+ tree.produceIntersections(i);
}
class QKdPointTree
@@ -731,53 +825,34 @@ void QWingedEdge::intersectAndAdd()
qSort(intersections.data(), intersections.data() + intersections.size());
- const QBezier *bezier = m_segments.bezierAt(i);
- if (bezier) {
- int first = m_segments.segmentAt(i).va;
- int second = m_segments.segmentAt(i).vb;
+ int first = m_segments.segmentAt(i).va;
+ int second = m_segments.segmentAt(i).vb;
- qreal alpha = 0.0;
- int last = first;
- for (int j = 0; j < intersections.size(); ++j) {
- const QPathSegments::Intersection &isect = intersections.at(j);
+ int last = first;
+ for (int j = 0; j < intersections.size(); ++j) {
+ const QPathSegments::Intersection &isect = intersections.at(j);
- addBezierEdge(bezier, last, isect.vertex, alpha, isect.t, pathId);
-
- alpha = isect.t;
- last = isect.vertex;
- }
-
- addBezierEdge(bezier, last, second, alpha, 1.0, pathId);
- } else {
- int first = m_segments.segmentAt(i).va;
- int second = m_segments.segmentAt(i).vb;
-
- int last = first;
- for (int j = 0; j < intersections.size(); ++j) {
- const QPathSegments::Intersection &isect = intersections.at(j);
-
- QPathEdge *ep = edge(addEdge(last, isect.vertex));
-
- if (ep) {
- const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(isect.vertex).y() ? 1 : -1;
- if (pathId == 0)
- ep->windingA += dir;
- else
- ep->windingB += dir;
- }
-
- last = isect.vertex;
- }
-
- QPathEdge *ep = edge(addEdge(last, second));
+ QPathEdge *ep = edge(addEdge(last, isect.vertex));
if (ep) {
- const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(second).y() ? 1 : -1;
+ const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(isect.vertex).y() ? 1 : -1;
if (pathId == 0)
ep->windingA += dir;
else
ep->windingB += dir;
}
+
+ last = isect.vertex;
+ }
+
+ QPathEdge *ep = edge(addEdge(last, second));
+
+ if (ep) {
+ const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(second).y() ? 1 : -1;
+ if (pathId == 0)
+ ep->windingA += dir;
+ else
+ ep->windingB += dir;
}
}
}
@@ -832,7 +907,6 @@ static bool isLine(const QBezier &bezier)
void QPathSegments::setPath(const QPainterPath &path)
{
m_points.reset();
- m_beziers.reset();
m_intersections.reset();
m_segments.reset();
@@ -879,8 +953,25 @@ void QPathSegments::addPath(const QPainterPath &path)
if (isLine(bezier)) {
m_segments << Segment(m_pathId, last, current);
} else {
- m_segments << Segment(m_pathId, last, current, m_beziers.size());
- m_beziers << bezier;
+ QRectF bounds = bezier.bounds();
+
+ // threshold based on similar algorithm as in qtriangulatingstroker.cpp
+ int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * (2 * qreal(3.14) / 6));
+
+ if (threshold < 3) threshold = 3;
+ qreal one_over_threshold_minus_1 = qreal(1) / (threshold - 1);
+
+ for (int t = 1; t < threshold - 1; ++t) {
+ currentPoint = bezier.pointAt(t * one_over_threshold_minus_1);
+
+ int index = m_points.size();
+ m_segments << Segment(m_pathId, last, index);
+ last = index;
+
+ m_points << currentPoint;
+ }
+
+ m_segments << Segment(m_pathId, last, current);
}
}
last = current;
@@ -896,24 +987,19 @@ void QPathSegments::addPath(const QPainterPath &path)
m_segments << Segment(m_pathId, last, lastMoveTo);
for (int i = firstSegment; i < m_segments.size(); ++i) {
- const QBezier *bezier = bezierAt(i);
- if (bezier) {
- m_segments.at(i).bounds = bezier->bounds();
- } else {
- const QLineF line = lineAt(i);
+ const QLineF line = lineAt(i);
- qreal x1 = line.p1().x();
- qreal y1 = line.p1().y();
- qreal x2 = line.p2().x();
- qreal y2 = line.p2().y();
+ qreal x1 = line.p1().x();
+ qreal y1 = line.p1().y();
+ qreal x2 = line.p2().x();
+ qreal y2 = line.p2().y();
- if (x2 < x1)
- qSwap(x1, x2);
- if (y2 < y1)
- qSwap(y1, y2);
+ if (x2 < x1)
+ qSwap(x1, x2);
+ if (y2 < y1)
+ qSwap(y1, y2);
- m_segments.at(i).bounds = QRectF(x1, y1, x2 - x1, y2 - y1);
- }
+ m_segments.at(i).bounds = QRectF(x1, y1, x2 - x1, y2 - y1);
}
++m_pathId;
@@ -935,10 +1021,9 @@ qreal QWingedEdge::delta(int vertex, int a, int b) const
qreal result = b_angle - a_angle;
- if (qFuzzyIsNull(result) || qFuzzyCompare(result, 128))
- return 0;
-
- if (result < 0)
+ if (result >= 128.)
+ return result - 128.;
+ else if (result < 0)
return result + 128.;
else
return result;
@@ -949,28 +1034,17 @@ static inline QPointF tangentAt(const QWingedEdge &list, int vi, int ei)
const QPathEdge *ep = list.edge(ei);
Q_ASSERT(ep);
- qreal t;
qreal sign;
if (ep->first == vi) {
- t = ep->t0;
sign = 1;
} else {
- t = ep->t1;
sign = -1;
}
- QPointF normal;
- if (ep->bezier) {
- normal = ep->bezier->derivedAt(t);
-
- if (qFuzzyIsNull(normal.x()) && qFuzzyIsNull(normal.y()))
- normal = ep->bezier->secondDerivedAt(t);
- } else {
- const QPointF a = *list.vertex(ep->first);
- const QPointF b = *list.vertex(ep->second);
- normal = b - a;
- }
+ const QPointF a = *list.vertex(ep->first);
+ const QPointF b = *list.vertex(ep->second);
+ QPointF normal = b - a;
return normalize(sign * normal);
}
@@ -980,83 +1054,9 @@ static inline QPointF midPoint(const QWingedEdge &list, int ei)
const QPathEdge *ep = list.edge(ei);
Q_ASSERT(ep);
- if (ep->bezier) {
- return ep->bezier->pointAt(0.5 * (ep->t0 + ep->t1));
- } else {
- const QPointF a = *list.vertex(ep->first);
- const QPointF b = *list.vertex(ep->second);
- return a + 0.5 * (b - a);
- }
-}
-
-static QBezier transform(const QBezier &bezier, const QPointF &xAxis, const QPointF &yAxis, const QPointF &origin)
-{
- QPointF points[4] = {
- bezier.pt1(),
- bezier.pt2(),
- bezier.pt3(),
- bezier.pt4()
- };
-
- for (int i = 0; i < 4; ++i) {
- const QPointF p = points[i] - origin;
-
- points[i].rx() = dot(xAxis, p);
- points[i].ry() = dot(yAxis, p);
- }
-
- return QBezier::fromPoints(points[0], points[1], points[2], points[3]);
-}
-
-static bool isLeftOf(const QWingedEdge &list, int vi, int ai, int bi)
-{
- const QPathEdge *ap = list.edge(ai);
- const QPathEdge *bp = list.edge(bi);
-
- Q_ASSERT(ap);
- Q_ASSERT(bp);
-
- if (!(ap->bezier || bp->bezier))
- return false;
-
- const QPointF tangent = tangentAt(list, vi, ai);
- const QPointF normal(tangent.y(), -tangent.x());
-
- const QPointF origin = *list.vertex(vi);
-
- const QPointF dpA = midPoint(list, ai) - origin;
- const QPointF dpB = midPoint(list, bi) - origin;
-
- qreal xA = dot(normal, dpA);
- qreal xB = dot(normal, dpB);
-
- if (xA <= 0 && xB >= 0)
- return true;
-
- if (xA >= 0 && xB <= 0)
- return false;
-
- if (!ap->bezier)
- return xB > 0;
-
- if (!bp->bezier)
- return xA < 0;
-
- // both are beziers on the same side of the tangent
-
- // transform the beziers into the local coordinate system
- // such that positive y is along the tangent, and positive x is along the normal
-
- QBezier bezierA = transform(*ap->bezier, normal, tangent, origin);
- QBezier bezierB = transform(*bp->bezier, normal, tangent, origin);
-
- qreal y = qMin(bezierA.pointAt(0.5 * (ap->t0 + ap->t1)).y(),
- bezierB.pointAt(0.5 * (bp->t0 + bp->t1)).y());
-
- xA = bezierA.pointAt(bezierA.tForY(ap->t0, ap->t1, y)).x();
- xB = bezierB.pointAt(bezierB.tForY(bp->t0, bp->t1, y)).x();
-
- return xA < xB;
+ const QPointF a = *list.vertex(ep->first);
+ const QPointF b = *list.vertex(ep->second);
+ return a + 0.5 * (b - a);
}
QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus(int vi, int ei) const
@@ -1085,7 +1085,6 @@ QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus(int vi, int ei) const
status.flip();
Q_ASSERT(edge(status.edge)->vertex(status.direction) == vi);
-
qreal d2 = delta(vi, ei, status.edge);
#ifdef QDEBUG_CLIPPER
@@ -1093,8 +1092,7 @@ QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus(int vi, int ei) const
qDebug() << "Delta to edge" << status.edge << d2 << ", angles: " << op->angle << op->invAngle;
#endif
- if (!(qFuzzyIsNull(d2) && isLeftOf(*this, vi, status.edge, ei))
- && (d2 < d || (qFuzzyCompare(d2, d) && isLeftOf(*this, vi, status.edge, position)))) {
+ if (d2 < d) {
position = status.edge;
d = d2;
}
@@ -1211,15 +1209,15 @@ static qreal computeAngle(const QPointF &v)
#endif
}
-int QWingedEdge::addEdge(const QPointF &a, const QPointF &b, const QBezier *bezier, qreal t0, qreal t1)
+int QWingedEdge::addEdge(const QPointF &a, const QPointF &b)
{
int fi = insert(a);
int si = insert(b);
- return addEdge(fi, si, bezier, t0, t1);
+ return addEdge(fi, si);
}
-int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal t1)
+int QWingedEdge::addEdge(int fi, int si)
{
if (fi == si)
return -1;
@@ -1237,29 +1235,11 @@ int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal
QPathEdge *ep = edge(ei);
- ep->bezier = bezier;
- ep->t0 = t0;
- ep->t1 = t1;
-
- if (bezier) {
- QPointF aTangent = bezier->derivedAt(t0);
- QPointF bTangent = -bezier->derivedAt(t1);
-
- if (qFuzzyIsNull(aTangent.x()) && qFuzzyIsNull(aTangent.y()))
- aTangent = bezier->secondDerivedAt(t0);
-
- if (qFuzzyIsNull(bTangent.x()) && qFuzzyIsNull(bTangent.y()))
- bTangent = bezier->secondDerivedAt(t1);
-
- ep->angle = computeAngle(aTangent);
- ep->invAngle = computeAngle(bTangent);
- } else {
- const QPointF tangent = QPointF(*sp) - QPointF(*fp);
- ep->angle = computeAngle(tangent);
- ep->invAngle = ep->angle + 64;
- if (ep->invAngle >= 128)
- ep->invAngle -= 128;
- }
+ const QPointF tangent = QPointF(*sp) - QPointF(*fp);
+ ep->angle = computeAngle(tangent);
+ ep->invAngle = ep->angle + 64;
+ if (ep->invAngle >= 128)
+ ep->invAngle -= 128;
QPathVertex *vertices[2] = { fp, sp };
QPathEdge::Direction dirs[2] = { QPathEdge::Backward, QPathEdge::Forward };
@@ -1314,74 +1294,6 @@ int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal
return ei;
}
-void QWingedEdge::addBezierEdge(const QBezier *bezier, int vertexA, int vertexB, qreal alphaA, qreal alphaB, int path)
-{
- if (qFuzzyCompare(alphaA, alphaB))
- return;
-
- qreal alphaMid = (alphaA + alphaB) * 0.5;
-
- qreal s0 = 0;
- qreal s1 = 1;
- int count = bezier->stationaryYPoints(s0, s1);
-
- m_splitPoints.clear();
- m_splitPoints << alphaA;
- m_splitPoints << alphaMid;
- m_splitPoints << alphaB;
-
- if (count > 0 && !qFuzzyCompare(s0, alphaA) && !qFuzzyCompare(s0, alphaMid) && !qFuzzyCompare(s0, alphaB) && s0 > alphaA && s0 < alphaB)
- m_splitPoints << s0;
-
- if (count > 1 && !qFuzzyCompare(s1, alphaA) && !qFuzzyCompare(s1, alphaMid) && !qFuzzyCompare(s1, alphaB) && s1 > alphaA && s1 < alphaB)
- m_splitPoints << s1;
-
- if (count > 0)
- qSort(m_splitPoints.begin(), m_splitPoints.end());
-
- int last = vertexA;
- for (int i = 0; i < m_splitPoints.size() - 1; ++i) {
- const qreal t0 = m_splitPoints[i];
- const qreal t1 = m_splitPoints[i+1];
-
- int current;
- if ((i + 1) == (m_splitPoints.size() - 1)) {
- current = vertexB;
- } else {
- current = insert(bezier->pointAt(t1));
- }
-
- QPathEdge *ep = edge(addEdge(last, current, bezier, t0, t1));
-
- if (ep) {
- const int dir = m_vertices.at(last).y < m_vertices.at(current).y ? 1 : -1;
- if (path == 0)
- ep->windingA += dir;
- else
- ep->windingB += dir;
- }
-
- last = current;
- }
-}
-
-void QWingedEdge::addBezierEdge(const QBezier *bezier, const QPointF &a, const QPointF &b, qreal alphaA, qreal alphaB, int path)
-{
- if (qFuzzyCompare(alphaA, alphaB))
- return;
-
- if (comparePoints(a, b)) {
- int v = insert(a);
-
- addBezierEdge(bezier, v, v, alphaA, alphaB, path);
- } else {
- int va = insert(a);
- int vb = insert(b);
-
- addBezierEdge(bezier, va, vb, alphaA, alphaB, path);
- }
-}
-
int QWingedEdge::insert(const QPathVertex &vertex)
{
if (!m_vertices.isEmpty()) {
@@ -1430,37 +1342,12 @@ static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge
status.traversal = traversal;
status.direction = QPathEdge::Forward;
- const QBezier *bezier = 0;
- qreal t0 = 1;
- qreal t1 = 0;
- bool forward = true;
-
path.moveTo(*list.vertex(list.edge(edge)->first));
do {
const QPathEdge *ep = list.edge(status.edge);
- if (ep->bezier != bezier || (bezier && t0 != ep->t1 && t1 != ep->t0)) {
- if (bezier) {
- QBezier sub = bezier->bezierOnInterval(t0, t1);
-
- if (forward)
- path.cubicTo(sub.pt2(), sub.pt3(), sub.pt4());
- else
- path.cubicTo(sub.pt3(), sub.pt2(), sub.pt1());
- }
-
- bezier = ep->bezier;
- t0 = 1;
- t1 = 0;
- forward = status.direction == QPathEdge::Forward;
- }
-
- if (ep->bezier) {
- t0 = qMin(t0, ep->t0);
- t1 = qMax(t1, ep->t1);
- } else
- addLineTo(path, *list.vertex(ep->vertex(status.direction)));
+ addLineTo(path, *list.vertex(ep->vertex(status.direction)));
if (status.traversal == QPathEdge::LeftTraversal)
ep->flag &= ~16;
@@ -1469,14 +1356,6 @@ static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge
status = list.next(status);
} while (status.edge != edge);
-
- if (bezier) {
- QBezier sub = bezier->bezierOnInterval(t0, t1);
- if (forward)
- path.cubicTo(sub.pt2(), sub.pt3(), sub.pt4());
- else
- path.cubicTo(sub.pt3(), sub.pt2(), sub.pt1());
- }
}
void QWingedEdge::simplify()
@@ -1705,6 +1584,9 @@ QPainterPath QPathClipper::clip(Operation operation)
if (subjectPath == clipPath)
return op == BoolSub ? QPainterPath() : subjectPath;
+ bool subjectIsRect = pathToRect(subjectPath, 0);
+ bool clipIsRect = pathToRect(clipPath, 0);
+
const QRectF clipBounds = clipPath.boundingRect();
const QRectF subjectBounds = subjectPath.boundingRect();
@@ -1732,8 +1614,7 @@ QPainterPath QPathClipper::clip(Operation operation)
}
if (clipBounds.contains(subjectBounds)) {
- QRectF clipRect;
- if (pathToRect(clipPath, &clipRect) && clipRect.contains(subjectBounds)) {
+ if (clipIsRect) {
switch (op) {
case BoolSub:
return QPainterPath();
@@ -1746,17 +1627,16 @@ QPainterPath QPathClipper::clip(Operation operation)
}
}
} else if (subjectBounds.contains(clipBounds)) {
- QRectF subjectRect;
- if (pathToRect(subjectPath, &subjectRect) && subjectRect.contains(clipBounds)) {
+ if (subjectIsRect) {
switch (op) {
case BoolSub:
if (clipPath.fillRule() == Qt::OddEvenFill) {
QPainterPath result = clipPath;
- result.addRect(subjectRect);
+ result.addRect(subjectBounds);
return result;
} else {
QPainterPath result = clipPath.simplified();
- result.addRect(subjectRect);
+ result.addRect(subjectBounds);
return result;
}
break;
@@ -1769,6 +1649,13 @@ QPainterPath QPathClipper::clip(Operation operation)
}
}
}
+
+ if (op == BoolAnd) {
+ if (subjectIsRect)
+ return intersect(clipPath, subjectBounds);
+ else if (clipIsRect)
+ return intersect(subjectPath, clipBounds);
+ }
}
QWingedEdge list(subjectPath, clipPath);
@@ -1930,25 +1817,10 @@ bool QWingedEdge::isInside(qreal x, qreal y) const
QPointF b = *vertex(ep->second);
if ((a.y() < y && b.y() > y) || (a.y() > y && b.y() < y)) {
- if (ep->bezier) {
- qreal maxX = qMax(a.x(), qMax(b.x(), qMax(ep->bezier->x2, ep->bezier->x3)));
- qreal minX = qMin(a.x(), qMin(b.x(), qMin(ep->bezier->x2, ep->bezier->x3)));
-
- if (minX > x) {
- winding += w;
- } else if (maxX > x) {
- const qreal t = ep->bezier->tForY(ep->t0, ep->t1, y);
- const qreal intersection = ep->bezier->pointAt(t).x();
-
- if (intersection > x)
- winding += w;
- }
- } else {
- qreal intersectionX = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y());
+ qreal intersectionX = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y());
- if (intersectionX > x)
- winding += w;
- }
+ if (intersectionX > x)
+ winding += w;
}
}
@@ -1964,17 +1836,9 @@ static QVector<QCrossingEdge> findCrossings(const QWingedEdge &list, qreal y)
QPointF b = *list.vertex(edge->second);
if ((a.y() < y && b.y() > y) || (a.y() > y && b.y() < y)) {
- if (edge->bezier) {
- const qreal t = edge->bezier->tForY(edge->t0, edge->t1, y);
- const qreal intersection = edge->bezier->pointAt(t).x();
-
- const QCrossingEdge edge = { i, intersection };
- crossings << edge;
- } else {
- const qreal intersection = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y());
- const QCrossingEdge edge = { i, intersection };
- crossings << edge;
- }
+ const qreal intersection = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y());
+ const QCrossingEdge edge = { i, intersection };
+ crossings << edge;
}
}
return crossings;
@@ -2052,4 +1916,243 @@ bool QPathClipper::handleCrossingEdges(QWingedEdge &list, qreal y, ClipperMode m
return false;
}
+namespace {
+
+QList<QPainterPath> toSubpaths(const QPainterPath &path)
+{
+
+ QList<QPainterPath> subpaths;
+ if (path.isEmpty())
+ return subpaths;
+
+ QPainterPath current;
+ for (int i = 0; i < path.elementCount(); ++i) {
+ const QPainterPath::Element &e = path.elementAt(i);
+ switch (e.type) {
+ case QPainterPath::MoveToElement:
+ if (current.elementCount() > 1)
+ subpaths += current;
+ current = QPainterPath();
+ current.moveTo(e);
+ break;
+ case QPainterPath::LineToElement:
+ current.lineTo(e);
+ break;
+ case QPainterPath::CurveToElement: {
+ current.cubicTo(e, path.elementAt(i + 1), path.elementAt(i + 2));
+ i+=2;
+ break;
+ }
+ case QPainterPath::CurveToDataElement:
+ Q_ASSERT(!"toSubpaths(), bad element type");
+ break;
+ }
+ }
+
+ if (current.elementCount() > 1)
+ subpaths << current;
+
+ return subpaths;
+}
+
+enum Edge
+{
+ Left, Top, Right, Bottom
+};
+
+static bool isVertical(Edge edge)
+{
+ return edge == Left || edge == Right;
+}
+
+template <Edge edge>
+bool compare(const QPointF &p, qreal t)
+{
+ switch (edge)
+ {
+ case Left:
+ return p.x() < t;
+ case Right:
+ return p.x() > t;
+ case Top:
+ return p.y() < t;
+ default:
+ return p.y() > t;
+ }
+}
+
+template <Edge edge>
+QPointF intersectLine(const QPointF &a, const QPointF &b, qreal t)
+{
+ QLineF line(a, b);
+ switch (edge) {
+ case Left: // fall-through
+ case Right:
+ return line.pointAt((t - a.x()) / (b.x() - a.x()));
+ default:
+ return line.pointAt((t - a.y()) / (b.y() - a.y()));
+ }
+}
+
+void addLine(QPainterPath &path, const QLineF &line)
+{
+ if (path.elementCount() > 0)
+ path.lineTo(line.p1());
+ else
+ path.moveTo(line.p1());
+
+ path.lineTo(line.p2());
+}
+
+template <Edge edge>
+void clipLine(const QPointF &a, const QPointF &b, qreal t, QPainterPath &result)
+{
+ bool outA = compare<edge>(a, t);
+ bool outB = compare<edge>(b, t);
+ if (outA && outB)
+ return;
+
+ if (outA)
+ addLine(result, QLineF(intersectLine<edge>(a, b, t), b));
+ else if(outB)
+ addLine(result, QLineF(a, intersectLine<edge>(a, b, t)));
+ else
+ addLine(result, QLineF(a, b));
+}
+
+void addBezier(QPainterPath &path, const QBezier &bezier)
+{
+ if (path.elementCount() > 0)
+ path.lineTo(bezier.pt1());
+ else
+ path.moveTo(bezier.pt1());
+
+ path.cubicTo(bezier.pt2(), bezier.pt3(), bezier.pt4());
+}
+
+template <Edge edge>
+void clipBezier(const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, qreal t, QPainterPath &result)
+{
+ QBezier bezier = QBezier::fromPoints(a, b, c, d);
+
+ bool outA = compare<edge>(a, t);
+ bool outB = compare<edge>(b, t);
+ bool outC = compare<edge>(c, t);
+ bool outD = compare<edge>(d, t);
+
+ int outCount = int(outA) + int(outB) + int(outC) + int(outD);
+
+ if (outCount == 4)
+ return;
+
+ if (outCount == 0) {
+ addBezier(result, bezier);
+ return;
+ }
+
+ QTransform flip = isVertical(edge) ? QTransform(0, 1, 1, 0, 0, 0) : QTransform();
+ QBezier unflipped = bezier;
+ QBezier flipped = bezier.mapBy(flip);
+
+ qreal t0 = 0, t1 = 1;
+ int stationary = flipped.stationaryYPoints(t0, t1);
+
+ qreal segments[4];
+ QPointF points[4];
+ points[0] = unflipped.pt1();
+ segments[0] = 0;
+
+ int segmentCount = 0;
+ if (stationary > 0) {
+ ++segmentCount;
+ segments[segmentCount] = t0;
+ points[segmentCount] = unflipped.pointAt(t0);
+ }
+ if (stationary > 1) {
+ ++segmentCount;
+ segments[segmentCount] = t1;
+ points[segmentCount] = unflipped.pointAt(t1);
+ }
+ ++segmentCount;
+ segments[segmentCount] = 1;
+ points[segmentCount] = unflipped.pt4();
+
+ qreal lastIntersection = 0;
+ for (int i = 0; i < segmentCount; ++i) {
+ outA = compare<edge>(points[i], t);
+ outB = compare<edge>(points[i+1], t);
+
+ if (outA != outB) {
+ qreal intersection = flipped.tForY(segments[i], segments[i+1], t);
+
+ if (outB)
+ addBezier(result, unflipped.getSubRange(lastIntersection, intersection));
+
+ lastIntersection = intersection;
+ }
+ }
+
+ if (!outB)
+ addBezier(result, unflipped.getSubRange(lastIntersection, 1));
+}
+
+// clips a single subpath against a single edge
+template <Edge edge>
+QPainterPath clip(const QPainterPath &path, qreal t)
+{
+ QPainterPath result;
+ for (int i = 1; i < path.elementCount(); ++i) {
+ const QPainterPath::Element &element = path.elementAt(i);
+ Q_ASSERT(!element.isMoveTo());
+ if (element.isLineTo()) {
+ clipLine<edge>(path.elementAt(i-1), path.elementAt(i), t, result);
+ } else {
+ clipBezier<edge>(path.elementAt(i-1), path.elementAt(i), path.elementAt(i+1), path.elementAt(i+2), t, result);
+ i += 2;
+ }
+ }
+
+ int last = path.elementCount() - 1;
+ if (QPointF(path.elementAt(last)) != QPointF(path.elementAt(0)))
+ clipLine<edge>(path.elementAt(last), path.elementAt(0), t, result);
+
+ return result;
+}
+
+QPainterPath intersectPath(const QPainterPath &path, const QRectF &rect)
+{
+ QList<QPainterPath> subpaths = toSubpaths(path);
+
+ QPainterPath result;
+ result.setFillRule(path.fillRule());
+ for (int i = 0; i < subpaths.size(); ++i) {
+ QPainterPath subPath = subpaths.at(i);
+ QRectF bounds = subPath.boundingRect();
+ if (bounds.intersects(rect)) {
+ if (bounds.left() < rect.left())
+ subPath = clip<Left>(subPath, rect.left());
+ if (bounds.right() > rect.right())
+ subPath = clip<Right>(subPath, rect.right());
+
+ bounds = subPath.boundingRect();
+
+ if (bounds.top() < rect.top())
+ subPath = clip<Top>(subPath, rect.top());
+ if (bounds.bottom() > rect.bottom())
+ subPath = clip<Bottom>(subPath, rect.bottom());
+
+ if (subPath.elementCount() > 1)
+ result.addPath(subPath);
+ }
+ }
+ return result;
+}
+
+}
+
+QPainterPath QPathClipper::intersect(const QPainterPath &path, const QRectF &rect)
+{
+ return intersectPath(path, rect);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index b90086215b..7962400d85 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -87,6 +87,7 @@ public:
bool contains();
static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
+ static QPainterPath intersect(const QPainterPath &path, const QRectF &rect);
private:
Q_DISABLE_COPY(QPathClipper)
@@ -150,10 +151,6 @@ public:
qreal angle;
qreal invAngle;
- const QBezier *bezier;
- qreal t0;
- qreal t1;
-
int next(Traversal traversal, Direction direction) const;
void setNext(Traversal traversal, Direction direction, int next);
@@ -181,9 +178,8 @@ public:
};
struct Segment {
- Segment(int pathId, int vertexA, int vertexB, int bezierIndex = -1)
+ Segment(int pathId, int vertexA, int vertexB)
: path(pathId)
- , bezier(bezierIndex)
, va(vertexA)
, vb(vertexB)
, intersection(-1)
@@ -191,7 +187,6 @@ public:
}
int path;
- int bezier;
// vertices
int va;
@@ -215,7 +210,6 @@ public:
const Segment &segmentAt(int index) const;
const QLineF lineAt(int index) const;
- const QBezier *bezierAt(int index) const;
const QRectF &elementBounds(int index) const;
int pathId(int index) const;
@@ -230,7 +224,6 @@ public:
private:
QDataBuffer<QPointF> m_points;
QDataBuffer<Segment> m_segments;
- QDataBuffer<QBezier> m_beziers;
QDataBuffer<Intersection> m_intersections;
int m_pathId;
@@ -271,8 +264,8 @@ public:
TraversalStatus next(const TraversalStatus &status) const;
- int addEdge(const QPointF &a, const QPointF &b, const QBezier *bezier = 0, qreal t0 = 0, qreal t1 = 1);
- int addEdge(int vertexA, int vertexB, const QBezier *bezier = 0, qreal t0 = 0, qreal t1 = 1);
+ int addEdge(const QPointF &a, const QPointF &b);
+ int addEdge(int vertexA, int vertexB);
bool isInside(qreal x, qreal y) const;
@@ -284,11 +277,7 @@ private:
void printNode(int i, FILE *handle);
- QBezier bezierFromIndex(int index) const;
-
void removeEdge(int ei);
- void addBezierEdge(const QBezier *bezier, const QPointF &a, const QPointF &b, qreal alphaA, qreal alphaB, int path);
- void addBezierEdge(const QBezier *bezier, int vertexA, int vertexB, qreal alphaA, qreal alphaB, int path);
int insert(const QPathVertex &vertex);
TraversalStatus findInsertStatus(int vertex, int edge) const;
@@ -311,9 +300,6 @@ inline QPathEdge::QPathEdge(int a, int b)
, second(b)
, angle(0)
, invAngle(0)
- , bezier(0)
- , t0(0)
- , t1(0)
{
m_next[0][0] = -1;
m_next[1][0] = -1;
@@ -395,15 +381,6 @@ inline const QLineF QPathSegments::lineAt(int index) const
return QLineF(m_points.at(segment.va), m_points.at(segment.vb));
}
-inline const QBezier *QPathSegments::bezierAt(int index) const
-{
- const Segment &segment = m_segments.at(index);
- if (segment.bezier >= 0)
- return &m_beziers.at(segment.bezier);
- else
- return 0;
-}
-
inline const QRectF &QPathSegments::elementBounds(int index) const
{
return m_segments.at(index).bounds;
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index ee8b078fc1..44049c0d8f 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1415,6 +1415,7 @@ void QPdfBaseEngine::setProperty(PrintEnginePropertyKey key, const QVariant &val
case PPK_FullPage:
d->fullPage = value.toBool();
break;
+ case PPK_CopyCount: // fallthrough
case PPK_NumberOfCopies:
d->copies = value.toInt();
break;
@@ -1504,6 +1505,17 @@ QVariant QPdfBaseEngine::property(PrintEnginePropertyKey key) const
case PPK_FullPage:
ret = d->fullPage;
break;
+ case PPK_CopyCount:
+ ret = d->copies;
+ break;
+ case PPK_SupportsMultipleCopies:
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ if (QCUPSSupport::isAvailable())
+ ret = true;
+ else
+#endif
+ ret = false;
+ break;
case PPK_NumberOfCopies:
#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
if (QCUPSSupport::isAvailable())
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index f79c5cc067..9c4d05da49 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -216,8 +216,6 @@ public:
private:
void updateClipPath(const QPainterPath & path, Qt::ClipOperation op);
-
- friend int qt_printerRealNumCopies(QPaintEngine *);
};
class QPdfBaseEnginePrivate : public QAlphaPaintEnginePrivate
diff --git a/src/gui/painting/qprintengine.h b/src/gui/painting/qprintengine.h
index 35715fbf97..71ff954d79 100644
--- a/src/gui/painting/qprintengine.h
+++ b/src/gui/painting/qprintengine.h
@@ -86,6 +86,8 @@ public:
PPK_PaperSources,
PPK_CustomPaperSize,
PPK_PageMargins,
+ PPK_CopyCount,
+ PPK_SupportsMultipleCopies,
PPK_PaperSize = PPK_PageSize,
PPK_CustomBase = 0xff00
diff --git a/src/gui/painting/qprintengine_mac.mm b/src/gui/painting/qprintengine_mac.mm
index 7195c631f8..a5482252cb 100644
--- a/src/gui/painting/qprintengine_mac.mm
+++ b/src/gui/painting/qprintengine_mac.mm
@@ -114,8 +114,11 @@ bool QMacPrintEngine::end()
Q_D(QMacPrintEngine);
if (d->state == QPrinter::Aborted)
return true; // I was just here a function call ago :)
- if(d->paintEngine->type() == QPaintEngine::CoreGraphics)
+ if(d->paintEngine->type() == QPaintEngine::CoreGraphics) {
+ // We dont need the paint engine to call restoreGraphicsState()
+ static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->stackCount = 0;
static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->hd = 0;
+ }
d->paintEngine->end();
if (d->state != QPrinter::Idle)
d->releaseSession();
@@ -685,6 +688,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
case PPK_FullPage:
d->fullPage = value.toBool();
break;
+ case PPK_CopyCount: // fallthrough
case PPK_NumberOfCopies:
PMSetCopies(d->settings, value.toInt(), false);
break;
@@ -787,6 +791,15 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const
case PPK_NumberOfCopies:
ret = 1;
break;
+ case PPK_CopyCount: {
+ UInt32 copies = 1;
+ PMGetCopies(d->settings, &copies);
+ ret = (uint) copies;
+ break;
+ }
+ case PPK_SupportsMultipleCopies:
+ ret = true;
+ break;
case PPK_Orientation:
PMOrientation orientation;
PMGetOrientation(d->format, &orientation);
diff --git a/src/gui/painting/qprintengine_qws.cpp b/src/gui/painting/qprintengine_qws.cpp
index 2d355b8d25..396d712ae9 100644
--- a/src/gui/painting/qprintengine_qws.cpp
+++ b/src/gui/painting/qprintengine_qws.cpp
@@ -268,9 +268,13 @@ QVariant QtopiaPrintEngine::property(PrintEnginePropertyKey key) const
case PPK_FullPage:
ret = d->fullPage;
break;
+ case PPK_CopyCount: // fallthrough
case PPK_NumberOfCopies:
ret = d->numCopies;
break;
+ case PPK_SupportsMultipleCopies:
+ ret = false;
+ break;
case PPK_Orientation:
ret = d->orientation;
break;
@@ -329,6 +333,7 @@ void QtopiaPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
case PPK_FullPage:
d->fullPage = value.toBool();
break;
+ case PPK_CopyCount: // fallthrough
case PPK_NumberOfCopies:
d->numCopies = value.toInt();
break;
diff --git a/src/gui/painting/qprintengine_win.cpp b/src/gui/painting/qprintengine_win.cpp
index 76dad72723..dd4de997b5 100644
--- a/src/gui/painting/qprintengine_win.cpp
+++ b/src/gui/painting/qprintengine_win.cpp
@@ -368,7 +368,8 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
}
// We only want to convert the glyphs to text if the entire string is compatible with ASCII
- bool convertToText = true;
+ // and if we actually have access to the chars.
+ bool convertToText = ti.chars != 0;
for (int i=0; i < ti.num_chars; ++i) {
if (ti.chars[i].unicode() >= 0x80) {
convertToText = false;
@@ -1241,6 +1242,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
d->updateOrigin();
break;
+ case PPK_CopyCount: // fallthrough
case PPK_NumberOfCopies:
if (!d->devMode)
break;
@@ -1407,6 +1409,14 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
value = d->fullPage;
break;
+ case PPK_CopyCount:
+ value = d->num_copies;
+ break;
+
+ case PPK_SupportsMultipleCopies:
+ value = true;
+ break;
+
case PPK_NumberOfCopies:
value = 1;
break;
diff --git a/src/gui/painting/qprintengine_win_p.h b/src/gui/painting/qprintengine_win_p.h
index a3271cb190..d435831ac8 100644
--- a/src/gui/painting/qprintengine_win_p.h
+++ b/src/gui/painting/qprintengine_win_p.h
@@ -108,7 +108,6 @@ public:
private:
friend class QPrintDialog;
friend class QPageSetupDialog;
- friend int qt_printerRealNumCopies(QPaintEngine *);
};
class QWin32PrintEnginePrivate : public QAlphaPaintEnginePrivate
diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp
index 4d2b50ae35..ae2141662d 100644
--- a/src/gui/painting/qprinter.cpp
+++ b/src/gui/painting/qprinter.cpp
@@ -158,27 +158,6 @@ QSizeF qt_printerPaperSize(QPrinter::Orientation orientation,
(qt_paperSizes[paperSize][height_index] * 72 / 25.4) / multiplier);
}
-
-// returns the actual num copies set on a printer, not
-// the number that is documented in QPrinter::numCopies()
-int qt_printerRealNumCopies(QPaintEngine *engine)
-{
- int numCopies = 1;
- if (engine->type() == QPaintEngine::PostScript
- || engine->type() == QPaintEngine::Pdf)
- {
- QPdfBaseEngine *base = static_cast<QPdfBaseEngine *>(engine);
- numCopies = base->d_func()->copies;
- }
-#ifdef Q_WS_WIN
- else if (engine->type() == QPaintEngine::Windows) {
- QWin32PrintEngine *base = static_cast<QWin32PrintEngine *>(engine);
- numCopies = base->d_func()->num_copies;
- }
-#endif
- return numCopies;
-}
-
void QPrinterPrivate::createDefaultEngines()
{
QPrinter::OutputFormat realOutputFormat = outputFormat;
@@ -302,7 +281,7 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
printer to provide, in dots per inch (DPI).
\i setFullPage() tells QPrinter whether you want to deal with the
full page or just with the part the printer can draw on.
- \i setNumCopies() tells QPrinter how many copies of the document
+ \i setCopyCount() tells QPrinter how many copies of the document
it should print.
\endlist
@@ -403,6 +382,7 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
\value AllPages All pages should be printed.
\value Selection Only the selection should be printed.
\value PageRange The specified page range should be printed.
+ \value CurrentPage Only the current page should be printed.
\sa QAbstractPrintDialog::PrintRange
*/
@@ -592,6 +572,7 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
\value AllPages All the pages should be printed.
\value Selection Only the selection should be printed.
\value PageRange Print according to the from page and to page options.
+ \value CurrentPage Only the current page should be printed.
\sa setPrintRange(), printRange()
*/
@@ -607,6 +588,7 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
\value PrintSelection Describes if printing selections should be enabled.
\value PrintPageRange Describes if printing page ranges (from, to) should
be enabled
+ \value PrintCurrentPage if Print Current Page option should be enabled
\sa setOptionEnabled(), isOptionEnabled()
*/
@@ -748,7 +730,6 @@ void QPrinter::setOutputFormat(OutputFormat format)
d->outputFormat = format;
QPrintEngine *oldPrintEngine = d->printEngine;
- QPaintEngine *oldPaintEngine = d->paintEngine; // same as the above - shouldn't be deleted
const bool def_engine = d->use_default_engine;
d->printEngine = 0;
@@ -761,7 +742,7 @@ void QPrinter::setOutputFormat(OutputFormat format)
// PPK_NumberOfCopies need special treatmeant since it in most cases
// will return 1, disregarding the actual value that was set
if (key == QPrintEngine::PPK_NumberOfCopies)
- prop = QVariant(qt_printerRealNumCopies(oldPaintEngine));
+ prop = QVariant(copyCount());
else
prop = oldPrintEngine->property(key);
if (prop.isValid())
@@ -1263,6 +1244,7 @@ QPrinter::ColorMode QPrinter::colorMode() const
/*!
+ \obsolete
Returns the number of copies to be printed. The default value is 1.
On Windows, Mac OS X and X11 systems that support CUPS, this will always
@@ -1275,6 +1257,8 @@ QPrinter::ColorMode QPrinter::colorMode() const
buffering up the copies and in those cases the application must make an
explicit call to the print code for each copy.
+ Use copyCount() in conjunction with supportsMultipleCopies() instead.
+
\sa setNumCopies(), actualNumCopies()
*/
@@ -1286,6 +1270,7 @@ int QPrinter::numCopies() const
/*!
+ \obsolete
\since 4.6
Returns the number of copies that will be printed. The default
@@ -1294,22 +1279,26 @@ int QPrinter::numCopies() const
This function always returns the actual value specified in the print
dialog or using setNumCopies().
+ Use copyCount() instead.
+
\sa setNumCopies(), numCopies()
*/
int QPrinter::actualNumCopies() const
{
- Q_D(const QPrinter);
- return qt_printerRealNumCopies(d->paintEngine);
+ return copyCount();
}
/*!
+ \obsolete
Sets the number of copies to be printed to \a numCopies.
The printer driver reads this setting and prints the specified
number of copies.
+ Use setCopyCount() instead.
+
\sa numCopies()
*/
@@ -1321,6 +1310,58 @@ void QPrinter::setNumCopies(int numCopies)
d->addToManualSetList(QPrintEngine::PPK_NumberOfCopies);
}
+/*!
+ \since 4.7
+
+ Sets the number of copies to be printed to \a count.
+
+ The printer driver reads this setting and prints the specified number of
+ copies.
+
+ \sa copyCount(), supportsMultipleCopies()
+*/
+
+void QPrinter::setCopyCount(int count)
+{
+ Q_D(QPrinter);
+ ABORT_IF_ACTIVE("QPrinter::setCopyCount;");
+ d->printEngine->setProperty(QPrintEngine::PPK_CopyCount, count);
+ d->addToManualSetList(QPrintEngine::PPK_CopyCount);
+}
+
+/*!
+ \since 4.7
+
+ Returns the number of copies that will be printed. The default value is 1.
+
+ \sa setCopyCount(), supportsMultipleCopies()
+*/
+
+int QPrinter::copyCount() const
+{
+ Q_D(const QPrinter);
+ return d->printEngine->property(QPrintEngine::PPK_CopyCount).toInt();
+}
+
+/*!
+ \since 4.7
+
+ Returns true if the printer supports printing multiple copies of the same
+ document in one job; otherwise false is returned.
+
+ On most systems this function will return true. However, on X11 systems
+ that do not support CUPS, this function will return false. That means the
+ application has to handle the number of copies by printing the same
+ document the required number of times.
+
+ \sa setCopyCount(), copyCount()
+*/
+
+bool QPrinter::supportsMultipleCopies() const
+{
+ Q_D(const QPrinter);
+ return d->printEngine->property(QPrintEngine::PPK_SupportsMultipleCopies).toBool();
+}
/*!
\since 4.1
@@ -2262,8 +2303,8 @@ bool QPrinter::isOptionEnabled( PrinterOption option ) const
\value PPK_FullPage A boolean describing if the printer should be
full page or not.
- \value PPK_NumberOfCopies An integer specifying the number of
- copies
+ \value PPK_NumberOfCopies Obsolete. An integer specifying the number of
+ copies. Use PPK_CopyCount instead.
\value PPK_Orientation Specifies a QPrinter::Orientation value.
@@ -2310,6 +2351,11 @@ bool QPrinter::isOptionEnabled( PrinterOption option ) const
\value PPK_PageMargins A QList<QVariant> containing the left, top,
right and bottom margin values.
+ \value PPK_CopyCount An integer specifying the number of copies to print.
+
+ \value PPK_SupportsMultipleCopies A boolean value indicating whether or not
+ the printer supports printing multiple copies in one job.
+
\value PPK_CustomBase Basis for extension.
*/
diff --git a/src/gui/painting/qprinter.h b/src/gui/painting/qprinter.h
index 5aa891e769..996a954eca 100644
--- a/src/gui/painting/qprinter.h
+++ b/src/gui/painting/qprinter.h
@@ -124,7 +124,7 @@ public:
enum OutputFormat { NativeFormat, PdfFormat, PostScriptFormat };
// ### Qt 5: Merge with QAbstractPrintDialog::PrintRange
- enum PrintRange { AllPages, Selection, PageRange };
+ enum PrintRange { AllPages, Selection, PageRange, CurrentPage };
enum Unit {
Millimeter,
@@ -199,6 +199,10 @@ public:
int actualNumCopies() const;
+ void setCopyCount(int);
+ int copyCount() const;
+ bool supportsMultipleCopies() const;
+
void setPaperSource(PaperSource);
PaperSource paperSource() const;
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index bea2b6eeea..bfeef725f8 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -704,28 +704,13 @@ bool QRegion::intersects(const QRegion &region) const
}
/*!
+ \fn bool QRegion::intersects(const QRect &rect) const
\since 4.2
Returns true if this region intersects with \a rect, otherwise
returns false.
*/
-bool QRegion::intersects(const QRect &rect) const
-{
- if (isEmpty() || rect.isNull())
- return false;
- const QRect r = rect.normalized();
- if (!rect_intersects(boundingRect(), r))
- return false;
- if (rectCount() == 1)
- return true;
-
- const QVector<QRect> myRects = rects();
- for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it)
- if (rect_intersects(r, *it))
- return true;
- return false;
-}
#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN)
/*!
@@ -4349,5 +4334,24 @@ bool QRegion::operator==(const QRegion &r) const
return EqualRegion(d->qt_rgn, r.d->qt_rgn);
}
+bool QRegion::intersects(const QRect &rect) const
+{
+ if (isEmptyHelper(d->qt_rgn) || rect.isNull())
+ return false;
+
+ const QRect r = rect.normalized();
+ if (!rect_intersects(d->qt_rgn->extents, r))
+ return false;
+ if (d->qt_rgn->numRects == 1)
+ return true;
+
+ const QVector<QRect> myRects = rects();
+ for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it)
+ if (rect_intersects(r, *it))
+ return true;
+ return false;
+}
+
+
#endif
QT_END_NAMESPACE
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index 094d42e849..e43544cec2 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -1043,6 +1043,47 @@ QVector<qfixed> QDashStroker::patternForStyle(Qt::PenStyle style)
return pattern;
}
+static inline bool lineRectIntersectsRect(qfixed2d p1, qfixed2d p2, const qfixed2d &tl, const qfixed2d &br)
+{
+ return ((p1.x > tl.x || p2.x > tl.x) && (p1.x < br.x || p2.x < br.x)
+ && (p1.y > tl.y || p2.y > tl.y) && (p1.y < br.y || p2.y < br.y));
+}
+
+// If the line intersects the rectangle, this function will return true.
+static bool lineIntersectsRect(qfixed2d p1, qfixed2d p2, const qfixed2d &tl, const qfixed2d &br)
+{
+ if (!lineRectIntersectsRect(p1, p2, tl, br))
+ return false;
+ if (p1.x == p2.x || p1.y == p2.y)
+ return true;
+
+ if (p1.y > p2.y)
+ qSwap(p1, p2); // make p1 above p2
+ qfixed2d u;
+ qfixed2d v;
+ qfixed2d w = {p2.x - p1.x, p2.y - p1.y};
+ if (p1.x < p2.x) {
+ // backslash
+ u.x = tl.x - p1.x; u.y = br.y - p1.y;
+ v.x = br.x - p1.x; v.y = tl.y - p1.y;
+ } else {
+ // slash
+ u.x = tl.x - p1.x; u.y = tl.y - p1.y;
+ v.x = br.x - p1.x; v.y = br.y - p1.y;
+ }
+#if defined(QFIXED_IS_26_6) || defined(QFIXED_IS_16_16)
+ qint64 val1 = qint64(u.x) * qint64(w.y) - qint64(u.y) * qint64(w.x);
+ qint64 val2 = qint64(v.x) * qint64(w.y) - qint64(v.y) * qint64(w.x);
+ return (val1 < 0 && val2 > 0) || (val1 > 0 && val2 < 0);
+#elif defined(QFIXED_IS_32_32)
+ // Cannot do proper test because it may overflow.
+ return true;
+#else
+ qreal val1 = u.x * w.y - u.y * w.x;
+ qreal val2 = v.x * w.y - v.y * w.x;
+ return (val1 < 0 && val2 > 0) || (val1 > 0 && val2 < 0);
+#endif
+}
void QDashStroker::processCurrentSubpath()
{
@@ -1067,9 +1108,11 @@ void QDashStroker::processCurrentSubpath()
if (qFuzzyIsNull(sumLength))
return;
+ qreal invSumLength = qreal(1) / sumLength;
+
Q_ASSERT(dashCount > 0);
- dashCount = (dashCount / 2) * 2; // Round down to even number
+ dashCount = dashCount & -2; // Round down to even number
int idash = 0; // Index to current dash
qreal pos = 0; // The position on the curve, 0 <= pos <= path.length
@@ -1077,11 +1120,12 @@ void QDashStroker::processCurrentSubpath()
qreal doffset = m_dashOffset * m_stroke_width;
// make sure doffset is in range [0..sumLength)
- doffset -= qFloor(doffset / sumLength) * sumLength;
+ doffset -= qFloor(doffset * invSumLength) * sumLength;
while (doffset >= dashes[idash]) {
doffset -= dashes[idash];
- idash = (idash + 1) % dashCount;
+ if (++idash >= dashCount)
+ idash = 0;
}
qreal estart = 0; // The elements starting position
@@ -1119,12 +1163,41 @@ void QDashStroker::processCurrentSubpath()
estop = estart + elen;
bool done = pos >= estop;
+
+ if (clipping) {
+ // Check if the entire line can be clipped away.
+ if (!lineIntersectsRect(prev, e, clip_tl, clip_br)) {
+ // Cut away full dash sequences.
+ elen -= qFloor(elen * invSumLength) * sumLength;
+ // Update dash offset.
+ while (!done) {
+ qreal dpos = pos + dashes[idash] - doffset - estart;
+
+ Q_ASSERT(dpos >= 0);
+
+ if (dpos > elen) { // dash extends this line
+ doffset = dashes[idash] - (dpos - elen); // subtract the part already used
+ pos = estop; // move pos to next path element
+ done = true;
+ } else { // Dash is on this line
+ pos = dpos + estart;
+ done = pos >= estop;
+ if (++idash >= dashCount)
+ idash = 0;
+ doffset = 0; // full segment so no offset on next.
+ }
+ }
+ hasMoveTo = false;
+ move_to_pos = e;
+ }
+ }
+
// Dash away...
while (!done) {
QPointF p2;
- int idash_incr = 0;
bool has_offset = doffset > 0;
+ bool evenDash = (idash & 1) == 0;
qreal dpos = pos + dashes[idash] - doffset - estart;
Q_ASSERT(dpos >= 0);
@@ -1138,39 +1211,36 @@ void QDashStroker::processCurrentSubpath()
p2 = cline.pointAt(dpos/elen);
pos = dpos + estart;
done = pos >= estop;
- idash_incr = 1;
+ if (++idash >= dashCount)
+ idash = 0;
doffset = 0; // full segment so no offset on next.
}
- if (idash % 2 == 0) {
+ if (evenDash) {
line_to_pos.x = qt_real_to_fixed(p2.x());
line_to_pos.y = qt_real_to_fixed(p2.y());
- // If we have an offset, we're continuing a dash
- // from a previous element and should only
- // continue the current dash, without starting a
- // new subpath.
- if (!has_offset || !hasMoveTo) {
- emitMoveTo(move_to_pos.x, move_to_pos.y);
- hasMoveTo = true;
- }
-
if (!clipping
- // if move_to is inside...
- || (move_to_pos.x > clip_tl.x && move_to_pos.x < clip_br.x
- && move_to_pos.y > clip_tl.y && move_to_pos.y < clip_br.y)
- // Or if line_to is inside...
- || (line_to_pos.x > clip_tl.x && line_to_pos.x < clip_br.x
- && line_to_pos.y > clip_tl.y && line_to_pos.y < clip_br.y))
+ || lineRectIntersectsRect(move_to_pos, line_to_pos, clip_tl, clip_br))
{
+ // If we have an offset, we're continuing a dash
+ // from a previous element and should only
+ // continue the current dash, without starting a
+ // new subpath.
+ if (!has_offset || !hasMoveTo) {
+ emitMoveTo(move_to_pos.x, move_to_pos.y);
+ hasMoveTo = true;
+ }
+
emitLineTo(line_to_pos.x, line_to_pos.y);
+ } else {
+ hasMoveTo = false;
}
+ move_to_pos = line_to_pos;
} else {
move_to_pos.x = qt_real_to_fixed(p2.x());
move_to_pos.y = qt_real_to_fixed(p2.y());
}
-
- idash = (idash + idash_incr) % dashCount;
}
// Shuffle to the next cycle...
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 7b7f3250fc..631a9cf8fa 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -55,42 +55,53 @@ QT_BEGIN_NAMESPACE
// #define CACHE_DEBUG
-void QTextureGlyphCache::populate(const QTextItemInt &ti,
- const QVarLengthArray<glyph_t> &glyphs,
- const QVarLengthArray<QFixedPoint> &)
+// returns the highest number closest to v, which is a power of 2
+// NB! assumes 32 bit ints
+static inline int qt_next_power_of_two(int v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ ++v;
+ return v;
+}
+
+void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
+ const QFixedPoint *)
{
#ifdef CACHE_DEBUG
- printf("Populating with '%s'\n", QString::fromRawData(ti.chars, ti.num_chars).toLatin1().data());
+ printf("Populating with %d glyphs\n", numGlyphs);
qDebug() << " -> current transformation: " << m_transform;
#endif
- m_current_textitem = &ti;
+ m_current_fontengine = fontEngine;
const int margin = glyphMargin();
+ const int paddingDoubled = glyphPadding() * 2;
QHash<glyph_t, Coord> listItemCoordinates;
int rowHeight = 0;
// check each glyph for its metrics and get the required rowHeight.
- for (int i=0; i < glyphs.size(); ++i) {
+ for (int i=0; i < numGlyphs; ++i) {
const glyph_t glyph = glyphs[i];
if (coords.contains(glyph))
continue;
if (listItemCoordinates.contains(glyph))
continue;
- glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyph, m_transform);
+ glyph_metrics_t metrics = fontEngine->boundingBox(glyph, m_transform);
#ifdef CACHE_DEBUG
- printf("'%c' (%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f, ti.ascent=%.2f, ti.descent=%.2f\n",
- ti.chars[i].toLatin1(),
+ printf("(%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n",
glyph,
metrics.width.toReal(),
metrics.height.toReal(),
metrics.xoff.toReal(),
metrics.yoff.toReal(),
metrics.x.toReal(),
- metrics.y.toReal(),
- ti.ascent.toReal(),
- ti.descent.toReal());
+ metrics.y.toReal());
#endif
int glyph_width = metrics.width.ceil().toInt();
int glyph_height = metrics.height.ceil().toInt();
@@ -114,28 +125,27 @@ void QTextureGlyphCache::populate(const QTextItemInt &ti,
if (listItemCoordinates.isEmpty())
return;
- rowHeight += margin * 2;
+ rowHeight += margin * 2 + paddingDoubled;
if (isNull())
- createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, rowHeight);
+ createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, qt_next_power_of_two(rowHeight));
// now actually use the coords and paint the wanted glyps into cache.
QHash<glyph_t, Coord>::iterator iter = listItemCoordinates.begin();
while (iter != listItemCoordinates.end()) {
Coord c = iter.value();
+ m_currentRowHeight = qMax(m_currentRowHeight, c.h + margin * 2);
+
if (m_cx + c.w > m_w) {
// no room on the current line, start new glyph strip
m_cx = 0;
- m_cy = m_h;
+ m_cy += m_currentRowHeight + paddingDoubled;
+ m_currentRowHeight = 0; // New row
}
if (m_cy + c.h > m_h) {
- int new_height;
- if (m_cx == 0) { // add a whole row
- new_height = m_h + rowHeight;
- m_cy = m_h;
- } else { // just extend row
- new_height = m_cy + rowHeight;
- }
+ int new_height = m_h*2;
+ while (new_height < m_cy + c.h)
+ new_height *= 2;
// if no room in the current texture - realloc a larger texture
resizeTextureData(m_w, new_height);
m_h = new_height;
@@ -147,14 +157,7 @@ void QTextureGlyphCache::populate(const QTextItemInt &ti,
fillTexture(c, iter.key());
coords.insert(iter.key(), c);
- if (m_cx + c.w > m_w) {
- m_cx = 0;
- m_cy += rowHeight;
- } else {
- // for the Mono case, glyph_width is 8-bit aligned,
- // and therefore so will m_cx
- m_cx += c.w;
- }
+ m_cx += c.w + paddingDoubled;
++iter;
}
@@ -182,11 +185,11 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const
break;
};
- QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_textitem->fontEngine);
+ QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_fontengine);
QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
- QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g);
+ QFontEngineFT::Glyph *glyph = gset->getGlyph(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);
@@ -194,9 +197,9 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const
} else
#endif
if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
- return m_current_textitem->fontEngine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
+ return m_current_fontengine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
else
- return m_current_textitem->fontEngine->alphaMapForGlyph(g, m_transform);
+ return m_current_fontengine->alphaMapForGlyph(g, m_transform);
return QImage();
}
@@ -324,10 +327,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g)
QPoint base(c.x + glyphMargin(), c.y + glyphMargin() + c.baseLineY-1);
if (m_image.rect().contains(base))
m_image.setPixel(base, 255);
- m_image.save(QString::fromLatin1("cache-%1-%2-%3.png")
- .arg(m_current_textitem->font().family())
- .arg(m_current_textitem->font().pointSize())
- .arg(m_transform.type()));
+ m_image.save(QString::fromLatin1("cache-%1.png").arg(int(this)));
#endif
}
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index d347e618bb..390fe51b28 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -76,7 +76,9 @@ class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache
{
public:
QTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix)
- : QFontEngineGlyphCache(matrix, type), m_w(0), m_h(0), m_cx(0), m_cy(0) { }
+ : QFontEngineGlyphCache(matrix, type), m_current_fontengine(0),
+ m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0)
+ { }
virtual ~QTextureGlyphCache() { }
@@ -90,13 +92,13 @@ public:
int baseLineY;
};
- void populate(const QTextItemInt &ti,
- const QVarLengthArray<glyph_t> &glyphs,
- const QVarLengthArray<QFixedPoint> &positions);
+ void populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
+ const QFixedPoint *positions);
virtual void createTextureData(int width, int height) = 0;
virtual void resizeTextureData(int width, int height) = 0;
virtual int glyphMargin() const { return 0; }
+ virtual int glyphPadding() const { return 0; }
virtual void fillTexture(const Coord &coord, glyph_t glyph) = 0;
@@ -113,12 +115,13 @@ public:
QImage textureMapForGlyph(glyph_t g) const;
protected:
- const QTextItemInt *m_current_textitem;
+ QFontEngine *m_current_fontengine;
int m_w; // image width
int m_h; // image height
int m_cx; // current x
int m_cy; // current y
+ int m_currentRowHeight; // Height of last row
};
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 4f42a5852e..80b75202ac 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -47,6 +47,7 @@
#include "qpainterpath.h"
#include "qvariant.h"
#include <qmath.h>
+#include <qnumeric.h>
#include <private/qbezier_p.h>
@@ -410,6 +411,12 @@ QTransform &QTransform::translate(qreal dx, qreal dy)
{
if (dx == 0 && dy == 0)
return *this;
+#ifndef QT_NO_DEBUG
+ if (qIsNaN(dx) | qIsNaN(dy)) {
+ qWarning() << "QTransform::translate with NaN called";
+ return *this;
+ }
+#endif
switch(inline_type()) {
case TxNone:
@@ -447,6 +454,12 @@ QTransform &QTransform::translate(qreal dx, qreal dy)
*/
QTransform QTransform::fromTranslate(qreal dx, qreal dy)
{
+#ifndef QT_NO_DEBUG
+ if (qIsNaN(dx) | qIsNaN(dy)) {
+ qWarning() << "QTransform::fromTranslate with NaN called";
+ return QTransform();
+}
+#endif
QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true);
if (dx == 0 && dy == 0)
transform.m_type = TxNone;
@@ -466,6 +479,12 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
{
if (sx == 1 && sy == 1)
return *this;
+#ifndef QT_NO_DEBUG
+ if (qIsNaN(sx) | qIsNaN(sy)) {
+ qWarning() << "QTransform::scale with NaN called";
+ return *this;
+ }
+#endif
switch(inline_type()) {
case TxNone:
@@ -501,6 +520,12 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
*/
QTransform QTransform::fromScale(qreal sx, qreal sy)
{
+#ifndef QT_NO_DEBUG
+ if (qIsNaN(sx) | qIsNaN(sy)) {
+ qWarning() << "QTransform::fromScale with NaN called";
+ return QTransform();
+}
+#endif
QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true);
if (sx == 1. && sy == 1.)
transform.m_type = TxNone;
@@ -520,6 +545,12 @@ QTransform & QTransform::shear(qreal sh, qreal sv)
{
if (sh == 0 && sv == 0)
return *this;
+#ifndef QT_NO_DEBUG
+ if (qIsNaN(sh) | qIsNaN(sv)) {
+ qWarning() << "QTransform::shear with NaN called";
+ return *this;
+ }
+#endif
switch(inline_type()) {
case TxNone:
@@ -575,6 +606,12 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
{
if (a == 0)
return *this;
+#ifndef QT_NO_DEBUG
+ if (qIsNaN(a)) {
+ qWarning() << "QTransform::rotate with NaN called";
+ return *this;
+ }
+#endif
qreal sina = 0;
qreal cosa = 0;
@@ -660,6 +697,12 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
*/
QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
{
+#ifndef QT_NO_DEBUG
+ if (qIsNaN(a)) {
+ qWarning() << "QTransform::rotateRadians with NaN called";
+ return *this;
+ }
+#endif
qreal sina = qSin(a);
qreal cosa = qCos(a);
@@ -1037,8 +1080,18 @@ QDataStream & operator>>(QDataStream &s, QTransform &t)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QTransform &m)
{
- dbg.nospace() << "QTransform("
- << "11=" << m.m11()
+ static const char *typeStr[] =
+ {
+ "TxNone",
+ "TxTranslate",
+ "TxScale",
+ "TxRotate",
+ "TxShear",
+ "TxProject"
+ };
+
+ dbg.nospace() << "QTransform(type=" << typeStr[m.type()] << ','
+ << " 11=" << m.m11()
<< " 12=" << m.m12()
<< " 13=" << m.m13()
<< " 21=" << m.m21()
@@ -1048,6 +1101,7 @@ QDebug operator<<(QDebug dbg, const QTransform &m)
<< " 32=" << m.m32()
<< " 33=" << m.m33()
<< ')';
+
return dbg.space();
}
#endif
diff --git a/src/gui/painting/qwindowsurface.cpp b/src/gui/painting/qwindowsurface.cpp
index 8bd63448d5..e18ea3fb6f 100644
--- a/src/gui/painting/qwindowsurface.cpp
+++ b/src/gui/painting/qwindowsurface.cpp
@@ -49,13 +49,19 @@ QT_BEGIN_NAMESPACE
class QWindowSurfacePrivate
{
public:
- QWindowSurfacePrivate(QWidget *w) : window(w), staticContentsSupport(false) {}
+ QWindowSurfacePrivate(QWidget *w)
+ : window(w)
+ , staticContentsSupport(0)
+ , partialUpdateSupport(1)
+ {
+ }
QWidget *window;
QRect geometry;
QRegion staticContents;
QList<QImage*> bufferImages;
- bool staticContentsSupport;
+ uint staticContentsSupport : 1;
+ uint partialUpdateSupport : 1;
};
/*!
@@ -284,6 +290,10 @@ bool QWindowSurface::hasStaticContentsSupport() const
void QWindowSurface::setStaticContentsSupport(bool enable)
{
+ if (enable && !d_ptr->partialUpdateSupport) {
+ qWarning("QWindowSurface::setStaticContentsSupport: static contents support requires partial update support");
+ return;
+ }
d_ptr->staticContentsSupport = enable;
}
@@ -302,6 +312,20 @@ bool QWindowSurface::hasStaticContents() const
return d_ptr->staticContentsSupport && !d_ptr->staticContents.isEmpty();
}
+bool QWindowSurface::hasPartialUpdateSupport() const
+{
+ return d_ptr->partialUpdateSupport;
+}
+
+void QWindowSurface::setPartialUpdateSupport(bool enable)
+{
+ if (!enable && d_ptr->staticContentsSupport) {
+ qWarning("QWindowSurface::setPartialUpdateSupport: static contents support requires partial update support");
+ return;
+ }
+ d_ptr->partialUpdateSupport = enable;
+}
+
void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
{
// make sure we don't detach
diff --git a/src/gui/painting/qwindowsurface_p.h b/src/gui/painting/qwindowsurface_p.h
index 0a453af36a..6171ae8547 100644
--- a/src/gui/painting/qwindowsurface_p.h
+++ b/src/gui/painting/qwindowsurface_p.h
@@ -73,8 +73,12 @@ public:
QWidget *window() const;
virtual QPaintDevice *paintDevice() = 0;
- virtual void flush(QWidget *widget, const QRegion &region,
- const QPoint &offset) = 0;
+
+ // 'widget' can be a child widget, in which case 'region' is in child widget coordinates and
+ // offset is the (child) widget's offset in relation to the window surface. On QWS, 'offset'
+ // can be larger than just the offset from the top-level widget as there may also be window
+ // decorations which are painted into the window surface.
+ virtual void flush(QWidget *widget, const QRegion &region, const QPoint &offset) = 0;
virtual void setGeometry(const QRect &rect);
QRect geometry() const;
@@ -90,6 +94,7 @@ public:
inline QRect rect(const QWidget *widget) const;
bool hasStaticContentsSupport() const;
+ bool hasPartialUpdateSupport() const;
void setStaticContents(const QRegion &region);
QRegion staticContents() const;
@@ -97,6 +102,7 @@ public:
protected:
bool hasStaticContents() const;
void setStaticContentsSupport(bool enable);
+ void setPartialUpdateSupport(bool enable);
private:
QWindowSurfacePrivate *d_ptr;
diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp
index d05c7e4f5b..b25dce528a 100644
--- a/src/gui/painting/qwindowsurface_s60.cpp
+++ b/src/gui/painting/qwindowsurface_s60.cpp
@@ -44,8 +44,8 @@
#include <QtGui/qpaintdevice.h>
#include <private/qwidget_p.h>
#include "qwindowsurface_s60_p.h"
-#include "qpixmap_s60_p.h"
-#include "qt_s60_p.h"
+#include <private/qpixmap_s60_p.h>
+#include <private/qt_s60_p.h>
#include "private/qdrawhelper_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/gui/s60framework/s60framework.pri b/src/gui/s60framework/s60framework.pri
index d30f80ad47..f9d89dc37e 100644
--- a/src/gui/s60framework/s60framework.pri
+++ b/src/gui/s60framework/s60framework.pri
@@ -10,6 +10,8 @@ minimalAppResource31 = \
"END"
MMP_RULES += minimalAppResource31
+SYMBIAN_RESOURCES += s60framework/s60main.rss
+
SOURCES += s60framework/qs60mainapplication.cpp \
s60framework/qs60mainappui.cpp \
s60framework/qs60maindocument.cpp
diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp
index 70f152d573..63ad94ef59 100644
--- a/src/gui/statemachine/qguistatemachine.cpp
+++ b/src/gui/statemachine/qguistatemachine.cpp
@@ -469,12 +469,6 @@ static QEvent *cloneEvent(QEvent *e)
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::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index b1924e7566..8036728135 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -981,7 +981,7 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt
qreal y = position.y() + line.y() + line.ascent();
p->save();
p->setFont(option->font);
- p->drawText(int(x), int(y), elidedText);
+ p->drawText(QPointF(x, y), elidedText);
p->restore();
break;
}
@@ -4760,7 +4760,7 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
int margins = 0;
// we add 4 pixels for label margins
- if (btn->icon.isNull() || !btn->text.isEmpty())
+ if (!btn->icon.isNull() || !btn->text.isEmpty())
margins = 4 + proxy()->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
: PM_CheckBoxLabelSpacing, opt, widget);
sz += QSize(w + margins, 4);
@@ -5662,10 +5662,16 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
OSType iconType = 0;
switch (standardIcon) {
case QStyle::SP_MessageBoxQuestion:
+ iconType = kQuestionMarkIcon;
+ break;
case QStyle::SP_MessageBoxInformation:
+ iconType = kAlertNoteIcon;
+ break;
case QStyle::SP_MessageBoxWarning:
+ iconType = kAlertCautionIcon;
+ break;
case QStyle::SP_MessageBoxCritical:
- iconType = kGenericApplicationIcon;
+ iconType = kAlertStopIcon;
break;
case SP_DesktopIcon:
iconType = kDesktopIcon;
@@ -5755,88 +5761,88 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
switch (standardIcon) {
#ifndef QT_NO_IMAGEFORMAT_PNG
case SP_FileDialogNewFolder:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-128.png"), QSize(128, 128));
break;
case SP_FileDialogBack:
return standardIconImplementation(SP_ArrowBack, option, widget);
case SP_FileDialogToParent:
return standardIconImplementation(SP_ArrowUp, option, widget);
case SP_FileDialogDetailedView:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewdetailed-128.png"), QSize(128, 128));
break;
case SP_FileDialogInfoView:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/fileinfo-128.png"), QSize(128, 128));
break;
case SP_FileDialogContentsView:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filecontents-128.png"), QSize(128, 128));
break;
case SP_FileDialogListView:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-128.png"), QSize(128, 128));
break;
case SP_DialogOkButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-ok-128.png"), QSize(128, 128));
break;
case SP_DialogCancelButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-cancel-128.png"), QSize(128, 128));
break;
case SP_DialogHelpButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-help-128.png"), QSize(128, 128));
break;
case SP_DialogOpenButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-open-128.png"), QSize(128, 128));
break;
case SP_DialogSaveButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-save-128.png"), QSize(128, 128));
break;
case SP_DialogCloseButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-close-128.png"), QSize(128, 128));
break;
case SP_DialogApplyButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-apply-128.png"), QSize(128, 128));
break;
case SP_DialogResetButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-clear-128.png"), QSize(128, 128));
break;
case SP_DialogDiscardButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-delete-128.png"), QSize(128, 128));
break;
case SP_DialogYesButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-yes-128.png"), QSize(128, 128));
break;
case SP_DialogNoButton:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/standardbutton-no-128.png"), QSize(128, 128));
break;
case SP_ArrowForward:
if (rtl)
@@ -5847,24 +5853,24 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
return standardIconImplementation(SP_ArrowRight, option, widget);
return standardIconImplementation(SP_ArrowLeft, option, widget);
case SP_ArrowLeft:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/left-128.png"), QSize(128, 128));
break;
case SP_ArrowRight:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/right-128.png"), QSize(128, 128));
break;
case SP_ArrowUp:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/up-128.png"), QSize(128, 128));
break;
case SP_ArrowDown:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/down-128.png"), QSize(128, 128));
break;
case SP_DirHomeIcon:
case SP_DirIcon:
@@ -5882,71 +5888,71 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
QSize(128, 128), QIcon::Normal, QIcon::On);
break;
case SP_DriveCDIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/cdr-128.png"), QSize(128, 128));
break;
case SP_DriveDVDIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/dvd-128.png"), QSize(128, 128));
break;
case SP_FileIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/file-128.png"), QSize(128, 128));
break;
case SP_FileLinkIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/filelink-128.png"), QSize(128, 128));
break;
case SP_TrashIcon:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-32.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-128.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-32.png"), QSize(32, 32));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/trash-128.png"), QSize(128, 128));
break;
case SP_BrowserReload:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-24.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-24.png"), QSize(24, 24));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/refresh-32.png"), QSize(32, 32));
break;
case SP_BrowserStop:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-24.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-24.png"), QSize(24, 24));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/stop-32.png"), QSize(32, 32));
break;
case SP_MediaPlay:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-play-32.png"), QSize(32, 32));
break;
case SP_MediaPause:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-pause-32.png"), QSize(32, 32));
break;
case SP_MediaStop:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-stop-32.png"), QSize(32, 32));
break;
case SP_MediaSeekForward:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-forward-32.png"), QSize(32, 32));
break;
case SP_MediaSeekBackward:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-seek-backward-32.png"), QSize(32, 32));
break;
case SP_MediaSkipForward:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-forward-32.png"), QSize(32, 32));
break;
case SP_MediaSkipBackward:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-16.png"));
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-32.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-16.png"), QSize(16, 16));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-skip-backward-32.png"), QSize(32, 32));
break;
case SP_MediaVolume:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-16.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-16.png"), QSize(16, 16));
break;
case SP_MediaVolumeMuted:
- icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-muted-16.png"));
+ icon.addFile(QLatin1String(":/trolltech/styles/commonstyle/images/media-volume-muted-16.png"), QSize(16, 16));
break;
#endif // QT_NO_IMAGEFORMAT_PNG
default:
diff --git a/src/gui/styles/qgtkpainter.cpp b/src/gui/styles/qgtkpainter.cpp
index 6cc745508f..1f68f2f768 100644
--- a/src/gui/styles/qgtkpainter.cpp
+++ b/src/gui/styles/qgtkpainter.cpp
@@ -142,7 +142,7 @@ QPixmap QGtkPainter::renderTheme(uchar *bdata, uchar *wdata, const QRect &rect)
}
QGtkPainter::QGtkPainter(QPainter *_painter)
- : m_window(QGtkStylePrivate::gtkWidget(QLatin1String("GtkWindow")))
+ : m_window(QGtkStylePrivate::gtkWidget("GtkWindow"))
, m_painter(_painter)
, m_alpha(true)
, m_hflipped(false)
diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp
index ddae3d8eaa..9c61023a04 100644
--- a/src/gui/styles/qgtkstyle.cpp
+++ b/src/gui/styles/qgtkstyle.cpp
@@ -222,7 +222,7 @@ QPalette QGtkStyle::standardPalette() const
QPalette palette = QCleanlooksStyle::standardPalette();
if (d->isThemeAvailable()) {
GtkStyle *style = d->gtkStyle();
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
GtkWidget *gtkEntry = d->getTextColorWidget();
GdkColor gdkBg, gdkBase, gdkText, gdkForeground, gdkSbg, gdkSfg;
@@ -253,7 +253,7 @@ QPalette QGtkStyle::standardPalette() const
palette.setColor(QPalette::Base, base);
QColor alternateRowColor = palette.base().color().lighter(93); // ref gtkstyle.c draw_flat_box
- GtkWidget *gtkTreeView = d->gtkWidget(QLS("GtkTreeView"));
+ GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView");
GdkColor *gtkAltBase = NULL;
d->gtk_widget_style_get(gtkTreeView, "odd-row-color", &gtkAltBase, NULL);
if (gtkAltBase) {
@@ -421,14 +421,14 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
return 0;
case PM_ButtonShiftHorizontal: {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
guint horizontal_shift;
d->gtk_widget_style_get(gtkButton, "child-displacement-x", &horizontal_shift, NULL);
return horizontal_shift;
}
case PM_ButtonShiftVertical: {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
guint vertical_shift;
d->gtk_widget_style_get(gtkButton, "child-displacement-y", &vertical_shift, NULL);
return vertical_shift;
@@ -438,7 +438,7 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
return 0;
case PM_MenuPanelWidth: {
- GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu"));
+ GtkWidget *gtkMenu = d->gtkWidget("GtkMenu");
guint horizontal_padding = 0;
// horizontal-padding is used by Maemo to get thicker borders
if (!d->gtk_check_version(2, 10, 0))
@@ -495,7 +495,7 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
case PM_SliderThickness:
case PM_SliderControlThickness: {
- GtkWidget *gtkScale = d->gtkWidget(QLS("GtkHScale"));
+ GtkWidget *gtkScale = d->gtkWidget("GtkHScale");
gint val;
d->gtk_widget_style_get(gtkScale, "slider-width", &val, NULL);
if (metric == PM_SliderControlThickness)
@@ -506,7 +506,7 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
case PM_ScrollBarExtent: {
gint sliderLength;
gint trough_border;
- GtkWidget *hScrollbar = d->gtkWidget(QLS("GtkHScrollbar"));
+ GtkWidget *hScrollbar = d->gtkWidget("GtkHScrollbar");
d->gtk_widget_style_get(hScrollbar,
"trough-border", &trough_border,
"slider-width", &sliderLength,
@@ -519,34 +519,34 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
case PM_SliderLength:
gint val;
- d->gtk_widget_style_get(d->gtkWidget(QLS("GtkHScale")), "slider-length", &val, NULL);
+ d->gtk_widget_style_get(d->gtkWidget("GtkHScale"), "slider-length", &val, NULL);
return val;
case PM_ExclusiveIndicatorWidth:
case PM_ExclusiveIndicatorHeight:
case PM_IndicatorWidth:
case PM_IndicatorHeight: {
- GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton"));
+ GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
gint size, spacing;
d->gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, "indicator-size", &size, NULL);
return size + 2 * spacing;
}
case PM_MenuBarVMargin: {
- GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar"));
+ GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
return qMax(0, gtkMenubar->style->ythickness);
}
case PM_ScrollView_ScrollBarSpacing:
{
gint spacing = 3;
- GtkWidget *gtkScrollWindow = d->gtkWidget(QLS("GtkScrolledWindow"));
+ GtkWidget *gtkScrollWindow = d->gtkWidget("GtkScrolledWindow");
Q_ASSERT(gtkScrollWindow);
d->gtk_widget_style_get(gtkScrollWindow, "scrollbar-spacing", &spacing, NULL);
return spacing;
}
case PM_SubMenuOverlap: {
gint offset = 0;
- GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu"));
+ GtkWidget *gtkMenu = d->gtkWidget("GtkMenu");
d->gtk_widget_style_get(gtkMenu, "horizontal-offset", &offset, NULL);
return offset;
}
@@ -587,7 +587,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg
{
if (d->isKDE4Session())
return QCleanlooksStyle::styleHint(hint, option, widget, returnData);
- GtkWidget *gtkToolbar = d->gtkWidget(QLS("GtkToolbar"));
+ GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar");
GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS;
g_object_get(gtkToolbar, "toolbar-style", &toolbar_style, NULL);
switch (toolbar_style) {
@@ -610,7 +610,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg
return int(false);
case SH_ComboBox_Popup: {
- GtkWidget *gtkComboBox = d->gtkWidget(QLS("GtkComboBox"));
+ GtkWidget *gtkComboBox = d->gtkWidget("GtkComboBox");
gboolean appears_as_list;
d->gtk_widget_style_get((GtkWidget*)gtkComboBox, "appears-as-list", &appears_as_list, NULL);
return appears_as_list ? 0 : 1;
@@ -634,7 +634,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg
if (widget && widget->isWindow())
scrollbars_within_bevel = true;
else if (!d->gtk_check_version(2, 12, 0)) {
- GtkWidget *gtkScrollWindow = d->gtkWidget(QLS("GtkScrolledWindow"));
+ GtkWidget *gtkScrollWindow = d->gtkWidget("GtkScrolledWindow");
d->gtk_widget_style_get(gtkScrollWindow, "scrollbars-within-bevel", &scrollbars_within_bevel, NULL);
}
return !scrollbars_within_bevel;
@@ -712,7 +712,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
GtkStyle *style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(),
"*.GtkScrolledWindow", "*.GtkScrolledWindow", d->gtk_window_get_type());
if (style)
- gtkFramePainter.paintShadow(d->gtkWidget(QLS("GtkFrame")), "viewport", pmRect,
+ gtkFramePainter.paintShadow(d->gtkWidget("GtkFrame"), "viewport", pmRect,
option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE,
shadow_type, style);
QPixmapCache::insert(pmKey, pixmap);
@@ -739,7 +739,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
case PE_PanelTipLabel: {
- GtkWidget *gtkWindow = d->gtkWidget(QLS("GtkWindow")); // The Murrine Engine currently assumes a widget is passed
+ GtkWidget *gtkWindow = d->gtkWidget("GtkWindow"); // The Murrine Engine currently assumes a widget is passed
style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), "gtk-tooltips", "GtkWindow",
d->gtk_window_get_type());
gtkPainter.paintFlatBox(gtkWindow, "tooltip", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, style);
@@ -754,7 +754,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
}
GtkShadowType shadow_type;
- GtkWidget *gtkStatusbarFrame = d->gtkWidget(QLS("GtkStatusbar.GtkFrame"));
+ GtkWidget *gtkStatusbarFrame = d->gtkWidget("GtkStatusbar.GtkFrame");
d->gtk_widget_style_get(gtkStatusbarFrame->parent, "shadow-type", &shadow_type, NULL);
gtkPainter.paintShadow(gtkStatusbarFrame, "frame", option->rect, GTK_STATE_NORMAL,
shadow_type, gtkStatusbarFrame->style);
@@ -763,12 +763,14 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
case PE_IndicatorHeaderArrow:
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
- GtkWidget *gtkTreeHeader = d->gtkWidget(QLS("GtkTreeView.GtkButton"));
+ GtkWidget *gtkTreeHeader = d->gtkWidget("GtkTreeView.GtkButton");
GtkStateType state = gtkPainter.gtkState(option);
style = gtkTreeHeader->style;
GtkArrowType type = GTK_ARROW_UP;
QRect r = header->rect;
QImage arrow;
+ // This sorting indicator inversion is intentional, and follows the GNOME HIG.
+ // See http://library.gnome.org/devel/hig-book/stable/controls-lists.html.en#controls-lists-sortable
if (header->sortIndicator & QStyleOptionHeader::SortUp)
type = GTK_ARROW_UP;
else if (header->sortIndicator & QStyleOptionHeader::SortDown)
@@ -801,7 +803,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
rect.translate(2, 0);
GtkExpanderStyle openState = GTK_EXPANDER_EXPANDED;
GtkExpanderStyle closedState = GTK_EXPANDER_COLLAPSED;
- GtkWidget *gtkTreeView = d->gtkWidget(QLS("GtkTreeView"));
+ GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView");
GtkStateType state = GTK_STATE_NORMAL;
if (!(option->state & State_Enabled))
@@ -837,7 +839,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
case PE_IndicatorToolBarSeparator:
{
const int margin = 6;
- GtkWidget *gtkSeparator = d->gtkWidget(QLS("GtkToolbar.GtkSeparatorToolItem"));
+ GtkWidget *gtkSeparator = d->gtkWidget("GtkToolbar.GtkSeparatorToolItem");
if (option->state & State_Horizontal) {
const int offset = option->rect.width()/2;
QRect rect = option->rect.adjusted(offset, margin, 0, -margin);
@@ -857,7 +859,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
case PE_IndicatorToolBarHandle: {
- GtkWidget *gtkToolbar = d->gtkWidget(QLS("GtkToolbar"));
+ GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar");
GtkShadowType shadow_type;
d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL);
//Note when the toolbar is horizontal, the handle is vertical
@@ -905,7 +907,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
GtkStateType state = gtkPainter.gtkState(option);
QColor arrowColor = option->palette.buttonText().color();
- GtkWidget *gtkArrow = d->gtkWidget(QLS("GtkArrow"));
+ GtkWidget *gtkArrow = d->gtkWidget("GtkArrow");
GdkColor color = fromQColor(arrowColor);
d->gtk_widget_modify_fg (gtkArrow, state, &color);
gtkPainter.paintArrow(gtkArrow, "button", arrowRect,
@@ -921,7 +923,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
case PE_PanelMenu: {
- GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu"));
+ GtkWidget *gtkMenu = d->gtkWidget("GtkMenu");
gtkPainter.setAlphaSupport(false); // Note, alpha disabled for performance reasons
gtkPainter.paintBox(gtkMenu, "menu", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, gtkMenu->style, QString());
}
@@ -933,7 +935,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
// This is only used by floating tool bars
if (qobject_cast<const QToolBar *>(widget)) {
- GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar"));
+ GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
gtkPainter.paintBox( gtkMenubar, "toolbar", option->rect,
GTK_STATE_NORMAL, GTK_SHADOW_OUT, style);
gtkPainter.paintBox( gtkMenubar, "menu", option->rect,
@@ -942,7 +944,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
case PE_FrameLineEdit: {
- GtkWidget *gtkEntry = d->gtkWidget(QLS("GtkEntry"));
+ GtkWidget *gtkEntry = d->gtkWidget("GtkEntry");
gboolean interior_focus;
@@ -976,7 +978,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
case PE_PanelLineEdit:
if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
- GtkWidget *gtkEntry = d->gtkWidget(QLS("GtkEntry"));
+ GtkWidget *gtkEntry = d->gtkWidget("GtkEntry");
if (panel->lineWidth > 0)
proxy()->drawPrimitive(PE_FrameLineEdit, option, painter, widget);
uint resolve_mask = option->palette.resolve();
@@ -994,7 +996,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
case PE_FrameTabWidget:
if (const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast<const QStyleOptionTabWidgetFrame*>(option)) {
- GtkWidget *gtkNotebook = d->gtkWidget(QLS("GtkNotebook"));
+ GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook");
style = gtkPainter.getStyle(gtkNotebook);
gtkPainter.setAlphaSupport(false);
GtkShadowType shadow = GTK_SHADOW_OUT;
@@ -1042,7 +1044,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
GtkStateType state = gtkPainter.gtkState(option);
if (option->state & State_On || option->state & State_Sunken)
state = GTK_STATE_ACTIVE;
- GtkWidget *gtkButton = d->gtkWidget(isTool ? QLS("GtkToolButton.GtkButton") : QLS("GtkButton"));
+ GtkWidget *gtkButton = isTool ? d->gtkWidget("GtkToolButton.GtkButton") : d->gtkWidget("GtkButton");
gint focusWidth, focusPad;
gboolean interiorFocus = false;
d->gtk_widget_style_get (gtkButton,
@@ -1098,14 +1100,14 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
else
shadow = GTK_SHADOW_OUT;
- GtkWidget *gtkRadioButton = d->gtkWidget(QLS("GtkRadioButton"));
+ GtkWidget *gtkRadioButton = d->gtkWidget("GtkRadioButton");
gint spacing;
d->gtk_widget_style_get(gtkRadioButton, "indicator-spacing", &spacing, NULL);
QRect buttonRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing);
gtkPainter.setClipRect(option->rect);
// ### Note: Ubuntulooks breaks when the proper widget is passed
// Murrine engine requires a widget not to get RGBA check - warnings
- GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton"));
+ GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
QString key(QLS("radiobutton"));
if (option->state & State_HasFocus) { // Themes such as Nodoka check this flag
key += QLatin1Char('f');
@@ -1133,7 +1135,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
int spacing;
- GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton"));
+ GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
QString key(QLS("checkbutton"));
if (option->state & State_HasFocus) { // Themes such as Nodoka checks this flag
key += QLatin1Char('f');
@@ -1275,7 +1277,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
// Draw prelight background
- GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton"));
+ GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
if (option->state & State_MouseOver) {
QRect bgRect = textRect | checkBoxRect;
@@ -1348,7 +1350,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ?
GTK_SHADOW_IN : GTK_SHADOW_OUT;
- QString comboBoxPath = QLS(comboBox->editable ? "GtkComboBoxEntry" : "GtkComboBox");
+ const QHashableLatin1Literal comboBoxPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry") : QHashableLatin1Literal("GtkComboBox");
// We use the gtk widget to position arrows and separators for us
GtkWidget *gtkCombo = d->gtkWidget(comboBoxPath);
@@ -1356,7 +1358,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
d->gtk_widget_set_direction(gtkCombo, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
d->gtk_widget_size_allocate(gtkCombo, &geometry);
- QString buttonPath = comboBoxPath + QLS(".GtkToggleButton");
+ QHashableLatin1Literal buttonPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton")
+ : QHashableLatin1Literal("GtkComboBox.GtkToggleButton");
GtkWidget *gtkToggleButton = d->gtkWidget(buttonPath);
d->gtk_widget_set_direction(gtkToggleButton, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
if (gtkToggleButton && (appears_as_list || comboBox->editable)) {
@@ -1365,7 +1368,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
// Draw the combo box as a line edit with a button next to it
if (comboBox->editable || appears_as_list) {
GtkStateType frameState = (state == GTK_STATE_PRELIGHT) ? GTK_STATE_NORMAL : state;
- QString entryPath = QLS(comboBox->editable ? "GtkComboBoxEntry.GtkEntry" : "GtkComboBox.GtkFrame");
+ QHashableLatin1Literal entryPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkEntry") : QHashableLatin1Literal("GtkComboBox.GtkFrame");
GtkWidget *gtkEntry = d->gtkWidget(entryPath);
d->gtk_widget_set_direction(gtkEntry, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
QRect frameRect = option->rect;
@@ -1391,11 +1394,11 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
else {
gtkCachedPainter.paintFlatBox(gtkEntry, "entry_bg", contentRect,
option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE,
- GTK_SHADOW_NONE, gtkEntry->style, entryPath + QString::number(focus));
+ GTK_SHADOW_NONE, gtkEntry->style, entryPath.toString() + QString::number(focus));
}
gtkCachedPainter.paintShadow(gtkEntry, comboBox->editable ? "entry" : "frame", frameRect, frameState,
- GTK_SHADOW_IN, gtkEntry->style, entryPath +
+ GTK_SHADOW_IN, gtkEntry->style, entryPath.toString() +
QString::number(focus) + QString::number(comboBox->editable) +
QString::number(option->direction));
if (focus)
@@ -1416,7 +1419,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
Q_ASSERT(gtkToggleButton);
gtkCachedPainter.paintBox( gtkToggleButton, "button", arrowButtonRect, buttonState,
- shadow, gtkToggleButton->style, buttonPath +
+ shadow, gtkToggleButton->style, buttonPath.toString() +
QString::number(focus) + QString::number(option->direction));
if (focus)
GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS);
@@ -1429,12 +1432,17 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
gtkCachedPainter.paintBox(gtkToggleButton, "button",
buttonRect, state,
shadow, gtkToggleButton->style,
- buttonPath + QString::number(focus));
+ buttonPath.toString() + QString::number(focus));
if (focus)
GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS);
+ QHashableLatin1Literal buttonPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton")
+ : QHashableLatin1Literal("GtkComboBox.GtkToggleButton");
+
// Draw the separator between label and arrows
- QString vSeparatorPath = buttonPath + QLS(".GtkHBox.GtkVSeparator");
+ QHashableLatin1Literal vSeparatorPath = comboBox->editable
+ ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkHBox.GtkVSeparator")
+ : QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkHBox.GtkVSeparator");
if (GtkWidget *gtkVSeparator = d->gtkWidget(vSeparatorPath)) {
QRect vLineRect(gtkVSeparator->allocation.x,
@@ -1444,7 +1452,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
gtkCachedPainter.paintVline( gtkVSeparator, "vseparator",
vLineRect, state, gtkVSeparator->style,
- 0, vLineRect.height(), 0, vSeparatorPath);
+ 0, vLineRect.height(), 0, vSeparatorPath.toString());
gint interiorFocus = true;
@@ -1469,8 +1477,18 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
else
state = GTK_STATE_NORMAL;
- QString arrowPath = comboBoxPath + QLS(appears_as_list ? ".GtkToggleButton.GtkArrow"
- : ".GtkToggleButton.GtkHBox.GtkArrow");
+ QHashableLatin1Literal arrowPath("");
+ if (comboBox->editable) {
+ if (appears_as_list)
+ arrowPath = QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkArrow");
+ else
+ arrowPath = QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkHBox.GtkArrow");
+ } else {
+ if (appears_as_list)
+ arrowPath = QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkArrow");
+ else
+ arrowPath = QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkHBox.GtkArrow");
+ }
GtkWidget *gtkArrow = d->gtkWidget(arrowPath);
gfloat scale = 0.7;
@@ -1497,7 +1515,11 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (sunken) {
int xoff, yoff;
- GtkWidget *gtkButton = d->gtkWidget(comboBoxPath + QLS(".GtkToggleButton"));
+ const QHashableLatin1Literal toggleButtonPath = comboBox->editable
+ ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton")
+ : QHashableLatin1Literal("GtkComboBox.GtkToggleButton");
+
+ GtkWidget *gtkButton = d->gtkWidget(toggleButtonPath);
d->gtk_widget_style_get(gtkButton, "child-displacement-x", &xoff, NULL);
d->gtk_widget_style_get(gtkButton, "child-displacement-y", &yoff, NULL);
arrowRect = arrowRect.adjusted(xoff, yoff, xoff, yoff);
@@ -1509,7 +1531,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
gtkCachedPainter.setClipRect(option->rect);
gtkCachedPainter.paintArrow( gtkArrow, "arrow", arrowRect,
GTK_ARROW_DOWN, state, GTK_SHADOW_NONE, TRUE,
- style, arrowPath + QString::number(option->direction));
+ style, arrowPath.toString() + QString::number(option->direction));
}
}
END_STYLE_PIXMAPCACHE;
@@ -1570,7 +1592,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
QStyleOptionToolButton label = *toolbutton;
label.state = bflags;
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkToolButton.GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkToolButton.GtkButton");
QPalette pal = toolbutton->palette;
if (option->state & State_Enabled &&
option->state & State_MouseOver && !(widget && widget->testAttribute(Qt::WA_SetPalette))) {
@@ -1605,8 +1627,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- GtkWidget *gtkHScrollBar = d->gtkWidget(QLS("GtkHScrollbar"));
- GtkWidget *gtkVScrollBar = d->gtkWidget(QLS("GtkVScrollbar"));
+ GtkWidget *gtkHScrollBar = d->gtkWidget("GtkHScrollbar");
+ GtkWidget *gtkVScrollBar = d->gtkWidget("GtkVScrollbar");
// Fill background in case the scrollbar is partially transparent
painter->fillRect(option->rect, option->palette.background());
@@ -1751,10 +1773,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- GtkWidget *gtkSpinButton = d->gtkWidget(
- spinBox->buttonSymbols == QAbstractSpinBox::NoButtons ?
- QLS("GtkEntry") :
- QLS("GtkSpinButton"));
+ GtkWidget *gtkSpinButton = spinBox->buttonSymbols == QAbstractSpinBox::NoButtons
+ ? d->gtkWidget("GtkEntry")
+ : d->gtkWidget("GtkSpinButton");
bool isEnabled = (spinBox->state & State_Enabled);
bool hover = isEnabled && (spinBox->state & State_MouseOver);
bool sunken = (spinBox->state & State_Sunken);
@@ -1906,8 +1927,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- GtkWidget *hScaleWidget = d->gtkWidget(QLS("GtkHScale"));
- GtkWidget *vScaleWidget = d->gtkWidget(QLS("GtkVScale"));
+ GtkWidget *hScaleWidget = d->gtkWidget("GtkHScale");
+ GtkWidget *vScaleWidget = d->gtkWidget("GtkVScale");
QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
@@ -2097,7 +2118,7 @@ void QGtkStyle::drawControl(ControlElement element,
switch (element) {
case CE_ProgressBarLabel:
if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
- GtkWidget *gtkProgressBar = d->gtkWidget(QLS("GtkProgressBar"));
+ GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar");
if (!gtkProgressBar)
return;
@@ -2200,7 +2221,7 @@ void QGtkStyle::drawControl(ControlElement element,
if (button->features & QStyleOptionButton::HasMenu)
ir = ir.adjusted(0, 0, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0);
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
QPalette pal = button->palette;
int labelState = GTK_STATE_INSENSITIVE;
if (option->state & State_Enabled)
@@ -2221,7 +2242,7 @@ void QGtkStyle::drawControl(ControlElement element,
bool isRadio = (element == CE_RadioButton);
// Draw prelight background
- GtkWidget *gtkRadioButton = d->gtkWidget(QLS("GtkRadioButton"));
+ GtkWidget *gtkRadioButton = d->gtkWidget("GtkRadioButton");
if (option->state & State_MouseOver) {
gtkPainter.paintFlatBox(gtkRadioButton, "checkbutton", option->rect,
@@ -2289,7 +2310,7 @@ void QGtkStyle::drawControl(ControlElement element,
}
if (!cb->currentText.isEmpty() && !cb->editable) {
- GtkWidget *gtkCombo = d->gtkWidget(QLS("GtkComboBox"));
+ GtkWidget *gtkCombo = d->gtkWidget("GtkComboBox");
QPalette pal = cb->palette;
int labelState = GTK_STATE_INSENSITIVE;
@@ -2366,7 +2387,7 @@ void QGtkStyle::drawControl(ControlElement element,
// Draws the header in tables.
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
Q_UNUSED(header);
- GtkWidget *gtkTreeView = d->gtkWidget(QLS("GtkTreeView"));
+ GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView");
// Get the middle column
GtkTreeViewColumn *column = d->gtk_tree_view_get_column((GtkTreeView*)gtkTreeView, 1);
Q_ASSERT(column);
@@ -2387,7 +2408,7 @@ void QGtkStyle::drawControl(ControlElement element,
#ifndef QT_NO_SIZEGRIP
case CE_SizeGrip: {
- GtkWidget *gtkStatusbar = d->gtkWidget(QLS("GtkStatusbar.GtkFrame"));
+ GtkWidget *gtkStatusbar = d->gtkWidget("GtkStatusbar.GtkFrame");
QRect gripRect = option->rect.adjusted(0, 0, -gtkStatusbar->style->xthickness, -gtkStatusbar->style->ythickness);
gtkPainter.paintResizeGrip( gtkStatusbar, "statusbar", gripRect, GTK_STATE_NORMAL,
GTK_SHADOW_OUT, QApplication::isRightToLeft() ?
@@ -2399,7 +2420,7 @@ void QGtkStyle::drawControl(ControlElement element,
#endif // QT_NO_SIZEGRIP
case CE_MenuBarEmptyArea: {
- GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar"));
+ GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
GdkColor gdkBg = gtkMenubar->style->bg[GTK_STATE_NORMAL]; // Theme can depend on transparency
painter->fillRect(option->rect, QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8));
if (widget) { // See CE_MenuBarItem
@@ -2422,8 +2443,8 @@ void QGtkStyle::drawControl(ControlElement element,
painter->save();
if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
- GtkWidget *gtkMenubarItem = d->gtkWidget(QLS("GtkMenuBar.GtkMenuItem"));
- GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar"));
+ GtkWidget *gtkMenubarItem = d->gtkWidget("GtkMenuBar.GtkMenuItem");
+ GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
style = gtkMenubarItem->style;
@@ -2479,7 +2500,7 @@ void QGtkStyle::drawControl(ControlElement element,
break;
case CE_Splitter: {
- GtkWidget *gtkWindow = d->gtkWidget(QLS("GtkWindow")); // The Murrine Engine currently assumes a widget is passed
+ GtkWidget *gtkWindow = d->gtkWidget("GtkWindow"); // The Murrine Engine currently assumes a widget is passed
gtkPainter.paintHandle(gtkWindow, "splitter", option->rect, gtkPainter.gtkState(option), GTK_SHADOW_NONE,
!(option->state & State_Horizontal) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL,
style);
@@ -2499,7 +2520,7 @@ void QGtkStyle::drawControl(ControlElement element,
if (toolbar->positionWithinLine != QStyleOptionToolBar::End)
rect.adjust(0, 0, 1, 0);
- GtkWidget *gtkToolbar = d->gtkWidget(QLS("GtkToolbar"));
+ GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar");
GtkShadowType shadow_type = GTK_SHADOW_NONE;
d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL);
gtkPainter.paintBox( gtkToolbar, "toolbar", rect,
@@ -2518,15 +2539,15 @@ void QGtkStyle::drawControl(ControlElement element,
const int windowsItemHMargin = 3; // menu item hor text margin
const int windowsItemVMargin = 26; // menu item ver text margin
const int windowsRightBorder = 15; // right border on windows
- GtkWidget *gtkMenuItem = menuItem->checked ? d->gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")) :
- d->gtkWidget(QLS("GtkMenu.GtkMenuItem"));
+ GtkWidget *gtkMenuItem = menuItem->checked ? d->gtkWidget("GtkMenu.GtkCheckMenuItem") :
+ d->gtkWidget("GtkMenu.GtkMenuItem");
style = gtkPainter.getStyle(gtkMenuItem);
QColor borderColor = option->palette.background().color().darker(160);
QColor shadow = option->palette.dark().color();
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
- GtkWidget *gtkMenuSeparator = d->gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem"));
+ GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem");
painter->setPen(shadow.lighter(106));
gboolean wide_separators = 0;
gint separator_height = 0;
@@ -2570,7 +2591,7 @@ void QGtkStyle::drawControl(ControlElement element,
bool ignoreCheckMark = false;
gint checkSize;
- d->gtk_widget_style_get(d->gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")), "indicator-size", &checkSize, NULL);
+ d->gtk_widget_style_get(d->gtkWidget("GtkMenu.GtkCheckMenuItem"), "indicator-size", &checkSize, NULL);
int checkcol = qMax(menuItem->maxIconWidth, qMax(20, checkSize));
@@ -2781,7 +2802,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget);
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
@@ -2807,7 +2828,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_TabBarTabShape:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
- GtkWidget *gtkNotebook = d->gtkWidget(QLS("GtkNotebook"));
+ GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook");
style = gtkPainter.getStyle(gtkNotebook);
QRect rect = option->rect;
@@ -2874,7 +2895,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_ProgressBarGroove:
if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
Q_UNUSED(bar);
- GtkWidget *gtkProgressBar = d->gtkWidget(QLS("GtkProgressBar"));
+ GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar");
GtkStateType state = gtkPainter.gtkState(option);
gtkPainter.paintBox( gtkProgressBar, "trough", option->rect, state, GTK_SHADOW_IN, gtkProgressBar->style);
}
@@ -2884,7 +2905,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_ProgressBarContents:
if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
GtkStateType state = option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE;
- GtkWidget *gtkProgressBar = d->gtkWidget(QLS("GtkProgressBar"));
+ GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar");
style = gtkProgressBar->style;
gtkPainter.paintBox( gtkProgressBar, "trough", option->rect, state, GTK_SHADOW_IN, style);
int xt = style->xthickness;
@@ -3042,7 +3063,7 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- GtkWidget *gtkSpinButton = d->gtkWidget(QLS("GtkSpinButton"));
+ GtkWidget *gtkSpinButton = d->gtkWidget("GtkSpinButton");
int center = spinbox->rect.height() / 2;
int xt = spinbox->frame ? gtkSpinButton->style->xthickness : 0;
int yt = spinbox->frame ? gtkSpinButton->style->ythickness : 0;
@@ -3096,15 +3117,19 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple
if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
// We employ the gtk widget to position arrows and separators for us
QString comboBoxPath = box->editable ? QLS("GtkComboBoxEntry") : QLS("GtkComboBox");
- GtkWidget *gtkCombo = d->gtkWidget(comboBoxPath);
+ GtkWidget *gtkCombo = box->editable ? d->gtkWidget("GtkComboBoxEntry")
+ : d->gtkWidget("GtkComboBox");
d->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())};
d->gtk_widget_size_allocate(gtkCombo, &geometry);
int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, option, widget);
- QString arrowPath = comboBoxPath + QLS(".GtkToggleButton");
-
- if (!box->editable && !appears_as_list)
- arrowPath += QLS(".GtkHBox.GtkArrow");
+ QHashableLatin1Literal arrowPath("GtkComboBoxEntry.GtkToggleButton");
+ if (!box->editable) {
+ if (appears_as_list)
+ arrowPath = "GtkComboBox.GtkToggleButton";
+ else
+ arrowPath = "GtkComboBox.GtkToggleButton.GtkHBox.GtkArrow";
+ }
GtkWidget *arrowWidget = d->gtkWidget(arrowPath);
if (!arrowWidget)
@@ -3163,7 +3188,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
case CT_ToolButton:
if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkToolButton.GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkToolButton.GtkButton");
newSize = size + QSize(2 * gtkButton->style->xthickness, 2 + 2 * gtkButton->style->ythickness);
if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) {
QSize minSize(0, 25);
@@ -3181,14 +3206,14 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
int textMargin = 8;
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
- GtkWidget *gtkMenuSeparator = d->gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem"));
+ GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem");
GtkRequisition sizeReq = {0, 0};
d->gtk_widget_size_request(gtkMenuSeparator, &sizeReq);
newSize = QSize(size.width(), sizeReq.height);
break;
}
- GtkWidget *gtkMenuItem = d->gtkWidget(QLS("GtkMenu.GtkCheckMenuItem"));
+ GtkWidget *gtkMenuItem = d->gtkWidget("GtkMenu.GtkCheckMenuItem");
GtkStyle* style = gtkMenuItem->style;
// Note we get the perfect height for the default font since we
@@ -3210,12 +3235,12 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
case CT_SpinBox:
// QSpinBox does some nasty things that depends on CT_LineEdit
- newSize = size + QSize(0, -d->gtkWidget(QLS("GtkSpinButton"))->style->ythickness * 2);
+ newSize = size + QSize(0, -d->gtkWidget("GtkSpinButton")->style->ythickness * 2);
break;
case CT_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
gint focusPadding, focusWidth;
d->gtk_widget_style_get(gtkButton, "focus-padding", &focusPadding, NULL);
d->gtk_widget_style_get(gtkButton, "focus-line-width", &focusWidth, NULL);
@@ -3223,7 +3248,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
newSize += QSize(2*gtkButton->style->xthickness + 4, 2*gtkButton->style->ythickness);
newSize += QSize(2*(focusWidth + focusPadding + 2), 2*(focusWidth + focusPadding));
- GtkWidget *gtkButtonBox = d->gtkWidget(QLS("GtkHButtonBox"));
+ GtkWidget *gtkButtonBox = d->gtkWidget("GtkHButtonBox");
gint minWidth = 85, minHeight = 0;
d->gtk_widget_style_get(gtkButtonBox, "child-min-width", &minWidth,
"child-min-height", &minHeight, NULL);
@@ -3236,13 +3261,13 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
break;
case CT_Slider: {
- GtkWidget *gtkSlider = d->gtkWidget(QLS("GtkHScale"));
+ GtkWidget *gtkSlider = d->gtkWidget("GtkHScale");
newSize = size + QSize(2*gtkSlider->style->xthickness, 2*gtkSlider->style->ythickness);
}
break;
case CT_LineEdit: {
- GtkWidget *gtkEntry = d->gtkWidget(QLS("GtkEntry"));
+ GtkWidget *gtkEntry = d->gtkWidget("GtkEntry");
newSize = size + QSize(2*gtkEntry->style->xthickness, 2 + 2*gtkEntry->style->ythickness);
}
break;
@@ -3253,7 +3278,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
case CT_ComboBox:
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- GtkWidget *gtkCombo = d->gtkWidget(QLS("GtkComboBox"));
+ GtkWidget *gtkCombo = d->gtkWidget("GtkComboBox");
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);
@@ -3408,7 +3433,7 @@ QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option,
return option->rect;
case SE_PushButtonContents:
if (!d->gtk_check_version(2, 10, 0)) {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
GtkBorder *border = 0;
d->gtk_widget_style_get(gtkButton, "inner-border", &border, NULL);
if (border) {
diff --git a/src/gui/styles/qgtkstyle_p.cpp b/src/gui/styles/qgtkstyle_p.cpp
index ad6746f8bc..3c6a1efe3e 100644
--- a/src/gui/styles/qgtkstyle_p.cpp
+++ b/src/gui/styles/qgtkstyle_p.cpp
@@ -60,6 +60,7 @@
#include <QtCore/QHash>
#include <QtCore/QUrl>
#include <QtCore/QLibrary>
+#include <QtCore/QDebug>
#include <private/qapplication_p.h>
#include <private/qiconloader_p.h>
@@ -233,17 +234,22 @@ static void update_toolbar_style(GtkWidget *gtkToolBar, GParamSpec *, gpointer)
}
}
-static QString classPath(GtkWidget *widget)
+static QHashableLatin1Literal classPath(GtkWidget *widget)
{
- char* class_path;
+ char *class_path;
QGtkStylePrivate::gtk_widget_path (widget, NULL, &class_path, NULL);
- QString path = QLS(class_path);
+
+ char *copy = class_path;
+ if (strncmp(copy, "GtkWindow.", 10) == 0)
+ copy += 10;
+ if (strncmp(copy, "GtkFixed.", 9) == 0)
+ copy += 9;
+
+ copy = strdup(copy);
+
g_free(class_path);
- // Remove the prefixes
- path.remove(QLS("GtkWindow."));
- path.remove(QLS("GtkFixed."));
- return path;
+ return QHashableLatin1Literal::fromData(copy);
}
@@ -261,6 +267,7 @@ bool QGtkStyleFilter::eventFilter(QObject *obj, QEvent *e)
}
QList<QGtkStylePrivate *> QGtkStylePrivate::instances;
+QGtkStylePrivate::WidgetMap *QGtkStylePrivate::widgetMap = 0;
QGtkStylePrivate::QGtkStylePrivate()
: QCleanlooksStylePrivate()
@@ -282,7 +289,7 @@ void QGtkStylePrivate::init()
qApp->installEventFilter(&filter);
}
-GtkWidget* QGtkStylePrivate::gtkWidget(const QString &path)
+GtkWidget* QGtkStylePrivate::gtkWidget(const QHashableLatin1Literal &path)
{
GtkWidget *widget = gtkWidgetMap()->value(path);
if (!widget) {
@@ -292,10 +299,10 @@ GtkWidget* QGtkStylePrivate::gtkWidget(const QString &path)
return widget;
}
-GtkStyle* QGtkStylePrivate::gtkStyle(const QString &path)
+GtkStyle* QGtkStylePrivate::gtkStyle(const QHashableLatin1Literal &path)
{
- if (gtkWidgetMap()->contains(path))
- return gtkWidgetMap()->value(path)->style;
+ if (GtkWidget *w = gtkWidgetMap()->value(path))
+ return w->style;
return 0;
}
@@ -494,7 +501,7 @@ void QGtkStylePrivate::initGtkWidgets() const
}
static QString themeName;
- if (!gtkWidgetMap()->contains(QLS("GtkWindow")) && themeName.isEmpty()) {
+ if (!gtkWidgetMap()->contains("GtkWindow") && themeName.isEmpty()) {
themeName = getThemeName();
if (themeName.isEmpty()) {
@@ -519,14 +526,14 @@ void QGtkStylePrivate::initGtkWidgets() const
QGtkStylePrivate::gtk_widget_realize(gtkWindow);
if (displayDepth == -1)
displayDepth = QGtkStylePrivate::gdk_drawable_get_depth(gtkWindow->window);
- gtkWidgetMap()->insert(QLS("GtkWindow"), gtkWindow);
+ gtkWidgetMap()->insert(QHashableLatin1Literal::fromData(strdup("GtkWindow")), gtkWindow);
// Make all other widgets. respect the text direction
if (qApp->layoutDirection() == Qt::RightToLeft)
QGtkStylePrivate::gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
- if (!gtkWidgetMap()->contains(QLS("GtkButton"))) {
+ if (!gtkWidgetMap()->contains("GtkButton")) {
GtkWidget *gtkButton = QGtkStylePrivate::gtk_button_new();
addWidget(gtkButton);
g_signal_connect(gtkButton, "style-set", G_CALLBACK(gtkStyleSetCallback), 0);
@@ -563,12 +570,12 @@ void QGtkStylePrivate::initGtkWidgets() const
// When styles change subwidgets can get rearranged
// as with the combo box. We need to update the widget map
// to reflect this;
- QHash<QString, GtkWidget*> oldMap = *gtkWidgetMap();
+ QHash<QHashableLatin1Literal, GtkWidget*> oldMap = *gtkWidgetMap();
gtkWidgetMap()->clear();
- QHashIterator<QString, GtkWidget*> it(oldMap);
+ QHashIterator<QHashableLatin1Literal, GtkWidget*> it(oldMap);
while (it.hasNext()) {
it.next();
- if (!it.key().contains(QLatin1Char('.'))) {
+ if (!strchr(it.key().data(), '.')) {
addAllSubWidgets(it.value());
}
}
@@ -583,8 +590,13 @@ void QGtkStylePrivate::initGtkWidgets() const
*/
void QGtkStylePrivate::cleanupGtkWidgets()
{
- if (gtkWidgetMap()->contains(QLS("GtkWindow"))) // Gtk will destroy all children
- gtk_widget_destroy(gtkWidgetMap()->value(QLS("GtkWindow")));
+ if (!widgetMap)
+ return;
+ if (widgetMap->contains("GtkWindow")) // Gtk will destroy all children
+ gtk_widget_destroy(widgetMap->value("GtkWindow"));
+ for (QHash<QHashableLatin1Literal, GtkWidget *>::const_iterator it = widgetMap->constBegin();
+ it != widgetMap->constEnd(); ++it)
+ free(const_cast<char *>(it.key().data()));
}
static bool resolveGConf()
@@ -675,7 +687,7 @@ QString QGtkStylePrivate::getThemeName()
int QGtkStylePrivate::getSpinboxArrowSize() const
{
const int MIN_ARROW_WIDTH = 6;
- GtkWidget *spinButton = gtkWidget(QLS("GtkSpinButton"));
+ GtkWidget *spinButton = gtkWidget("GtkSpinButton");
GtkStyle *style = spinButton->style;
gint size = pango_font_description_get_size (style->font_desc);
gint arrow_size;
@@ -695,17 +707,17 @@ bool QGtkStylePrivate::isKDE4Session()
void QGtkStylePrivate::applyCustomPaletteHash()
{
- QPalette menuPal = gtkWidgetPalette(QLS("GtkMenu"));
- GdkColor gdkBg = gtkWidget(QLS("GtkMenu"))->style->bg[GTK_STATE_NORMAL];
+ QPalette menuPal = gtkWidgetPalette("GtkMenu");
+ GdkColor gdkBg = gtkWidget("GtkMenu")->style->bg[GTK_STATE_NORMAL];
QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8);
menuPal.setBrush(QPalette::Base, bgColor);
menuPal.setBrush(QPalette::Window, bgColor);
qApp->setPalette(menuPal, "QMenu");
- QPalette toolbarPal = gtkWidgetPalette(QLS("GtkToolbar"));
+ QPalette toolbarPal = gtkWidgetPalette("GtkToolbar");
qApp->setPalette(toolbarPal, "QToolBar");
- QPalette menuBarPal = gtkWidgetPalette(QLS("GtkMenuBar"));
+ QPalette menuBarPal = gtkWidgetPalette("GtkMenuBar");
qApp->setPalette(menuBarPal, "QMenuBar");
}
@@ -714,7 +726,7 @@ void QGtkStylePrivate::applyCustomPaletteHash()
*/
GtkWidget* QGtkStylePrivate::getTextColorWidget() const
{
- return gtkWidget(QLS("GtkEntry"));
+ return gtkWidget("GtkEntry");
}
void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget)
@@ -723,7 +735,7 @@ void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget)
static GtkWidget* protoLayout = 0;
if (!protoLayout) {
protoLayout = QGtkStylePrivate::gtk_fixed_new();
- QGtkStylePrivate::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value(QLS("GtkWindow"))), protoLayout);
+ QGtkStylePrivate::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value("GtkWindow")), protoLayout);
}
Q_ASSERT(protoLayout);
@@ -736,8 +748,19 @@ void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget)
void QGtkStylePrivate::addWidgetToMap(GtkWidget *widget)
{
if (Q_GTK_IS_WIDGET(widget)) {
- gtk_widget_realize(widget);
- gtkWidgetMap()->insert(classPath(widget), widget);
+ gtk_widget_realize(widget);
+ QHashableLatin1Literal widgetPath = classPath(widget);
+
+ WidgetMap *map = gtkWidgetMap();
+ WidgetMap::iterator it = map->find(widgetPath);
+ if (it != map->end()) {
+ free(const_cast<char *>(it.key().data()));
+ map->erase(it);
+ }
+ map->insert(widgetPath, widget);
+#ifdef DUMP_GTK_WIDGET_TREE
+ qWarning("Inserted Gtk Widget: %s", widgetPath.data());
+#endif
}
}
@@ -750,7 +773,7 @@ void QGtkStylePrivate::addAllSubWidgets(GtkWidget *widget, gpointer v)
}
// Updates window/windowtext palette based on the indicated gtk widget
-QPalette QGtkStylePrivate::gtkWidgetPalette(const QString &gtkWidgetName) const
+QPalette QGtkStylePrivate::gtkWidgetPalette(const QHashableLatin1Literal &gtkWidgetName) const
{
GtkWidget *gtkWidget = QGtkStylePrivate::gtkWidget(gtkWidgetName);
Q_ASSERT(gtkWidget);
@@ -1086,6 +1109,28 @@ QIcon QGtkStylePrivate::getFilesystemIcon(const QFileInfo &info)
return icon;
}
+bool operator==(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2)
+{
+ return l1.size() == l2.size() || qstrcmp(l1.data(), l2.data()) == 0;
+}
+
+// copied from qHash.cpp
+uint qHash(const QHashableLatin1Literal &key)
+{
+ int n = key.size();
+ const uchar *p = reinterpret_cast<const uchar *>(key.data());
+ uint h = 0;
+ uint g;
+
+ while (n--) {
+ h = (h << 4) + *p++;
+ if ((g = (h & 0xf0000000)) != 0)
+ h ^= g >> 23;
+ h &= ~g;
+ }
+ return h;
+}
+
QT_END_NAMESPACE
#endif // !defined(QT_NO_STYLE_GTK)
diff --git a/src/gui/styles/qgtkstyle_p.h b/src/gui/styles/qgtkstyle_p.h
index 31a16dbdb9..68a04e9371 100644
--- a/src/gui/styles/qgtkstyle_p.h
+++ b/src/gui/styles/qgtkstyle_p.h
@@ -56,6 +56,10 @@
#include <QtCore/qglobal.h>
#if !defined(QT_NO_STYLE_GTK)
+#include <QtCore/qstring.h>
+#include <QtCore/qstringbuilder.h>
+#include <QtCore/qcoreapplication.h>
+
#include <QtGui/QFileDialog>
#include <QtGui/QGtkStyle>
@@ -72,6 +76,59 @@ typedef unsigned long XID;
#define QLS(x) QLatin1String(x)
+QT_BEGIN_NAMESPACE
+
+// ### Qt 4.7 - merge with QLatin1Literal
+class QHashableLatin1Literal
+{
+public:
+ int size() const { return m_size; }
+ const char *data() const { return m_data; }
+
+#ifdef __SUNPRO_CC
+ QHashableLatin1Literal(const char* str)
+ : m_size(strlen(str)), m_data(str) {}
+#else
+ template <int N>
+ QHashableLatin1Literal(const char (&str)[N])
+ : m_size(N - 1), m_data(str) {}
+#endif
+
+ QHashableLatin1Literal(const QHashableLatin1Literal &other)
+ : m_size(other.m_size), m_data(other.m_data)
+ {}
+
+ QHashableLatin1Literal &operator=(const QHashableLatin1Literal &other)
+ {
+ if (this == &other)
+ return *this;
+ *const_cast<int *>(&m_size) = other.m_size;
+ *const_cast<char **>(&m_data) = const_cast<char *>(other.m_data);
+ return *this;
+ }
+
+ QString toString() const { return QString::fromLatin1(m_data, m_size); }
+
+ static QHashableLatin1Literal fromData(const char *str)
+ {
+ return QHashableLatin1Literal(str, qstrlen(str));
+ }
+
+private:
+ QHashableLatin1Literal(const char *str, int length)
+ : m_size(length), m_data(str)
+ {}
+
+ const int m_size;
+ const char *m_data;
+};
+
+bool operator==(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2);
+inline bool operator!=(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2) { return !operator==(l1, l2); }
+uint qHash(const QHashableLatin1Literal &key);
+
+QT_END_NAMESPACE
+
class GConf;
class GConfClient;
@@ -252,7 +309,6 @@ typedef char* (*Ptr_gnome_icon_lookup_sync) (
GnomeIconLookupFlags flags,
GnomeIconLookupResultFlags *result);
-
class QGtkStylePrivate : public QCleanlooksStylePrivate
{
Q_DECLARE_PUBLIC(QGtkStyle)
@@ -262,8 +318,8 @@ public:
QGtkStyleFilter filter;
- static GtkWidget* gtkWidget(const QString &path);
- static GtkStyle* gtkStyle(const QString &path = QLatin1String("GtkWindow"));
+ static GtkWidget* gtkWidget(const QHashableLatin1Literal &path);
+ static GtkStyle* gtkStyle(const QHashableLatin1Literal &path = QHashableLatin1Literal("GtkWindow"));
virtual void resolveGtk() const;
virtual void initGtkMenu() const;
@@ -418,17 +474,25 @@ public:
static Ptr_gnome_icon_lookup_sync gnome_icon_lookup_sync;
static Ptr_gnome_vfs_init gnome_vfs_init;
- virtual QPalette gtkWidgetPalette(const QString &gtkWidgetName) const;
+ virtual QPalette gtkWidgetPalette(const QHashableLatin1Literal &gtkWidgetName) const;
protected:
- typedef QHash<QString, GtkWidget*> WidgetMap;
+ typedef QHash<QHashableLatin1Literal, GtkWidget*> WidgetMap;
+
+ static inline void destroyWidgetMap()
+ {
+ cleanupGtkWidgets();
+ delete widgetMap;
+ widgetMap = 0;
+ }
static inline WidgetMap *gtkWidgetMap()
{
- static WidgetMap *map = 0;
- if (!map)
- map = new WidgetMap();
- return map;
+ if (!widgetMap) {
+ widgetMap = new WidgetMap();
+ qAddPostRoutine(destroyWidgetMap);
+ }
+ return widgetMap;
}
static QStringList extract_filter(const QString &rawFilter);
@@ -443,6 +507,7 @@ protected:
private:
static QList<QGtkStylePrivate *> instances;
+ static WidgetMap *widgetMap;
friend class QGtkStyleUpdateScheduler;
};
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm
index 5bd939f5b3..f5b0b0c09b 100644
--- a/src/gui/styles/qmacstyle_mac.mm
+++ b/src/gui/styles/qmacstyle_mac.mm
@@ -237,12 +237,14 @@ void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt)
// fill body
if (active) {
- p->fillRect(rect, QColor(151, 151, 151));
+ int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 16 : 0;
+ p->fillRect(rect, QColor(151 + d, 151 + d, 151 + d));
} else {
+ int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 9 : 0;
QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
- gradient.setColorAt(0, QColor(207, 207, 207));
- gradient.setColorAt(0.5, QColor(206, 206, 206));
- gradient.setColorAt(1, QColor(201, 201, 201));
+ gradient.setColorAt(0, QColor(207 + d, 207 + d, 207 + d));
+ gradient.setColorAt(0.5, QColor(206 + d, 206 + d, 206 + d));
+ gradient.setColorAt(1, QColor(201 + d, 201 + d, 201 + d));
p->fillRect(rect, gradient);
}
@@ -432,13 +434,13 @@ static inline bool isTreeView(const QWidget *widget)
QString qt_mac_removeMnemonics(const QString &original)
{
- // copied from qt_format_text (to be bug-for-bug compatible).
QString returnText(original.size(), 0);
int finalDest = 0;
int currPos = 0;
int l = original.length();
while (l) {
- if (original.at(currPos) == QLatin1Char('&')) {
+ if (original.at(currPos) == QLatin1Char('&')
+ && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) {
++currPos;
--l;
if (l == 0)
@@ -2141,7 +2143,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
if (qstyleoption_cast<const QStyleOptionComboBox *>(opt) != 0)
ret = 0;
else
- ret = QWindowsStyle::pixelMetric(metric, opt, widget);
+ ret = 1;
break;
case PM_MaximumDragDistance:
ret = -1;
@@ -3097,14 +3099,16 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
HIRect hirect = qt_hirectForQRect(opt->rect);
HIThemeDrawButton(&hirect, &bi, cg, kHIThemeOrientationNormal, 0);
break; }
+
case PE_Frame: {
QPen oldPen = p->pen();
- QPen newPen;
- newPen.setBrush(opt->palette.dark());
- p->setPen(newPen);
+ p->setPen(opt->palette.base().color().darker(140));
p->drawRect(opt->rect.adjusted(0, 0, -1, -1));
+ p->setPen(opt->palette.base().color().darker(180));
+ p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
p->setPen(oldPen);
break; }
+
case PE_FrameLineEdit:
if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
if (frame->state & State_Sunken) {
@@ -3146,6 +3150,18 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
break;
case PE_PanelLineEdit:
QWindowsStyle::drawPrimitive(pe, opt, p, w);
+ // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit).
+ // Focus frame is drawn outside the rectangle passed in the option-rect.
+ if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
+ if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) {
+ int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin);
+ int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin);
+ QStyleOptionFrame focusFrame = *panel;
+ focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin);
+ drawControl(CE_FocusFrame, &focusFrame, p, w);
+ }
+ }
+
break;
case PE_FrameTabWidget:
if (const QStyleOptionTabWidgetFrame *twf
@@ -3169,7 +3185,6 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft());
} break;
case PE_FrameStatusBarItem:
- QCommonStyle::drawPrimitive(pe, opt, p, w);
break;
case PE_IndicatorTabClose: {
bool hover = (opt->state & State_MouseOver);
@@ -3266,10 +3281,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (header->orientation == Qt::Horizontal){
switch (header->position) {
case QStyleOptionHeader::Beginning:
+ ir.adjust(-1, -1, 0, 0);
break;
case QStyleOptionHeader::Middle:
+ ir.adjust(-1, -1, 0, 0);
+ break;
+ case QStyleOptionHeader::OnlyOneSection:
case QStyleOptionHeader::End:
- ir.adjust(-1, 0, 0, 0);
+ ir.adjust(-1, -1, 1, 0);
break;
default:
break;
diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp
index 9f69fd8591..fbb5e4d6be 100644
--- a/src/gui/styles/qplastiquestyle.cpp
+++ b/src/gui/styles/qplastiquestyle.cpp
@@ -56,7 +56,6 @@ static const int blueFrameWidth = 2; // with of line edit focus frame
#include <qabstractitemview.h>
#include <qcheckbox.h>
#include <qcombobox.h>
-#include <qdatetime.h>
#include <qdebug.h>
#include <qdialogbuttonbox.h>
#include <qformlayout.h>
@@ -81,6 +80,7 @@ static const int blueFrameWidth = 2; // with of line edit focus frame
#include <qsplitter.h>
#include <qstyleoption.h>
#include <qtextedit.h>
+#include <qelapsedtimer.h>
#include <qtoolbar.h>
#include <qtoolbox.h>
#include <qtoolbutton.h>
@@ -980,7 +980,7 @@ public:
#ifndef QT_NO_PROGRESSBAR
QList<QProgressBar *> bars;
int progressBarAnimateTimer;
- QTime timer;
+ QElapsedTimer timer;
#endif
};
@@ -5846,7 +5846,6 @@ void QPlastiqueStyle::polish(QApplication *app)
void QPlastiqueStyle::polish(QPalette &pal)
{
QWindowsStyle::polish(pal);
- pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110));
#ifdef Q_WS_MAC
pal.setBrush(QPalette::Shadow, Qt::black);
#endif
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
index 5bc36f8141..55aa6b0f3c 100644
--- a/src/gui/styles/qs60style_s60.cpp
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -58,12 +58,12 @@
#include <AknsSkinInstance.h>
#include <AknsBasicBackgroundControlContext.h>
#include <avkon.mbg>
-#include <AknFontAccess.h>
-#include <AknLayoutFont.h>
+#include <aknfontaccess.h>
+#include <aknlayoutfont.h>
#include <AknUtils.h>
#include <aknnavi.h>
#include <gulicon.h>
-#include <AknBitmapAnimation.h>
+#include <aknbitmapanimation.h>
#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
diff --git a/src/gui/styles/qs60style_simulated.cpp b/src/gui/styles/qs60style_simulated.cpp
index f87cf282e4..3f09ebc0c3 100644
--- a/src/gui/styles/qs60style_simulated.cpp
+++ b/src/gui/styles/qs60style_simulated.cpp
@@ -94,12 +94,12 @@ bool saveThemeToBlob(const QString &themeBlob,
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;
+ dataOut << partPictures.count();
+ QHashIterator<QString, QPicture> i(partPictures);
+ while (i.hasNext()) {
+ i.next();
+ dataOut << i.key();
+ dataOut << i.value(); // the QPicture
}
QDataStream blobOut(&blob);
diff --git a/src/gui/styles/qstylehelper.cpp b/src/gui/styles/qstylehelper.cpp
index 071ec232b4..296c51c05a 100644
--- a/src/gui/styles/qstylehelper.cpp
+++ b/src/gui/styles/qstylehelper.cpp
@@ -54,24 +54,71 @@
#include <private/qt_cocoa_helpers_mac_p.h>
#endif
+#include <qstringbuilder.h>
+
QT_BEGIN_NAMESPACE
+// internal helper. Converts an integer value to an unique string token
+template <typename T>
+struct HexString
+{
+ inline HexString(const T t)
+ : val(t)
+ {}
+
+ inline void write(QChar *&dest) const
+ {
+ const ushort hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ const char *c = reinterpret_cast<const char *>(&val);
+ for (uint i = 0; i < sizeof(T); ++i) {
+ *dest++ = hexChars[*c & 0xf];
+ *dest++ = hexChars[(*c & 0xf0) >> 4];
+ ++c;
+ }
+ }
+
+ const T val;
+};
+
+// specialization to enable fast concatenating of our string tokens to a string
+template <typename T>
+struct QConcatenable<HexString<T> >
+{
+ typedef HexString<T> type;
+ enum { ExactSize = true };
+ static int size(const HexString<T> &str) { return sizeof(str.val) * 2; }
+ static inline void appendTo(const HexString<T> &str, QChar *&out) { str.write(out); }
+};
+
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());
+
+ QString tmp = key
+ % QLatin1Char('-')
+ % HexString<uint>(option->state)
+ % QLatin1Char('-')
+ % HexString<uint>(option->direction)
+ % QLatin1Char('-')
+ % HexString<uint>(complexOption ? uint(complexOption->activeSubControls) : 0u)
+ % QLatin1Char('-')
+ % HexString<quint64>(option->palette.cacheKey())
+ % QLatin1Char('-')
+ % HexString<uint>(size.width())
+ % QLatin1Char('x')
+ % HexString<uint>(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'));
+ tmp = tmp
+ % QLatin1Char('-')
+ % HexString<uint>(spinBox->buttonSymbols)
+ % QLatin1Char('-')
+ % HexString<uint>(spinBox->stepEnabled)
+ % QLatin1Char('-')
+ % QLatin1Char(spinBox->frame ? '1' : '0');
}
#endif // QT_NO_SPINBOX
return tmp;
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index 0b615bca29..515b6c79ab 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -1065,7 +1065,7 @@ QRect QRenderRule::boxRect(const QRect& cr, int flags) const
r.adjust(-p[LeftEdge], -p[TopEdge], p[RightEdge], p[BottomEdge]);
}
}
- if (!hasNativeBorder() && (flags & Border)) {
+ if (hasBorder() && (flags & Border)) {
const int *b = border()->borders;
r.adjust(-b[LeftEdge], -b[TopEdge], b[RightEdge], b[BottomEdge]);
}
@@ -1352,6 +1352,12 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorRole fr, QPalette
if (br != QPalette::NoRole)
p->setBrush(br, bg->brush);
p->setBrush(QPalette::Window, bg->brush);
+ if (bg->brush.style() == Qt::SolidPattern) {
+ p->setBrush(QPalette::Light, bg->brush.color().lighter(115));
+ p->setBrush(QPalette::Midlight, bg->brush.color().lighter(107));
+ p->setBrush(QPalette::Dark, bg->brush.color().darker(150));
+ p->setBrush(QPalette::Shadow, bg->brush.color().darker(300));
+ }
}
if (!hasPalette())
@@ -2537,7 +2543,7 @@ void QStyleSheetStyle::setPalette(QWidget *w)
int state;
QPalette::ColorGroup group;
} map[3] = {
- { PseudoClass_Active | PseudoClass_Enabled, QPalette::Active },
+ { int(PseudoClass_Active | PseudoClass_Enabled), QPalette::Active },
{ PseudoClass_Disabled, QPalette::Disabled },
{ PseudoClass_Enabled, QPalette::Inactive }
};
@@ -3170,8 +3176,8 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
if (subRule1.hasDrawable()) {
QRect r(gr.topLeft(),
slider->orientation == Qt::Horizontal
- ? QPoint(hr.x()+hr.width()/2, gr.y()+gr.height())
- : QPoint(gr.x()+gr.width(), hr.y()+hr.height()/2));
+ ? QPoint(hr.x()+hr.width()/2, gr.y()+gr.height() - 1)
+ : QPoint(gr.x()+gr.width() - 1, hr.y()+hr.height()/2));
subRule1.drawRule(p, r);
}
@@ -3458,10 +3464,17 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
case CE_RadioButton:
case CE_CheckBox:
- rule.drawRule(p, opt->rect);
- ParentStyle::drawControl(ce, opt, p, w);
- return;
-
+ if (rule.hasBox() || !rule.hasNativeBorder() || rule.hasDrawable() || hasStyleRule(w, PseudoElement_Indicator)) {
+ rule.drawRule(p, opt->rect);
+ ParentStyle::drawControl(ce, opt, p, w);
+ return;
+ } else if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
+ QStyleOptionButton butOpt(*btn);
+ rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button);
+ baseStyle()->drawControl(ce, &butOpt, p, w);
+ return;
+ }
+ break;
case CE_RadioButtonLabel:
case CE_CheckBoxLabel:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp
index 6c485907ba..1653baa6f7 100644
--- a/src/gui/styles/qwindowsstyle.cpp
+++ b/src/gui/styles/qwindowsstyle.cpp
@@ -497,7 +497,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
{
#ifndef Q_OS_WINCE
NONCLIENTMETRICS ncm;
- ncm.cbSize = sizeof(NONCLIENTMETRICS);
+ ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
ret = qMax(ncm.iScrollHeight, ncm.iScrollWidth);
else
@@ -3105,7 +3105,9 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On),
&copy.palette.brush(QPalette::Button));
copy.rect.adjust(4, 1, -5, -1);
- if (!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) ) {
+ if ((!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled))
+ && proxy()->styleHint(SH_EtchDisabledText, opt, widget) )
+ {
QStyleOptionSpinBox lightCopy = copy;
lightCopy.rect.adjust(1, 1, 1, 1);
lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light());
@@ -3138,7 +3140,9 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On),
&copy.palette.brush(QPalette::Button));
copy.rect.adjust(4, 0, -5, -1);
- if (!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) ) {
+ if ((!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled))
+ && proxy()->styleHint(SH_EtchDisabledText, opt, widget) )
+ {
QStyleOptionSpinBox lightCopy = copy;
lightCopy.rect.adjust(1, 1, 1, 1);
lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light());
diff --git a/src/gui/styles/qwindowsstyle_p.h b/src/gui/styles/qwindowsstyle_p.h
index 808abe14bf..2a89b846c5 100644
--- a/src/gui/styles/qwindowsstyle_p.h
+++ b/src/gui/styles/qwindowsstyle_p.h
@@ -58,8 +58,8 @@
#ifndef QT_NO_STYLE_WINDOWS
#include <qlist.h>
-#include <qdatetime.h>
#include <qhash.h>
+#include <qelapsedtimer.h>
QT_BEGIN_NAMESPACE
@@ -80,7 +80,7 @@ public:
QList<QProgressBar *> bars;
int animationFps;
int animateTimer;
- QTime startTime;
+ QElapsedTimer startTime;
int animateStep;
QColor inactiveCaptionText;
QColor activeCaptionColor;
diff --git a/src/gui/styles/qwindowsvistastyle_p.h b/src/gui/styles/qwindowsvistastyle_p.h
index 673568d29c..ab941a1e3d 100644
--- a/src/gui/styles/qwindowsvistastyle_p.h
+++ b/src/gui/styles/qwindowsvistastyle_p.h
@@ -86,6 +86,7 @@
#include <qlistview.h>
#include <qtableview.h>
#include <qbasictimer.h>
+#include <qdatetime.h>
#include <qcommandlinkbutton.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index b349bcfbe9..21a31a35ec 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -73,7 +73,7 @@
#endif
#endif
#ifdef Q_OS_SYMBIAN
-#include "qt_s60_p.h"
+#include <private/qt_s60_p.h>
#endif
#include <QMutexLocker>
@@ -1286,9 +1286,11 @@ QFont::StyleHint QFont::styleHint() const
\value PreferAntialias antialias if possible.
\value OpenGLCompatible forces the use of OpenGL compatible
fonts.
- \value NoFontMerging If a font does not contain a character requested
- to draw then Qt automatically chooses a similar looking for that contains
- the character. This flag disables this feature.
+ \value NoFontMerging If the font selected for a certain writing system
+ does not contain a character requested to draw, then Qt automatically chooses a similar
+ looking font that contains the character. The NoFontMerging flag disables this feature.
+ Please note that enabling this flag will not prevent Qt from automatically picking a
+ suitable font when the selected font does not support the writing system of the text.
Any of these may be OR-ed with one of these flags:
@@ -1297,6 +1299,8 @@ QFont::StyleHint QFont::styleHint() const
\value PreferQuality prefer the best quality font. The font matcher
will use the nearest standard point size that the font
supports.
+ \value ForceIntegerMetrics forces the use of integer values in font engines that support fractional
+ font metrics.
*/
/*!
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index a2fff703ef..6f624246b9 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -76,17 +76,18 @@ public:
};
enum StyleStrategy {
- PreferDefault = 0x0001,
- PreferBitmap = 0x0002,
- PreferDevice = 0x0004,
- PreferOutline = 0x0008,
- ForceOutline = 0x0010,
- PreferMatch = 0x0020,
- PreferQuality = 0x0040,
- PreferAntialias = 0x0080,
- NoAntialias = 0x0100,
- OpenGLCompatible = 0x0200,
- NoFontMerging = 0x8000
+ PreferDefault = 0x0001,
+ PreferBitmap = 0x0002,
+ PreferDevice = 0x0004,
+ PreferOutline = 0x0008,
+ ForceOutline = 0x0010,
+ PreferMatch = 0x0020,
+ PreferQuality = 0x0040,
+ PreferAntialias = 0x0080,
+ NoAntialias = 0x0100,
+ OpenGLCompatible = 0x0200,
+ ForceIntegerMetrics = 0x0400,
+ NoFontMerging = 0x8000
};
enum Weight {
@@ -291,6 +292,7 @@ private:
friend class QFontMetricsF;
friend class QFontInfo;
friend class QPainter;
+ friend class QPainterPrivate;
friend class QPSPrintEngineFont;
friend class QApplication;
friend class QWidget;
diff --git a/src/gui/text/qfont_s60.cpp b/src/gui/text/qfont_s60.cpp
index 52c77d63ba..ccd17a2123 100644
--- a/src/gui/text/qfont_s60.cpp
+++ b/src/gui/text/qfont_s60.cpp
@@ -40,8 +40,8 @@
****************************************************************************/
#include "qfont.h"
-#include "qt_s60_p.h"
-#include "qpixmap_s60_p.h"
+#include <private/qt_s60_p.h>
+#include <private/qpixmap_s60_p.h>
#include "qmutex.h"
QT_BEGIN_NAMESPACE
diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp
index 62d77931a7..a3d8d65663 100644
--- a/src/gui/text/qfontdatabase_qws.cpp
+++ b/src/gui/text/qfontdatabase_qws.cpp
@@ -632,8 +632,9 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
#ifndef QT_NO_FREETYPE
QScopedPointer<QFontEngineFT> fte(new QFontEngineFT(def));
- if (fte->init(faceId, style->antialiased,
- style->antialiased ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) {
+ bool antialias = style->antialiased && !(request.styleStrategy & QFont::NoAntialias);
+ if (fte->init(faceId, antialias,
+ antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) {
#ifdef QT_NO_QWS_QPF2
return fte.take();
#else
@@ -793,7 +794,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
" family: %s [%s], script: %d\n"
" weight: %d, style: %d\n"
" stretch: %d\n"
- " pixelSize: %d\n"
+ " pixelSize: %g\n"
" pitch: %c",
family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index 376ad43d91..3ad0806405 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -45,8 +45,8 @@
#include "qfontengine_s60_p.h"
#include "qabstractfileengine.h"
#include "qdesktopservices.h"
-#include "qpixmap_s60_p.h"
-#include "qt_s60_p.h"
+#include <private/qpixmap_s60_p.h>
+#include <private/qt_s60_p.h>
#include "qendian.h"
#include <private/qcore_symbian_p.h>
#if defined(QT_NO_FREETYPE)
diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp
index a6ceee16b5..c50d363d94 100644
--- a/src/gui/text/qfontdatabase_win.cpp
+++ b/src/gui/text/qfontdatabase_win.cpp
@@ -1111,7 +1111,6 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0)
return;
#else
- // supported from 2000 on, so no need to deal with the *A variant
PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"),
"AddFontResourceExW");
if (!ptrAddFontResourceExW
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index bb1e60db77..3b2e4e9c4c 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -41,9 +41,9 @@
#include <qplatformdefs.h>
-#include <qdatetime.h>
#include <qdebug.h>
#include <qpaintdevice.h>
+#include <qelapsedtimer.h>
#include <private/qt_x11_p.h>
#include "qx11info_x11.h"
@@ -1218,7 +1218,7 @@ static void load(const QString &family = QString(), int script = -1, bool forceX
}
#ifdef QFONTDATABASE_DEBUG
- QTime t;
+ QElapsedTimer t;
t.start();
#endif
@@ -1301,7 +1301,7 @@ static void initializeDb()
if (!db || db->count)
return;
- QTime t;
+ QElapsedTimer t;
t.start();
#ifndef QT_NO_FONTCONFIG
@@ -1314,7 +1314,7 @@ static void initializeDb()
}
loadFontConfig();
- FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", t.elapsed());
+ FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", int(t.elapsed()));
#endif
t.start();
@@ -1939,8 +1939,13 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
fe = loadFc(d, script, req);
if (fe != 0 && fe->fontDef.pixelSize != req.pixelSize) {
- delete fe;
- fe = loadXlfd(d->screen, script, req);
+ QFontEngine *xlfdFontEngine = loadXlfd(d->screen, script, req);
+ if (xlfdFontEngine->fontDef.family == fe->fontDef.family) {
+ delete fe;
+ fe = xlfdFontEngine;
+ } else {
+ delete xlfdFontEngine;
+ }
}
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 629db66eff..194c5f3dd4 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -596,8 +596,9 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &t)
{
QImage i = alphaMapForGlyph(glyph);
if (t.type() > QTransform::TxTranslate)
- i = i.transformed(t);
+ i = i.transformed(t).convertToFormat(QImage::Format_Indexed8);
Q_ASSERT(i.depth() <= 8); // To verify that transformed didn't change the format...
+
return i;
}
@@ -606,11 +607,14 @@ QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, int /* margin */, const Q
QImage alphaMask = alphaMapForGlyph(glyph, t);
QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32);
+ QVector<QRgb> colorTable = alphaMask.colorTable();
for (int y=0; y<alphaMask.height(); ++y) {
uint *dst = (uint *) rgbMask.scanLine(y);
uchar *src = (uchar *) alphaMask.scanLine(y);
- for (int x=0; x<alphaMask.width(); ++x)
- dst[x] = qRgb(src[x], src[x], src[x]);
+ for (int x=0; x<alphaMask.width(); ++x) {
+ int val = qAlpha(colorTable.at(src[x]));
+ dst[x] = qRgb(val, val, val);
+ }
}
return rgbMask;
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 17ade64004..449dffdc91 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -619,7 +619,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
transform = false;
antialias = true;
freetype = 0;
- default_load_flags = 0;
+ default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
default_hint_style = HintNone;
subpixelType = Subpixel_None;
lcdFilterType = 0;
@@ -746,7 +746,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph) const
{
- Glyph *g = set->glyph_data.value(glyph);
+ Glyph *g = set->getGlyph(glyph);
if (g)
return g;
@@ -858,10 +858,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
}
}
- Glyph *g = set->glyph_data.value(glyph);
+ Glyph *g = set->getGlyph(glyph);
if (g && g->format == format) {
if (uploadToServer && !g->uploadedToServer) {
- set->glyph_data[glyph] = 0;
+ set->setGlyph(glyph, 0);
delete g;
g = 0;
} else {
@@ -1158,7 +1158,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
uploadGlyphToServer(set, glyph, g, &info, glyph_buffer_size);
}
- set->glyph_data[glyph] = g;
+ set->setGlyph(glyph, g);
return g;
}
@@ -1368,7 +1368,7 @@ QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransfor
if (!gs) {
// don't try to load huge fonts
- bool draw_as_outline = fontDef.pixelSize * qSqrt(matrix.det()) >= 64;
+ bool draw_as_outline = fontDef.pixelSize * qSqrt(qAbs(matrix.det())) >= 64;
if (draw_as_outline)
return 0;
@@ -1381,8 +1381,7 @@ QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransfor
}
gs = &transformedGlyphSets[0];
- qDeleteAll(gs->glyph_data);
- gs->glyph_data.clear();
+ gs->clear();
gs->id = allocateServerGlyphSet();
@@ -1398,7 +1397,7 @@ bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, G
FT_Face face = 0;
for (int i = 0; i < num_glyphs; ++i) {
- Glyph *glyph = gs->glyph_data.value(glyphs[i]);
+ Glyph *glyph = gs->getGlyph(glyphs[i]);
if (glyph == 0 || glyph->format != format) {
if (!face) {
face = lockFace();
@@ -1635,7 +1634,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
FT_Face face = 0;
if (flags & QTextEngine::DesignMetrics) {
for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.glyph_data.value(glyphs->glyphs[i]);
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
if (g) {
glyphs->advances_x[i] = QFixed::fromFixed(g->linearAdvance);
} else {
@@ -1648,7 +1647,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
}
} else {
for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.glyph_data.value(glyphs->glyphs[i]);
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
if (g) {
glyphs->advances_x[i] = QFixed(g->advance);
} else {
@@ -1677,7 +1676,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
QFixed ymax = 0;
QFixed xmax = 0;
for (int i = 0; i < glyphs.numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.glyph_data.value(glyphs.glyphs[i]);
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs.glyphs[i]);
if (!g) {
if (!face)
face = lockFace();
@@ -1719,7 +1718,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
{
FT_Face face = 0;
glyph_metrics_t overall;
- Glyph *g = defaultGlyphSet.glyph_data.value(glyph);
+ Glyph *g = defaultGlyphSet.getGlyph(glyph);
if (!g) {
face = lockFace();
g = loadGlyph(glyph, Format_None, true);
@@ -1783,8 +1782,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr
transformedGlyphSets.prepend(QGlyphSet());
}
glyphSet = &transformedGlyphSets[0];
- qDeleteAll(glyphSet->glyph_data);
- glyphSet->glyph_data.clear();
+ glyphSet->clear();
glyphSet->id = allocateServerGlyphSet();
glyphSet->transformationMatrix = m;
}
@@ -1792,7 +1790,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr
} else {
glyphSet = &defaultGlyphSet;
}
- Glyph * g = glyphSet->glyph_data.value(glyph);
+ Glyph * g = glyphSet->getGlyph(glyph);
if (!g) {
face = lockFace();
g = loadGlyphMetrics(glyphSet, glyph);
@@ -1881,7 +1879,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransfor
void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
{
- delete defaultGlyphSet.glyph_data.take(glyph);
+ defaultGlyphSet.removeGlyphFromCache(glyph);
}
int QFontEngineFT::glyphCount() const
@@ -1937,11 +1935,53 @@ QFontEngineFT::QGlyphSet::QGlyphSet()
transformationMatrix.yy = 0x10000;
transformationMatrix.xy = 0;
transformationMatrix.yx = 0;
+ memset(fast_glyph_data, 0, sizeof(fast_glyph_data));
+ fast_glyph_count = 0;
}
QFontEngineFT::QGlyphSet::~QGlyphSet()
{
+ clear();
+}
+
+void QFontEngineFT::QGlyphSet::clear()
+{
+ if (fast_glyph_count > 0) {
+ for (int i = 0; i < 256; ++i) {
+ if (fast_glyph_data[i]) {
+ delete fast_glyph_data[i];
+ fast_glyph_data[i] = 0;
+ }
+ }
+ fast_glyph_count = 0;
+ }
qDeleteAll(glyph_data);
+ glyph_data.clear();
+}
+
+void QFontEngineFT::QGlyphSet::removeGlyphFromCache(int index)
+{
+ if (index < 256) {
+ if (fast_glyph_data[index]) {
+ delete fast_glyph_data[index];
+ fast_glyph_data[index] = 0;
+ if (fast_glyph_count > 0)
+ --fast_glyph_count;
+ }
+ } else {
+ delete glyph_data.take(index);
+ }
+}
+
+void QFontEngineFT::QGlyphSet::setGlyph(int index, Glyph *glyph)
+{
+ if (index < 256) {
+ if (!fast_glyph_data[index])
+ ++fast_glyph_count;
+ fast_glyph_data[index] = glyph;
+ } else {
+ glyph_data.insert(index, glyph);
+ }
}
unsigned long QFontEngineFT::allocateServerGlyphSet()
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 98dd002719..12b7da86a1 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -180,7 +180,21 @@ public:
FT_Matrix transformationMatrix;
unsigned long id; // server sided id, GlyphSet for X11
bool outline_drawing;
+
+ void removeGlyphFromCache(int index);
+ void clear();
+ inline Glyph *getGlyph(int index) const
+ {
+ if (index < 256)
+ return fast_glyph_data[index];
+ return glyph_data.value(index);
+ }
+ void setGlyph(int index, Glyph *glyph);
+
+private:
mutable QHash<int, Glyph *> glyph_data; // maps from glyph index to glyph data
+ mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
+ mutable int fast_glyph_count;
};
virtual QFontEngine::FaceId faceId() const;
@@ -252,7 +266,7 @@ public:
QGlyphSet *defaultGlyphs() { return &defaultGlyphSet; }
GlyphFormat defaultGlyphFormat() const { return defaultFormat; }
- inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.glyph_data.value(g); }
+ inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.getGlyph(g); }
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render);
diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm
index 48bc6351e4..0bfdbc04f3 100644
--- a/src/gui/text/qfontengine_mac.mm
+++ b/src/gui/text/qfontengine_mac.mm
@@ -53,6 +53,7 @@
#include <qvarlengtharray.h>
#include <qdebug.h>
#include <qendian.h>
+#include <qmath.h>
#include <ApplicationServices/ApplicationServices.h>
#include <AppKit/AppKit.h>
@@ -303,12 +304,20 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
outGlyphs[idx] = tmpGlyphs[i] | fontIndex;
outAdvances_x[idx] = QFixed::fromReal(tmpPoints[i + 1].x - tmpPoints[i].x);
outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i + 1].y - tmpPoints[i].y);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ outAdvances_x[idx] = outAdvances_x[idx].round();
+ outAdvances_y[idx] = outAdvances_y[idx].round();
+ }
}
CGSize lastGlyphAdvance;
CTFontGetAdvancesForGlyphs(runFont, kCTFontHorizontalOrientation, tmpGlyphs + glyphCount - 1, &lastGlyphAdvance, 1);
outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex;
- outAdvances_x[rtl ? 0 : (glyphCount - 1)] = QFixed::fromReal(lastGlyphAdvance.width).ceil();
+ outAdvances_x[rtl ? 0 : (glyphCount - 1)] =
+ (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(lastGlyphAdvance.width).round()
+ : QFixed::fromReal(lastGlyphAdvance.width);
}
outGlyphs += glyphCount;
outAttributes += glyphCount;
@@ -378,8 +387,11 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *, int, QGlyphLayout *, int *
glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
{
QFixed w;
- for (int i = 0; i < glyphs.numGlyphs; ++i)
- w += glyphs.effectiveAdvance(i);
+ for (int i = 0; i < glyphs.numGlyphs; ++i) {
+ w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? glyphs.effectiveAdvance(i).round()
+ : glyphs.effectiveAdvance(i);
+ }
return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0);
}
glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
@@ -393,33 +405,51 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
ret.y = -QFixed::fromReal(rect.origin.y) - ret.height;
CGSize advances[1];
CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1);
- ret.xoff = QFixed::fromReal(advances[0].width).ceil();
- ret.yoff = QFixed::fromReal(advances[0].height).ceil();
+ ret.xoff = QFixed::fromReal(advances[0].width);
+ ret.yoff = QFixed::fromReal(advances[0].height);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ ret.xoff = ret.xoff.round();
+ ret.yoff = ret.yoff.round();
+ }
+
return ret;
}
QFixed QCoreTextFontEngine::ascent() const
{
- return QFixed::fromReal(CTFontGetAscent(ctfont)).ceil();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetAscent(ctfont)).round()
+ : QFixed::fromReal(CTFontGetAscent(ctfont));
}
QFixed QCoreTextFontEngine::descent() const
{
+ QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont));
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ d = d.round();
+
// subtract a pixel to even out the historical +1 in QFontMetrics::height().
// Fix in Qt 5.
- return QFixed::fromReal(CTFontGetDescent(ctfont)).ceil() - 1;
+ return d - 1;
}
QFixed QCoreTextFontEngine::leading() const
{
- return QFixed::fromReal(CTFontGetLeading(ctfont)).ceil();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetLeading(ctfont)).round()
+ : QFixed::fromReal(CTFontGetLeading(ctfont));
}
QFixed QCoreTextFontEngine::xHeight() const
{
- return QFixed::fromReal(CTFontGetXHeight(ctfont)).ceil();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round()
+ : QFixed::fromReal(CTFontGetXHeight(ctfont));
}
QFixed QCoreTextFontEngine::averageCharWidth() const
{
// ### Need to implement properly and get the information from the OS/2 Table.
- return QFontEngine::averageCharWidth();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFontEngine::averageCharWidth().round()
+ : QFontEngine::averageCharWidth();
}
qreal QCoreTextFontEngine::maxCharWidth() const
@@ -787,6 +817,7 @@ struct QGlyphLayoutInfo
int *mappedFonts;
QTextEngine::ShaperFlags flags;
QFontEngineMacMulti::ShaperItem *shaperItem;
+ unsigned int styleStrategy;
};
static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATSULineRef lineRef, URefCon refCon,
@@ -856,6 +887,11 @@ static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATS
QFixed yAdvance = FixedToQFixed(baselineDeltas[glyphIdx]);
QFixed xAdvance = FixedToQFixed(layoutData[glyphIdx + 1].realPos - layoutData[glyphIdx].realPos);
+ if (nfo->styleStrategy & QFont::ForceIntegerMetrics) {
+ yAdvance = yAdvance.round();
+ xAdvance = xAdvance.round();
+ }
+
if (glyphId != 0xffff || i == 0) {
if (i < nfo->glyphs->numGlyphs)
{
@@ -1032,6 +1068,7 @@ bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyph
nfo.callbackCalled = false;
nfo.flags = flags;
nfo.shaperItem = shaperItem;
+ nfo.styleStrategy = fontDef.styleStrategy;
int prevNumGlyphs = *nglyphs;
@@ -1061,8 +1098,6 @@ bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyph
| kATSLineDisableAllJustification
;
- layopts |= kATSLineUseDeviceMetrics;
-
if (fontDef.styleStrategy & QFont::NoAntialias)
layopts |= kATSLineNoAntiAliasing;
@@ -1366,14 +1401,22 @@ void QFontEngineMac::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
for (int i = 0; i < glyphs->numGlyphs; ++i) {
glyphs->advances_x[i] = QFixed::fromReal(metrics[i].deviceAdvance.x);
glyphs->advances_y[i] = QFixed::fromReal(metrics[i].deviceAdvance.y);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ glyphs->advances_x[i] = glyphs->advances_x[i].round();
+ glyphs->advances_y[i] = glyphs->advances_y[i].round();
+ }
}
}
glyph_metrics_t QFontEngineMac::boundingBox(const QGlyphLayout &glyphs)
{
QFixed w;
- for (int i = 0; i < glyphs.numGlyphs; ++i)
- w += glyphs.effectiveAdvance(i);
+ for (int i = 0; i < glyphs.numGlyphs; ++i) {
+ w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? glyphs.effectiveAdvance(i).round()
+ : glyphs.effectiveAdvance(i);
+ }
return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0);
}
@@ -1398,39 +1441,58 @@ glyph_metrics_t QFontEngineMac::boundingBox(glyph_t glyph)
gm.xoff = QFixed::fromReal(metrics.deviceAdvance.x);
gm.yoff = QFixed::fromReal(metrics.deviceAdvance.y);
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ gm.x = gm.x.floor();
+ gm.y = gm.y.floor();
+ gm.xoff = gm.xoff.round();
+ gm.yoff = gm.yoff.round();
+ }
+
return gm;
}
QFixed QFontEngineMac::ascent() const
{
- return m_ascent;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_ascent.round()
+ : m_ascent;
}
QFixed QFontEngineMac::descent() const
{
// subtract a pixel to even out the historical +1 in QFontMetrics::height().
// Fix in Qt 5.
- return m_descent - 1;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_descent.round() - 1
+ : m_descent;
}
QFixed QFontEngineMac::leading() const
{
- return m_leading;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_leading.round()
+ : m_leading;
}
qreal QFontEngineMac::maxCharWidth() const
{
- return m_maxCharWidth;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? qRound(m_maxCharWidth)
+ : m_maxCharWidth;
}
QFixed QFontEngineMac::xHeight() const
{
- return m_xHeight;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_xHeight.round()
+ : m_xHeight;
}
QFixed QFontEngineMac::averageCharWidth() const
{
- return m_averageCharWidth;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_averageCharWidth.round()
+ : m_averageCharWidth;
}
static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path)
diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
index 136737dc78..a0593cc478 100644
--- a/src/gui/text/qfontengine_qpf.cpp
+++ b/src/gui/text/qfontengine_qpf.cpp
@@ -920,8 +920,18 @@ void QFontEngineQPF::loadGlyph(glyph_t glyph)
if (!renderingFontEngine)
return;
-
- QImage img = renderingFontEngine->alphaMapForGlyph(glyph).convertToFormat(QImage::Format_Indexed8);
+ QImage img = renderingFontEngine->alphaMapForGlyph(glyph);
+ if (img.format() != QImage::Format_Indexed8) {
+ bool mono = img.depth() == 1;
+ img = img.convertToFormat(QImage::Format_Indexed8);
+ if (mono) {
+ //### we know that 1 is opaque and 0 is transparent
+ uchar *byte = img.bits();
+ int count = img.byteCount();
+ while (count--)
+ *byte++ *= 0xff;
+ }
+ }
glyph_metrics_t metrics = renderingFontEngine->boundingBox(glyph);
renderingFontEngine->removeGlyphFromCache(glyph);
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index eea196eb4c..a805612ac4 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -213,7 +213,7 @@ void QFontEngineWin::getCMap()
unitsPerEm = otm->otmEMSquare;
x_height = (int)otm->otmsXHeight;
loadKerningPairs(designToDevice);
- _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpFullName)).toLatin1();
+ _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName)).toLatin1();
lineWidth = otm->otmsUnderscoreSize;
fsType = otm->otmfsType;
free(otm);
@@ -1037,8 +1037,8 @@ QFontEngine::Properties QFontEngineWin::properties() const
Properties p;
p.emSquare = unitsPerEm;
p.italicAngle = otm->otmItalicAngle;
- p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpFamilyName)).toLatin1();
- p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpStyleName)).toLatin1();
+ p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFamilyName)).toLatin1();
+ p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpStyleName)).toLatin1();
#ifndef QT_NO_PRINTER
p.postscriptName = QPdf::stripSpecialCharacters(p.postscriptName);
#endif
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index e455bb44f1..5163c94727 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -328,7 +328,7 @@ int QFontMetrics::height() const
{
QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
Q_ASSERT(engine != 0);
- return qRound(engine->ascent() + engine->descent()) + 1;
+ return qRound(engine->ascent()) + qRound(engine->descent()) + 1;
}
/*!
@@ -356,7 +356,7 @@ int QFontMetrics::lineSpacing() const
{
QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
Q_ASSERT(engine != 0);
- return qRound(engine->leading() + engine->ascent() + engine->descent()) + 1;
+ return qRound(engine->leading()) + qRound(engine->ascent()) + qRound(engine->descent()) + 1;
}
/*!
@@ -535,7 +535,7 @@ int QFontMetrics::width(const QString &text, int len) const
if (len == 0)
return 0;
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
return qRound(layout.width(0, len));
}
@@ -611,7 +611,7 @@ int QFontMetrics::charWidth(const QString &text, int pos) const
int from = qMax(0, pos - 8);
int to = qMin(text.length(), pos + 8);
QString cstr = QString::fromRawData(text.unicode() + from, to - from);
- QTextEngine layout(cstr, d.data());
+ QStackTextEngine layout(cstr, d.data());
layout.ignoreBidi = true;
layout.itemize();
width = qRound(layout.width(pos-from, 1));
@@ -660,7 +660,7 @@ QRect QFontMetrics::boundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, text.length());
@@ -830,7 +830,7 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
@@ -1375,7 +1375,7 @@ qreal QFontMetricsF::width(const QString &text) const
int pos = text.indexOf(QLatin1Char('\x9c'));
int len = (pos != -1) ? pos : text.length();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
return layout.width(0, len).toReal();
@@ -1452,7 +1452,7 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const
if (len == 0)
return QRectF();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, len);
@@ -1625,7 +1625,7 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
new file mode 100644
index 0000000000..c7817c6e59
--- /dev/null
+++ b/src/gui/text/qstatictext.cpp
@@ -0,0 +1,660 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstatictext.h"
+#include "qstatictext_p.h"
+#include <private/qtextengine_p.h>
+#include <private/qfontengine_p.h>
+
+#include <QtGui/qapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QStaticText
+ \brief The QStaticText class enables optimized drawing of text when the text and its layout
+ is updated rarely.
+ \since 4.7
+
+ \ingroup multimedia
+ \ingroup text
+ \mainclass
+
+ QStaticText provides a way to cache layout data for a block of text so that it can be drawn
+ more efficiently than by using QPainter::drawText() in which the layout information is
+ recalculated with every call.
+
+ The class primarily provides an optimization for cases where the text, its font and the
+ transformations on the painter are static over several paint events. If the text or its layout
+ is changed for every iteration, QPainter::drawText() is the more efficient alternative, since
+ the static text's layout would have to be recalculated to take the new state into consideration.
+
+ Translating the painter will not cause the layout of the text to be recalculated, but will cause
+ a very small performance impact on drawStaticText(). Altering any other parts of the painter's
+ transformation or the painter's font will cause the layout of the static text to be
+ recalculated. This should be avoided as often as possible to maximize the performance
+ benefit of using QStaticText.
+
+ In addition, only affine transformations are supported by drawStaticText(). Calling
+ drawStaticText() on a projected painter will perform slightly worse than using the regular
+ drawText() call, so this should be avoided.
+
+ \code
+ class MyWidget: public QWidget
+ {
+ public:
+ MyWidget(QWidget *parent = 0) : QWidget(parent), m_staticText("This is static text")
+
+ protected:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ painter.drawStaticText(0, 0, m_staticText);
+ }
+
+ private:
+ QStaticText m_staticText;
+ };
+ \endcode
+
+ The QStaticText class can be used to mimic the behavior of QPainter::drawText() to a specific
+ point with no boundaries, and also when QPainter::drawText() is called with a bounding
+ rectangle.
+
+ If a bounding rectangle is not required, create a QStaticText object without setting a preferred
+ text width. The text will then occupy a single line.
+
+ If you set a text width on the QStaticText object, this will bound the text. The text will
+ be formatted so that no line exceeds the given width. The text width set for QStaticText will
+ not automatically be used for clipping. To achieve clipping in addition to line breaks, use
+ QPainter::setClipRect(). The position of the text is decided by the argument passed to
+ QPainter::drawStaticText() and can change from call to call with a minimal impact on
+ performance.
+
+ QStaticText will attempt to guess the format of the input text using Qt::mightBeRichText().
+ To force QStaticText to display its contents as either plain text or rich text, use the
+ function QStaticText::setTextFormat() and pass in, respectively, Qt::PlainText and
+ Qt::RichText.
+
+ If it's the first time the static text is drawn, or if the static text, or the painter's font
+ or matrix have been altered since the last time it was drawn, the text's layout has to be
+ recalculated. This will impose an overhead on the QPainter::drawStaticText() call where the
+ relayout occurs. To avoid this overhead in the paint event, you can call prepare() ahead of
+ time to ensure that the layout is calculated.
+
+ \sa QPainter::drawText(), QPainter::drawStaticText(), QTextLayout, QTextDocument
+*/
+
+/*!
+ \enum QStaticText::PerformanceHint
+
+ This enum the different performance hints that can be set on the QStaticText. These hints
+ can be used to indicate that the QStaticText should use additional caches, if possible,
+ to improve performance at the expense of memory. In particular, setting the performance hint
+ AggressiveCaching on the QStaticText will improve performance when using the OpenGL graphics
+ system or when drawing to a QGLWidget.
+
+ \value ModerateCaching Do basic caching for high performance at a low memory cost.
+ \value AggressiveCaching Use additional caching when available. This may improve performance
+ at a higher memory cost.
+*/
+
+/*!
+ Constructs an empty QStaticText
+*/
+QStaticText::QStaticText()
+ : data(new QStaticTextPrivate)
+{
+}
+
+/*!
+ Constructs a QStaticText object with the given \a text and bounded by the given \a size.
+
+ If an invalid size is passed for \a size the text will be unbounded.
+*/
+QStaticText::QStaticText(const QString &text)
+ : data(new QStaticTextPrivate)
+{
+ data->text = text;
+ data->invalidate();
+}
+
+/*!
+ Constructs a QStaticText object which is a copy of \a other.
+*/
+QStaticText::QStaticText(const QStaticText &other)
+{
+ data = other.data;
+}
+
+/*!
+ Destroys the QStaticText.
+*/
+QStaticText::~QStaticText()
+{
+ Q_ASSERT(!data || data->ref >= 1);
+}
+
+/*!
+ \internal
+*/
+void QStaticText::detach()
+{
+ if (data->ref != 1)
+ data.detach();
+}
+
+/*!
+ Prepares the QStaticText object for being painted with the given \a matrix and the given \a font
+ to avoid overhead when the actual drawStaticText() call is made.
+
+ When drawStaticText() is called, the layout of the QStaticText will be recalculated if any part
+ of the QStaticText object has changed since the last time it was drawn. It will also be
+ recalculated if the painter's font or matrix are not the same as when the QStaticText was last
+ drawn.
+
+ To avoid the overhead of creating the layout the first time you draw the QStaticText after
+ making changes, you can use the prepare() function and pass in the \a matrix and \a font you
+ expect to use when drawing the text.
+
+ \sa QPainter::setFont(), QPainter::setMatrix()
+*/
+void QStaticText::prepare(const QTransform &matrix, const QFont &font)
+{
+ data->matrix = matrix;
+ data->font = font;
+ data->init();
+}
+
+
+/*!
+ Assigns \a other to this QStaticText.
+*/
+QStaticText &QStaticText::operator=(const QStaticText &other)
+{
+ data = other.data;
+ return *this;
+}
+
+/*!
+ Compares \a other to this QStaticText. Returns true if the texts, fonts and text widths
+ are equal.
+*/
+bool QStaticText::operator==(const QStaticText &other) const
+{
+ return (data == other.data
+ || (data->text == other.data->text
+ && data->font == other.data->font
+ && data->textWidth == other.data->textWidth));
+}
+
+/*!
+ Compares \a other to this QStaticText. Returns true if the texts, fonts or maximum sizes
+ are different.
+*/
+bool QStaticText::operator!=(const QStaticText &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Sets the text of the QStaticText to \a text.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa text()
+*/
+void QStaticText::setText(const QString &text)
+{
+ detach();
+ data->text = text;
+ data->invalidate();
+}
+
+/*!
+ Sets the text format of the QStaticText to \a textFormat. If \a textFormat is set to
+ Qt::AutoText (the default), the format of the text will try to be determined using the
+ function Qt::mightBeRichText(). If the text format is Qt::PlainText, then the text will be
+ displayed as is, whereas it will be interpreted as HTML if the format is Qt::RichText. HTML tags
+ that alter the font of the text, its color, or its layout are supported by QStaticText.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa textFormat(), setText(), text()
+*/
+void QStaticText::setTextFormat(Qt::TextFormat textFormat)
+{
+ detach();
+ data->textFormat = textFormat;
+ data->invalidate();
+}
+
+/*!
+ Returns the text format of the QStaticText.
+
+ \sa setTextFormat(), setText(), text()
+*/
+Qt::TextFormat QStaticText::textFormat() const
+{
+ return Qt::TextFormat(data->textFormat);
+}
+
+/*!
+ Returns the text of the QStaticText.
+
+ \sa setText()
+*/
+QString QStaticText::text() const
+{
+ return data->text;
+}
+
+/*!
+ Sets the performance hint of the QStaticText according to the \a
+ performanceHint provided. The \a performanceHint is used to
+ customize how much caching is done internally to improve
+ performance.
+
+ The default is QStaticText::ModerateCaching.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa performanceHint()
+*/
+void QStaticText::setPerformanceHint(PerformanceHint performanceHint)
+{
+ if ((performanceHint == ModerateCaching && !data->useBackendOptimizations)
+ || (performanceHint == AggressiveCaching && data->useBackendOptimizations)) {
+ return;
+ }
+ detach();
+ data->useBackendOptimizations = (performanceHint == AggressiveCaching);
+ data->invalidate();
+}
+
+/*!
+ Returns which performance hint is set for the QStaticText.
+
+ \sa setPerformanceHint()
+*/
+QStaticText::PerformanceHint QStaticText::performanceHint() const
+{
+ return data->useBackendOptimizations ? AggressiveCaching : ModerateCaching;
+}
+
+/*!
+ Sets the preferred width for this QStaticText. If the text is wider than the specified width,
+ it will be broken into multiple lines and grow vertically. If the text cannot be split into
+ multiple lines, it will be larger than the specified \a textWidth.
+
+ Setting the preferred text width to a negative number will cause the text to be unbounded.
+
+ Use size() to get the actual size of the text.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa textWidth(), size()
+*/
+void QStaticText::setTextWidth(qreal textWidth)
+{
+ detach();
+ data->textWidth = textWidth;
+ data->invalidate();
+}
+
+/*!
+ Returns the preferred width for this QStaticText.
+
+ \sa setTextWidth()
+*/
+qreal QStaticText::textWidth() const
+{
+ return data->textWidth;
+}
+
+/*!
+ Returns the size of the bounding rect for this QStaticText.
+
+ \sa textWidth()
+*/
+QSizeF QStaticText::size() const
+{
+ if (data->needsRelayout)
+ data->init();
+ return data->actualSize;
+}
+
+QStaticTextPrivate::QStaticTextPrivate()
+ : textWidth(-1.0), items(0), itemCount(0), glyphPool(0), positionPool(0),
+ needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText)
+{
+}
+
+QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other)
+ : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix),
+ items(0), itemCount(0), glyphPool(0), positionPool(0), needsRelayout(true),
+ useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat)
+{
+}
+
+QStaticTextPrivate::~QStaticTextPrivate()
+{
+ delete[] items;
+ delete[] glyphPool;
+ delete[] positionPool;
+}
+
+QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q)
+{
+ return q->data.data();
+}
+
+Q_GUI_EXPORT extern int qt_defaultDpiX();
+Q_GUI_EXPORT extern int qt_defaultDpiY();
+
+namespace {
+
+ class DrawTextItemRecorder: public QPaintEngine
+ {
+ public:
+ DrawTextItemRecorder(int expectedItemCount, QStaticTextItem *items,
+ int expectedGlyphCount, QFixedPoint *positionPool, glyph_t *glyphPool)
+ : m_items(items),
+ m_itemCount(0), m_glyphCount(0),
+ m_expectedItemCount(expectedItemCount),
+ m_expectedGlyphCount(expectedGlyphCount),
+ m_glyphPool(glyphPool),
+ m_positionPool(positionPool),
+ m_dirtyPen(false)
+ {
+ }
+
+ virtual void updateState(const QPaintEngineState &newState)
+ {
+ if (newState.state() & QPaintEngine::DirtyPen)
+ m_dirtyPen = true;
+ }
+
+ virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
+ {
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+
+ m_itemCount++;
+ m_glyphCount += ti.glyphs.numGlyphs;
+ if (m_items == 0)
+ return;
+
+ Q_ASSERT(m_itemCount <= m_expectedItemCount);
+ Q_ASSERT(m_glyphCount <= m_expectedGlyphCount);
+
+ QStaticTextItem *currentItem = (m_items + (m_itemCount - 1));
+ currentItem->fontEngine = ti.fontEngine;
+ currentItem->font = ti.font();
+ currentItem->chars = ti.chars;
+ currentItem->numChars = ti.num_chars;
+ currentItem->numGlyphs = ti.glyphs.numGlyphs;
+ currentItem->glyphs = m_glyphPool;
+ currentItem->glyphPositions = m_positionPool;
+ if (m_dirtyPen)
+ currentItem->color = state->pen().color();
+
+ QTransform matrix = state->transform();
+ matrix.translate(position.x(), position.y());
+
+ QVarLengthArray<glyph_t> glyphs;
+ QVarLengthArray<QFixedPoint> positions;
+ ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+
+ int size = glyphs.size();
+ Q_ASSERT(size == ti.glyphs.numGlyphs);
+ Q_ASSERT(size == positions.size());
+
+ memmove(currentItem->glyphs, glyphs.constData(), sizeof(glyph_t) * size);
+ memmove(currentItem->glyphPositions, positions.constData(), sizeof(QFixedPoint) * size);
+
+ m_glyphPool += size;
+ m_positionPool += size;
+ }
+
+
+ virtual bool begin(QPaintDevice *) { return true; }
+ virtual bool end() { return true; }
+ virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
+ virtual Type type() const
+ {
+ return User;
+ }
+
+ int itemCount() const
+ {
+ return m_itemCount;
+ }
+
+ int glyphCount() const
+ {
+ return m_glyphCount;
+ }
+
+ private:
+ QStaticTextItem *m_items;
+ int m_itemCount;
+ int m_glyphCount;
+ int m_expectedItemCount;
+ int m_expectedGlyphCount;
+
+ glyph_t *m_glyphPool;
+ QFixedPoint *m_positionPool;
+
+ bool m_dirtyPen;
+ };
+
+ class DrawTextItemDevice: public QPaintDevice
+ {
+ public:
+ DrawTextItemDevice(int expectedItemCount = -1, QStaticTextItem *items = 0,
+ int expectedGlyphCount = -1, QFixedPoint *positionPool = 0,
+ glyph_t *glyphPool = 0)
+ {
+ m_paintEngine = new DrawTextItemRecorder(expectedItemCount, items,
+ expectedGlyphCount, positionPool, glyphPool);
+ }
+
+ ~DrawTextItemDevice()
+ {
+ delete m_paintEngine;
+ }
+
+ int metric(PaintDeviceMetric m) const
+ {
+ int val;
+ switch (m) {
+ case PdmWidth:
+ case PdmHeight:
+ case PdmWidthMM:
+ case PdmHeightMM:
+ val = 0;
+ break;
+ case PdmDpiX:
+ case PdmPhysicalDpiX:
+ val = qt_defaultDpiX();
+ break;
+ case PdmDpiY:
+ case PdmPhysicalDpiY:
+ val = qt_defaultDpiY();
+ break;
+ case PdmNumColors:
+ val = 16777216;
+ break;
+ case PdmDepth:
+ val = 24;
+ break;
+ default:
+ val = 0;
+ qWarning("DrawTextItemDevice::metric: Invalid metric command");
+ }
+ return val;
+ }
+
+ virtual QPaintEngine *paintEngine() const
+ {
+ return m_paintEngine;
+ }
+
+ int itemCount() const
+ {
+ return m_paintEngine->itemCount();
+ }
+
+ int glyphCount() const
+ {
+ return m_paintEngine->glyphCount();
+ }
+
+ private:
+ DrawTextItemRecorder *m_paintEngine;
+ };
+}
+
+void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p)
+{
+ bool preferRichText = textFormat == Qt::RichText
+ || (textFormat == Qt::AutoText && Qt::mightBeRichText(text));
+
+ if (!preferRichText) {
+ QTextLayout textLayout;
+ textLayout.setText(text);
+ textLayout.setFont(font);
+
+ qreal leading = QFontMetricsF(font).leading();
+ qreal height = -leading;
+
+ textLayout.beginLayout();
+ while (1) {
+ QTextLine line = textLayout.createLine();
+ if (!line.isValid())
+ break;
+
+ if (textWidth >= 0.0)
+ line.setLineWidth(textWidth);
+ height += leading;
+ line.setPosition(QPointF(0.0, height));
+ height += line.height();
+ }
+ textLayout.endLayout();
+
+ actualSize = textLayout.boundingRect().size();
+ textLayout.draw(p, topLeftPosition);
+ } else {
+ QTextDocument document;
+#ifndef QT_NO_CSSPARSER
+ QColor color = p->pen().color();
+ document.setDefaultStyleSheet(QString::fromLatin1("body { color: #%1%2%3 }")
+ .arg(QString::number(color.red(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.green(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.blue(), 16), 2, QLatin1Char('0')));
+#endif
+ document.setDefaultFont(font);
+ document.setDocumentMargin(0.0);
+ if (textWidth >= 0.0)
+ document.setTextWidth(textWidth);
+#ifndef QT_NO_TEXTHTMLPARSER
+ document.setHtml(text);
+#else
+ document.setPlainText(text);
+#endif
+
+ document.adjustSize();
+ p->save();
+ p->translate(topLeftPosition);
+ document.drawContents(p);
+ p->restore();
+
+ actualSize = document.size();
+ }
+}
+
+void QStaticTextPrivate::init()
+{
+ delete[] items;
+ delete[] glyphPool;
+ delete[] positionPool;
+
+ position = QPointF(0, 0);
+
+ // Draw once to count number of items and glyphs, so that we can use as little memory
+ // as possible to store the data
+ DrawTextItemDevice counterDevice;
+ {
+ QPainter painter(&counterDevice);
+ painter.setFont(font);
+ painter.setTransform(matrix);
+
+ paintText(QPointF(0, 0), &painter);
+
+ }
+
+ itemCount = counterDevice.itemCount();
+ items = new QStaticTextItem[itemCount];
+
+ if (useBackendOptimizations) {
+ for (int i=0; i<itemCount; ++i)
+ items[i].useBackendOptimizations = true;
+ }
+
+
+ int glyphCount = counterDevice.glyphCount();
+ glyphPool = new glyph_t[glyphCount];
+ positionPool = new QFixedPoint[glyphCount];
+
+ // Draw again to actually record the items and glyphs
+ DrawTextItemDevice recorderDevice(itemCount, items, glyphCount, positionPool, glyphPool);
+ {
+ QPainter painter(&recorderDevice);
+ painter.setFont(font);
+ painter.setTransform(matrix);
+
+ paintText(QPointF(0, 0), &painter);
+ }
+
+ needsRelayout = false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
new file mode 100644
index 0000000000..f3bef93f05
--- /dev/null
+++ b/src/gui/text/qstatictext.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATICTEXT_H
+#define QSTATICTEXT_H
+
+#include <QtCore/qsize.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qmetatype.h>
+
+#include <QtGui/qtransform.h>
+#include <QtGui/qfont.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QStaticTextPrivate;
+class Q_GUI_EXPORT QStaticText
+{
+public:
+ enum PerformanceHint {
+ ModerateCaching,
+ AggressiveCaching
+ };
+
+ QStaticText();
+ QStaticText(const QString &text);
+ QStaticText(const QStaticText &other);
+ ~QStaticText();
+
+ void setText(const QString &text);
+ QString text() const;
+
+ void setTextFormat(Qt::TextFormat textFormat);
+ Qt::TextFormat textFormat() const;
+
+ void setTextWidth(qreal textWidth);
+ qreal textWidth() const;
+
+ QSizeF size() const;
+
+ void prepare(const QTransform &matrix = QTransform(), const QFont &font = QFont());
+
+ void setPerformanceHint(PerformanceHint performanceHint);
+ PerformanceHint performanceHint() const;
+
+ QStaticText &operator=(const QStaticText &);
+ bool operator==(const QStaticText &) const;
+ bool operator!=(const QStaticText &) const;
+
+private:
+ void detach();
+
+ QExplicitlySharedDataPointer<QStaticTextPrivate> data;
+ friend class QStaticTextPrivate;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QStaticText)
+
+QT_END_HEADER
+
+#endif // QSTATICTEXT_H
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
new file mode 100644
index 0000000000..f017ed1dcd
--- /dev/null
+++ b/src/gui/text/qstatictext_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATICTEXT_P_H
+#define QSTATICTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of internal files. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qtextureglyphcache_p.h>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_NAMESPACE
+
+class QStaticTextUserData
+{
+public:
+ enum Type {
+ NoUserData,
+ OpenGLUserData
+ };
+
+ QStaticTextUserData(Type t) : type(t) {}
+ virtual ~QStaticTextUserData() {}
+
+ Type type;
+};
+
+class Q_GUI_EXPORT QStaticTextItem
+{
+public:
+ QStaticTextItem() : chars(0), numChars(0), fontEngine(0), userData(0),
+ useBackendOptimizations(false), userDataNeedsUpdate(0) {}
+ ~QStaticTextItem() { delete userData; }
+
+ void setUserData(QStaticTextUserData *newUserData)
+ {
+ if (userData == newUserData)
+ return;
+
+ delete userData;
+ userData = newUserData;
+ }
+
+ QFixedPoint *glyphPositions; // 8 bytes per glyph
+ glyph_t *glyphs; // 4 bytes per glyph
+ const QChar *chars; // 2 bytes per glyph
+ // =================
+ // 14 bytes per glyph
+
+ // 12 bytes for pointers
+ int numGlyphs; // 4 bytes per item
+ int numChars; // 4 bytes per item
+ QFontEngine *fontEngine; // 4 bytes per item
+ QFont font; // 8 bytes per item
+ QColor color; // 10 bytes per item
+ QStaticTextUserData *userData; // 8 bytes per item
+ char useBackendOptimizations : 1; // 1 byte per item
+ char userDataNeedsUpdate : 1; //
+ // ================
+ // 51 bytes per item
+};
+
+class QStaticText;
+class Q_AUTOTEST_EXPORT QStaticTextPrivate
+{
+public:
+ QStaticTextPrivate();
+ QStaticTextPrivate(const QStaticTextPrivate &other);
+ ~QStaticTextPrivate();
+
+ void init();
+ void paintText(const QPointF &pos, QPainter *p);
+
+ void invalidate()
+ {
+ needsRelayout = true;
+ }
+
+ QAtomicInt ref; // 4 bytes per text
+
+ QString text; // 4 bytes per text
+ QFont font; // 8 bytes per text
+ qreal textWidth; // 8 bytes per text
+ QSizeF actualSize; // 16 bytes per text
+ QPointF position; // 16 bytes per text
+
+ QTransform matrix; // 80 bytes per text
+ QStaticTextItem *items; // 4 bytes per text
+ int itemCount; // 4 bytes per text
+ glyph_t *glyphPool; // 4 bytes per text
+ QFixedPoint *positionPool; // 4 bytes per text
+
+ unsigned char needsRelayout : 1;
+ unsigned char useBackendOptimizations : 1; // 1 byte per text
+ unsigned char textFormat : 2;
+ // ================
+ // 163 bytes per text
+
+ static QStaticTextPrivate *get(const QStaticText *q);
+};
+
+QT_END_NAMESPACE
+
+#endif // QSTATICTEXT_P_H
diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp
index 6750c093d3..e594b7e1ae 100644
--- a/src/gui/text/qsyntaxhighlighter.cpp
+++ b/src/gui/text/qsyntaxhighlighter.cpp
@@ -59,23 +59,24 @@ class QSyntaxHighlighterPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSyntaxHighlighter)
public:
- inline QSyntaxHighlighterPrivate() : rehighlightPending(false) {}
+ inline QSyntaxHighlighterPrivate()
+ : rehighlightPending(false), inReformatBlocks(false)
+ {}
QPointer<QTextDocument> doc;
void _q_reformatBlocks(int from, int charsRemoved, int charsAdded);
- void reformatBlock(QTextBlock block);
-
+ void reformatBlocks(int from, int charsRemoved, int charsAdded);
+ void reformatBlock(const 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)));
+ inReformatBlocks = true;
cursor.beginEditBlock();
int from = cursor.position();
cursor.movePosition(operation);
- _q_reformatBlocks(from, 0, cursor.position() - from);
+ reformatBlocks(from, 0, cursor.position() - from);
cursor.endEditBlock();
- QObject::connect(doc, SIGNAL(contentsChange(int,int,int)),
- q_func(), SLOT(_q_reformatBlocks(int,int,int)));
+ inReformatBlocks = false;
}
inline void _q_delayedRehighlight() {
@@ -83,17 +84,19 @@ public:
return;
rehighlightPending = false;
q_func()->rehighlight();
- return;
}
void applyFormatChanges();
QVector<QTextCharFormat> formatChanges;
QTextBlock currentBlock;
bool rehighlightPending;
+ bool inReformatBlocks;
};
void QSyntaxHighlighterPrivate::applyFormatChanges()
{
+ bool formatsChanged = false;
+
QTextLayout *layout = currentBlock.layout();
QList<QTextLayout::FormatRange> ranges = layout->additionalFormats();
@@ -101,19 +104,26 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
const int preeditAreaStart = layout->preeditAreaPosition();
const int preeditAreaLength = layout->preeditAreaText().length();
- QList<QTextLayout::FormatRange>::Iterator it = ranges.begin();
- while (it != ranges.end()) {
- if (it->start >= preeditAreaStart
- && it->start + it->length <= preeditAreaStart + preeditAreaLength)
- ++it;
- else
- it = ranges.erase(it);
+ if (preeditAreaLength != 0) {
+ QList<QTextLayout::FormatRange>::Iterator it = ranges.begin();
+ while (it != ranges.end()) {
+ if (it->start >= preeditAreaStart
+ && it->start + it->length <= preeditAreaStart + preeditAreaLength) {
+ ++it;
+ } else {
+ it = ranges.erase(it);
+ formatsChanged = true;
+ }
+ }
+ } else if (!ranges.isEmpty()) {
+ ranges.clear();
+ formatsChanged = true;
}
QTextCharFormat emptyFormat;
QTextLayout::FormatRange r;
- r.start = r.length = -1;
+ r.start = -1;
int i = 0;
while (i < formatChanges.count()) {
@@ -135,34 +145,46 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
r.length = i - r.start;
- if (r.start >= preeditAreaStart) {
- r.start += preeditAreaLength;
- } else if (r.start + r.length >= preeditAreaStart) {
- r.length += preeditAreaLength;
+ if (preeditAreaLength != 0) {
+ if (r.start >= preeditAreaStart)
+ r.start += preeditAreaLength;
+ else if (r.start + r.length >= preeditAreaStart)
+ r.length += preeditAreaLength;
}
ranges << r;
- r.start = r.length = -1;
+ formatsChanged = true;
+ r.start = -1;
}
if (r.start != -1) {
r.length = formatChanges.count() - r.start;
- if (r.start >= preeditAreaStart) {
- r.start += preeditAreaLength;
- } else if (r.start + r.length >= preeditAreaStart) {
- r.length += preeditAreaLength;
+ if (preeditAreaLength != 0) {
+ if (r.start >= preeditAreaStart)
+ r.start += preeditAreaLength;
+ else if (r.start + r.length >= preeditAreaStart)
+ r.length += preeditAreaLength;
}
ranges << r;
+ formatsChanged = true;
}
- layout->setAdditionalFormats(ranges);
+ if (formatsChanged) {
+ layout->setAdditionalFormats(ranges);
+ doc->markContentsDirty(currentBlock.position(), currentBlock.length());
+ }
}
void QSyntaxHighlighterPrivate::_q_reformatBlocks(int from, int charsRemoved, int charsAdded)
{
- Q_UNUSED(charsRemoved);
+ if (!inReformatBlocks)
+ reformatBlocks(from, charsRemoved, charsAdded);
+}
+
+void QSyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
+{
rehighlightPending = false;
QTextBlock block = doc->findBlock(from);
@@ -191,21 +213,18 @@ void QSyntaxHighlighterPrivate::_q_reformatBlocks(int from, int charsRemoved, in
formatChanges.clear();
}
-void QSyntaxHighlighterPrivate::reformatBlock(QTextBlock block)
+void QSyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block)
{
Q_Q(QSyntaxHighlighter);
Q_ASSERT_X(!currentBlock.isValid(), "QSyntaxHighlighter::reformatBlock()", "reFormatBlock() called recursively");
currentBlock = block;
- QTextBlock previous = block.previous();
formatChanges.fill(QTextCharFormat(), block.length() - 1);
q->highlightBlock(block.text());
applyFormatChanges();
- doc->markContentsDirty(block.position(), block.length());
-
currentBlock = QTextBlock();
}
@@ -349,8 +368,8 @@ void QSyntaxHighlighter::setDocument(QTextDocument *doc)
if (d->doc) {
connect(d->doc, SIGNAL(contentsChange(int,int,int)),
this, SLOT(_q_reformatBlocks(int,int,int)));
- QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight()));
d->rehighlightPending = true;
+ QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight()));
}
}
@@ -391,11 +410,16 @@ void QSyntaxHighlighter::rehighlight()
void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
{
Q_D(QSyntaxHighlighter);
- if (!d->doc)
+ if (!d->doc || !block.isValid() || block.document() != d->doc)
return;
+ const bool rehighlightPending = d->rehighlightPending;
+
QTextCursor cursor(block);
d->rehighlight(cursor, QTextCursor::EndOfBlock);
+
+ if (rehighlightPending)
+ d->rehighlightPending = rehighlightPending;
}
/*!
@@ -460,7 +484,6 @@ void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
void QSyntaxHighlighter::setFormat(int start, int count, const QTextCharFormat &format)
{
Q_D(QSyntaxHighlighter);
-
if (start < 0 || start >= d->formatChanges.count())
return;
@@ -628,7 +651,7 @@ QTextBlockUserData *QSyntaxHighlighter::currentBlockUserData() const
\since 4.4
Returns the current text block.
- */
+*/
QTextBlock QSyntaxHighlighter::currentBlock() const
{
Q_D(const QSyntaxHighlighter);
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 2206e5e241..3c596e55ed 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -91,7 +91,7 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_CONTEXTMENU
-#if defined(Q_WS_WIN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
extern bool qt_use_rtl_extensions;
#endif
#endif
@@ -441,7 +441,6 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text,
QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged()));
// convenience signal forwards
- QObject::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));
QObject::connect(doc, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool)));
QObject::connect(doc, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool)));
QObject::connect(doc, SIGNAL(modificationChanged(bool)), q, SIGNAL(modificationChanged(bool)));
@@ -452,8 +451,11 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text,
if (!document)
doc->setUndoRedoEnabled(false);
+ //Saving the index save some time.
+ static int contentsChangedIndex = QTextDocument::staticMetaObject.indexOfSignal("contentsChanged()");
+ static int textChangedIndex = QTextControl::staticMetaObject.indexOfSignal("textChanged()");
// avoid multiple textChanged() signals being emitted
- QObject::disconnect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));
+ QMetaObject::disconnect(doc, contentsChangedIndex, q, textChangedIndex);
if (!text.isEmpty()) {
// clear 'our' cursor for insertion to prevent
@@ -488,7 +490,7 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text,
}
cursor.setCharFormat(charFormatForInsertion);
- QObject::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged()));
+ QMetaObject::connect(doc, contentsChangedIndex, q, textChangedIndex);
emit q->textChanged();
if (!document)
doc->setUndoRedoEnabled(previousUndoRedoState);
@@ -846,9 +848,9 @@ void QTextControl::copy()
QApplication::clipboard()->setMimeData(data);
}
-void QTextControl::paste()
+void QTextControl::paste(QClipboard::Mode mode)
{
- const QMimeData *md = QApplication::clipboard()->mimeData();
+ const QMimeData *md = QApplication::clipboard()->mimeData(mode);
if (md)
insertFromMimeData(md);
}
@@ -1229,7 +1231,12 @@ void QTextControlPrivate::keyPressEvent(QKeyEvent *e)
q->cut();
}
else if (e == QKeySequence::Paste) {
- q->paste();
+ QClipboard::Mode mode = QClipboard::Clipboard;
+#ifdef Q_WS_X11
+ if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert)
+ mode = QClipboard::Selection;
+#endif
+ q->paste(mode);
}
#endif
else if (e == QKeySequence::Delete) {
@@ -1764,8 +1771,8 @@ void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPoint
QMenu *menu = q->createStandardContextMenu(docPos, contextWidget);
if (!menu)
return;
- menu->exec(screenPos);
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(screenPos);
#endif
}
@@ -2075,7 +2082,7 @@ QMenu *QTextControl::createStandardContextMenu(const QPointF &pos, QWidget *pare
}
#endif
-#if defined(Q_WS_WIN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
if ((d->interactionFlags & Qt::TextEditable) && qt_use_rtl_extensions) {
#else
if (d->interactionFlags & Qt::TextEditable) {
diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h
index 40507f4095..8399d5096c 100644
--- a/src/gui/text/qtextcontrol_p.h
+++ b/src/gui/text/qtextcontrol_p.h
@@ -62,6 +62,7 @@
#include <QtCore/qrect.h>
#include <QtGui/qabstracttextdocumentlayout.h>
#include <QtGui/qtextdocumentfragment.h>
+#include <QtGui/qclipboard.h>
#ifdef QT3_SUPPORT
#include <QtGui/qtextobject.h>
@@ -191,7 +192,7 @@ public Q_SLOTS:
#ifndef QT_NO_CLIPBOARD
void cut();
void copy();
- void paste();
+ void paste(QClipboard::Mode mode = QClipboard::Clipboard);
#endif
void undo();
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index c81d538937..c91df3cadf 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -1145,7 +1145,7 @@ void QTextCursor::setPosition(int pos, MoveMode m)
Returns the absolute position of the cursor within the document.
The cursor is positioned between characters.
- \sa setPosition() movePosition() anchor()
+ \sa setPosition() movePosition() anchor() positionInBlock()
*/
int QTextCursor::position() const
{
@@ -1155,6 +1155,22 @@ int QTextCursor::position() const
}
/*!
+ \since 4.7
+ Returns the relative position of the cursor within the block.
+ The cursor is positioned between characters.
+
+ This is equivalent to \c{ position() - block().position()}.
+
+ \sa position()
+*/
+int QTextCursor::positionInBlock() const
+{
+ if (!d || !d->priv)
+ return 0;
+ return d->position - d->block().position();
+}
+
+/*!
Returns the anchor position; this is the same as position() unless
there is a selection in which case position() marks one end of the
selection and anchor() marks the other end. Just like the cursor
@@ -2414,9 +2430,17 @@ int QTextCursor::blockNumber() const
return d->block().blockNumber();
}
+
/*!
\since 4.2
Returns the position of the cursor within its containing line.
+
+ Note that this is the column number relative to a wrapped line,
+ not relative to the block (i.e. the paragraph).
+
+ You probably want to call positionInBlock() instead.
+
+ \sa positionInBlock()
*/
int QTextCursor::columnNumber() const
{
diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h
index 38bc39d240..3e968a31fd 100644
--- a/src/gui/text/qtextcursor.h
+++ b/src/gui/text/qtextcursor.h
@@ -89,6 +89,7 @@ public:
void setPosition(int pos, MoveMode mode = MoveAnchor);
int position() const;
+ int positionInBlock() const;
int anchor() const;
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index f5d322a998..3e556a733e 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -61,6 +61,7 @@
#include <qapplication.h>
#include "qtextcontrol_p.h"
#include "private/qtextedit_p.h"
+#include "private/qdataurl_p.h"
#include "qtextdocument_p.h"
#include <private/qprinter_p.h>
@@ -434,6 +435,30 @@ void QTextDocument::redo(QTextCursor *cursor)
}
}
+/*! \enum QTextDocument::Stacks
+
+ \value UndoStack The undo stack.
+ \value RedoStack The redo stack.
+ \value UndoAndRedoStacks Both the undo and redo stacks.
+*/
+
+/*!
+ \since 4.7
+ Clears the stacks specified by \a stacksToClear.
+
+ This method clears any commands on the undo stack, the redo stack,
+ or both (the default). If commands are cleared, the appropriate
+ signals are emitted, QTextDocument::undoAvailable() or
+ QTextDocument::redoAvailable().
+
+ \sa QTextDocument::undoAvailable() QTextDocument::redoAvailable()
+*/
+void QTextDocument::clearUndoRedoStacks(Stacks stacksToClear)
+{
+ Q_D(QTextDocument);
+ d->clearUndoRedoStacks(stacksToClear, true);
+}
+
/*!
\overload
@@ -1749,9 +1774,9 @@ void QTextDocument::print(QPrinter *printer) const
int pageCopies;
if (printer->collateCopies() == true){
docCopies = 1;
- pageCopies = printer->numCopies();
+ pageCopies = printer->supportsMultipleCopies() ? 1 : printer->copyCount();
} else {
- docCopies = printer->numCopies();
+ docCopies = printer->supportsMultipleCopies() ? 1 : printer->copyCount();
pageCopies = 1;
}
@@ -1924,6 +1949,10 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name)
}
#endif
+ // handle data: URLs
+ if (r.isNull() && name.scheme() == QLatin1String("data"))
+ r = qDecodeDataUrl(name).second;
+
// if resource was not loaded try to load it here
if (!doc && r.isNull() && name.isRelative()) {
QUrl currentURL = d->url;
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index b5bcb41277..0140772e1d 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -256,6 +256,13 @@ public:
void undo(QTextCursor *cursor);
void redo(QTextCursor *cursor);
+ enum Stacks {
+ UndoStack = 0x01,
+ RedoStack = 0x02,
+ UndoAndRedoStacks = UndoStack | RedoStack
+ };
+ void clearUndoRedoStacks(Stacks historyToClear = UndoAndRedoStacks);
+
int maximumBlockCount() const;
void setMaximumBlockCount(int maximum);
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 372b9dc3e2..e2bca04d8c 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
// 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 }
+ QTextUndoCommand c = { a1, a2, 0, 0, quint8(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
@@ -259,8 +259,7 @@ void QTextDocumentPrivate::clear()
objects.clear();
title.clear();
- undoState = 0;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks);
text = QString();
unreachableCharacterCount = 0;
modifiedState = 0;
@@ -292,7 +291,7 @@ QTextDocumentPrivate::~QTextDocumentPrivate()
cursors.clear();
undoState = 0;
undoEnabled = true;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
}
void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
@@ -871,6 +870,7 @@ int QTextDocumentPrivate::undoRedo(bool undo)
undoEnabled = false;
beginEditBlock();
int editPos = -1;
+ int editLength = -1;
while (1) {
if (undo)
--undoState;
@@ -883,12 +883,16 @@ int QTextDocumentPrivate::undoRedo(bool undo)
PMDEBUG(" erase: from %d, length %d", c.pos, c.length);
c.command = QTextUndoCommand::Removed;
editPos = c.pos;
+ editLength = 0;
break;
case QTextUndoCommand::Removed:
PMDEBUG(" insert: format %d (from %d, length %d, strpos=%d)", c.format, c.pos, c.length, c.strPos);
insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation);
c.command = QTextUndoCommand::Inserted;
- editPos = c.pos + c.length;
+ if (editPos != (int)c.pos)
+ editLength = 0;
+ editPos = c.pos;
+ editLength += c.length;
break;
case QTextUndoCommand::BlockInserted:
case QTextUndoCommand::BlockAdded:
@@ -899,6 +903,7 @@ int QTextDocumentPrivate::undoRedo(bool undo)
else
c.command = QTextUndoCommand::BlockDeleted;
editPos = c.pos;
+ editLength = 0;
break;
case QTextUndoCommand::BlockRemoved:
case QTextUndoCommand::BlockDeleted:
@@ -909,7 +914,10 @@ int QTextDocumentPrivate::undoRedo(bool undo)
c.command = QTextUndoCommand::BlockInserted;
else
c.command = QTextUndoCommand::BlockAdded;
- editPos = c.pos + 1;
+ if (editPos != (int)c.pos)
+ editLength = 0;
+ editPos = c.pos;
+ editLength += 1;
break;
case QTextUndoCommand::CharFormatChanged: {
resetBlockRevision = -1; // ## TODO
@@ -920,7 +928,10 @@ int QTextDocumentPrivate::undoRedo(bool undo)
int oldFormat = it.value()->format;
setCharFormat(c.pos, c.length, formats.charFormat(c.format));
c.format = oldFormat;
- editPos = c.pos + c.length;
+ if (editPos != (int)c.pos)
+ editLength = 0;
+ editPos = c.pos;
+ editLength += c.length;
break;
}
case QTextUndoCommand::BlockFormatChanged: {
@@ -988,13 +999,19 @@ int QTextDocumentPrivate::undoRedo(bool undo)
break;
}
undoEnabled = true;
- if (editPos < 0 && docChangeFrom >= 0) {
- editPos = qMin(docChangeFrom + docChangeLength, length() - 1);
- }
+
+ int newCursorPos = -1;
+
+ if (editPos >=0)
+ newCursorPos = editPos + editLength;
+ else if (docChangeFrom >= 0)
+ newCursorPos= qMin(docChangeFrom + docChangeLength, length() - 1);
+
endEditBlock();
emitUndoAvailable(isUndoAvailable());
emitRedoAvailable(isRedoAvailable());
- return editPos;
+
+ return newCursorPos;
}
/*!
@@ -1027,7 +1044,7 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
if (!undoEnabled)
return;
if (undoState < undoStack.size())
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
if (!undoStack.isEmpty() && modified) {
QTextUndoCommand &last = undoStack[undoState - 1];
@@ -1050,26 +1067,46 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
emit document()->undoCommandAdded();
}
-void QTextDocumentPrivate::truncateUndoStack()
+void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear,
+ bool emitSignals)
{
- if (undoState == undoStack.size())
- return;
-
- for (int i = undoState; i < undoStack.size(); ++i) {
- QTextUndoCommand c = undoStack[i];
- if (c.command & QTextUndoCommand::Removed) {
- // ########
-// QTextFragment *f = c.fragment_list;
-// while (f) {
-// QTextFragment *n = f->right;
-// delete f;
-// f = n;
-// }
- } else if (c.command & QTextUndoCommand::Custom) {
- delete c.custom;
+ bool undoCommandsAvailable = undoState != 0;
+ bool redoCommandsAvailable = undoState != undoStack.size();
+ if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
+ for (int i = 0; i < undoState; ++i) {
+ QTextUndoCommand c = undoStack[undoState];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
}
+ undoStack.remove(0, undoState);
+ undoStack.resize(undoStack.size() - undoState);
+ undoState = 0;
+ if (emitSignals)
+ emitUndoAvailable(false);
+ } else if (stacksToClear == QTextDocument::RedoStack
+ && redoCommandsAvailable) {
+ for (int i = undoState; i < undoStack.size(); ++i) {
+ QTextUndoCommand c = undoStack[i];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
+ }
+ undoStack.resize(undoState);
+ if (emitSignals)
+ emitRedoAvailable(false);
+ } else if (stacksToClear == QTextDocument::UndoAndRedoStacks
+ && !undoStack.isEmpty()) {
+ for (int i = 0; i < undoStack.size(); ++i) {
+ QTextUndoCommand c = undoStack[i];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
+ }
+ undoState = 0;
+ undoStack.resize(0);
+ if (emitSignals && undoCommandsAvailable)
+ emitUndoAvailable(false);
+ if (emitSignals && redoCommandsAvailable)
+ emitRedoAvailable(false);
}
- undoStack.resize(undoState);
}
void QTextDocumentPrivate::emitUndoAvailable(bool available)
@@ -1097,7 +1134,7 @@ void QTextDocumentPrivate::enableUndoRedo(bool enable)
if (!enable) {
undoState = 0;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
emitUndoAvailable(false);
emitRedoAvailable(false);
}
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index 4ecc2fa6cf..ac5ed3c86e 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -252,10 +252,11 @@ public:
inline QFont defaultFont() const { return formats.defaultFont(); }
inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); }
+ void clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, bool emitSignals = false);
+
private:
bool split(int pos);
bool unite(uint f);
- void truncateUndoStack();
void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op);
int insert_block(int pos, uint strPos, int format, int blockformat, QTextUndoCommand::Operation op, int command);
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 76eb34039c..d34553f13e 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1124,14 +1124,13 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
bool kerningEnabled = this->font(si).d->kerning;
HB_ShaperItem entire_shaper_item;
- entire_shaper_item.kerning_applied = false;
+ qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item));
entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(layoutData->string.constData());
entire_shaper_item.stringLength = layoutData->string.length();
entire_shaper_item.item.script = (HB_Script)si.analysis.script;
entire_shaper_item.item.pos = si.position;
entire_shaper_item.item.length = length(item);
entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;
- entire_shaper_item.glyphIndicesPresent = false;
HB_UChar16 upperCased[256]; // XXX what about making this 4096, so we don't have to extend it ever.
if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
@@ -1299,10 +1298,10 @@ QTextEngine::QTextEngine()
}
QTextEngine::QTextEngine(const QString &str, const QFont &f)
- : fnt(f)
+ : text(str),
+ fnt(f)
{
init(this);
- text = str;
}
QTextEngine::~QTextEngine()
@@ -2467,7 +2466,7 @@ void QTextEngine::splitItem(int item, int pos) const
if (pos <= 0)
return;
- layoutData->items.insert(item + 1, QScriptItem(layoutData->items[item]));
+ layoutData->items.insert(item + 1, layoutData->items[item]);
QScriptItem &oldItem = layoutData->items[item];
QScriptItem &newItem = layoutData->items[item+1];
newItem.position += pos;
@@ -2610,10 +2609,9 @@ void QTextEngine::resolveAdditionalFormats() const
}
QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f)
- : _layoutData(string, _memory, MemSize)
+ : QTextEngine(string, f),
+ _layoutData(string, _memory, MemSize)
{
- fnt = f;
- text = string;
stackEngine = true;
layoutData = &_layoutData;
}
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index f36cbd2619..5054b66941 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -382,6 +382,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine
QFixed y;
QFixed width;
QFixed textWidth;
+ QFixed textAdvance;
int from;
signed int length : 29;
mutable uint justified : 1;
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 3c0e85ec91..ce7915d8e9 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -305,7 +305,7 @@ Qt::LayoutDirection QTextInlineObject::textDirection() const
Once the layout is done, these lines can be drawn on a paint
device.
- Here's some pseudo code that presents the layout phase:
+ Here's some code snippet that presents the layout phase:
\snippet doc/src/snippets/code/src_gui_text_qtextlayout.cpp 0
The text can be drawn by calling the layout's draw() function:
@@ -1570,6 +1570,20 @@ qreal QTextLine::naturalTextWidth() const
return eng->lines[i].textWidth.toReal();
}
+/*! \since 4.7
+ Returns the horizontal advance of the text. The advance of the text
+ is the distance from its position to the next position at which
+ text would naturally be drawn.
+
+ By adding the advance to the position of the text line and using this
+ as the position of a second text line, you will be able to position
+ the two lines side-by-side without gaps in-between.
+*/
+qreal QTextLine::horizontalAdvance() const
+{
+ return eng->lines[i].textAdvance.toReal();
+}
+
/*!
Lays out the line with the given \a width. The line is filled from
its starting position with as many characters as will fit into
@@ -1928,6 +1942,7 @@ void QTextLine::layout_helper(int maxGlyphs)
found:
if (lbh.rightBearing > 0) // If right bearing has not yet been adjusted
lbh.adjustRightBearing();
+ line.textAdvance = line.textWidth;
line.textWidth -= qMin(QFixed(), lbh.rightBearing);
if (line.length == 0) {
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index edae7decde..8c93ed65b6 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -202,6 +202,7 @@ public:
bool leadingIncluded() const;
qreal naturalTextWidth() const;
+ qreal horizontalAdvance() const;
QRectF naturalTextRect() const;
enum Edge {
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index d369bff002..7992de515c 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -493,10 +493,10 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat
format.nonBreakableLines() ? QString::fromLatin1("true") : QString::fromLatin1("false"));
if (format.hasProperty(QTextFormat::TabPositions)) {
QList<QTextOption::Tab> tabs = format.tabPositions();
- writer.writeStartElement(styleNS, QString::fromLatin1("style-tab-stops"));
+ writer.writeStartElement(styleNS, QString::fromLatin1("tab-stops"));
QList<QTextOption::Tab>::Iterator iterator = tabs.begin();
while(iterator != tabs.end()) {
- writer.writeEmptyElement(styleNS, QString::fromLatin1("style-tab-stop"));
+ writer.writeEmptyElement(styleNS, QString::fromLatin1("tab-stop"));
writer.writeAttribute(styleNS, QString::fromLatin1("position"), pixelToPoint(iterator->position) );
QString type;
switch(iterator->type) {
@@ -511,7 +511,7 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat
++iterator;
}
- writer.writeEndElement(); // style-tab-stops
+ writer.writeEndElement(); // tab-stops
}
writer.writeEndElement(); // paragraph-properties
@@ -698,11 +698,11 @@ void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCe
if (padding > 0)
writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding));
if (format.bottomPadding() > 0)
- writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(format.bottomPadding()));
+ writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"), pixelToPoint(format.bottomPadding()));
if (format.leftPadding() > 0)
- writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(format.leftPadding()));
+ writer.writeAttribute(foNS, QString::fromLatin1("padding-left"), pixelToPoint(format.leftPadding()));
if (format.rightPadding() > 0)
- writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(format.rightPadding()));
+ writer.writeAttribute(foNS, QString::fromLatin1("padding-right"), pixelToPoint(format.rightPadding()));
}
if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index d30c996014..6f099a979a 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -280,6 +280,21 @@ static QFile::Permissions modeToPermissions(quint32 mode)
return ret;
}
+static QDateTime readMSDosDate(const uchar *src)
+{
+ uint dosDate = readUInt(src);
+ quint64 uDate;
+ uDate = (quint64)(dosDate >> 16);
+ uint tm_mday = (uDate & 0x1f);
+ uint tm_mon = ((uDate & 0x1E0) >> 5);
+ uint tm_year = (((uDate & 0x0FE00) >> 9) + 1980);
+ uint tm_hour = ((dosDate & 0xF800) >> 11);
+ uint tm_min = ((dosDate & 0x7E0) >> 5);
+ uint tm_sec = ((dosDate & 0x1f) << 1);
+
+ return QDateTime(QDate(tm_year, tm_mon, tm_mday), QTime(tm_hour, tm_min, tm_sec));
+}
+
struct LocalFileHeader
{
uchar signature[4]; // 0x04034b50
@@ -343,7 +358,7 @@ struct FileHeader
};
QZipReader::FileInfo::FileInfo()
- : isDir(false), isFile(true), isSymLink(false), crc32(0), size(0)
+ : isDir(false), isFile(false), isSymLink(false), crc32(0), size(0)
{
}
@@ -365,9 +380,15 @@ QZipReader::FileInfo& QZipReader::FileInfo::operator=(const FileInfo &other)
permissions = other.permissions;
crc32 = other.crc32;
size = other.size;
+ lastModified = other.lastModified;
return *this;
}
+bool QZipReader::FileInfo::isValid() const
+{
+ return isDir || isFile || isSymLink;
+}
+
class QZipPrivate
{
public:
@@ -403,6 +424,7 @@ void QZipPrivate::fillFileInfo(int index, QZipReader::FileInfo &fileInfo) const
fileInfo.permissions = modeToPermissions(mode);
fileInfo.crc32 = readUInt(header.h.crc_32);
fileInfo.size = readUInt(header.h.uncompressed_size);
+ fileInfo.lastModified = readMSDosDate(header.h.last_mod_file);
}
class QZipReaderPrivate : public QZipPrivate
@@ -750,6 +772,14 @@ QZipReader::~QZipReader()
}
/*!
+ Returns device used for reading zip archive.
+*/
+QIODevice* QZipReader::device() const
+{
+ return d->device;
+}
+
+/*!
Returns true if the user can read the file; otherwise returns false.
*/
bool QZipReader::isReadable() const
@@ -796,6 +826,7 @@ int QZipReader::count() const
/*!
Returns a FileInfo of an entry in the zipfile.
The \a index is the index into the directoy listing of the zipfile.
+ Returns an invalid FileInfo if \a index is out of boundaries.
\sa fileInfoList()
*/
@@ -803,7 +834,8 @@ QZipReader::FileInfo QZipReader::entryInfoAt(int index) const
{
d->scanFiles();
QZipReader::FileInfo fi;
- d->fillFileInfo(index, fi);
+ if (index >= 0 && index < d->fileHeaders.count())
+ d->fillFileInfo(index, fi);
return fi;
}
@@ -1022,6 +1054,14 @@ QZipWriter::~QZipWriter()
}
/*!
+ Returns device used for writing zip archive.
+*/
+QIODevice* QZipWriter::device() const
+{
+ return d->device;
+}
+
+/*!
Returns true if the user can write to the archive; otherwise returns false.
*/
bool QZipWriter::isWritable() const
diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h
index 67a2ace547..6466a7b37b 100644
--- a/src/gui/text/qzipreader_p.h
+++ b/src/gui/text/qzipreader_p.h
@@ -55,6 +55,7 @@
// We mean it.
//
+#include <QtCore/qdatetime.h>
#include <QtCore/qfile.h>
#include <QtCore/qstring.h>
@@ -62,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QZipReaderPrivate;
-class Q_AUTOTEST_EXPORT QZipReader
+class Q_GUI_EXPORT QZipReader
{
public:
QZipReader(const QString &fileName, QIODevice::OpenMode mode = QIODevice::ReadOnly );
@@ -70,15 +71,18 @@ public:
explicit QZipReader(QIODevice *device);
~QZipReader();
+ QIODevice* device() const;
+
bool isReadable() const;
bool exists() const;
- struct Q_AUTOTEST_EXPORT FileInfo
+ struct Q_GUI_EXPORT FileInfo
{
FileInfo();
FileInfo(const FileInfo &other);
~FileInfo();
FileInfo &operator=(const FileInfo &other);
+ bool isValid() const;
QString filePath;
uint isDir : 1;
uint isFile : 1;
@@ -86,6 +90,7 @@ public:
QFile::Permissions permissions;
uint crc32;
qint64 size;
+ QDateTime lastModified;
void *d;
};
diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h
index 9322f4ad7e..a50c1727bb 100644
--- a/src/gui/text/qzipwriter_p.h
+++ b/src/gui/text/qzipwriter_p.h
@@ -69,6 +69,8 @@ public:
explicit QZipWriter(QIODevice *device);
~QZipWriter();
+ QIODevice* device() const;
+
bool isWritable() const;
bool exists() const;
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index b7615a43e8..9ec314299c 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -37,7 +37,9 @@ HEADERS += \
text/qtexttable_p.h \
text/qzipreader_p.h \
text/qzipwriter_p.h \
- text/qtextodfwriter_p.h
+ text/qtextodfwriter_p.h \
+ text/qstatictext_p.h \
+ text/qstatictext.h
SOURCES += \
text/qfont.cpp \
@@ -66,7 +68,8 @@ SOURCES += \
text/qsyntaxhighlighter.cpp \
text/qcssparser.cpp \
text/qzip.cpp \
- text/qtextodfwriter.cpp
+ text/qtextodfwriter.cpp \
+ text/qstatictext.cpp
win32 {
SOURCES += \
diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp
index cefdb27c6d..8e7ec80d6e 100644
--- a/src/gui/util/qcompleter.cpp
+++ b/src/gui/util/qcompleter.cpp
@@ -62,7 +62,7 @@
\snippet doc/src/snippets/code/src_gui_util_qcompleter.cpp 0
- A QDirModel can be used to provide auto completion of file names.
+ A QFileSystemModel can be used to provide auto completion of file names.
For example:
\snippet doc/src/snippets/code/src_gui_util_qcompleter.cpp 1
@@ -120,7 +120,7 @@
completion is then performed one level at a time.
Let's take the example of a user typing in a file system path.
- The model is a (hierarchical) QDirModel. The completion
+ The model is a (hierarchical) QFileSystemModel. The completion
occurs for every element in the path. For example, if the current
text is \c C:\Wind, QCompleter might suggest \c Windows to
complete the current path element. Similarly, if the current text
@@ -130,12 +130,12 @@
split the path into a list of strings that are matched at each level.
For \c C:\Windows\Sy, it needs to be split as "C:", "Windows" and "Sy".
The default implementation of splitPath(), splits the completionPrefix
- using QDir::separator() if the model is a QDirModel.
+ using QDir::separator() if the model is a QFileSystemModel.
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}
- for list models and the absolute file path if the mode is a QDirModel.
+ for list models and the absolute file path if the mode is a QFileSystemModel.
\sa QAbstractItemModel, QLineEdit, QComboBox, {Completer Example}
*/
@@ -147,6 +147,7 @@
#include "QtGui/qscrollbar.h"
#include "QtGui/qstringlistmodel.h"
#include "QtGui/qdirmodel.h"
+#include "QtGui/qfilesystemmodel.h"
#include "QtGui/qheaderview.h"
#include "QtGui/qlistview.h"
#include "QtGui/qapplication.h"
@@ -470,9 +471,13 @@ QMatchData QCompletionEngine::filterHistory()
QAbstractItemModel *source = c->proxy->sourceModel();
if (curParts.count() <= 1 || c->proxy->showAll || !source)
return QMatchData();
- bool dirModel = false;
+ bool isDirModel = false;
+ bool isFsModel = false;
#ifndef QT_NO_DIRMODEL
- dirModel = (qobject_cast<QDirModel *>(source) != 0);
+ isDirModel = (qobject_cast<QDirModel *>(source) != 0);
+#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+ isFsModel = (qobject_cast<QFileSystemModel *>(source) != 0);
#endif
QVector<int> v;
QIndexMapper im(v);
@@ -482,7 +487,7 @@ QMatchData QCompletionEngine::filterHistory()
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)) && !defined(Q_OS_SYMBIAN)
- && (!dirModel || QDir::toNativeSeparators(str) != QDir::separator())
+ && ((!isFsModel && !isDirModel) || QDir::toNativeSeparators(str) != QDir::separator())
#endif
)
m.indices.append(i);
@@ -838,6 +843,13 @@ void QCompleterPrivate::_q_complete(QModelIndex index, bool highlighted)
completion += QDir::separator();
}
#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+ // add a trailing separator in inline
+ if (mode == QCompleter::InlineCompletion) {
+ if (qobject_cast<QFileSystemModel *>(proxy->sourceModel()) && QFileInfo(completion).isDir())
+ completion += QDir::separator();
+ }
+#endif
}
if (highlighted) {
@@ -891,6 +903,14 @@ void QCompleterPrivate::showPopup(const QRect& rect)
popup->show();
}
+void QCompleterPrivate::_q_fileSystemModelDirectoryLoaded(const QString &path)
+{
+ Q_Q(QCompleter);
+ //the path given by QFileSystemModel does not end with /
+ if (!q->completionPrefix().isEmpty() && q->completionPrefix() != path + QLatin1Char('/'))
+ q->complete();
+}
+
/*!
Constructs a completer object with the given \a parent.
*/
@@ -971,7 +991,7 @@ QWidget *QCompleter::widget() const
be list model or a tree model. If a model has been already previously set
and it has the QCompleter as its parent, it is deleted.
- For convenience, if \a model is a QDirModel, QCompleter switches its
+ For convenience, if \a model is a QFileSystemModel, QCompleter switches its
caseSensitivity to Qt::CaseInsensitive on Windows and Qt::CaseSensitive
on other platforms.
@@ -995,6 +1015,18 @@ void QCompleter::setModel(QAbstractItemModel *model)
#endif
}
#endif // QT_NO_DIRMODEL
+#ifndef QT_NO_FILESYSTEMMODEL
+ QFileSystemModel *fsModel = qobject_cast<QFileSystemModel *>(model);
+ if (fsModel) {
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
+ setCaseSensitivity(Qt::CaseInsensitive);
+#else
+ setCaseSensitivity(Qt::CaseSensitive);
+#endif
+ setCompletionRole(QFileSystemModel::FileNameRole);
+ connect(fsModel, SIGNAL(directoryLoaded(QString)), this, SLOT(_q_fileSystemModelDirectoryLoaded(QString)));
+ }
+#endif // QT_NO_FILESYSTEMMODEL
}
/*!
@@ -1078,7 +1110,7 @@ void QCompleter::setPopup(QAbstractItemView *popup)
delete d->popup;
if (popup->model() != d->proxy)
popup->setModel(d->proxy);
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA)
popup->show();
#else
popup->hide();
@@ -1626,10 +1658,11 @@ QAbstractItemModel *QCompleter::completionModel() const
The default implementation returns the \l{Qt::EditRole}{edit role} of the
item for list models. It returns the absolute file path if the model is a
- QDirModel.
+ QFileSystemModel.
\sa splitPath()
*/
+
QString QCompleter::pathFromIndex(const QModelIndex& index) const
{
Q_D(const QCompleter);
@@ -1639,16 +1672,27 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const
QAbstractItemModel *sourceModel = d->proxy->sourceModel();
if (!sourceModel)
return QString();
+ bool isDirModel = false;
+ bool isFsModel = false;
#ifndef QT_NO_DIRMODEL
- QDirModel *dirModel = qobject_cast<QDirModel *>(sourceModel);
- if (!dirModel)
+ isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != 0;
#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+ isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != 0;
+#endif
+ if (!isDirModel && !isFsModel)
return sourceModel->data(index, d->role).toString();
QModelIndex idx = index;
QStringList list;
do {
- QString t = sourceModel->data(idx, Qt::EditRole).toString();
+ QString t;
+ if (isDirModel)
+ t = sourceModel->data(idx, Qt::EditRole).toString();
+#ifndef QT_NO_FILESYSTEMMODEL
+ else
+ t = sourceModel->data(idx, QFileSystemModel::FileNameRole).toString();
+#endif
list.prepend(t);
QModelIndex parent = idx.parent();
idx = parent.sibling(parent.row(), index.column());
@@ -1668,7 +1712,7 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const
in the model().
The default implementation of splitPath() splits a file system path based on
- QDir::separator() when the sourceModel() is a QDirModel.
+ QDir::separator() when the sourceModel() is a QFileSystemModel.
When used with list models, the first item in the returned list is used for
matching.
@@ -1678,12 +1722,19 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const
QStringList QCompleter::splitPath(const QString& path) const
{
bool isDirModel = false;
+ bool isFsModel = false;
#ifndef QT_NO_DIRMODEL
Q_D(const QCompleter);
isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != 0;
#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+#ifdef QT_NO_DIRMODEL
+ Q_D(const QCompleter);
+#endif
+ isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != 0;
+#endif
- if (!isDirModel || path.isEmpty())
+ if ((!isDirModel && !isFsModel) || path.isEmpty())
return QStringList(completionPrefix());
QString pathCopy = QDir::toNativeSeparators(path);
diff --git a/src/gui/util/qcompleter.h b/src/gui/util/qcompleter.h
index 5123a40432..0cef9be3bc 100644
--- a/src/gui/util/qcompleter.h
+++ b/src/gui/util/qcompleter.h
@@ -159,6 +159,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_complete(QModelIndex))
Q_PRIVATE_SLOT(d_func(), void _q_completionSelected(const QItemSelection&))
Q_PRIVATE_SLOT(d_func(), void _q_autoResizePopup())
+ Q_PRIVATE_SLOT(d_func(), void _q_fileSystemModelDirectoryLoaded(const QString&))
};
#endif // QT_NO_COMPLETER
diff --git a/src/gui/util/qcompleter_p.h b/src/gui/util/qcompleter_p.h
index 44be4c0204..8f00793856 100644
--- a/src/gui/util/qcompleter_p.h
+++ b/src/gui/util/qcompleter_p.h
@@ -98,6 +98,7 @@ public:
void _q_complete(QModelIndex, bool = false);
void _q_completionSelected(const QItemSelection&);
void _q_autoResizePopup();
+ void _q_fileSystemModelDirectoryLoaded(const QString &path);
void setCurrentIndex(QModelIndex, bool = true);
};
diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp
index 39240e6a37..a415180fb9 100644
--- a/src/gui/util/qdesktopservices_s60.cpp
+++ b/src/gui/util/qdesktopservices_s60.cpp
@@ -415,11 +415,11 @@ QString QDesktopServices::storageLocation(StandardLocation type)
//return QDir::homePath(); break;
break;
case DataLocation:
- CEikonEnv::Static()->FsSession().PrivatePath(path);
+ qt_s60GetRFs().PrivatePath(path);
path.Insert(0, writableExeDrive().Name());
break;
case CacheLocation:
- CEikonEnv::Static()->FsSession().PrivatePath(path);
+ qt_s60GetRFs().PrivatePath(path);
path.Insert(0, writableExeDrive().Name());
path.Append(KCacheSubDir);
break;
diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp
index 9f3b6e1e9e..aab7e16631 100644
--- a/src/gui/util/qdesktopservices_win.cpp
+++ b/src/gui/util/qdesktopservices_win.cpp
@@ -59,7 +59,7 @@
# endif
#endif
-#if defined(Q_CC_MINGW) && !defined(CSIDL_MYMUSIC)
+#ifndef CSIDL_MYMUSIC
#define CSIDL_MYMUSIC 13
#define CSIDL_MYVIDEO 14
#endif
@@ -97,19 +97,19 @@ static bool launchWebBrowser(const QUrl &url)
if (url.scheme() == QLatin1String("mailto")) {
//Retrieve the commandline for the default mail client
//the default key used below is the command line for the mailto: shell command
- DWORD bufferSize = 2 * MAX_PATH;
+ DWORD bufferSize = sizeof(wchar_t) * MAX_PATH;
long returnValue = -1;
QString command;
HKEY handle;
LONG res;
- wchar_t keyValue[2 * MAX_PATH] = {0};
+ wchar_t keyValue[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);
+ res = RegOpenKeyEx(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)
@@ -121,8 +121,8 @@ static bool launchWebBrowser(const QUrl &url)
if (res != ERROR_SUCCESS)
return false;
- bufferSize = 2 * MAX_PATH;
- returnValue = RegQueryValueExW(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
+ bufferSize = sizeof(wchar_t) * MAX_PATH;
+ returnValue = RegQueryValueEx(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
if (!returnValue)
command = QString::fromRawData((QChar*)keyValue, bufferSize);
RegCloseKey(handle);
diff --git a/src/gui/util/qsystemtrayicon_mac.mm b/src/gui/util/qsystemtrayicon_mac.mm
index d829947054..d943c8ca0e 100644
--- a/src/gui/util/qsystemtrayicon_mac.mm
+++ b/src/gui/util/qsystemtrayicon_mac.mm
@@ -93,6 +93,7 @@ extern bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret); //q
extern void qtsystray_sendActivated(QSystemTrayIcon *i, int r); //qsystemtrayicon.cpp
extern NSString *keySequenceToKeyEqivalent(const QKeySequence &accel); // qmenu_mac.mm
extern NSUInteger keySequenceModifierMask(const QKeySequence &accel); // qmenu_mac.mm
+extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum);
QT_END_NAMESPACE
QT_USE_NAMESPACE
@@ -110,7 +111,7 @@ QT_USE_NAMESPACE
-(QSystemTrayIcon*)icon;
-(NSStatusItem*)item;
-(QRectF)geometry;
-- (void)triggerSelector:(id)sender;
+- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton;
- (void)doubleClickSelector:(id)sender;
@end
@@ -121,7 +122,7 @@ QT_USE_NAMESPACE
-(id)initWithParent:(QNSStatusItem*)myParent;
-(QSystemTrayIcon*)icon;
-(void)menuTrackingDone:(NSNotification*)notification;
--(void)mousePressed:(NSEvent *)mouseEvent;
+-(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton;
@end
@@ -333,12 +334,10 @@ QT_END_NAMESPACE
[self setNeedsDisplay:YES];
}
--(void)mousePressed:(NSEvent *)mouseEvent
+-(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton
{
- int clickCount = [mouseEvent clickCount];
- down = !down;
- if(!down && [self icon]->contextMenu())
- [self icon]->contextMenu()->hide();
+ down = YES;
+ int clickCount = [mouseEvent clickCount];
[self setNeedsDisplay:YES];
#ifndef QT_MAC_USE_COCOA
@@ -348,47 +347,52 @@ QT_END_NAMESPACE
const short scale = hgt - 4;
#endif
- if( down && ![self icon]->icon().isNull() ) {
+ if (![self icon]->icon().isNull() ) {
NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage([self icon]->icon().pixmap(QSize(scale, scale), QIcon::Selected)));
[self setImage: nsaltimage];
[nsaltimage release];
}
-
- if (down)
- [parent triggerSelector:self];
- else if ((clickCount%2))
+ if ((clickCount == 2)) {
+ [self menuTrackingDone:nil];
[parent doubleClickSelector:self];
- while (down) {
- mouseEvent = [[self window] nextEventMatchingMask:NSLeftMouseDownMask | NSLeftMouseUpMask
- | NSLeftMouseDraggedMask | NSRightMouseDownMask | NSRightMouseUpMask
- | NSRightMouseDraggedMask];
- switch ([mouseEvent type]) {
- case NSRightMouseDown:
- case NSRightMouseUp:
- case NSLeftMouseDown:
- case NSLeftMouseUp:
- [self menuTrackingDone:nil];
- break;
- case NSRightMouseDragged:
- case NSLeftMouseDragged:
- default:
- /* Ignore any other kind of event. */
- break;
- }
- };
+ } else {
+ [parent triggerSelector:self button:mouseButton];
+ }
}
-(void)mouseDown:(NSEvent *)mouseEvent
{
- [self mousePressed:mouseEvent];
+ [self mousePressed:mouseEvent button:Qt::LeftButton];
+}
+
+-(void)mouseUp:(NSEvent *)mouseEvent
+{
+ Q_UNUSED(mouseEvent);
+ [self menuTrackingDone:nil];
}
- (void)rightMouseDown:(NSEvent *)mouseEvent
{
- [self mousePressed:mouseEvent];
+ [self mousePressed:mouseEvent button:Qt::RightButton];
+}
+
+-(void)rightMouseUp:(NSEvent *)mouseEvent
+{
+ Q_UNUSED(mouseEvent);
+ [self menuTrackingDone:nil];
}
+- (void)otherMouseDown:(NSEvent *)mouseEvent
+{
+ [self mousePressed:mouseEvent button:cocoaButton2QtButton([mouseEvent buttonNumber])];
+}
+
+-(void)otherMouseUp:(NSEvent *)mouseEvent
+{
+ Q_UNUSED(mouseEvent);
+ [self menuTrackingDone:nil];
+}
-(void)drawRect:(NSRect)rect {
[[parent item] drawStatusBarBackgroundInRect:rect withHighlight:down];
@@ -433,45 +437,40 @@ QT_END_NAMESPACE
}
return QRectF();
}
-- (void)triggerSelector:(id)sender {
+
+- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton {
Q_UNUSED(sender);
- if(!icon)
+ if (!icon)
return;
- qtsystray_sendActivated(icon, QSystemTrayIcon::Trigger);
+
+ if (mouseButton == Qt::MidButton)
+ qtsystray_sendActivated(icon, QSystemTrayIcon::MiddleClick);
+ else
+ qtsystray_sendActivated(icon, QSystemTrayIcon::Trigger);
+
if (icon->contextMenu()) {
-#if 0
- const QRectF geom = [self geometry];
- if(!geom.isNull()) {
- [[NSNotificationCenter defaultCenter] addObserver:imageCell
- selector:@selector(menuTrackingDone:)
- name:nil
- object:self];
- icon->contextMenu()->exec(geom.topLeft().toPoint(), 0);
- [imageCell menuTrackingDone:nil];
- } else
-#endif
- {
#ifndef QT_MAC_USE_COCOA
- [[[self item] view] removeAllToolTips];
- iconPrivate->updateToolTip_sys();
+ [[[self item] view] removeAllToolTips];
+ iconPrivate->updateToolTip_sys();
#endif
- NSMenu *m = [[QNSMenu alloc] initWithQMenu:icon->contextMenu()];
- [m setAutoenablesItems: NO];
- [[NSNotificationCenter defaultCenter] addObserver:imageCell
- selector:@selector(menuTrackingDone:)
- name:NSMenuDidEndTrackingNotification
- object:m];
- [item popUpStatusItemMenu: m];
- [m release];
- }
+ NSMenu *m = [[QNSMenu alloc] initWithQMenu:icon->contextMenu()];
+ [m setAutoenablesItems: NO];
+ [[NSNotificationCenter defaultCenter] addObserver:imageCell
+ selector:@selector(menuTrackingDone:)
+ name:NSMenuDidEndTrackingNotification
+ object:m];
+ [item popUpStatusItemMenu: m];
+ [m release];
}
}
+
- (void)doubleClickSelector:(id)sender {
Q_UNUSED(sender);
if(!icon)
return;
qtsystray_sendActivated(icon, QSystemTrayIcon::DoubleClick);
}
+
@end
class QSystemTrayIconQMenu : public QMenu
diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp
index 6db158e94c..8e482e050c 100644
--- a/src/gui/util/qsystemtrayicon_win.cpp
+++ b/src/gui/util/qsystemtrayicon_win.cpp
@@ -53,7 +53,6 @@
#include <qt_windows.h>
#include <commctrl.h>
-#include <shlwapi.h>
#include <QBitmap>
#include <QLibrary>
#include <QApplication>
@@ -326,8 +325,6 @@ bool QSystemTrayIconSys::winEvent( MSG *m, long *result )
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;
diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
index 30743675ec..bd2af854b7 100644
--- a/src/gui/util/util.pri
+++ b/src/gui/util/util.pri
@@ -41,5 +41,12 @@ embedded {
symbian {
LIBS += -lsendas2 -letext -lapmime
- contains(QT_CONFIG, s60): LIBS += -lplatformenv -lCommonUI
+ contains(QT_CONFIG, s60) {
+ LIBS += -lplatformenv
+ contains(CONFIG, is_using_gnupoc) {
+ LIBS += -lcommonui
+ } else {
+ LIBS += -lCommonUI
+ }
+ }
}
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp
index 73ec53e25a..8cffebd48d 100644
--- a/src/gui/widgets/qabstractscrollarea.cpp
+++ b/src/gui/widgets/qabstractscrollarea.cpp
@@ -983,6 +983,7 @@ bool QAbstractScrollArea::event(QEvent *e)
case QEvent::StyleChange:
case QEvent::LayoutDirectionChange:
case QEvent::ApplicationLayoutDirectionChange:
+ case QEvent::LayoutRequest:
d->layoutChildren();
// fall through
default:
diff --git a/src/gui/widgets/qabstractscrollarea_p.h b/src/gui/widgets/qabstractscrollarea_p.h
index 7c728594b6..9a0d66faa4 100644
--- a/src/gui/widgets/qabstractscrollarea_p.h
+++ b/src/gui/widgets/qabstractscrollarea_p.h
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
class QScrollBar;
class QAbstractScrollAreaScrollBarContainer;
-class Q_AUTOTEST_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate
+class Q_GUI_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate
{
Q_DECLARE_PUBLIC(QAbstractScrollArea)
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index 2888490f23..6a01d681c0 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -712,7 +712,15 @@ bool QAbstractSliderPrivate::scrollByDelta(Qt::Orientation orientation, Qt::Keyb
offset_accumulated = 0;
offset_accumulated += stepsToScrollF;
+#ifndef Q_WS_MAC
+ // Dont't scroll more than one page in any case:
stepsToScroll = qBound(-pageStep, int(offset_accumulated), pageStep);
+#else
+ // Native UI-elements on Mac can scroll hundreds of lines at a time as
+ // a result of acceleration. So keep the same behaviour in Qt, and
+ // dont restrict stepsToScroll to certain maximum (pageStep):
+ stepsToScroll = int(offset_accumulated);
+#endif
offset_accumulated -= int(offset_accumulated);
if (stepsToScroll == 0)
return false;
@@ -756,12 +764,12 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev)
SliderAction action = SliderNoAction;
#ifdef QT_KEYPAD_NAVIGATION
if (ev->isAutoRepeat()) {
- if (d->firstRepeat.isNull())
- d->firstRepeat = QTime::currentTime();
+ if (!d->firstRepeat.isValid())
+ d->firstRepeat.start();
else if (1 == d->repeatMultiplier) {
// This is the interval in milli seconds which one key repetition
// takes.
- const int repeatMSecs = d->firstRepeat.msecsTo(QTime::currentTime());
+ const int repeatMSecs = d->firstRepeat.elapsed();
/**
* The time it takes to currently navigate the whole slider.
@@ -779,8 +787,8 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev)
}
}
- else if (!d->firstRepeat.isNull()) {
- d->firstRepeat = QTime();
+ else if (!d->firstRepeat.isValid()) {
+ d->firstRepeat.invalidate();
d->repeatMultiplier = 1;
}
diff --git a/src/gui/widgets/qabstractslider_p.h b/src/gui/widgets/qabstractslider_p.h
index 6e6ff6e91c..19d1fca84f 100644
--- a/src/gui/widgets/qabstractslider_p.h
+++ b/src/gui/widgets/qabstractslider_p.h
@@ -54,6 +54,7 @@
//
#include "QtCore/qbasictimer.h"
+#include "QtCore/qelapsedtimer.h"
#include "private/qwidget_p.h"
#include "qstyle.h"
@@ -103,7 +104,7 @@ public:
/**
* The time of when the first auto repeating key press event occurs.
*/
- QTime firstRepeat;
+ QElapsedTimer firstRepeat;
#endif
diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp
index 4a6235c36a..7e2f20df1e 100644
--- a/src/gui/widgets/qabstractspinbox.cpp
+++ b/src/gui/widgets/qabstractspinbox.cpp
@@ -1248,8 +1248,11 @@ void QAbstractSpinBox::contextMenuEvent(QContextMenuEvent *event)
#else
Q_D(QAbstractSpinBox);
- d->reset();
QPointer<QMenu> menu = d->edit->createStandardContextMenu();
+ if (!menu)
+ return;
+
+ d->reset();
QAction *selAll = new QAction(tr("&Select All"), menu);
menu->insertAction(d->edit->d_func()->selectAllAction,
diff --git a/src/gui/widgets/qcheckbox.cpp b/src/gui/widgets/qcheckbox.cpp
index 4e0ff667d4..bc0900e94e 100644
--- a/src/gui/widgets/qcheckbox.cpp
+++ b/src/gui/widgets/qcheckbox.cpp
@@ -291,7 +291,7 @@ QSize QCheckBox::sizeHint() const
QFontMetrics fm = fontMetrics();
QStyleOptionButton opt;
initStyleOption(&opt);
- QSize sz = style()->itemTextRect(fm, QRect(0, 0, 1, 1), Qt::TextShowMnemonic, false,
+ QSize sz = style()->itemTextRect(fm, QRect(), Qt::TextShowMnemonic, false,
text()).size();
if (!opt.icon.isNull())
sz = QSize(sz.width() + opt.iconSize.width() + 4, qMax(sz.height(), opt.iconSize.height()));
diff --git a/src/gui/widgets/qcocoamenu_mac.mm b/src/gui/widgets/qcocoamenu_mac.mm
index a7e0b7960f..ce859191a7 100644
--- a/src/gui/widgets/qcocoamenu_mac.mm
+++ b/src/gui/widgets/qcocoamenu_mac.mm
@@ -46,6 +46,7 @@
#import <private/qcocoamenuloader_mac_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
#include <private/qapplication_p.h>
+#include <private/qaction_p.h>
#include <QtGui/QMenu>
@@ -70,6 +71,7 @@ QT_USE_NAMESPACE
self = [super init];
if (self) {
qmenu = menu;
+ previousAction = 0;
[self setAutoenablesItems:NO];
[self setDelegate:self];
}
@@ -81,13 +83,20 @@ QT_USE_NAMESPACE
Q_UNUSED(menu);
if (!item) {
- // ### According to the docs everything will be highlighted. Not sure what we should do in
- // Qt, so just return.
+ if (previousAction) {
+ qt_mac_clear_status_text(previousAction);
+ previousAction = 0;
+ }
return;
}
- if (QAction *action = reinterpret_cast<QAction *>([item tag]))
+ if (QAction *action = reinterpret_cast<QAction *>([item tag])) {
+ QMenu *qtmenu = static_cast<QT_MANGLE_NAMESPACE(QCocoaMenu) *>(menu)->qmenu;
+ previousAction = action;
action->activate(QAction::Hover);
+ qt_mac_menu_emit_hovered(qtmenu, action);
+ action->showStatusText(0); // 0 widget -> action's parent
+ }
}
- (void)menuWillOpen:(NSMenu*)menu;
@@ -100,9 +109,13 @@ QT_USE_NAMESPACE
qt_mac_menu_collapseSeparators(menu, qtmenu->separatorsCollapsible());
}
-- (void)menuWillClose:(NSMenu*)menu;
+- (void)menuDidClose:(NSMenu*)menu;
{
qt_mac_emit_menuSignals(((QT_MANGLE_NAMESPACE(QCocoaMenu) *)menu)->qmenu, false);
+ if (previousAction) {
+ qt_mac_clear_status_text(previousAction);
+ previousAction = 0;
+ }
}
- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
@@ -194,6 +207,18 @@ void qt_mac_emit_menuSignals(QMenu *menu, bool show)
}
qt_mac_menus_open_count += delta;
}
+
+void qt_mac_clear_status_text(QAction *action)
+{
+ action->d_func()->showStatusText(0, QString());
+}
+
+void qt_mac_menu_emit_hovered(QMenu *menu, QAction *action)
+{
+ emit menu->hovered(action);
+}
+
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/widgets/qcocoamenu_mac_p.h b/src/gui/widgets/qcocoamenu_mac_p.h
index 9f50c40875..d6ac8c59ab 100644
--- a/src/gui/widgets/qcocoamenu_mac_p.h
+++ b/src/gui/widgets/qcocoamenu_mac_p.h
@@ -55,13 +55,14 @@
#import <Cocoa/Cocoa.h>
QT_FORWARD_DECLARE_CLASS(QMenu)
+QT_FORWARD_DECLARE_CLASS(QAction)
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
@protocol NSMenuDelegate <NSObject>
- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item;
- (void)menuWillOpen:(NSMenu*)menu;
-- (void)menuWillClose:(NSMenu*)menu;
+- (void)menuDidClose:(NSMenu*)menu;
- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
whichItem:(NSMenuItem**)outItem;
@end
@@ -71,6 +72,7 @@ QT_FORWARD_DECLARE_CLASS(QMenu)
@interface QT_MANGLE_NAMESPACE(QCocoaMenu) : NSMenu <NSMenuDelegate>
{
QMenu *qmenu;
+ QAction *previousAction;
}
- (id)initWithQMenu:(QMenu*)menu;
- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action;
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index 12b1c4aa5e..ca58e6d850 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -112,7 +112,15 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt
const QModelIndex &index) const
{
QStyleOptionMenuItem menuOption;
- menuOption.palette = option.palette.resolve(QApplication::palette("QMenu"));
+
+ QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu"));
+ QVariant value = index.data(Qt::ForegroundRole);
+ if (qVariantCanConvert<QBrush>(value)) {
+ resolvedpalette.setBrush(QPalette::WindowText, qvariant_cast<QBrush>(value));
+ resolvedpalette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(value));
+ resolvedpalette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
+ }
+ menuOption.palette = resolvedpalette;
menuOption.state = QStyle::State_None;
if (mCombo->window()->isActiveWindow())
menuOption.state = QStyle::State_Active;
@@ -1280,7 +1288,8 @@ QComboBox::~QComboBox()
By default, this property has a value of 10.
- \note This property is ignored for non-editable comboboxes in Mac style.
+ \note This property is ignored for non-editable comboboxes in styles that returns
+ false for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style.
*/
int QComboBox::maxVisibleItems() const
{
@@ -2360,7 +2369,7 @@ void QComboBox::showPopup()
toCheck.push(idx);
#endif
++count;
- if (!usePopup && count > d->maxVisibleItems) {
+ if (!usePopup && count >= d->maxVisibleItems) {
toCheck.clear();
break;
}
diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h
index 9b19a66f1a..fb9af9ff99 100644
--- a/src/gui/widgets/qcombobox.h
+++ b/src/gui/widgets/qcombobox.h
@@ -111,10 +111,10 @@ public:
bool hasFrame() const;
inline int findText(const QString &text,
- Qt::MatchFlags flags = Qt::MatchExactly|Qt::MatchCaseSensitive) const
+ Qt::MatchFlags flags = static_cast<Qt::MatchFlags>(Qt::MatchExactly|Qt::MatchCaseSensitive)) const
{ return findData(text, Qt::DisplayRole, flags); }
int findData(const QVariant &data, int role = Qt::UserRole,
- Qt::MatchFlags flags = Qt::MatchExactly|Qt::MatchCaseSensitive) const;
+ Qt::MatchFlags flags = static_cast<Qt::MatchFlags>(Qt::MatchExactly|Qt::MatchCaseSensitive)) const;
enum InsertPolicy {
NoInsert,
diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp
index 762db864c4..50fa9c9b49 100644
--- a/src/gui/widgets/qdatetimeedit.cpp
+++ b/src/gui/widgets/qdatetimeedit.cpp
@@ -1175,7 +1175,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
return; }
}
QAbstractSpinBox::keyPressEvent(event);
- if (select && !(event->modifiers() & Qt::ShiftModifier) && !d->edit->hasSelectedText()) {
+ if (select && !d->edit->hasSelectedText()) {
if (inserted && d->sectionAt(d->edit->cursorPosition()) == QDateTimeParser::NoSectionIndex) {
QString str = d->displayText();
int pos = d->edit->cursorPosition();
diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp
index 6a0e36357a..732dbc9cc8 100644
--- a/src/gui/widgets/qdialogbuttonbox.cpp
+++ b/src/gui/widgets/qdialogbuttonbox.cpp
@@ -103,7 +103,7 @@ QT_BEGIN_NAMESPACE
You can mix and match normal buttons and standard buttons.
Currently the buttons are laid out in the following way if the button box is horizontal:
- \table 100%
+ \table
\row \o \inlineimage buttonbox-gnomelayout-horizontal.png GnomeLayout Horizontal
\o Button box laid out in horizontal GnomeLayout
\row \o \inlineimage buttonbox-kdelayout-horizontal.png KdeLayout Horizontal
@@ -116,25 +116,23 @@ QT_BEGIN_NAMESPACE
The buttons are laid out the following way if the button box is vertical:
- \table 100%
+ \table
+ \row \o GnomeLayout
+ \o KdeLayout
+ \o MacLayout
+ \o WinLayout
\row \o \inlineimage buttonbox-gnomelayout-vertical.png GnomeLayout Vertical
- \o Button box laid out in vertical GnomeLayout
- \row \o \inlineimage buttonbox-kdelayout-vertical.png KdeLayout Vertical
- \o Button box laid out in vertical KdeLayout
- \row \o \inlineimage buttonbox-maclayout-vertical.png MacLayout Vertical
- \o Button box laid out in vertical MacLayout
- \row \o \inlineimage buttonbox-winlayout-vertical.png WinLayout Vertical
- \o Button box laid out in vertical WinLayout
+ \o \inlineimage buttonbox-kdelayout-vertical.png KdeLayout Vertical
+ \o \inlineimage buttonbox-maclayout-vertical.png MacLayout Vertical
+ \o \inlineimage buttonbox-winlayout-vertical.png WinLayout Vertical
\endtable
Additionally, button boxes that contain only buttons with ActionRole or
- HelpRole can be considered modeless and have an alternate look on the mac:
+ HelpRole can be considered modeless and have an alternate look on Mac OS X:
- \table 100%
- \row \o \inlineimage buttonbox-mac-modeless-horizontal.png Screenshot of modeless horizontal MacLayout
- \o modeless horizontal MacLayout
- \row \o \inlineimage buttonbox-mac-modeless-vertical.png Screenshot of modeless vertical MacLayout
- \o modeless vertical MacLayout
+ \table
+ \row \o modeless horizontal MacLayout
+ \o \inlineimage buttonbox-mac-modeless-horizontal.png Screenshot of modeless horizontal MacLayout
\endtable
When a button is clicked in the button box, the clicked() signal is emitted
@@ -260,6 +258,7 @@ static const int layouts[2][5][14] =
}
};
+#if defined(QT_SOFTKEYS_ENABLED) && !defined(QT_NO_ACTION)
class QDialogButtonEnabledProxy : public QObject
{
public:
@@ -283,7 +282,7 @@ private:
QWidget *source;
QAction *target;
};
-
+#endif
class QDialogButtonBoxPrivate : public QWidgetPrivate
{
@@ -316,7 +315,7 @@ public:
void addButtonsToLayout(const QList<QAbstractButton *> &buttonList, bool reverse);
void retranslateStrings();
const char *standardButtonText(QDialogButtonBox::StandardButton sbutton) const;
-#ifdef QT_SOFTKEYS_ENABLED
+#if defined(QT_SOFTKEYS_ENABLED) && !defined(QT_NO_ACTION)
QAction *createSoftKey(QAbstractButton *button, QDialogButtonBox::ButtonRole role);
#endif
};
@@ -573,7 +572,7 @@ void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBo
QObject::connect(button, SIGNAL(clicked()), q, SLOT(_q_handleButtonClicked()));
QObject::connect(button, SIGNAL(destroyed()), q, SLOT(_q_handleButtonDestroyed()));
buttonLists[role].append(button);
-#ifdef QT_SOFTKEYS_ENABLED
+#if defined(QT_SOFTKEYS_ENABLED) && !defined(QT_NO_ACTION)
QAction *action = createSoftKey(button, role);
softKeyActions.insert(button, action);
new QDialogButtonEnabledProxy(action, button, action);
@@ -582,7 +581,7 @@ void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBo
layoutButtons();
}
-#ifdef QT_SOFTKEYS_ENABLED
+#if defined(QT_SOFTKEYS_ENABLED) && !defined(QT_NO_ACTION)
QAction* QDialogButtonBoxPrivate::createSoftKey(QAbstractButton *button, QDialogButtonBox::ButtonRole role)
{
Q_Q(QDialogButtonBox);
@@ -720,7 +719,7 @@ void QDialogButtonBoxPrivate::retranslateStrings()
if (buttonText) {
QPushButton *button = it.key();
button->setText(QDialogButtonBox::tr(buttonText));
-#ifdef QT_SOFTKEYS_ENABLED
+#if defined(QT_SOFTKEYS_ENABLED) && !defined(QT_NO_ACTION)
QAction *action = softKeyActions.value(button, 0);
if (action)
action->setText(button->text());
@@ -999,7 +998,7 @@ void QDialogButtonBox::removeButton(QAbstractButton *button)
}
}
}
-#ifdef QT_SOFTKEYS_ENABLED
+#if defined(QT_SOFTKEYS_ENABLED) && !defined(QT_NO_ACTION)
QAction *action = d->softKeyActions.value(button, 0);
if (action) {
d->softKeyActions.remove(button);
@@ -1245,7 +1244,7 @@ bool QDialogButtonBox::event(QEvent *event)
}else if (event->type() == QEvent::LanguageChange) {
d->retranslateStrings();
}
-#ifdef QT_SOFTKEYS_ENABLED
+#if defined(QT_SOFTKEYS_ENABLED) && !defined(QT_NO_ACTION)
else if (event->type() == QEvent::ParentChange) {
QWidget *dialog = 0;
QWidget *p = this;
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index 794863b62f..806654c99c 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -220,15 +220,17 @@ static quintptr tabId(const QDockAreaLayoutItem &item)
}
#endif
+static const int zero = 0;
+
QDockAreaLayoutInfo::QDockAreaLayoutInfo()
- : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
+ : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
#ifndef QT_NO_TABBAR
, tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth), tabBarVisible(false)
#endif
{
}
-QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos,
+QDockAreaLayoutInfo::QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos,
Qt::Orientation _o, int tbshape,
QMainWindow *window)
: sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
@@ -281,7 +283,7 @@ QSize QDockAreaLayoutInfo::minimumSize() const
#endif
{
if (!first)
- a += sep;
+ a += *sep;
a += pick(o, min_size);
}
b = qMax(b, perp(o, min_size));
@@ -349,7 +351,7 @@ QSize QDockAreaLayoutInfo::maximumSize() const
#endif
{
if (!first)
- a += sep;
+ a += *sep;
a += pick(o, max_size);
}
b = qMin(b, perp(o, max_size));
@@ -415,7 +417,7 @@ QSize QDockAreaLayoutInfo::sizeHint() const
{
if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
&& !previous->hasFixedSize(o)) {
- a += sep;
+ a += *sep;
}
a += gap ? item.size : pick(o, size_hint);
}
@@ -491,7 +493,7 @@ static int realMinSize(const QDockAreaLayoutInfo &info)
min = pick(info.o, item.minimumSize());
if (!first)
- result += info.sep;
+ result += *info.sep;
result += min;
first = false;
@@ -516,7 +518,7 @@ static int realMaxSize(const QDockAreaLayoutInfo &info)
max = pick(info.o, item.maximumSize());
if (!first)
- result += info.sep;
+ result += *info.sep;
result += max;
if (result >= QWIDGETSIZE_MAX)
@@ -555,7 +557,7 @@ void QDockAreaLayoutInfo::fitItems()
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.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep;
ls.empty = false;
}
}
@@ -938,7 +940,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta)
if (item.skip()) {
ls.empty = true;
} else {
- const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+ const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
ls.empty = false;
ls.pos = item.pos;
ls.size = item.size + separatorSpace;
@@ -956,7 +958,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta)
if (item.skip())
continue;
QLayoutStruct &ls = list[i];
- const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+ const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
item.size = ls.size - separatorSpace;
item.pos = ls.pos;
if (item.subinfo != 0) {
@@ -1041,11 +1043,11 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
int next = this->next(index);
if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
- item.pos += sep;
- item.size -= sep;
+ item.pos += *sep;
+ item.size -= *sep;
}
if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- item.size -= sep;
+ item.size -= *sep;
QPoint pos;
rpick(o, pos) = item.pos;
@@ -1083,11 +1085,11 @@ QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path)
#endif
{
if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
- item.pos -= sep;
- item.size += sep;
+ item.pos -= *sep;
+ item.size += *sep;
}
if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- item.size += sep;
+ item.size += *sep;
}
return item.widgetItem;
@@ -1255,9 +1257,9 @@ bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWid
QRect r = dockedGeometry(dockWidgetItem->widget());
gap_size = pick(o, r.size());
if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
- sep_size += sep;
+ sep_size += *sep;
if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- sep_size += sep;
+ sep_size += *sep;
}
if (gap_size + sep_size > space)
gap_size = pick(o, gap_item.minimumSize());
@@ -1364,7 +1366,7 @@ QRect QDockAreaLayoutInfo::separatorRect(int index) const
QPoint pos = rect.topLeft();
rpick(o, pos) = item.pos + item.size;
QSize s = rect.size();
- rpick(o, s) = sep;
+ rpick(o, s) = *sep;
return QRect(pos, s);
}
@@ -1413,7 +1415,7 @@ QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
continue;
QRect sepRect = separatorRect(i);
- if (!sepRect.isNull() && sep == 1)
+ 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)) {
@@ -1560,7 +1562,7 @@ void QDockAreaLayoutInfo::apply(bool animate)
}
}
#ifndef QT_NO_TABBAR
- if (sep == 1)
+ if (*sep == 1)
updateSeparatorWidgets();
#endif //QT_NO_TABBAR
}
@@ -1983,7 +1985,10 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
emit widget->dockLocationChanged(toDockWidgetArea(dockPos));
}
}
-
+ if (testing) {
+ //was it is not really added to the layout, we need to delete the object here
+ delete item.widgetItem;
+ }
}
} else if (nextMarker == SequenceMarker) {
int dummy;
@@ -2013,7 +2018,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
updateTabBar();
setCurrentTabId(tabId(item_list.at(index)));
}
- if (!testing && sep == 1)
+ if (!testing && *sep == 1)
updateSeparatorWidgets();
#endif
@@ -2276,13 +2281,13 @@ QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true)
const int tabShape = 0;
#endif
docks[QInternal::LeftDock]
- = QDockAreaLayoutInfo(sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
docks[QInternal::RightDock]
- = QDockAreaLayoutInfo(sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
docks[QInternal::TopDock]
- = QDockAreaLayoutInfo(sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
docks[QInternal::BottomDock]
- = QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
centralWidgetItem = 0;
@@ -2994,8 +2999,7 @@ bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
QRect r = constrainedRect(placeHolder->topLevelRect, desktop.screenGeometry(dockWidget));
dockWidget->d_func()->setWindowState(true, true, r);
}
- dockWidget->show();
-// dockWidget->setVisible(!placeHolder->hidden);
+ dockWidget->setVisible(!placeHolder->hidden);
#ifdef Q_WS_X11
if (placeHolder->window) // gets rid of the X11BypassWindowManager window flag
dockWidget->d_func()->setWindowState(true);
@@ -3031,7 +3035,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do
#else
int tbshape = 0;
#endif
- QDockAreaLayoutInfo new_info(sep, pos, orientation, tbshape, mainWindow);
+ QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow);
new_info.item_list.append(new QDockAreaLayoutInfo(info));
new_info.item_list.append(dockWidgetItem);
info = new_info;
@@ -3327,6 +3331,12 @@ void QDockAreaLayout::keepSize(QDockWidget *w)
item.flags |= QDockAreaLayoutItem::KeepSize;
}
+void QDockAreaLayout::styleChangedEvent()
+{
+ sep = mainWindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainWindow);
+ fitLayout();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DOCKWIDGET
diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h
index 0bc1aa9eee..0088f0053b 100644
--- a/src/gui/widgets/qdockarealayout_p.h
+++ b/src/gui/widgets/qdockarealayout_p.h
@@ -128,7 +128,7 @@ class Q_AUTOTEST_EXPORT QDockAreaLayoutInfo
{
public:
QDockAreaLayoutInfo();
- QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos, Qt::Orientation _o,
+ QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos, Qt::Orientation _o,
int tbhape, QMainWindow *window);
QSize minimumSize() const;
@@ -189,7 +189,7 @@ public:
QMainWindowLayout *mainWindowLayout() const;
- int sep;
+ const int *sep;
mutable QVector<QWidget*> separatorWidgets;
QInternal::DockPosition dockPos;
Qt::Orientation o;
@@ -300,6 +300,7 @@ public:
QSet<QTabBar*> usedTabBars() const;
QSet<QWidget*> usedSeparatorWidgets() const;
#endif //QT_NO_TABBAR
+ void styleChangedEvent();
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp
index fdace46ced..54189de819 100644
--- a/src/gui/widgets/qdockwidget.cpp
+++ b/src/gui/widgets/qdockwidget.cpp
@@ -1010,7 +1010,7 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
if (!floating && parent) {
QMainWindowLayout *mwlayout = qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout());
- if (!mwlayout || mwlayout->dockWidgetArea(q) == Qt::NoDockWidgetArea)
+ if (mwlayout && mwlayout->dockWidgetArea(q) == Qt::NoDockWidgetArea)
return; // this dockwidget can't be redocked
}
diff --git a/src/gui/widgets/qeffects.cpp b/src/gui/widgets/qeffects.cpp
index dd7fc480ed..a56d09338a 100644
--- a/src/gui/widgets/qeffects.cpp
+++ b/src/gui/widgets/qeffects.cpp
@@ -41,7 +41,6 @@
#include "qapplication.h"
#ifndef QT_NO_EFFECTS
-#include "qdatetime.h"
#include "qdesktopwidget.h"
#include "qeffects_p.h"
#include "qevent.h"
@@ -50,6 +49,7 @@
#include "qpixmap.h"
#include "qpointer.h"
#include "qtimer.h"
+#include "qelapsedtimer.h"
#include "qdebug.h"
QT_BEGIN_NAMESPACE
@@ -103,7 +103,7 @@ private:
int elapsed;
bool showWidget;
QTimer anim;
- QTime checkTime;
+ QElapsedTimer checkTime;
double windowOpacity;
};
@@ -384,7 +384,7 @@ private:
int orientation;
QTimer anim;
- QTime checkTime;
+ QElapsedTimer checkTime;
QPixmap pm;
};
diff --git a/src/gui/widgets/qfocusframe.cpp b/src/gui/widgets/qfocusframe.cpp
index d9cd5bb6fc..4f20bce001 100644
--- a/src/gui/widgets/qfocusframe.cpp
+++ b/src/gui/widgets/qfocusframe.cpp
@@ -53,11 +53,14 @@ class QFocusFramePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QFocusFrame)
QWidget *widget;
-
+ QWidget *frameParent;
+ bool showFrameAboveWidget;
public:
QFocusFramePrivate() {
widget = 0;
+ frameParent = 0;
sendChildEvents = false;
+ showFrameAboveWidget = false;
}
void updateSize();
void update();
@@ -66,10 +69,10 @@ public:
void QFocusFramePrivate::update()
{
Q_Q(QFocusFrame);
- q->setParent(widget->parentWidget());
+ q->setParent(frameParent);
updateSize();
if (q->parentWidget()->rect().intersects(q->geometry())) {
- if (q->style()->styleHint(QStyle::SH_FocusFrame_AboveWidget, 0, q))
+ if (showFrameAboveWidget)
q->raise();
else
q->stackUnder(widget);
@@ -84,7 +87,10 @@ void QFocusFramePrivate::updateSize()
Q_Q(QFocusFrame);
int vmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameVMargin),
hmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
- QRect geom(widget->x()-hmargin, widget->y()-vmargin,
+ QPoint pos(widget->x(), widget->y());
+ if (q->parentWidget() != widget->parentWidget())
+ pos = widget->parentWidget()->mapTo(q->parentWidget(), pos);
+ QRect geom(pos.x()-hmargin, pos.y()-vmargin,
widget->width()+(hmargin*2), widget->height()+(vmargin*2));
if(q->geometry() == geom)
return;
@@ -176,14 +182,52 @@ void
QFocusFrame::setWidget(QWidget *widget)
{
Q_D(QFocusFrame);
- if(widget == d->widget)
- return;
- if(d->widget)
- d->widget->removeEventFilter(this);
- if(widget && !widget->isWindow() && widget->parentWidget()->windowType() != Qt::SubWindow) {
+ if (style()->styleHint(QStyle::SH_FocusFrame_AboveWidget, 0, this))
+ d->showFrameAboveWidget = true;
+ else
+ d->showFrameAboveWidget = false;
+
+ if (widget == d->widget)
+ return;
+ if (d->widget) {
+ // Remove event filters from the widget hierarchy.
+ QWidget *p = d->widget;
+ do {
+ p->removeEventFilter(this);
+ if (!d->showFrameAboveWidget || p == d->frameParent)
+ break;
+ p = p->parentWidget();
+ }while (p);
+ }
+ if (widget && !widget->isWindow() && widget->parentWidget()->windowType() != Qt::SubWindow) {
d->widget = widget;
- widget->installEventFilter(this);
+ d->widget->installEventFilter(this);
+ QWidget *p = widget->parentWidget();
+ QWidget *prev = 0;
+ if (d->showFrameAboveWidget) {
+ // Find the right parent for the focus frame.
+ while (p) {
+ // Traverse the hirerarchy of the 'widget' for setting event filter.
+ // During this if come across toolbar or a top level, use that
+ // as the parent for the focus frame. If we find a scroll area
+ // use its viewport as the parent.
+ bool isScrollArea = false;
+ if (p->isWindow() || p->inherits("QToolBar") || (isScrollArea = p->inherits("QAbstractScrollArea"))) {
+ d->frameParent = p;
+ // The previous one in the hierarchy will be the viewport.
+ if (prev && isScrollArea)
+ d->frameParent = prev;
+ break;
+ } else {
+ p->installEventFilter(this);
+ prev = p;
+ p = p->parentWidget();
+ }
+ }
+ } else {
+ d->frameParent = p;
+ }
d->update();
} else {
d->widget = 0;
@@ -210,9 +254,15 @@ QFocusFrame::widget() const
void
QFocusFrame::paintEvent(QPaintEvent *)
{
+ Q_D(QFocusFrame);
QStylePainter p(this);
QStyleOption option;
initStyleOption(&option);
+ int vmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin);
+ int hmargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
+ QWidgetPrivate *wd = qt_widget_private(d->widget);
+ QRect rect = wd->clipRect().adjusted(0, 0, hmargin*2, vmargin*2);
+ p.setClipRect(rect);
p.drawControl(QStyle::CE_FocusFrame, option);
}
@@ -233,7 +283,13 @@ QFocusFrame::eventFilter(QObject *o, QEvent *e)
hide();
break;
case QEvent::ParentChange:
- d->update();
+ if (d->showFrameAboveWidget) {
+ QWidget *w = d->widget;
+ setWidget(0);
+ setWidget(w);
+ } else {
+ d->update();
+ }
break;
case QEvent::Show:
d->update();
@@ -254,6 +310,19 @@ QFocusFrame::eventFilter(QObject *o, QEvent *e)
default:
break;
}
+ } else if (d->showFrameAboveWidget) {
+ // Handle changes in the parent widgets we are monitoring.
+ switch(e->type()) {
+ case QEvent::Move:
+ case QEvent::Resize:
+ d->updateSize();
+ break;
+ case QEvent::ZOrderChange:
+ raise();
+ break;
+ default:
+ break;
+ }
}
return false;
}
diff --git a/src/gui/widgets/qframe.cpp b/src/gui/widgets/qframe.cpp
index c2e4b352e5..f51ddfdf9e 100644
--- a/src/gui/widgets/qframe.cpp
+++ b/src/gui/widgets/qframe.cpp
@@ -244,7 +244,7 @@ QFrame::~QFrame()
/*!
Returns the frame style.
- The default value is QFrame::NoFrame.
+ The default value is QFrame::Plain.
\sa setFrameStyle(), frameShape(), frameShadow()
*/
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp
index 8428ad7ca5..bdbd0b04ef 100644
--- a/src/gui/widgets/qlabel.cpp
+++ b/src/gui/widgets/qlabel.cpp
@@ -53,6 +53,7 @@
#include <qurl.h>
#include "qlabel_p.h"
#include "private/qstylesheetstyle_p.h"
+#include <qmath.h>
QT_BEGIN_NAMESPACE
@@ -661,7 +662,9 @@ QSize QLabelPrivate::sizeForWidth(int w) const
} else {
control->setTextWidth(-1);
}
- br = QRect(QPoint(0, 0), control->size().toSize());
+
+ QSizeF controlSize = control->size();
+ br = QRect(QPoint(0, 0), QSize(qCeil(controlSize.width()), qCeil(controlSize.height())));
// restore state
control->setTextWidth(oldTextWidth);
@@ -781,6 +784,95 @@ Qt::TextInteractionFlags QLabel::textInteractionFlags() const
return d->textInteractionFlags;
}
+/*!
+ Selects text from position \a start and for \a length characters.
+
+ \sa selectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+void QLabel::setSelection(int start, int length)
+{
+ Q_D(QLabel);
+ if (d->control) {
+ d->ensureTextPopulated();
+ QTextCursor cursor = d->control->textCursor();
+ cursor.setPosition(start);
+ cursor.setPosition(start + length, QTextCursor::KeepAnchor);
+ d->control->setTextCursor(cursor);
+ }
+}
+
+/*!
+ \property QLabel::hasSelectedText
+ \brief whether there is any text selected
+
+ hasSelectedText() returns true if some or all of the text has been
+ selected by the user; otherwise returns false.
+
+ By default, this property is false.
+
+ \sa selectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+bool QLabel::hasSelectedText() const
+{
+ Q_D(const QLabel);
+ if (d->control)
+ return d->control->textCursor().hasSelection();
+ return false;
+}
+
+/*!
+ \property QLabel::selectedText
+ \brief the selected text
+
+ If there is no selected text this property's value is
+ an empty string.
+
+ By default, this property contains an empty string.
+
+ \sa hasSelectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+QString QLabel::selectedText() const
+{
+ Q_D(const QLabel);
+ if (d->control)
+ return d->control->textCursor().selectedText();
+ return QString();
+}
+
+/*!
+ selectionStart() returns the index of the first selected character in the
+ label or -1 if no text is selected.
+
+ \sa selectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+int QLabel::selectionStart() const
+{
+ Q_D(const QLabel);
+ if (d->control && d->control->textCursor().hasSelection())
+ return d->control->textCursor().selectionStart();
+ return -1;
+}
+
/*!\reimp
*/
QSize QLabel::sizeHint() const
@@ -862,8 +954,8 @@ void QLabel::contextMenuEvent(QContextMenuEvent *ev)
return;
}
ev->accept();
- menu->exec(ev->globalPos());
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(ev->globalPos());
#endif
}
diff --git a/src/gui/widgets/qlabel.h b/src/gui/widgets/qlabel.h
index d916078da6..54babb1564 100644
--- a/src/gui/widgets/qlabel.h
+++ b/src/gui/widgets/qlabel.h
@@ -65,6 +65,8 @@ class Q_GUI_EXPORT QLabel : public QFrame
Q_PROPERTY(int indent READ indent WRITE setIndent)
Q_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks)
Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
+ Q_PROPERTY(bool hasSelectedText READ hasSelectedText)
+ Q_PROPERTY(QString selectedText READ selectedText)
public:
explicit QLabel(QWidget *parent=0, Qt::WindowFlags f=0);
@@ -111,6 +113,11 @@ public:
void setTextInteractionFlags(Qt::TextInteractionFlags flags);
Qt::TextInteractionFlags textInteractionFlags() const;
+ void setSelection(int, int);
+ bool hasSelectedText() const;
+ QString selectedText() const;
+ int selectionStart() const;
+
public Q_SLOTS:
void setText(const QString &);
void setPixmap(const QPixmap &);
diff --git a/src/gui/widgets/qlabel_p.h b/src/gui/widgets/qlabel_p.h
index 21eb128f59..fba72240b1 100644
--- a/src/gui/widgets/qlabel_p.h
+++ b/src/gui/widgets/qlabel_p.h
@@ -55,7 +55,7 @@
#include "qlabel.h"
-#include "../text/qtextdocumentlayout_p.h"
+#include "private/qtextdocumentlayout_p.h"
#include "private/qtextcontrol_p.h"
#include "qtextdocumentfragment.h"
#include "qframe_p.h"
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
index 9ec0feb851..d027b9104e 100644
--- a/src/gui/widgets/qlinecontrol.cpp
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -136,9 +136,9 @@ void QLineControl::copy(QClipboard::Mode mode) const
\sa insert()
*/
-void QLineControl::paste()
+void QLineControl::paste(QClipboard::Mode clipboardMode)
{
- QString clip = QApplication::clipboard()->text(QClipboard::Clipboard);
+ QString clip = QApplication::clipboard()->text(clipboardMode);
if (!clip.isEmpty() || hasSelectedText()) {
separate(); //make it a separate undo/redo command
insert(clip);
@@ -1350,6 +1350,7 @@ bool QLineControl::processEvent(QEvent* ev)
#endif
switch(ev->type()){
#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneMouseDoubleClick:
case QEvent::GraphicsSceneMouseMove:
case QEvent::GraphicsSceneMouseRelease:
case QEvent::GraphicsSceneMousePress:{
@@ -1439,6 +1440,7 @@ void QLineControl::processMouseEvent(QMouseEvent* ev)
moveCursor(cursor, mark);
break;
}
+ case QEvent::GraphicsSceneMouseDoubleClick:
case QEvent::MouseButtonDblClick:
if (ev->button() == Qt::LeftButton) {
selectWordAtPos(xToPos(ev->pos().x()));
@@ -1576,8 +1578,14 @@ void QLineControl::processKeyEvent(QKeyEvent* event)
copy();
}
else if (event == QKeySequence::Paste) {
- if (!isReadOnly())
- paste();
+ if (!isReadOnly()) {
+ QClipboard::Mode mode = QClipboard::Clipboard;
+#ifdef Q_WS_X11
+ if (event->modifiers() == (Qt::CTRL | Qt::SHIFT) && event->key() == Qt::Key_Insert)
+ mode = QClipboard::Selection;
+#endif
+ paste(mode);
+ }
}
else if (event == QKeySequence::Cut) {
if (!isReadOnly()) {
@@ -1761,7 +1769,6 @@ void QLineControl::processKeyEvent(QKeyEvent* event)
}
break;
#endif
-
default:
if (!handled)
unknown = true;
diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h
index 3f1bc2c605..5da1831c71 100644
--- a/src/gui/widgets/qlinecontrol_p.h
+++ b/src/gui/widgets/qlinecontrol_p.h
@@ -94,136 +94,207 @@ public:
delete [] m_maskData;
}
- int nextMaskBlank(int pos);
- int prevMaskBlank(int pos);
+ int nextMaskBlank(int pos)
+ {
+ int c = findInMask(pos, true, false);
+ m_separator |= (c != pos);
+ return (c != -1 ? c : m_maxLength);
+ }
+
+ int prevMaskBlank(int pos)
+ {
+ int c = findInMask(pos, false, false);
+ m_separator |= (c != pos);
+ return (c != -1 ? c : 0);
+ }
+
+ bool isUndoAvailable() const { return !m_readOnly && m_undoState; }
+ bool isRedoAvailable() const { return !m_readOnly && m_undoState < (int)m_history.size(); }
+ void clearUndo() { m_history.clear(); m_modifiedState = m_undoState = 0; }
- bool isUndoAvailable() const;
- bool isRedoAvailable() const;
- void clearUndo();
- bool isModified() const;
- void setModified(bool modified);
+ bool isModified() const { return m_modifiedState != m_undoState; }
+ void setModified(bool modified) { m_modifiedState = modified ? -1 : m_undoState; }
- bool allSelected() const;
- bool hasSelectedText() const;
+ bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); }
+ bool hasSelectedText() const { return !m_text.isEmpty() && m_selend > m_selstart; }
- int width() const;
- int height() const;
- int ascent() const;
- qreal naturalTextWidth() const;
+ int width() const { return qRound(m_textLayout.lineAt(0).width()) + 1; }
+ int height() const { return qRound(m_textLayout.lineAt(0).height()) + 1; }
+ int ascent() const { return m_ascent; }
+ qreal naturalTextWidth() const { return m_textLayout.lineAt(0).naturalTextWidth(); }
void setSelection(int start, int length);
- QString selectedText() const;
- QString textBeforeSelection() const;
- QString textAfterSelection() const;
+ inline QString selectedText() const { return hasSelectedText() ? m_text.mid(m_selstart, m_selend - m_selstart) : QString(); }
+ QString textBeforeSelection() const { return hasSelectedText() ? m_text.left(m_selstart) : QString(); }
+ QString textAfterSelection() const { return hasSelectedText() ? m_text.mid(m_selend) : QString(); }
- int selectionStart() const;
- int selectionEnd() const;
- bool inSelection(int x) const;
+ int selectionStart() const { return hasSelectedText() ? m_selstart : -1; }
+ int selectionEnd() const { return hasSelectedText() ? m_selend : -1; }
+ bool inSelection(int x) const
+ {
+ if (m_selstart >= m_selend)
+ return false;
+ int pos = xToPos(x, QTextLine::CursorOnCharacter);
+ return pos >= m_selstart && pos < m_selend;
+ }
- void removeSelection();
+ void removeSelection()
+ {
+ int priorState = m_undoState;
+ removeSelectedText();
+ finishChange(priorState);
+ }
- int start() const;
- int end() const;
+ int start() const { return 0; }
+ int end() const { return m_text.length(); }
#ifndef QT_NO_CLIPBOARD
void copy(QClipboard::Mode mode = QClipboard::Clipboard) const;
- void paste();
+ void paste(QClipboard::Mode mode = QClipboard::Clipboard);
#endif
- int cursor() const;
- int preeditCursor() const;
+ int cursor() const{ return m_cursor; }
+ int preeditCursor() const { return m_preeditCursor; }
+
+ int cursorWidth() const { return m_cursorWidth; }
+ void setCursorWidth(int value) { m_cursorWidth = value; }
- 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);
+ void 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);
+ }
+
+ void cursorWordForward(bool mark) { moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
+ void cursorWordBackward(bool mark) { moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
+
+ void home(bool mark) { moveCursor(0, mark); }
+ void end(bool mark) { moveCursor(text().length(), 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);
+ qreal cursorToX(int cursor) const { return m_textLayout.lineAt(0).cursorToX(cursor); }
+ qreal cursorToX() const
+ {
+ int cursor = m_cursor;
+ if (m_preeditCursor != -1)
+ cursor += m_preeditCursor;
+ return cursorToX(cursor);
+ }
- QString text() const;
- void setText(const QString &txt);
+ bool isReadOnly() const { return m_readOnly; }
+ void setReadOnly(bool enable) { m_readOnly = enable; }
- QString displayText() const;
+ QString text() const
+ {
+ QString res = m_maskData ? stripString(m_text) : m_text;
+ return (res.isNull() ? QString::fromLatin1("") : res);
+ }
+ void setText(const QString &txt) { internalSetText(txt, -1, false); }
+ QString displayText() const { return m_textLayout.text(); }
void backspace();
void del();
- void deselect();
- void selectAll();
+ void deselect() { internalDeselect(); finishChange(); }
+ void selectAll() { m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.length(), true); }
+
void insert(const QString &);
void clear();
- void undo();
- void redo();
+ void undo() { internalUndo(); finishChange(-1, true); }
+ void redo() { internalRedo(); finishChange(); }
void selectWordAtPos(int);
- uint echoMode() const;
- void setEchoMode(uint mode);
+ uint echoMode() const { return m_echoMode; }
+ void setEchoMode(uint mode)
+ {
+ m_echoMode = mode;
+ m_passwordEchoEditing = false;
+ updateDisplayText();
+ }
- void setMaxLength(int maxLength);
- int maxLength() const;
+ int maxLength() const { return m_maxLength; }
+ void setMaxLength(int maxLength)
+ {
+ if (m_maskData)
+ return;
+ m_maxLength = maxLength;
+ setText(m_text);
+ }
#ifndef QT_NO_VALIDATOR
- const QValidator *validator() const;
- void setValidator(const QValidator *);
+ const QValidator *validator() const { return m_validator; }
+ void setValidator(const QValidator *v) { m_validator = const_cast<QValidator*>(v); }
#endif
#ifndef QT_NO_COMPLETER
- QCompleter *completer() const;
- void setCompleter(const QCompleter*);
+ QCompleter *completer() const { return m_completer; }
+ /* Note that you must set the widget for the completer seperately */
+ void setCompleter(const QCompleter *c) { m_completer = const_cast<QCompleter*>(c); }
void complete(int key);
#endif
- void setCursorPosition(int pos);
- int cursorPosition() const;
+ int cursorPosition() const { return m_cursor; }
+ void setCursorPosition(int pos) { if (pos <= m_text.length()) moveCursor(qMax(0, pos)); }
- bool hasAcceptableInput() const;
+ bool hasAcceptableInput() const { return hasAcceptableInput(m_text); }
bool fixup();
- QString inputMask() const;
- void setInputMask(const QString &mask);
+ QString inputMask() const { return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString(); }
+ void setInputMask(const QString &mask)
+ {
+ parseInputMask(mask);
+ if (m_maskData)
+ moveCursor(nextMaskBlank(0));
+ }
// input methods
#ifndef QT_NO_IM
- bool composeMode() const;
- void setPreeditArea(int cursor, const QString &text);
+ bool composeMode() const { return !m_textLayout.preeditAreaText().isEmpty(); }
+ void setPreeditArea(int cursor, const QString &text) { m_textLayout.setPreeditArea(cursor, text); }
#endif
- QString preeditAreaText() const;
+ QString preeditAreaText() const { return m_textLayout.preeditAreaText(); }
void updatePasswordEchoEditing(bool editing);
- bool passwordEchoEditing() const;
+ bool passwordEchoEditing() const { return m_passwordEchoEditing; }
- QChar passwordCharacter() const;
- void setPasswordCharacter(const QChar &character);
+ QChar passwordCharacter() const { return m_passwordCharacter; }
+ void setPasswordCharacter(const QChar &character) { m_passwordCharacter = character; updateDisplayText(); }
- Qt::LayoutDirection layoutDirection() const;
- void setLayoutDirection(Qt::LayoutDirection direction);
- void setFont(const QFont &font);
+ Qt::LayoutDirection layoutDirection() const { return m_layoutDirection; }
+ void setLayoutDirection(Qt::LayoutDirection direction)
+ {
+ if (direction != m_layoutDirection) {
+ m_layoutDirection = direction;
+ updateDisplayText();
+ }
+ }
+
+ void setFont(const QFont &font) { m_textLayout.setFont(font); updateDisplayText(); }
void processInputMethodEvent(QInputMethodEvent *event);
void processMouseEvent(QMouseEvent* ev);
void processKeyEvent(QKeyEvent* ev);
- int cursorBlinkPeriod() const;
+ int cursorBlinkPeriod() const { return m_blinkPeriod; }
void setCursorBlinkPeriod(int msec);
- QString cancelText() const;
- void setCancelText(const QString &text);
+ QString cancelText() const { return m_cancelText; }
+ void setCancelText(const QString &text) { m_cancelText = text; }
- const QPalette &palette() const;
- void setPalette(const QPalette &);
+ const QPalette &palette() const { return m_palette; }
+ void setPalette(const QPalette &p) { m_palette = p; }
enum DrawFlags {
DrawText = 0x01,
@@ -363,406 +434,6 @@ private Q_SLOTS:
};
-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 qreal QLineControl::naturalTextWidth() const
-{
- return m_textLayout.lineAt(0).naturalTextWidth();
-}
-
-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
-{
- int cursor = m_cursor;
- if (m_preeditCursor != -1)
- cursor += m_preeditCursor;
- return cursorToX(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;
-}
-
-#ifndef QT_NO_VALIDATOR
-inline const QValidator *QLineControl::validator() const
-{
- return m_validator;
-}
-
-inline void QLineControl::setValidator(const QValidator *v)
-{
- m_validator = const_cast<QValidator*>(v);
-}
-#endif
-
-#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;
-}
-
-inline const QPalette & QLineControl::palette() const
-{
- return m_palette;
-}
-
-inline void QLineControl::setPalette(const QPalette &p)
-{
- m_palette = p;
-}
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index f041a36d86..c1c4abf3e9 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -383,8 +383,6 @@ void QLineEdit::setText(const QString& text)
d->control->setText(text);
}
-// ### Qt 4.7: remove this #if guard
-#if (QT_VERSION >= 0x407000) || defined(Q_WS_MAEMO_5)
/*!
\since 4.7
@@ -414,7 +412,6 @@ void QLineEdit::setPlaceholderText(const QString& placeholderText)
update();
}
}
-#endif
/*!
\property QLineEdit::displayText
@@ -542,11 +539,16 @@ void QLineEdit::setEchoMode(EchoMode mode)
if (mode == (EchoMode)d->control->echoMode())
return;
Qt::InputMethodHints imHints = inputMethodHints();
- if (mode == Password) {
+ if (mode == Password || mode == NoEcho) {
imHints |= Qt::ImhHiddenText;
} else {
imHints &= ~Qt::ImhHiddenText;
}
+ if (mode != Normal) {
+ imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ } else {
+ imHints &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ }
setInputMethodHints(imHints);
d->control->setEchoMode(mode);
update();
@@ -1643,12 +1645,8 @@ void QLineEdit::keyPressEvent(QKeyEvent *event)
if (!hasEditFocus() && !(event->modifiers() & Qt::ControlModifier)) {
if (!event->text().isEmpty() && event->text().at(0).isPrint()
&& !isReadOnly())
- {
setEditFocus(true);
-#ifndef Q_OS_SYMBIAN
- clear();
-#endif
- } else {
+ else {
event->ignore();
return;
}
@@ -1704,12 +1702,8 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
// commit text as they focus out without interfering with focus
if (QApplication::keypadNavigationEnabled()
&& hasFocus() && !hasEditFocus()
- && !e->preeditString().isEmpty()) {
+ && !e->preeditString().isEmpty())
setEditFocus(true);
-#ifndef Q_OS_SYMBIAN
- selectAll(); // so text is replaced rather than appended to
-#endif
- }
#endif
d->control->processInputMethodEvent(e);
@@ -1881,13 +1875,18 @@ void QLineEdit::paintEvent(QPaintEvent *)
}
QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height());
+ int minLB = qMax(0, -fm.minLeftBearing());
+ int minRB = qMax(0, -fm.minRightBearing());
+
if (d->control->text().isEmpty()) {
if (!hasFocus() && !d->placeholderText.isEmpty()) {
QColor col = pal.text().color();
col.setAlpha(128);
QPen oldpen = p.pen();
p.setPen(col);
- p.drawText(lineRect, va, d->placeholderText);
+ lineRect.adjust(minLB, 0, 0, 0);
+ QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, lineRect.width());
+ p.drawText(lineRect, va, elidedText);
p.setPen(oldpen);
return;
}
@@ -1901,8 +1900,6 @@ void QLineEdit::paintEvent(QPaintEvent *)
// the below code handles all scrolling based on the textline (widthUsed,
// minLB, minRB), the line edit rect (lineRect) and the cursor position
// (cix).
- int minLB = qMax(0, -fm.minLeftBearing());
- int minRB = qMax(0, -fm.minRightBearing());
int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB;
if ((minLB + widthUsed) <= lineRect.width()) {
// text fits in lineRect; use hscroll for alignment
@@ -2052,12 +2049,13 @@ void QLineEdit::dropEvent(QDropEvent* e)
*/
void QLineEdit::contextMenuEvent(QContextMenuEvent *event)
{
- QPointer<QMenu> menu = createStandardContextMenu();
- menu->exec(event->globalPos());
- delete menu;
+ if (QMenu *menu = createStandardContextMenu()) {
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(event->globalPos());
+ }
}
-#if defined(Q_WS_WIN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
extern bool qt_use_rtl_extensions;
#endif
@@ -2129,7 +2127,7 @@ QMenu *QLineEdit::createStandardContextMenu()
}
#endif
-#if defined(Q_WS_WIN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
if (!d->control->isReadOnly() && qt_use_rtl_extensions) {
#else
if (!d->control->isReadOnly()) {
diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h
index fa04bfc73c..94e0dbe6dc 100644
--- a/src/gui/widgets/qlineedit.h
+++ b/src/gui/widgets/qlineedit.h
@@ -83,10 +83,7 @@ class Q_GUI_EXPORT QLineEdit : public QWidget
Q_PROPERTY(bool undoAvailable READ isUndoAvailable)
Q_PROPERTY(bool redoAvailable READ isRedoAvailable)
Q_PROPERTY(bool acceptableInput READ hasAcceptableInput)
-// ### Qt 4.7: remove this #if guard
-#if (QT_VERSION >= 0x407000) || defined(Q_WS_MAEMO_5)
Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText)
-#endif
public:
explicit QLineEdit(QWidget* parent=0);
@@ -102,11 +99,8 @@ public:
QString displayText() const;
-// ### Qt 4.7: remove this #if guard
-#if (QT_VERSION >= 0x407000) || defined(Q_WS_MAEMO_5)
QString placeholderText() const;
void setPlaceholderText(const QString &);
-#endif
int maxLength() const;
void setMaxLength(int);
diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp
index 16a7c31423..44483ea699 100644
--- a/src/gui/widgets/qmainwindow.cpp
+++ b/src/gui/widgets/qmainwindow.cpp
@@ -1374,6 +1374,9 @@ bool QMainWindow::event(QEvent *event)
#endif // QT_NO_STATUSTIP
case QEvent::StyleChange:
+#ifndef QT_NO_DOCKWIDGET
+ d->layout->layoutState.dockAreaLayout.styleChangedEvent();
+#endif
if (!d->explicitIconSize)
setIconSize(QSize());
break;
@@ -1453,7 +1456,8 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
return;
// ### Disable the unified toolbar when using anything but the native graphics system.
- if (windowSurface())
+ // ### Disable when using alien widgets as well
+ if (windowSurface() || testAttribute(Qt::WA_NativeWindow) == false)
return;
d->useHIToolBar = set;
@@ -1535,11 +1539,15 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event)
#ifndef QT_NO_MENU
QMenu *popup = createPopupMenu();
- if (popup && !popup->isEmpty()) {
- popup->exec(event->globalPos());
- event->accept();
+ if (popup) {
+ if (!popup->isEmpty()) {
+ popup->setAttribute(Qt::WA_DeleteOnClose);
+ popup->popup(event->globalPos());
+ event->accept();
+ } else {
+ delete popup;
+ }
}
- delete popup;
#endif
}
#endif // QT_NO_CONTEXTMENU
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index d0ae90c83c..f84059db39 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -85,9 +85,8 @@
QT_BEGIN_NAMESPACE
-QPointer<QMenu> QMenuPrivate::mouseDown;
-QBasicTimer QMenuPrivate::menuDelayTimer;
-QBasicTimer QMenuPrivate::sloppyDelayTimer;
+QMenu *QMenuPrivate::mouseDown = 0;
+int QMenuPrivate::sloppyDelayTimer = 0;
/* QMenu code */
// internal class used for the torn off popup
@@ -261,9 +260,6 @@ void QMenuPrivate::updateActionRects() const
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..
@@ -337,7 +333,7 @@ void QMenuPrivate::updateActionRects() const
if (!sz.isEmpty()) {
- max_column_width = qMax(min_column_width, qMax(max_column_width, sz.width()));
+ max_column_width = qMax(max_column_width, sz.width());
//wrapping
if (!scroll &&
y+sz.height()+vmargin > dh - (deskFw * 2)) {
@@ -351,6 +347,10 @@ void QMenuPrivate::updateActionRects() const
}
max_column_width += tabWidth; //finally add in the tab width
+ 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));
+ max_column_width = qMax(min_column_width, max_column_width);
+
//calculate position
const int base_y = vmargin + fw + topmargin +
@@ -487,8 +487,8 @@ void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst)
if (action && action->isEnabled()) {
if (!delay)
q->internalDelayedPopup();
- else
- QMenuPrivate::menuDelayTimer.start(delay, q);
+ else if (!menuDelayTimer.isActive() && (!action->menu() || !action->menu()->isVisible()))
+ menuDelayTimer.start(delay, q);
if (activateFirst && action->menu())
action->menu()->d_func()->setFirstActionActive();
} else if (QMenu *menu = activeMenu) { //hide the current item
@@ -543,15 +543,6 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
{
Q_Q(QMenu);
tearoffHighlighted = 0;
- 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;
- }
if (currentAction)
q->update(actionRect(currentAction));
@@ -565,6 +556,7 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
#ifdef QT3_SUPPORT
emitHighlighted = action;
#endif
+
currentAction = action;
if (action) {
if (!action->isSeparator()) {
@@ -1813,7 +1805,7 @@ QSize QMenu::sizeHint() const
void QMenu::popup(const QPoint &p, QAction *atAction)
{
Q_D(QMenu);
- if (d->scroll) { //reset scroll state from last popup
+ if (d->scroll) { // reset scroll state from last popup
d->scroll->scrollOffset = 0;
d->scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone;
}
@@ -1842,7 +1834,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
QSize size = sizeHint();
QRect screen;
#ifndef QT_NO_GRAPHICSVIEW
- bool isEmbedded = d->nearestGraphicsProxyWidget(this);
+ bool isEmbedded = !bypassGraphicsProxyWidget(this) && d->nearestGraphicsProxyWidget(this);
if (isEmbedded)
screen = d->popupGeometry(this);
else
@@ -1868,9 +1860,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
}
#endif
if (d->ncols > 1) {
- pos.setY(screen.top()+desktopFrame);
+ pos.setY(screen.top() + desktopFrame);
} else if (atAction) {
- for(int i = 0, above_height = 0; i < d->actions.count(); 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;
@@ -1885,7 +1877,7 @@ 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 < d->actionRects.count(); i2++)
+ for (int i2 = i; i2 < d->actionRects.count(); i2++)
below_height += d->actionRects.at(i2).height();
size.setHeight(below_height);
}
@@ -1898,28 +1890,28 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
QPoint mouse = QCursor::pos();
d->mousePopupPos = mouse;
- const bool snapToMouse = (QRect(p.x()-3, p.y()-3, 6, 6).contains(mouse));
+ const bool snapToMouse = (QRect(p.x() - 3, p.y() - 3, 6, 6).contains(mouse));
if (adjustToDesktop) {
- //handle popup falling "off screen"
+ // handle popup falling "off screen"
if (isRightToLeft()) {
- if(snapToMouse) //position flowing left from the mouse
- pos.setX(mouse.x()-size.width());
+ if (snapToMouse) // position flowing left from the mouse
+ pos.setX(mouse.x() - size.width());
#ifndef QT_NO_MENUBAR
- //if in a menubar, it should be right-aligned
+ // if in a menubar, it should be right-aligned
if (qobject_cast<QMenuBar*>(d->causedPopup.widget))
pos.rx() -= size.width();
#endif //QT_NO_MENUBAR
- if (pos.x() < screen.left()+desktopFrame)
- pos.setX(qMax(p.x(), screen.left()+desktopFrame));
- if (pos.x()+size.width()-1 > screen.right()-desktopFrame)
- pos.setX(qMax(p.x()-size.width(), screen.right()-desktopFrame-size.width()+1));
+ if (pos.x() < screen.left() + desktopFrame)
+ pos.setX(qMax(p.x(), screen.left() + desktopFrame));
+ if (pos.x() + size.width() - 1 > screen.right() - desktopFrame)
+ pos.setX(qMax(p.x() - size.width(), screen.right() - desktopFrame - size.width() + 1));
} else {
- if (pos.x()+size.width()-1 > screen.right()-desktopFrame)
- pos.setX(screen.right()-desktopFrame-size.width()+1);
- if (pos.x() < screen.left()+desktopFrame)
+ if (pos.x() + size.width() - 1 > screen.right() - desktopFrame)
+ pos.setX(screen.right() - desktopFrame - size.width() + 1);
+ if (pos.x() < screen.left() + desktopFrame)
pos.setX(screen.left() + desktopFrame);
}
if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) {
@@ -1933,14 +1925,14 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
if (pos.y() < screen.top() + desktopFrame)
pos.setY(screen.top() + desktopFrame);
- if (pos.y()+size.height()-1 > screen.bottom() - desktopFrame) {
+ if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) {
if (d->scroll) {
d->scroll->scrollFlags |= uint(QMenuPrivate::QMenuScroller::ScrollDown);
int y = qMax(screen.y(),pos.y());
- size.setHeight(screen.bottom()-(desktopFrame*2)-y);
+ size.setHeight(screen.bottom() - (desktopFrame * 2) - y);
} else {
// Too big for screen, bias to see bottom of menu (for some reason)
- pos.setY(screen.bottom()-size.height()+1);
+ pos.setY(screen.bottom() - size.height() + 1);
}
}
}
@@ -1949,19 +1941,19 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
int hGuess = isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
int vGuess = QEffects::DownScroll;
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()))
+ 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;
} else {
- if ((snapToMouse && (pos.x() + size.width()/2 < mouse.x())) ||
- (qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width()/2 < d->causedPopup.widget->x()))
+ 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::LeftScroll;
}
#ifndef QT_NO_MENUBAR
- if ((snapToMouse && (pos.y() + size.height()/2 < mouse.y())) ||
+ if ((snapToMouse && (pos.y() + size.height() / 2 < mouse.y())) ||
(qobject_cast<QMenuBar*>(d->causedPopup.widget) &&
- pos.y() + size.width()/2 < d->causedPopup.widget->mapToGlobal(d->causedPopup.widget->pos()).y()))
+ pos.y() + size.width() / 2 < d->causedPopup.widget->mapToGlobal(d->causedPopup.widget->pos()).y()))
vGuess = QEffects::UpScroll;
#endif
if (QApplication::isEffectEnabled(Qt::UI_AnimateMenu)) {
@@ -2311,9 +2303,7 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e)
QAction *action = d->actionAt(e->pos());
if (action && action == d->currentAction) {
- if (action->menu())
- action->menu()->d_func()->setFirstActionActive();
- else {
+ if (!action->menu()){
#if defined(Q_WS_WIN)
//On Windows only context menus can be activated with the right button
if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0)
@@ -2387,8 +2377,8 @@ QMenu::event(QEvent *e)
}
} break;
case QEvent::ContextMenu:
- if(QMenuPrivate::menuDelayTimer.isActive()) {
- QMenuPrivate::menuDelayTimer.stop();
+ if(d->menuDelayTimer.isActive()) {
+ d->menuDelayTimer.stop();
internalDelayedPopup();
}
break;
@@ -2823,7 +2813,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e)
}
if (d->sloppyRegion.contains(e->pos())) {
d->sloppyAction = action;
- QMenuPrivate::sloppyDelayTimer.start(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6, this);
+ QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6);
} else {
d->setCurrentAction(action, style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this));
}
@@ -2861,11 +2851,12 @@ QMenu::timerEvent(QTimerEvent *e)
d->scrollMenu((QMenuPrivate::QMenuScroller::ScrollDirection)d->scroll->scrollDirection);
if (d->scroll->scrollFlags == QMenuPrivate::QMenuScroller::ScrollNone)
d->scroll->scrollTimer.stop();
- } else if(QMenuPrivate::menuDelayTimer.timerId() == e->timerId()) {
- QMenuPrivate::menuDelayTimer.stop();
+ } else if(d->menuDelayTimer.timerId() == e->timerId()) {
+ d->menuDelayTimer.stop();
internalDelayedPopup();
- } else if(QMenuPrivate::sloppyDelayTimer.timerId() == e->timerId()) {
- QMenuPrivate::sloppyDelayTimer.stop();
+ } else if(QMenuPrivate::sloppyDelayTimer == e->timerId()) {
+ killTimer(QMenuPrivate::sloppyDelayTimer);
+ QMenuPrivate::sloppyDelayTimer = 0;
internalSetSloppyAction();
} else if(d->searchBufferTimer.timerId() == e->timerId()) {
d->searchBuffer.clear();
diff --git a/src/gui/widgets/qmenu.h b/src/gui/widgets/qmenu.h
index 47dff2b4ee..a040afab17 100644
--- a/src/gui/widgets/qmenu.h
+++ b/src/gui/widgets/qmenu.h
@@ -417,6 +417,7 @@ private:
friend OSStatus qt_mac_menu_event(EventHandlerCallRef, EventRef, void *);
friend bool qt_mac_activate_action(OSMenuRef, uint, QAction::ActionEvent, bool);
friend void qt_mac_emit_menuSignals(QMenu *, bool);
+ friend void qt_mac_menu_emit_hovered(QMenu *menu, QAction *action);
#endif
};
diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm
index 7e4bbb51ad..aaa113be55 100644
--- a/src/gui/widgets/qmenu_mac.mm
+++ b/src/gui/widgets/qmenu_mac.mm
@@ -247,7 +247,7 @@ bool qt_mac_activate_action(MenuRef menu, uint command, QAction::ActionEvent act
//now walk up firing for each "caused" widget (like in the platform independent menu)
QWidget *caused = 0;
- if (GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, sizeof(caused), 0, &caused) == noErr) {
+ if (action_e == QAction::Hover && GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, sizeof(caused), 0, &caused) == noErr) {
MenuRef caused_menu = 0;
if (QMenu *qmenu2 = qobject_cast<QMenu*>(caused))
caused_menu = qmenu2->macMenu();
@@ -260,25 +260,17 @@ bool qt_mac_activate_action(MenuRef menu, uint command, QAction::ActionEvent act
QWidget *widget = 0;
GetMenuItemProperty(caused_menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(widget), 0, &widget);
if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) {
- if (action_e == QAction::Trigger) {
- emit qmenu->triggered(action->action);
- } else if (action_e == QAction::Hover) {
- action->action->showStatusText(widget);
- emit qmenu->hovered(action->action);
- }
+ action->action->showStatusText(widget);
+ emit qmenu->hovered(action->action);
} else if (QMenuBar *qmenubar = qobject_cast<QMenuBar*>(widget)) {
- if (action_e == QAction::Trigger) {
- emit qmenubar->triggered(action->action);
- } else if (action_e == QAction::Hover) {
- action->action->showStatusText(widget);
- emit qmenubar->hovered(action->action);
- }
+ action->action->showStatusText(widget);
+ emit qmenubar->hovered(action->action);
break; //nothing more..
}
//walk up
if (GetMenuItemProperty(caused_menu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget,
- sizeof(caused), 0, &caused) != noErr)
+ sizeof(caused), 0, &caused) != noErr)
break;
if (QMenu *qmenu2 = qobject_cast<QMenu*>(caused))
caused_menu = qmenu2->macMenu();
@@ -649,7 +641,7 @@ static NSMenuItem *createNSMenuItem(const QString &title)
NSMenuItem *item = [[NSMenuItem alloc]
initWithTitle:qt_mac_QStringToNSString(title)
action:@selector(qtDispatcherToQAction:) keyEquivalent:@""];
- [item setTarget:getMenuLoader()];
+ [item setTarget:nil];
return item;
}
#endif
@@ -673,6 +665,7 @@ void qt_mac_set_modal_state_helper_recursive(OSMenuRef menu, OSMenuRef merge, bo
}
}
#else
+ bool modalWindowOnScreen = qApp->activeModalWidget() != 0;
for (NSMenuItem *item in [menu itemArray]) {
OSMenuRef submenu = [item submenu];
if (submenu != merge) {
@@ -682,10 +675,20 @@ 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]);
- syncNSMenuItemEnabled(item, action->isEnabled());
- } else {
- syncNSMenuItemEnabled(item, YES);
- }
+ syncNSMenuItemEnabled(item, action->isEnabled());
+ } else {
+ syncNSMenuItemEnabled(item, YES);
+ }
+ // We sneak in some extra code here to handle a menu problem:
+ // If there is no window on screen, we cannot set 'nil' as
+ // menu item target, because then cocoa will disable the item
+ // (guess it assumes that there will be no first responder to
+ // catch the trigger anyway?) OTOH, If we have a modal window,
+ // then setting the menu loader as target will make cocoa not
+ // deliver the trigger because the loader is then seen as modally
+ // shaddowed). So either way there are shortcomings. Instead, we
+ // decide the target as late as possible:
+ [item setTarget:modalWindowOnScreen ? nil : getMenuLoader()];
} else {
syncNSMenuItemEnabled(item, NO);
}
@@ -749,32 +752,6 @@ bool qt_mac_menubar_is_open()
return qt_mac_menus_open_count > 0;
}
-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) {
- SetRootMenu(clear_menu);
- ReleaseMenu(clear_menu);
- } else {
- qWarning("QMenu: Internal error at %s:%d", __FILE__, __LINE__);
- }
- ClearMenuBar();
- qt_mac_command_set_enabled(0, kHICommandPreferences, false);
- InvalMenuBar();
-#else
- QMacCocoaAutoReleasePool pool;
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
- NSMenu *menu = [loader menu];
- [loader ensureAppMenuInMenu:menu];
- [NSApp setMainMenu:menu];
-#endif
-}
-
-
QMacMenuAction::~QMacMenuAction()
{
#ifdef QT_MAC_USE_COCOA
@@ -943,6 +920,7 @@ static NSMenuItem *qt_mac_menu_merge_action(OSMenuRef merge, QMacMenuAction *act
static QString qt_mac_menu_merge_text(QMacMenuAction *action)
{
QString ret;
+ extern QString qt_mac_applicationmenu_string(int type);
#ifdef QT_MAC_USE_COCOA
QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
#endif
@@ -950,22 +928,26 @@ static QString qt_mac_menu_merge_text(QMacMenuAction *action)
ret = action->action->text();
#ifndef QT_MAC_USE_COCOA
else if (action->command == kHICommandAbout)
- ret = QMenuBar::tr("About %1").arg(qAppName());
+ ret = qt_mac_applicationmenu_string(6).arg(qAppName());
else if (action->command == kHICommandAboutQt)
ret = QMenuBar::tr("About Qt");
else if (action->command == kHICommandPreferences)
- ret = QMenuBar::tr("Preferences");
+ ret = qt_mac_applicationmenu_string(4);
else if (action->command == kHICommandQuit)
- ret = QMenuBar::tr("Quit %1").arg(qAppName());
+ ret = qt_mac_applicationmenu_string(5).arg(qAppName());
#else
- else if (action->menuItem == [loader aboutMenuItem])
- ret = QMenuBar::tr("About %1").arg(qAppName());
- else if (action->menuItem == [loader aboutQtMenuItem])
- ret = QMenuBar::tr("About Qt");
- else if (action->menuItem == [loader preferencesMenuItem])
- ret = QMenuBar::tr("Preferences");
- else if (action->menuItem == [loader quitMenuItem])
- ret = QMenuBar::tr("Quit %1").arg(qAppName());
+ else if (action->menuItem == [loader aboutMenuItem]) {
+ ret = qt_mac_applicationmenu_string(6).arg(qAppName());
+ } else if (action->menuItem == [loader aboutQtMenuItem]) {
+ if (action->action->text() == QString("About Qt"))
+ ret = QMenuBar::tr("About Qt");
+ else
+ ret = action->action->text();
+ } else if (action->menuItem == [loader preferencesMenuItem]) {
+ ret = qt_mac_applicationmenu_string(4);
+ } else if (action->menuItem == [loader quitMenuItem]) {
+ ret = qt_mac_applicationmenu_string(5).arg(qAppName());
+ }
#endif
return ret;
}
@@ -1130,7 +1112,7 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction
action->menu = merge;
[cmd retain];
[cmd setAction:@selector(qtDispatcherToQAction:)];
- [cmd setTarget:getMenuLoader()];
+ [cmd setTarget:nil];
[action->menuItem release];
action->menuItem = cmd;
QMenuMergeList *list = QMenuPrivate::mergeMenuItemsHash.value(merge);
@@ -1420,7 +1402,11 @@ QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action)
} else {
[item setTitle: qt_mac_QStringToNSString(finalString)];
}
- [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))];
+
+ if (action->action->menuRole() == QAction::AboutRole || action->action->menuRole() == QAction::QuitRole)
+ [item setTitle:qt_mac_QStringToNSString(text)];
+ else
+ [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))];
// Cocoa Enabled
[item setEnabled: action->action->isEnabled()];
@@ -1845,7 +1831,7 @@ void QMenuBarPrivate::macDestroyMenuBar()
menubars()->remove(tlw);
mac_menubar = 0;
- if (qt_mac_current_menubar.qmenubar == q) {
+ if (!qt_mac_current_menubar.qmenubar || qt_mac_current_menubar.qmenubar == q) {
#ifdef QT_MAC_USE_COCOA
QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
[loader removeActionsFromAppMenu];
@@ -1936,43 +1922,53 @@ static bool qt_mac_is_ancestor(QWidget* possibleAncestor, QWidget *child)
Returns true if the entries of menuBar should be disabled,
based on the modality type of modalWidget.
*/
-static bool qt_mac_should_disable_menu(QMenuBar *menuBar, QWidget *modalWidget)
+static bool qt_mac_should_disable_menu(QMenuBar *menuBar)
{
- if (modalWidget == 0 || menuBar == 0)
+ QWidget *modalWidget = qApp->activeModalWidget();
+ if (!modalWidget)
+ return false;
+
+ if (menuBar && menuBar == menubars()->value(modalWidget))
+ // The menu bar is owned by the modal widget.
+ // In that case we should enable it:
return false;
- // If there is an application modal window on
- // screen, the entries of the menubar should be disabled:
+ // When there is an application modal window on screen, the entries of
+ // the menubar should be disabled. The exception in Qt is that if the
+ // modal window is the only window on screen, then we enable the menu bar.
QWidget *w = modalWidget;
+ QWidgetList topLevelWidgets = QApplication::topLevelWidgets();
while (w) {
- if (w->isVisible() && w->windowModality() == Qt::ApplicationModal)
- return true;
+ if (w->isVisible() && w->windowModality() == Qt::ApplicationModal) {
+ for (int i=0; i<topLevelWidgets.size(); ++i) {
+ QWidget *top = topLevelWidgets.at(i);
+ if (w != top && top->isVisible()) {
+ // INVARIANT: we found another visible window
+ // on screen other than our modalWidget. We therefore
+ // disable the menu bar to follow normal modality logic:
+ return true;
+ }
+ }
+ // INVARIANT: We have only one window on screen that happends
+ // to be application modal. We choose to enable the menu bar
+ // in that case to e.g. enable the quit menu item.
+ return false;
+ }
w = w->parentWidget();
}
// 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);
+ // if the menu bar belongs to an ancestor of modalWidget. If menuBar
+ // is nil, we understand it as the default menu bar set by the nib:
+ return menuBar ? qt_mac_is_ancestor(menuBar->parentWidget(), modalWidget) : false;
}
-/*!
- \internal
-
- This function will update the current menu bar and set it as the
- active menu bar in the Menu Manager.
-
- \warning This function is not portable.
-
- \sa QMenu::macMenu(), QMenuBar::macMenu()
-*/
-bool QMenuBar::macUpdateMenuBar()
+static QWidget *findWindowThatShouldDisplayMenubar()
{
- cancelAllMenuTracking();
- QMenuBar *mb = 0;
- //find a menu bar
QWidget *w = qApp->activeWindow();
-
if (!w) {
+ // We have no active window on screen. Try to
+ // find a window from the list of top levels:
QWidgetList tlws = QApplication::topLevelWidgets();
for(int i = 0; i < tlws.size(); ++i) {
QWidget *tlw = tlws.at(i);
@@ -1983,6 +1979,12 @@ bool QMenuBar::macUpdateMenuBar()
}
}
}
+ return w;
+}
+
+static QMenuBar *findMenubarForWindow(QWidget *w)
+{
+ QMenuBar *mb = 0;
if (w) {
mb = menubars()->value(w);
#ifndef QT_NO_MAINWINDOW
@@ -1996,11 +1998,96 @@ bool QMenuBar::macUpdateMenuBar()
while(w && !mb)
mb = menubars()->value((w = w->parentWidget()));
}
- if (!mb)
+
+ if (!mb) {
+ // We could not find a menu bar for the window. Lets
+ // check if we have a global (parentless) menu bar instead:
mb = fallback;
- //now set it
+ }
+
+ return mb;
+}
+
+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) {
+ SetRootMenu(clear_menu);
+ ReleaseMenu(clear_menu);
+ } else {
+ qWarning("QMenu: Internal error at %s:%d", __FILE__, __LINE__);
+ }
+ ClearMenuBar();
+ qt_mac_command_set_enabled(0, kHICommandPreferences, false);
+ InvalMenuBar();
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
+ NSMenu *menu = [loader menu];
+ [loader ensureAppMenuInMenu:menu];
+ [NSApp setMainMenu:menu];
+ const bool modal = qt_mac_should_disable_menu(0);
+ if (qt_mac_current_menubar.qmenubar || modal != qt_mac_current_menubar.modal)
+ qt_mac_set_modal_state(menu, modal);
+ qt_mac_current_menubar.qmenubar = 0;
+ qt_mac_current_menubar.modal = modal;
+#endif
+}
+
+/*!
+ \internal
+
+ This function will update the current menu bar and set it as the
+ active menu bar in the Menu Manager.
+
+ \warning This function is not portable.
+
+ \sa QMenu::macMenu(), QMenuBar::macMenu()
+*/
+bool QMenuBar::macUpdateMenuBar()
+{
+#ifdef QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ if (!qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar)))
+ return QMenuBarPrivate::macUpdateMenuBarImmediatly();
+ return true;
+#else
+ return QMenuBarPrivate::macUpdateMenuBarImmediatly();
+#endif
+}
+
+bool QMenuBarPrivate::macUpdateMenuBarImmediatly()
+{
bool ret = false;
+ cancelAllMenuTracking();
+ QWidget *w = findWindowThatShouldDisplayMenubar();
+ QMenuBar *mb = findMenubarForWindow(w);
+ extern bool qt_mac_app_fullscreen; //qapplication_mac.mm
+
+ // We need to see if we are in full screen mode, if so we need to
+ // switch the full screen mode to be able to show or hide the menubar.
+ if(w && mb) {
+ // This case means we are creating a menubar, check if full screen
+ if(w->isFullScreen()) {
+ // Ok, switch to showing the menubar when hovering over it.
+ SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
+ qt_mac_app_fullscreen = true;
+ }
+ } else if(w) {
+ // Removing a menubar
+ if(w->isFullScreen()) {
+ // Ok, switch to not showing the menubar when hovering on it
+ SetSystemUIMode(kUIModeAllHidden, 0);
+ qt_mac_app_fullscreen = true;
+ }
+ }
+
if (mb && mb->isNativeMenuBar()) {
+ bool modal = QApplicationPrivate::modalState();
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
#endif
@@ -2030,16 +2117,18 @@ bool QMenuBar::macUpdateMenuBar()
}
}
#endif
- QWidget *modalWidget = qApp->activeModalWidget();
- if (mb != menubars()->value(modalWidget)) {
- qt_mac_set_modal_state(menu, qt_mac_should_disable_menu(mb, modalWidget));
- }
+ // Check if menu is modally shaddowed and should be disabled:
+ modal = qt_mac_should_disable_menu(mb);
+ if (mb != qt_mac_current_menubar.qmenubar || modal != qt_mac_current_menubar.modal)
+ qt_mac_set_modal_state(menu, modal);
}
qt_mac_current_menubar.qmenubar = mb;
- qt_mac_current_menubar.modal = QApplicationPrivate::modalState();
+ qt_mac_current_menubar.modal = modal;
ret = true;
} else if (qt_mac_current_menubar.qmenubar && qt_mac_current_menubar.qmenubar->isNativeMenuBar()) {
- const bool modal = QApplicationPrivate::modalState();
+ // INVARIANT: The currently active menu bar (if any) is not native. But we do have a
+ // native menu bar from before. So we need to decide whether or not is should be enabled:
+ const bool modal = qt_mac_should_disable_menu(qt_mac_current_menubar.qmenubar);
if (modal != qt_mac_current_menubar.modal) {
ret = true;
if (OSMenuRef menu = qt_mac_current_menubar.qmenubar->macMenu()) {
@@ -2051,16 +2140,15 @@ bool QMenuBar::macUpdateMenuBar()
[NSApp setMainMenu:menu];
syncMenuBarItemsVisiblity(qt_mac_current_menubar.qmenubar->d_func()->mac_menubar);
#endif
- QWidget *modalWidget = qApp->activeModalWidget();
- if (qt_mac_current_menubar.qmenubar != menubars()->value(modalWidget)) {
- qt_mac_set_modal_state(menu, qt_mac_should_disable_menu(mb, modalWidget));
- }
+ qt_mac_set_modal_state(menu, modal);
}
qt_mac_current_menubar.modal = modal;
}
}
- if(!ret)
+
+ if (!ret) {
qt_mac_clear_menubar();
+ }
return ret;
}
@@ -2131,3 +2219,4 @@ static OSMenuRef qt_mac_create_menu(QWidget *w)
QT_END_NAMESPACE
+
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h
index 495872cd41..39cbbd8422 100644
--- a/src/gui/widgets/qmenu_p.h
+++ b/src/gui/widgets/qmenu_p.h
@@ -202,7 +202,7 @@ public:
bool activationRecursionGuard;
//selection
- static QPointer<QMenu> mouseDown;
+ static QMenu *mouseDown;
QPoint mousePopupPos;
uint hasHadMouse : 1;
uint aboutToHide : 1;
@@ -212,7 +212,7 @@ public:
QAction *selectAction;
QAction *cancelAction;
#endif
- static QBasicTimer menuDelayTimer;
+ QBasicTimer menuDelayTimer;
enum SelectionReason {
SelectedFromKeyboard,
SelectedFromElsewhere
@@ -272,7 +272,7 @@ public:
mutable bool hasCheckableItems;
//sloppy selection
- static QBasicTimer sloppyDelayTimer;
+ static int sloppyDelayTimer;
mutable QAction *sloppyAction;
QRegion sloppyRegion;
diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp
index 7224768783..4a9cfed3d2 100644
--- a/src/gui/widgets/qmenu_symbian.cpp
+++ b/src/gui/widgets/qmenu_symbian.cpp
@@ -48,7 +48,7 @@
#include <private/qapplication_p.h>
#include <private/qmenu_p.h>
#include <private/qmenubar_p.h>
-#include <qt_s60_p.h>
+#include <private/qt_s60_p.h>
#include <QtCore/qlibrary.h>
#ifdef Q_WS_S60
diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp
index e368d3da7a..ef37fd1d39 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -268,19 +268,15 @@ void QMenuBarPrivate::updateGeometries()
QRect QMenuBarPrivate::actionRect(QAction *act) const
{
- Q_Q(const QMenuBar);
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())
+ if (index < 0 || 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);
+ return actionRects.at(index);
}
void QMenuBarPrivate::focusFirstAction()
@@ -505,6 +501,9 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start) const
//keep moving along..
x += rect.width() + itemSpacing;
+
+ //make sure we follow the layout direction
+ rect = QStyle::visualRect(q->layoutDirection(), q->rect(), rect);
}
}
@@ -1932,9 +1931,9 @@ void QMenuBar::setNativeMenuBar(bool nativeMenuBar)
d->macCreateMenuBar(parentWidget());
}
macUpdateMenuBar();
- updateGeometry();
- setVisible(false);
- setVisible(true);
+ updateGeometry();
+ if (!d->nativeMenuBar && parentWidget())
+ setVisible(true);
#endif
}
}
diff --git a/src/gui/widgets/qmenubar_p.h b/src/gui/widgets/qmenubar_p.h
index e4db6ce275..82070feaa5 100644
--- a/src/gui/widgets/qmenubar_p.h
+++ b/src/gui/widgets/qmenubar_p.h
@@ -196,6 +196,7 @@ public:
return 0;
}
} *mac_menubar;
+ static bool macUpdateMenuBarImmediatly();
bool macWidgetHasNativeMenubar(QWidget *widget);
void macCreateMenuBar(QWidget *);
void macDestroyMenuBar();
diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp
index ab598d9121..2734fba343 100644
--- a/src/gui/widgets/qplaintextedit.cpp
+++ b/src/gui/widgets/qplaintextedit.cpp
@@ -911,6 +911,7 @@ void QPlainTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCurso
setTopBlock(block.blockNumber(), line);
if (moveCursor) {
+ cursor.setVisualNavigation(true);
// move using movePosition to keep the cursor's x
lastY += verticalOffset();
bool moved = false;
@@ -943,8 +944,8 @@ void QPlainTextEditPrivate::_q_adjustScrollbars()
int vSliderLength = 0;
if (!centerOnScroll && q->isVisible()) {
QTextBlock block = doc->lastBlock();
- const int visible = static_cast<int>(viewport->rect().height() - margin - 1);
- int y = 0;
+ const qreal visible = viewport->rect().height() - margin - 1;
+ qreal y = 0;
int visibleFromBottom = 0;
while (block.isValid()) {
@@ -952,7 +953,7 @@ void QPlainTextEditPrivate::_q_adjustScrollbars()
block = block.previous();
continue;
}
- y += int(documentLayout->blockBoundingRect(block).height());
+ y += documentLayout->blockBoundingRect(block).height();
QTextLayout *layout = block.layout();
int layoutLineCount = layout->lineCount();
@@ -961,7 +962,7 @@ void QPlainTextEditPrivate::_q_adjustScrollbars()
while (lineNumber < layoutLineCount) {
QTextLine line = layout->lineAt(lineNumber);
const QRectF lr = line.naturalTextRect();
- if (int(lr.top()) >= y - visible)
+ if (lr.top() >= y - visible)
break;
++lineNumber;
}
@@ -1319,6 +1320,26 @@ QTextCursor QPlainTextEdit::textCursor() const
return d->control->textCursor();
}
+/*!
+ Returns the reference of the anchor at position \a pos, or an
+ empty string if no anchor exists at that point.
+
+ \since 4.7
+ */
+QString QPlainTextEdit::anchorAt(const QPoint &pos) const
+{
+ Q_D(const QPlainTextEdit);
+ int cursorPos = d->control->hitTest(pos + QPoint(d->horizontalOffset(),
+ d->verticalOffset()),
+ Qt::ExactHit);
+ if (cursorPos < 0)
+ return QString();
+
+ QTextDocumentPrivate *pieceTable = document()->docHandle();
+ QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos);
+ QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format);
+ return fmt.anchorHref();
+}
/*!
Undoes the last operation.
@@ -2393,7 +2414,7 @@ void QPlainTextEdit::setReadOnly(bool ro)
then the focus policy is also automatically set to Qt::ClickFocus.
The default value depends on whether the QPlainTextEdit is read-only
- or editable, and whether it is a QTextBrowser or not.
+ or editable.
*/
void QPlainTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
diff --git a/src/gui/widgets/qplaintextedit.h b/src/gui/widgets/qplaintextedit.h
index 15cf096732..106ae6d853 100644
--- a/src/gui/widgets/qplaintextedit.h
+++ b/src/gui/widgets/qplaintextedit.h
@@ -159,6 +159,8 @@ public:
QRect cursorRect(const QTextCursor &cursor) const;
QRect cursorRect() const;
+ QString anchorAt(const QPoint &pos) const;
+
bool overwriteMode() const;
void setOverwriteMode(bool overwrite);
diff --git a/src/gui/widgets/qradiobutton.cpp b/src/gui/widgets/qradiobutton.cpp
index d73ff2f993..20b6c7202e 100644
--- a/src/gui/widgets/qradiobutton.cpp
+++ b/src/gui/widgets/qradiobutton.cpp
@@ -195,7 +195,7 @@ QSize QRadioButton::sizeHint() const
ensurePolished();
QStyleOptionButton opt;
initStyleOption(&opt);
- QSize sz = style()->itemTextRect(fontMetrics(), QRect(0, 0, 1, 1), Qt::TextShowMnemonic,
+ QSize sz = style()->itemTextRect(fontMetrics(), QRect(), Qt::TextShowMnemonic,
false, text()).size();
if (!opt.icon.isNull())
sz = QSize(sz.width() + opt.iconSize.width() + 4, qMax(sz.height(), opt.iconSize.height()));
diff --git a/src/gui/widgets/qscrollarea.cpp b/src/gui/widgets/qscrollarea.cpp
index 6b81d9fd87..38e799e2fb 100644
--- a/src/gui/widgets/qscrollarea.cpp
+++ b/src/gui/widgets/qscrollarea.cpp
@@ -482,14 +482,14 @@ void QScrollArea::ensureWidgetVisible(QWidget *childWidget, int xmargin, int yma
d->hbar->setValue(focusRect.center().x() - d->viewport->width() / 2);
else if (focusRect.right() > visibleRect.right())
d->hbar->setValue(focusRect.right() - d->viewport->width());
- else
+ else if (focusRect.left() < visibleRect.left())
d->hbar->setValue(focusRect.left());
if (focusRect.height() > visibleRect.height())
d->vbar->setValue(focusRect.center().y() - d->viewport->height() / 2);
else if (focusRect.bottom() > visibleRect.bottom())
d->vbar->setValue(focusRect.bottom() - d->viewport->height());
- else
+ else if (focusRect.top() < visibleRect.top())
d->vbar->setValue(focusRect.top());
}
diff --git a/src/gui/widgets/qscrollbar.cpp b/src/gui/widgets/qscrollbar.cpp
index 4eff260588..4ee9f2795d 100644
--- a/src/gui/widgets/qscrollbar.cpp
+++ b/src/gui/widgets/qscrollbar.cpp
@@ -47,7 +47,7 @@
#include "qstyle.h"
#include "qstyleoption.h"
#include "qmenu.h"
-#include <QtCore/qdatetime.h>
+#include <QtCore/qelapsedtimer.h>
#ifndef QT_NO_SCROLLBAR
@@ -523,6 +523,7 @@ bool QScrollBar::event(QEvent *event)
break;
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel: {
+ event->ignore();
// override wheel event without adding virtual function override
QWheelEvent *ev = static_cast<QWheelEvent *>(event);
int delta = ev->delta();
@@ -612,7 +613,7 @@ void QScrollBar::mousePressEvent(QMouseEvent *e)
}
const int initialDelay = 500; // default threshold
d->activateControl(d->pressedControl, initialDelay);
- QTime time;
+ QElapsedTimer time;
time.start();
repaint(style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this));
if (time.elapsed() >= initialDelay && d->repeatActionTimer.isActive()) {
diff --git a/src/gui/widgets/qsplitter.cpp b/src/gui/widgets/qsplitter.cpp
index 965094e8e7..88b7517e5e 100644
--- a/src/gui/widgets/qsplitter.cpp
+++ b/src/gui/widgets/qsplitter.cpp
@@ -227,6 +227,33 @@ QSize QSplitterHandle::sizeHint() const
/*!
\reimp
*/
+void QSplitterHandle::resizeEvent(QResizeEvent *event)
+{
+ Q_D(const QSplitterHandle);
+
+ // When splitters are only 1 pixel large we increase the
+ // actual grab area to five pixels
+
+ // Note that QSplitter uses contentsRect for layouting
+ // and ensures that handles are drawn on top of widgets
+ // We simply use the contents margins for draggin and only
+ // paint the mask area
+ bool useTinyMode = (d->s->handleWidth() == 1);
+ setAttribute(Qt::WA_MouseNoMask, useTinyMode);
+ if (useTinyMode) {
+ if (orientation() == Qt::Horizontal)
+ setContentsMargins(2, 0, 2, 0);
+ else
+ setContentsMargins(0, 2, 0, 2);
+ setMask(QRegion(contentsRect()));
+ }
+
+ QWidget::resizeEvent(event);
+}
+
+/*!
+ \reimp
+*/
bool QSplitterHandle::event(QEvent *event)
{
Q_D(QSplitterHandle);
@@ -301,7 +328,7 @@ void QSplitterHandle::paintEvent(QPaintEvent *)
Q_D(QSplitterHandle);
QPainter p(this);
QStyleOption opt(0);
- opt.rect = rect();
+ opt.rect = contentsRect();
opt.palette = palette();
if (orientation() == Qt::Horizontal)
opt.state = QStyle::State_Horizontal;
@@ -1276,7 +1303,6 @@ void QSplitter::childEvent(QChildEvent *c)
if (!c->child()->isWidgetType())
return;
QWidget *w = static_cast<QWidget*>(c->child());
-
if (c->added() && !d->blockChildAdd && !w->isWindow() && !d->findWidget(w)) {
d->insertWidget_helper(d->list.count(), w, false);
} else if (c->polished() && !d->blockChildAdd) {
@@ -1306,25 +1332,23 @@ void QSplitter::setRubberBand(int pos)
Q_D(QSplitter);
if (pos < 0) {
if (d->rubberBand)
- QTimer::singleShot(0, d->rubberBand, SLOT(deleteLater()));
+ d->rubberBand->deleteLater();
return;
}
QRect r = contentsRect();
const int rBord = 3; // customizable?
int hw = handleWidth();
if (!d->rubberBand) {
- d->rubberBand = new QRubberBand(QRubberBand::Line);
+ QBoolBlocker b(d->blockChildAdd);
+ d->rubberBand = new QRubberBand(QRubberBand::Line, this);
// For accessibility to identify this special widget.
d->rubberBand->setObjectName(QLatin1String("qt_rubberband"));
}
- if (d->orient == Qt::Horizontal)
- d->rubberBand->setGeometry(QRect(QPoint(pos + hw / 2 - rBord, r.y()),
- QSize(2 * rBord, r.height())).translated(mapToGlobal(QPoint())));
- else
- d->rubberBand->setGeometry(QRect(QPoint(r.x(), pos + hw / 2 - rBord),
- QSize(r.width(), 2 * rBord)).translated(mapToGlobal(QPoint())));
- if (!d->rubberBand->isVisible())
- d->rubberBand->show();
+
+ const QRect newGeom = d->orient == Qt::Horizontal ? QRect(QPoint(pos + hw / 2 - rBord, r.y()), QSize(2 * rBord, r.height()))
+ : QRect(QPoint(r.x(), pos + hw / 2 - rBord), QSize(r.width(), 2 * rBord));
+ d->rubberBand->setGeometry(newGeom);
+ d->rubberBand->show();
}
/*!
@@ -1555,16 +1579,14 @@ QSize QSplitter::sizeHint() const
ensurePolished();
int l = 0;
int t = 0;
- QObjectList childList = children();
- for (int i = 0; i < childList.size(); ++i) {
- if (QWidget *w = qobject_cast<QWidget *>(childList.at(i))) {
- if (w->isHidden())
- continue;
- QSize s = w->sizeHint();
- if (s.isValid()) {
- l += d->pick(s);
- t = qMax(t, d->trans(s));
- }
+ for (int i = 0; i < d->list.size(); ++i) {
+ QWidget *w = d->list.at(i)->widget;
+ if (w->isHidden())
+ continue;
+ QSize s = w->sizeHint();
+ if (s.isValid()) {
+ l += d->pick(s);
+ t = qMax(t, d->trans(s));
}
}
return orientation() == Qt::Horizontal ? QSize(l, t) : QSize(t, l);
@@ -1667,6 +1689,9 @@ void QSplitter::setSizes(const QList<int> &list)
By default, this property contains a value that depends on the user's platform
and style preferences.
+
+ If you set handleWidth to 1, the actual grab area will grow to overlap a
+ few pixels of it's respective widgets.
*/
int QSplitter::handleWidth() const
diff --git a/src/gui/widgets/qsplitter.h b/src/gui/widgets/qsplitter.h
index a793f24fc6..c3b304dc59 100644
--- a/src/gui/widgets/qsplitter.h
+++ b/src/gui/widgets/qsplitter.h
@@ -172,6 +172,7 @@ protected:
void mouseMoveEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
+ void resizeEvent(QResizeEvent *);
bool event(QEvent *);
void moveSplitter(int p);
diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp
index 22e825561b..8aaaade29e 100644
--- a/src/gui/widgets/qtabbar.cpp
+++ b/src/gui/widgets/qtabbar.cpp
@@ -69,6 +69,7 @@
QT_BEGIN_NAMESPACE
+
inline static bool verticalTabs(QTabBar::Shape shape)
{
return shape == QTabBar::RoundedWest
@@ -95,9 +96,20 @@ void QTabBarPrivate::updateMacBorderMetrics()
metrics.left = 0;
metrics.right = 0;
qt_mac_updateContentBorderMetricts(window, metrics);
-
- // hide the base line separator if the tabs have docuemnt mode enabled (Cocoa)
- qt_mac_showBaseLineSeparator(window, !documentMode);
+#if QT_MAC_USE_COCOA
+ // In Cocoa we need to keep track of the drawRect method.
+ // If documentMode is enabled we need to change it, unless
+ // a toolbar is present.
+ // Notice that all the information is kept in the window,
+ // that's why we get the private widget for it instead of
+ // the private widget for this widget.
+ QWidgetPrivate *privateWidget = qt_widget_private(q->window());
+ if(privateWidget)
+ privateWidget->changeMethods = documentMode;
+ // Since in Cocoa there is no simple way to remove the baseline, so we just ask the
+ // top level to do the magic for us.
+ privateWidget->syncUnifiedMode();
+#endif // QT_MAC_USE_COCOA
}
#endif
}
@@ -580,16 +592,10 @@ void QTabBarPrivate::layoutTab(int index)
}
}
-void QTabBarPrivate::layoutWidgets(int index)
+void QTabBarPrivate::layoutWidgets(int start)
{
Q_Q(QTabBar);
- int start = 0;
- int end = q->count();
- if (index != -1) {
- start = qMax(index, 0);
- end = qMin(end, start + 1);
- }
- for (int i = start; i < end; ++i) {
+ for (int i = start; i < q->count(); ++i) {
layoutTab(i);
}
}
@@ -1171,8 +1177,9 @@ void QTabBar::setCurrentIndex(int index)
update();
d->makeVisible(index);
d->tabList[index].lastTab = oldIndex;
- d->layoutWidgets(oldIndex);
- d->layoutWidgets(index);
+ if (oldIndex >= 0 && oldIndex < count())
+ d->layoutTab(oldIndex);
+ d->layoutTab(index);
#ifdef QT3_SUPPORT
emit selected(index);
#endif
@@ -1947,7 +1954,8 @@ void QTabBar::changeEvent(QEvent *event)
{
Q_D(QTabBar);
if (event->type() == QEvent::StyleChange) {
- d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, 0, this));
+ if (!d->elideModeSetByUser)
+ d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, 0, this));
if (!d->useScrollButtonsSetByUser)
d->useScrollButtons = !style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, 0, this);
d->refresh();
@@ -1980,6 +1988,7 @@ void QTabBar::setElideMode(Qt::TextElideMode mode)
{
Q_D(QTabBar);
d->elideMode = mode;
+ d->elideModeSetByUser = true;
d->refresh();
}
@@ -2196,6 +2205,7 @@ bool QTabBar::documentMode() const
void QTabBar::setDocumentMode(bool enabled)
{
Q_D(QTabBar);
+
d->documentMode = enabled;
d->updateMacBorderMetrics();
}
diff --git a/src/gui/widgets/qtabbar_p.h b/src/gui/widgets/qtabbar_p.h
index 7588035961..37741f7b31 100644
--- a/src/gui/widgets/qtabbar_p.h
+++ b/src/gui/widgets/qtabbar_p.h
@@ -75,7 +75,7 @@ class QTabBarPrivate : public QWidgetPrivate
public:
QTabBarPrivate()
:currentIndex(-1), pressedIndex(-1), shape(QTabBar::RoundedNorth), layoutDirty(false),
- drawBase(true), scrollOffset(0), useScrollButtonsSetByUser(false) , expanding(true), closeButtonOnTabs(false),
+ drawBase(true), scrollOffset(0), elideModeSetByUser(false), useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false),
dragInProgress(false), documentMode(false), movingTab(0)
#ifdef Q_WS_MAC
@@ -178,7 +178,7 @@ public:
void refresh();
void layoutTabs();
- void layoutWidgets(int index = -1);
+ void layoutWidgets(int start = 0);
void layoutTab(int index);
void updateMacBorderMetrics();
void setupMovableTab();
@@ -186,6 +186,7 @@ public:
void makeVisible(int index);
QSize iconSize;
Qt::TextElideMode elideMode;
+ bool elideModeSetByUser;
bool useScrollButtons;
bool useScrollButtonsSetByUser;
diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp
index b6886b4a40..45417307fc 100644
--- a/src/gui/widgets/qtextedit.cpp
+++ b/src/gui/widgets/qtextedit.cpp
@@ -1212,12 +1212,9 @@ void QTextEdit::keyPressEvent(QKeyEvent *e)
default:
if (QApplication::keypadNavigationEnabled()) {
if (!hasEditFocus() && !(e->modifiers() & Qt::ControlModifier)) {
- if (e->text()[0].isPrint()) {
+ if (e->text()[0].isPrint())
setEditFocus(true);
-#ifndef Q_OS_SYMBIAN
- clear();
-#endif
- } else {
+ else {
e->ignore();
return;
}
@@ -1677,12 +1674,8 @@ void QTextEdit::inputMethodEvent(QInputMethodEvent *e)
#ifdef QT_KEYPAD_NAVIGATION
if (d->control->textInteractionFlags() & Qt::TextEditable
&& QApplication::keypadNavigationEnabled()
- && !hasEditFocus()) {
+ && !hasEditFocus())
setEditFocus(true);
-#ifndef Q_OS_SYMBIAN
- selectAll(); // so text is replaced rather than appended to
-#endif
- }
#endif
d->sendControlEvent(e);
ensureCursorVisible();
diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp
index 8beda554b1..7ed27ea33d 100644
--- a/src/gui/widgets/qtoolbar.cpp
+++ b/src/gui/widgets/qtoolbar.cpp
@@ -533,6 +533,14 @@ void QToolBarPrivate::plug(const QRect &r)
/*!
+ \fn void QToolBar::visibilityChanged(bool visible)
+ \since 4.7
+
+ This signal is emitted when the toolbar becomes \a visible (or
+ invisible). This happens when the widget is hidden or shown.
+*/
+
+/*!
Constructs a QToolBar with the given \a parent.
*/
QToolBar::QToolBar(QWidget *parent)
@@ -1122,6 +1130,7 @@ bool QToolBar::event(QEvent *event)
// fallthrough intended
case QEvent::Show:
d->toggleViewAction->setChecked(event->type() == QEvent::Show);
+ emit visibilityChanged(event->type() == QEvent::Show);
#if defined(Q_WS_MAC)
if (toolbarInUnifiedToolBar(this)) {
// I can static_cast because I did the qobject_cast in the if above, therefore
diff --git a/src/gui/widgets/qtoolbar.h b/src/gui/widgets/qtoolbar.h
index 90f20dd43b..b733477fd0 100644
--- a/src/gui/widgets/qtoolbar.h
+++ b/src/gui/widgets/qtoolbar.h
@@ -143,6 +143,7 @@ Q_SIGNALS:
void iconSizeChanged(const QSize &iconSize);
void toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle);
void topLevelChanged(bool topLevel);
+ void visibilityChanged(bool visible);
protected:
void actionEvent(QActionEvent *event);
diff --git a/src/gui/widgets/qtoolbarlayout.cpp b/src/gui/widgets/qtoolbarlayout.cpp
index 4eb252a1d9..f87510ffd1 100644
--- a/src/gui/widgets/qtoolbarlayout.cpp
+++ b/src/gui/widgets/qtoolbarlayout.cpp
@@ -654,7 +654,11 @@ void QToolBarLayout::setExpanded(bool exp)
if (!tb)
return;
if (QMainWindow *win = qobject_cast<QMainWindow*>(tb->parentWidget())) {
+#ifdef QT_NO_DOCKWIDGET
+ animating = false;
+#else
animating = !tb->isWindow() && win->isAnimated();
+#endif
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
if (expanded) {
tb->raise();
diff --git a/src/gui/widgets/qvalidator.cpp b/src/gui/widgets/qvalidator.cpp
index a5276d38bf..b75db45032 100644
--- a/src/gui/widgets/qvalidator.cpp
+++ b/src/gui/widgets/qvalidator.cpp
@@ -400,8 +400,10 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
qlonglong entered = QLocalePrivate::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow);
if (overflow || !ok)
return Invalid;
- if (entered >= b && entered <= t)
- return Acceptable;
+ if (entered >= b && entered <= t) {
+ locale().toInt(input, &ok);
+ return ok ? Acceptable : Intermediate;
+ }
if (entered >= 0) {
// the -entered < b condition is necessary to allow people to type
@@ -412,6 +414,20 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
}
}
+/*! \reimp */
+void QIntValidator::fixup(QString &input) const
+{
+ QByteArray buff;
+ if (!locale().d()->validateChars(input, QLocalePrivate::IntegerMode, &buff)) {
+ QLocale cl(QLocale::C);
+ if (!cl.d()->validateChars(input, QLocalePrivate::IntegerMode, &buff))
+ return;
+ }
+ bool ok, overflow;
+ qlonglong entered = QLocalePrivate::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow);
+ if (ok && !overflow)
+ input = locale().toString(entered);
+}
/*!
Sets the range of the validator to only accept integers between \a
@@ -507,7 +523,7 @@ public:
In addition, QDoubleValidator is always guaranteed to accept a number
formatted according to the "C" locale. QDoubleValidator will not accept
- numbers with thousand-seperators.
+ numbers with thousand-separators.
\sa QIntValidator, QRegExpValidator, {Line Edits Example}
*/
diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h
index 30afbd6713..63734ca21d 100644
--- a/src/gui/widgets/qvalidator.h
+++ b/src/gui/widgets/qvalidator.h
@@ -105,6 +105,7 @@ public:
~QIntValidator();
QValidator::State validate(QString &, int &) const;
+ void fixup(QString &input) const;
void setBottom(int);
void setTop(int);
@@ -136,10 +137,11 @@ class Q_GUI_EXPORT QDoubleValidator : public QValidator
Q_PROPERTY(double bottom READ bottom WRITE setBottom)
Q_PROPERTY(double top READ top WRITE setTop)
Q_PROPERTY(int decimals READ decimals WRITE setDecimals)
+ Q_ENUMS(Notation)
Q_PROPERTY(Notation notation READ notation WRITE setNotation)
public:
- explicit QDoubleValidator(QObject * parent);
+ explicit QDoubleValidator(QObject * parent = 0);
QDoubleValidator(double bottom, double top, int decimals, QObject * parent);
~QDoubleValidator();
@@ -183,7 +185,7 @@ class Q_GUI_EXPORT QRegExpValidator : public QValidator
Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp)
public:
- explicit QRegExpValidator(QObject *parent);
+ explicit QRegExpValidator(QObject *parent = 0);
QRegExpValidator(const QRegExp& rx, QObject *parent);
~QRegExpValidator();
diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp
index 2a6a7da307..7180c4dd79 100644
--- a/src/gui/widgets/qworkspace.cpp
+++ b/src/gui/widgets/qworkspace.cpp
@@ -44,7 +44,6 @@
#include "qapplication.h"
#include "qbitmap.h"
#include "qcursor.h"
-#include "qdatetime.h"
#include "qdesktopwidget.h"
#include "qevent.h"
#include "qhash.h"
@@ -59,6 +58,7 @@
#include "qscrollbar.h"
#include "qstyle.h"
#include "qstyleoption.h"
+#include "qelapsedtimer.h"
#include "qtooltip.h"
#include "qdebug.h"
#include <private/qwidget_p.h>
@@ -450,10 +450,10 @@ void QWorkspaceTitleBar::mousePressEvent(QMouseEvent *e)
case QStyle::SC_TitleBarSysMenu:
if (d->flags & Qt::WindowSystemMenuHint) {
d->buttonDown = QStyle::SC_None;
- static QTime *t = 0;
+ static QElapsedTimer *t = 0;
static QWorkspaceTitleBar *tc = 0;
if (!t)
- t = new QTime;
+ t = new QElapsedTimer;
if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
emit showOperationMenu();
t->start();
@@ -1839,7 +1839,7 @@ bool QWorkspace::event(QEvent *e)
bool QWorkspace::eventFilter(QObject *o, QEvent * e)
{
Q_D(QWorkspace);
- static QTime* t = 0;
+ static QElapsedTimer* t = 0;
static QWorkspace* tc = 0;
if (o == d->maxtools) {
switch (e->type()) {
@@ -1847,7 +1847,7 @@ bool QWorkspace::eventFilter(QObject *o, QEvent * e)
{
QMenuBar* b = (QMenuBar*)o->parent();
if (!t)
- t = new QTime;
+ t = new QElapsedTimer;
if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
if (isRightToLeft()) {
QPoint p = b->mapToGlobal(QPoint(b->x() + b->width(), b->y() + b->height()));
diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri
index 6883dd8219..937b8d69ed 100644
--- a/src/gui/widgets/widgets.pri
+++ b/src/gui/widgets/widgets.pri
@@ -164,6 +164,6 @@ wince*: {
!static: QMAKE_WRITE_DEFAULT_RC = 1
}
-symbian*: {
+symbian: {
SOURCES += widgets/qmenu_symbian.cpp
}