summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-05-11 12:39:09 +0200
committerSamuel Rødal <samuel.rodal@nokia.com>2011-05-11 12:39:09 +0200
commit5e2b0aa1b344bc93af29d7977aa7e497bfc7a9cf (patch)
treec478b00d1c04166f3c1c163971edb4575b065b13
parentd1622207ba501b93bd83b88d61a5631d3d0da0cc (diff)
parentfda40e37df1152b5a8c572fe4bc53620bfcbcc45 (diff)
Merge remote branch 'staging/master' into refactor
Conflicts: src/gui/painting/qdrawhelper_p.h src/gui/painting/qgraphicssystemfactory.cpp src/gui/painting/qpainter.cpp src/gui/painting/qunifiedtoolbarsurface_mac.cpp src/gui/painting/qunifiedtoolbarsurface_mac_p.h src/openvg/openvg.pro src/openvg/qpaintengine_vg.cpp src/openvg/qwindowsurface_vg.cpp src/openvg/qwindowsurface_vgegl.cpp src/plugins/platforms/wayland/qwaylanddisplay.cpp src/widgets/graphicsview/qgraphicsscene.cpp
-rwxr-xr-xbin/createpackage.pl14
-rwxr-xr-xbin/syncqt6
-rw-r--r--config.profiles/symbian/bld.inf6
-rw-r--r--config.profiles/symbian/qt.sisx1
-rw-r--r--config.profiles/symbian/qt_stub.pkg53
-rw-r--r--config.profiles/symbian/qt_stub.sisbin0 -> 324 bytes
-rwxr-xr-xconfigure35
-rw-r--r--dist/changes-4.8.012
-rw-r--r--doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp35
-rw-r--r--mkspecs/common/symbian/template.applite1
-rw-r--r--mkspecs/features/module.prf2
-rw-r--r--mkspecs/features/symbian/sis_targets.prf6
-rw-r--r--mkspecs/features/symbian/symbian_appbooster.prf32
-rw-r--r--mkspecs/hurd-g++/qmake.conf128
-rw-r--r--qmake/generators/makefile.cpp4
-rw-r--r--qmake/generators/unix/unixmake2.cpp6
-rw-r--r--qmake/generators/win32/borland_bmake.cpp8
-rw-r--r--qmake/generators/win32/mingw_make.cpp8
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp8
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp22
-rw-r--r--qmake/generators/win32/msvc_vcproj.h1
-rw-r--r--qmake/generators/win32/msvc_vcxproj.cpp18
-rw-r--r--qmake/generators/win32/msvc_vcxproj.h10
-rw-r--r--qtbase.pro11
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp1
-rw-r--r--src/corelib/animation/qabstractanimation.cpp6
-rw-r--r--src/corelib/animation/qabstractanimation_p.h5
-rw-r--r--src/corelib/concurrent/qtconcurrentfilter.h554
-rw-r--r--src/corelib/concurrent/qtconcurrentfunctionwrappers.h119
-rw-r--r--src/corelib/concurrent/qtconcurrentmap.h632
-rw-r--r--src/corelib/global/qglobal.h70
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp3
-rw-r--r--src/corelib/io/qprocess.cpp97
-rw-r--r--src/corelib/io/qprocess_p.h104
-rw-r--r--src/corelib/io/qprocess_symbian.cpp5
-rw-r--r--src/corelib/io/qprocess_unix.cpp40
-rw-r--r--src/corelib/io/qprocess_win.cpp45
-rw-r--r--src/corelib/io/qsettings.cpp29
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp11
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h2
-rw-r--r--src/corelib/plugin/qlibrary.cpp13
-rw-r--r--src/corelib/thread/qmutex_unix.cpp13
-rw-r--r--src/corelib/thread/qthread_symbian.cpp4
-rw-r--r--src/corelib/thread/qthread_win.cpp2
-rw-r--r--src/corelib/tools/qdatetime.cpp21
-rw-r--r--src/corelib/tools/qelapsedtimer_symbian.cpp2
-rw-r--r--src/corelib/tools/qlocale.cpp2
-rw-r--r--src/corelib/tools/qlocale_symbian.cpp167
-rw-r--r--src/corelib/tools/qstring.h4
-rw-r--r--src/corelib/tools/qtextboundaryfinder.cpp4
-rw-r--r--src/corelib/tools/qvector.h5
-rw-r--r--src/gui/guikernel/qclipboard.h1
-rw-r--r--src/gui/guikernel/qplatformclipboard_qpa.cpp9
-rw-r--r--src/gui/guikernel/qplatformclipboard_qpa.h3
-rw-r--r--src/gui/image/qpixmap.cpp8
-rw-r--r--src/gui/painting/qbrush.cpp191
-rw-r--r--src/gui/painting/qbrush.h12
-rw-r--r--src/gui/painting/qdrawhelper.cpp238
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp40
-rw-r--r--src/gui/painting/qdrawhelper_p.h255
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp56
-rw-r--r--src/gui/painting/qpaintbuffer.cpp16
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp81
-rw-r--r--src/gui/painting/qpaintengineex.cpp46
-rw-r--r--src/gui/painting/qpainter.cpp41
-rw-r--r--src/gui/painting/qpainter.h5
-rw-r--r--src/gui/painting/qpainterpath.cpp1
-rw-r--r--src/gui/painting/qprintengine_pdf.cpp5
-rw-r--r--src/gui/painting/qstroker.cpp1
-rw-r--r--src/gui/text/qfontengine_ft.cpp102
-rw-r--r--src/gui/text/qfontengine_ft_p.h1
-rw-r--r--src/gui/text/qglyphrun.cpp (renamed from src/gui/text/qglyphs.cpp)123
-rw-r--r--src/gui/text/qglyphrun.h (renamed from src/gui/text/qglyphs.h)32
-rw-r--r--src/gui/text/qglyphrun_p.h (renamed from src/gui/text/qglyphs_p.h)16
-rw-r--r--src/gui/text/qrawfont.cpp74
-rw-r--r--src/gui/text/qrawfont.h4
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp1
-rw-r--r--src/gui/text/qtextlayout.cpp24
-rw-r--r--src/gui/text/qtextlayout.h6
-rw-r--r--src/gui/text/qtextobject.cpp10
-rw-r--r--src/gui/text/qtextobject.h4
-rw-r--r--src/gui/text/text.pri10
-rw-r--r--src/network/access/access.pri4
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp10
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h1
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp11
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp80
-rw-r--r--src/network/access/qnetworkaccesscachebackend.cpp9
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp12
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp73
-rw-r--r--src/network/access/qnetworkaccessmanager.h1
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h12
-rw-r--r--src/network/access/qnetworkcookie.cpp9
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp1983
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h309
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp26
-rw-r--r--src/network/access/qnetworkrequest.cpp7
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp15
-rw-r--r--src/network/kernel/qhostinfo.cpp2
-rw-r--r--src/network/kernel/qnetworkproxy.cpp98
-rw-r--r--src/network/kernel/qnetworkproxy.h16
-rw-r--r--src/network/kernel/qnetworkproxy_symbian.cpp13
-rw-r--r--src/network/socket/qabstractsocket.cpp4
-rw-r--r--src/network/socket/qhttpsocketengine.cpp8
-rw-r--r--src/network/socket/qsocks5socketengine.cpp7
-rw-r--r--src/network/ssl/qsslconfiguration.cpp4
-rw-r--r--src/network/ssl/qsslsocket.cpp2
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp2
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h2
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h18
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp8
-rw-r--r--src/opengl/qpaintengine_opengl.cpp60
-rw-r--r--src/opengl/qwindowsurface_gl.cpp23
-rw-r--r--src/plugins/accessible/widgets/complexwidgets.cpp6
-rw-r--r--src/plugins/accessible/widgets/qaccessiblewidgets.cpp17
-rw-r--r--src/plugins/accessible/widgets/simplewidgets.cpp33
-rw-r--r--src/plugins/bearer/corewlan/corewlan.pro2
-rw-r--r--src/plugins/platforms/minimal/minimal.pro1
-rw-r--r--src/plugins/platforms/wayland/qwaylandclipboard.cpp286
-rw-r--r--src/plugins/platforms/wayland/qwaylandclipboard.h90
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.cpp8
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.h1
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.h1
-rw-r--r--src/plugins/platforms/wayland/qwaylandintegration.cpp9
-rw-r--r--src/plugins/platforms/wayland/qwaylandintegration.h3
-rw-r--r--src/plugins/platforms/wayland/wayland.pro10
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp1
-rw-r--r--src/plugins/platforms/xcb/xcb.pro4
-rw-r--r--src/plugins/platforms/xlib/qxlibclipboard.cpp8
-rw-r--r--src/plugins/platforms/xlib/qxlibclipboard.h2
-rw-r--r--src/plugins/platforms/xlib/qxlibstatic.h3
-rw-r--r--src/plugins/platforms/xlib/xlib.pro2
-rw-r--r--src/qt_install.pri2
-rw-r--r--src/s60installs/eabi/QtOpenGLu.def2
-rw-r--r--src/sql/drivers/mysql/qsql_mysql.cpp8
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.cpp20
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp403
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.h17
-rw-r--r--src/tools/uic/uic.cpp6
-rw-r--r--src/uitools/quiloader.cpp2
-rw-r--r--src/widgets/accessible/qaccessible.h36
-rw-r--r--src/widgets/accessible/qaccessible_win.cpp246
-rw-r--r--src/widgets/accessible/qaccessibleobject.cpp4
-rw-r--r--src/widgets/dialogs/qcolordialog_mac.mm5
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp12
-rw-r--r--src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp4
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp16
-rw-r--r--src/widgets/graphicsview/qgraphicslayout.cpp4
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp11
-rw-r--r--src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp4
-rw-r--r--src/widgets/graphicsview/qgraphicswidget_p.cpp4
-rw-r--r--src/widgets/itemviews/qabstractproxymodel.cpp24
-rw-r--r--src/widgets/itemviews/qabstractproxymodel.h3
-rw-r--r--src/widgets/itemviews/qdatawidgetmapper.cpp2
-rw-r--r--src/widgets/itemviews/qitemselectionmodel.cpp7
-rw-r--r--src/widgets/itemviews/qtableview.cpp22
-rw-r--r--src/widgets/itemviews/qtableview.h1
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp1
-rw-r--r--src/widgets/kernel/qwidget.cpp9
-rw-r--r--src/widgets/platforms/mac/qfont_mac.cpp7
-rw-r--r--src/widgets/platforms/mac/qfontengine_coretext.mm2
-rw-r--r--src/widgets/platforms/mac/qfontengine_coretext_p.h2
-rw-r--r--src/widgets/platforms/mac/qpaintengine_mac.cpp3
-rw-r--r--src/widgets/platforms/mac/qwidget_mac.mm12
-rw-r--r--src/widgets/platforms/s60/qapplication_s60.cpp3
-rw-r--r--src/widgets/platforms/s60/qfontdatabase_s60.cpp30
-rw-r--r--src/widgets/platforms/s60/qt_s60_p.h26
-rw-r--r--src/widgets/platforms/s60/qwidget_s60.cpp11
-rw-r--r--src/widgets/platforms/win/qapplication_win.cpp7
-rw-r--r--src/widgets/platforms/x11/qcursor_x11.cpp3
-rw-r--r--src/widgets/platforms/x11/qpaintengine_x11.cpp3
-rw-r--r--src/widgets/platforms/x11/qwidget_x11.cpp13
-rw-r--r--src/widgets/styles/qcleanlooksstyle.cpp16
-rw-r--r--src/widgets/styles/qcommonstyle.cpp16
-rw-r--r--src/widgets/styles/qgtkpainter.cpp5
-rw-r--r--src/widgets/styles/qgtkstyle.cpp3
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm2
-rw-r--r--src/widgets/styles/qplastiquestyle.cpp11
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp6
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp9
-rw-r--r--src/widgets/styles/qwindowsxpstyle.cpp10
-rw-r--r--src/widgets/util/qflickgesture.cpp4
-rw-r--r--src/widgets/util/qscroller.cpp3
-rw-r--r--src/widgets/util/qundogroup.cpp18
-rw-r--r--src/widgets/util/qundostack.cpp90
-rw-r--r--src/widgets/util/qundostack.h1
-rw-r--r--src/widgets/util/qundostack_p.h3
-rw-r--r--src/widgets/widgets/qdatetimeedit.cpp41
-rw-r--r--src/widgets/widgets/qdatetimeedit_p.h10
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp5
-rw-r--r--src/widgets/widgets/qdockwidget.cpp1
-rw-r--r--src/widgets/widgets/qmenu.cpp103
-rw-r--r--src/widgets/widgets/qmenu_p.h4
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp6
-rw-r--r--src/widgets/widgets/qtextedit.cpp1
-rw-r--r--src/widgets/widgets/qworkspace.cpp1
-rw-r--r--tests/arthur/baselineserver/src/baselineserver.cpp39
-rw-r--r--tests/arthur/baselineserver/src/baselineserver.h4
-rw-r--r--tests/arthur/common/baselineprotocol.cpp12
-rw-r--r--tests/arthur/common/baselineprotocol.h2
-rw-r--r--tests/arthur/common/paintcommands.cpp34
-rw-r--r--tests/arthur/common/paintcommands.h1
-rw-r--r--tests/arthur/data/qps/radial_gradients_extended.qps95
-rw-r--r--tests/arthur/data/qps/radial_gradients_extended_qps.pngbin0 -> 107978 bytes
-rw-r--r--tests/auto/corelib.pro3
-rw-r--r--tests/auto/gui.pro14
-rw-r--r--tests/auto/host.pro2
-rw-r--r--tests/auto/lancelot/tst_lancelot.cpp3
-rw-r--r--tests/auto/languagechange/languagechange.pro1
-rw-r--r--tests/auto/nativeimagehandleprovider/nativeimagehandleprovider.pro3
-rw-r--r--tests/auto/network.pro4
-rw-r--r--tests/auto/other.pro5
-rw-r--r--tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp6
-rw-r--r--tests/auto/qaccessibility/tst_qaccessibility.cpp441
-rw-r--r--tests/auto/qapplication/test/test.pro2
-rw-r--r--tests/auto/qbytearray/qbytearray.pro2
-rw-r--r--tests/auto/qchar/qchar.pro2
-rw-r--r--tests/auto/qcomplextext/qcomplextext.pro1
-rw-r--r--tests/auto/qdatetime/qdatetime.pro2
-rw-r--r--tests/auto/qdatetime/tst_qdatetime.cpp32
-rw-r--r--tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp23
-rw-r--r--tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro2
-rw-r--r--tests/auto/qdbusabstractadaptor/test/test.pro3
-rw-r--r--tests/auto/qdbusinterface/test/test.pro3
-rw-r--r--tests/auto/qdbusmarshall/qdbusmarshall.pro2
-rw-r--r--tests/auto/qdbusmetaobject/qdbusmetaobject.pro2
-rw-r--r--tests/auto/qdbustype/qdbustype.pro4
-rw-r--r--tests/auto/qdbusxmlparser/qdbusxmlparser.pro4
-rw-r--r--tests/auto/qdockwidget/qdockwidget.pro3
-rw-r--r--tests/auto/qfiledialog2/qfiledialog2.pro6
-rw-r--r--tests/auto/qfilesystementry/qfilesystementry.pro2
-rw-r--r--tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp31
-rw-r--r--tests/auto/qfontdialog/qfontdialog.pro3
-rw-r--r--tests/auto/qftp/qftp.pro2
-rw-r--r--tests/auto/qfuture/qfuture.pro2
-rw-r--r--tests/auto/qfuturewatcher/qfuturewatcher.pro2
-rw-r--r--tests/auto/qglyphrun/qglyphrun.pro (renamed from tests/auto/qglyphs/qglyphs.pro)4
-rw-r--r--tests/auto/qglyphrun/test.ttf (renamed from tests/auto/qglyphs/test.ttf)bin3712 -> 3712 bytes
-rw-r--r--tests/auto/qglyphrun/tst_qglyphrun.cpp (renamed from tests/auto/qglyphs/tst_qglyphs.cpp)154
-rw-r--r--tests/auto/qgraphicseffect/qgraphicseffect.pro3
-rw-r--r--tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro3
-rw-r--r--tests/auto/qgraphicsobject/qgraphicsobject.pro5
-rw-r--r--tests/auto/qgraphicsproxywidget/qgraphicsproxywidget.pro3
-rw-r--r--tests/auto/qgraphicsview/qgraphicsview.pro3
-rw-r--r--tests/auto/qgraphicswidget/qgraphicswidget.pro3
-rw-r--r--tests/auto/qgridlayout/qgridlayout.pro3
-rw-r--r--tests/auto/qheaderview/qheaderview.pro3
-rw-r--r--tests/auto/qimage/qimage.pro2
-rw-r--r--tests/auto/qimagereader/qimagereader.pro2
-rw-r--r--tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp54
-rw-r--r--tests/auto/qkeysequence/qkeysequence.pro5
-rw-r--r--tests/auto/qlabel/qlabel.pro3
-rw-r--r--tests/auto/qlayout/qlayout.pro6
-rw-r--r--tests/auto/qmdiarea/qmdiarea.pro3
-rw-r--r--tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp42
-rw-r--r--tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp8
-rw-r--r--tests/auto/qnetworkcookiejar/qnetworkcookiejar.pro2
-rw-r--r--tests/auto/qnetworkproxyfactory/qnetworkproxyfactory.pro2
-rw-r--r--tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp175
-rw-r--r--tests/auto/qnetworkreply/tst_qnetworkreply.cpp61
-rw-r--r--tests/auto/qpainter/qpainter.pro3
-rw-r--r--tests/auto/qpainter/tst_qpainter.cpp84
-rw-r--r--tests/auto/qpauseanimation/qpauseanimation.pro2
-rw-r--r--tests/auto/qpixmap/qpixmap.pro3
-rw-r--r--tests/auto/qpixmapfilter/qpixmapfilter.pro3
-rw-r--r--tests/auto/qplaintextedit/qplaintextedit.pro2
-rw-r--r--tests/auto/qplaintextedit/tst_qplaintextedit.cpp18
-rw-r--r--tests/auto/qpluginloader/tst_qpluginloader.cpp6
-rw-r--r--tests/auto/qprocessenvironment/tst_qprocessenvironment.cpp13
-rw-r--r--tests/auto/qrawfont/qrawfont.pro3
-rw-r--r--tests/auto/qrawfont/tst_qrawfont.cpp52
-rw-r--r--tests/auto/qregion/qregion.pro3
-rw-r--r--tests/auto/qringbuffer/qringbuffer.pro2
-rw-r--r--tests/auto/qsettings/qsettings.pro3
-rw-r--r--tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp137
-rw-r--r--tests/auto/qsql/qsql.pro2
-rw-r--r--tests/auto/qstandarditemmodel/qstandarditemmodel.pro3
-rw-r--r--tests/auto/qstatemachine/qstatemachine.pro2
-rw-r--r--tests/auto/qstatictext/qstatictext.pro2
-rw-r--r--tests/auto/qtableview/qtableview.pro3
-rw-r--r--tests/auto/qtablewidget/tst_qtablewidget.cpp3
-rw-r--r--tests/auto/qtabwidget/qtabwidget.pro2
-rw-r--r--tests/auto/qtessellator/qtessellator.pro3
-rw-r--r--tests/auto/qtextblock/qtextblock.pro3
-rw-r--r--tests/auto/qtextdocument/qtextdocument.pro2
-rw-r--r--tests/auto/qtextdocument/tst_qtextdocument.cpp2
-rw-r--r--tests/auto/qtextdocumentfragment/qtextdocumentfragment.pro3
-rw-r--r--tests/auto/qtextlist/qtextlist.pro3
-rw-r--r--tests/auto/qtextscriptengine/qtextscriptengine.pro3
-rw-r--r--tests/auto/qundogroup/testdata/qundogroup.ts25
-rw-r--r--tests/auto/qundogroup/tst_qundogroup.cpp37
-rw-r--r--tests/auto/qundostack/testdata/qundostack.ts25
-rw-r--r--tests/auto/qundostack/tst_qundostack.cpp94
-rw-r--r--tests/auto/qvector/tst_qvector.cpp79
-rw-r--r--tests/auto/qvolatileimage/qvolatileimage.pro3
-rw-r--r--tests/auto/qwidget/qwidget.pro3
-rw-r--r--tests/auto/qwidget/tst_qwidget.cpp45
-rw-r--r--tests/auto/qwindowsurface/qwindowsurface.pro3
-rw-r--r--tests/auto/qwizard/tst_qwizard.cpp13
-rw-r--r--tests/auto/selftests/benchlibtickcounter/benchlibtickcounter.pro2
-rw-r--r--tests/auto/selftests/test/test.pro2
-rw-r--r--tests/auto/uic/baseline/config_fromuic3.ui1647
-rw-r--r--tests/auto/uic/baseline/config_fromuic3.ui.h716
-rw-r--r--tests/auto/uic/baseline/mainwindowbase.ui1214
-rw-r--r--tests/auto/uic/baseline/mainwindowbase.ui.h968
-rw-r--r--tests/auto/uic/baseline/mydialog.ui.h1
-rw-r--r--tests/auto/uic/baseline/paletteeditoradvancedbase.ui617
-rw-r--r--tests/auto/uic/baseline/paletteeditoradvancedbase.ui.h485
-rw-r--r--tests/auto/uic/baseline/previewwidgetbase.ui340
-rw-r--r--tests/auto/uic/baseline/previewwidgetbase.ui.h316
-rw-r--r--tests/benchmarks/benchmarks.pro4
-rw-r--r--tests/benchmarks/corelib/io/io.pro2
-rw-r--r--tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro2
-rw-r--r--tests/benchmarks/corelib/tools/qstring/qstring.pro1
-rw-r--r--tests/benchmarks/dbus/qdbustype/qdbustype.pro2
-rw-r--r--tests/benchmarks/gui/graphicsview/functional/functional.pro3
-rw-r--r--tests/benchmarks/gui/graphicsview/graphicsview.pro1
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicslayout/qgraphicslayout.pro6
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp153
-rw-r--r--tests/benchmarks/gui/image/blendbench/main.cpp4
-rw-r--r--tests/benchmarks/gui/image/qpixmap/qpixmap.pro3
-rw-r--r--tests/benchmarks/gui/painting/qpainter/qpainter.pro3
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/qtracebench.pro3
-rw-r--r--tests/benchmarks/gui/text/qtext/qtext.pro5
-rw-r--r--tests/benchmarks/network/kernel/kernel.pro3
-rwxr-xr-xtests/benchmarks/network/kernel/qhostinfo/qhostinfo.pro2
-rw-r--r--tests/benchmarks/opengl/opengl.pro4
-rw-r--r--tests/manual/qgraphicslayout/flicker/flicker.pro8
-rw-r--r--tests/manual/qgraphicslayout/flicker/main.cpp56
-rw-r--r--tests/manual/qgraphicslayout/flicker/window.cpp73
-rw-r--r--tests/manual/qgraphicslayout/flicker/window.h284
-rw-r--r--tools/configure/configure.pro2
-rw-r--r--tools/configure/configureapp.cpp2
-rw-r--r--tools/uilib/abstractformbuilder.cpp159
-rw-r--r--tools/uilib/abstractformbuilder.h19
-rw-r--r--tools/uilib/formbuilder.cpp63
-rw-r--r--tools/uilib/formbuilder.h5
-rw-r--r--tools/uilib/formbuilderextra.cpp31
-rw-r--r--tools/uilib/formbuilderextra_p.h24
339 files changed, 7886 insertions, 9884 deletions
diff --git a/bin/createpackage.pl b/bin/createpackage.pl
index b7457e1c0b..aae20ae929 100755
--- a/bin/createpackage.pl
+++ b/bin/createpackage.pl
@@ -238,11 +238,7 @@ if ($templatepkg =~ m/_installer\.pkg$/i && $onlyUnsigned) {
my $unsigned_sis_name = $sisoutputbasename."_unsigned.sis";
my $stub_sis_name = $sisoutputbasename.".sis";
-# Store some utility variables
-my $scriptpath = dirname(__FILE__);
my $certtext = $certificate;
-# certificates are one step up in hierarchy
-my $certpath = File::Spec->catdir($scriptpath, File::Spec->updir(), "src/s60installs/");
# Check some pre-conditions and print error messages if needed.
unless (length($templatepkg)) {
@@ -265,6 +261,16 @@ if (length($certificate)) {
}
} else {
#If no certificate is given, check default options
+ my $scriptpath = dirname(__FILE__);
+ my $certpath = File::Spec->catdir($scriptpath, File::Spec->updir(), "src/s60installs");
+
+ unless (-e $certpath) {
+ my $qmakeCmd = File::Spec->catfile($scriptpath, "qmake");
+ $certpath = `$qmakeCmd -query QT_INSTALL_PREFIX`;
+ $certpath =~ s/\s+$//;
+ $certpath = File::Spec->catdir($certpath, "src/s60installs");
+ }
+
$certtext = "RnD";
$certificate = File::Spec->catfile($certpath, "rd.cer");
$key = File::Spec->catfile($certpath, "rd-key.pem");
diff --git a/bin/syncqt b/bin/syncqt
index 3d25ecc817..6050d31e9e 100755
--- a/bin/syncqt
+++ b/bin/syncqt
@@ -27,8 +27,8 @@ our $quoted_basedir;
# normally the script location should be enough, if not fall back to
# QTDIR environment variable. If that doesn't work, later ask the
# user to use the -qtdir option explicitly.
-my $qtbasedir = dirname(dirname($0));
-$qtbasedir = $ENV{"QTDIR"} if ($qtbasedir !~ /qtbase/);
+my $qtbasedir = $ENV{"QTDIR"};
+$qtbasedir = dirname(dirname($0)) if (!$qtbasedir);
$qtbasedir =~ s=\\=/=g if (defined $qtbasedir);
# will be defined based on the modules sync.profile
@@ -717,7 +717,7 @@ while ( @ARGV ) {
die "Cannot automatically detect/use provided path to QtBase's build directory!\n" .
"QTDIR detected/provided: " . (defined $qtbasedir ? $qtbasedir : "-none-") . "\n" .
"Please -qtdir option to provide the correct path.\nsyncqt failed"
- if (!defined $qtbasedir || (!-e "$qtbasedir/.qmake.cache" && $qtbasedir !~ /qtbase/));
+ if (!$qtbasedir || !-d "$qtbasedir/mkspecs");
# if we have no $basedir we cannot be sure which sources you want, so die
die "Could not find any sync.profile for your module!\nPass <module directory> to syncqt to sync your header files.\nsyncqt failed" if (!$basedir);
diff --git a/config.profiles/symbian/bld.inf b/config.profiles/symbian/bld.inf
index ddb51570cc..6ccb11c483 100644
--- a/config.profiles/symbian/bld.inf
+++ b/config.profiles/symbian/bld.inf
@@ -38,10 +38,12 @@ loc.prf /epoc32/tools/qt/mkspecs/features/loc.prf
//For UDA image
confml/qt.confml CONFML_EXPORT_PATH(qt.confml,uda_content)
implml/qt_copy.implml CRML_EXPORT_PATH(qt_copy.implml,uda_content)
-content/apps/qt.sisx CRML_EXPORT_PATH(../content/sis/,uda_content)
-content/apps/qt_stub.sis /epoc32/data/z/system/install/qt_stub.sis
+qt.sisx CRML_EXPORT_PATH(../content/sis/,uda_content)
#endif
+/* export stub sis to enable eclipsing */
+qt_stub.sis /epoc32/data/z/system/install/qt_stub.sis
+
//tools
../../bin/createpackage.bat /epoc32/tools/createpackage.bat
../../bin/createpackage.pl /epoc32/tools/createpackage.pl
diff --git a/config.profiles/symbian/qt.sisx b/config.profiles/symbian/qt.sisx
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/config.profiles/symbian/qt.sisx
@@ -0,0 +1 @@
+1 \ No newline at end of file
diff --git a/config.profiles/symbian/qt_stub.pkg b/config.profiles/symbian/qt_stub.pkg
index dadf696cf1..0ac4439536 100644
--- a/config.profiles/symbian/qt_stub.pkg
+++ b/config.profiles/symbian/qt_stub.pkg
@@ -15,56 +15,3 @@
; Unique Vendor name
:"Nokia, Qt"
-; Dependencies of Qt libraries
-
-"" - "z:\sys\bin\QtCore.dll"
-"" - "z:\sys\bin\QtXml.dll"
-"" - "z:\sys\bin\QtGui.dll"
-"" - "z:\sys\bin\QtNetwork.dll"
-"" - "z:\sys\bin\QtTest.dll"
-"" - "z:\sys\bin\QtSql.dll"
-"" - "z:\sys\bin\QtSvg.dll"
-"" - "z:\sys\bin\phonon.dll"
-"" - "z:\sys\bin\QtScript.dll"
-"" - "z:\sys\bin\QtXmlPatterns.dll"
-"" - "z:\sys\bin\QtDeclarative.dll"
-"" - "z:\sys\bin\QtOpenVG.dll"
-"" - "z:\sys\bin\QtOpenGL.dll"
-"" - "z:\sys\bin\QtMultimedia.dll"
-"" - "z:\private\10202D56\import\packages\2001E61C\backup_registration.xml"
-"" - "z:\sys\bin\qjpeg.dll"
-"" - "z:\resource\qt\plugins\imageformats\qjpeg.qtplugin"
-"" - "z:\sys\bin\qgif.dll"
-"" - "z:\resource\qt\plugins\imageformats\qgif.qtplugin"
-"" - "z:\sys\bin\qmng.dll"
-"" - "z:\resource\qt\plugins\imageformats\qmng.qtplugin"
-"" - "z:\sys\bin\qtiff.dll"
-"" - "z:\resource\qt\plugins\imageformats\qtiff.qtplugin"
-"" - "z:\sys\bin\qico.dll"
-"" - "z:\resource\qt\plugins\imageformats\qico.qtplugin"
-"" - "z:\sys\bin\qsvg.dll"
-"" - "z:\resource\qt\plugins\imageformats\qsvg.qtplugin"
-"" - "z:\sys\bin\qcncodecs.dll"
-"" - "z:\resource\qt\plugins\codecs\qcncodecs.qtplugin"
-"" - "z:\sys\bin\qjpcodecs.dll"
-"" - "z:\resource\qt\plugins\codecs\qjpcodecs.qtplugin"
-"" - "z:\sys\bin\qtwcodecs.dll"
-"" - "z:\resource\qt\plugins\codecs\qtwcodecs.qtplugin"
-"" - "z:\sys\bin\qkrcodecs.dll"
-"" - "z:\resource\qt\plugins\codecs\qkrcodecs.qtplugin"
-"" - "z:\sys\bin\qvggraphicssystem.dll"
-"" - "z:\resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin"
-"" - "z:\sys\bin\qglgraphicssystem.dll"
-"" - "z:\resource\qt\plugins\graphicssystems\qglgraphicssystem.qtplugin"
-"" - "z:\sys\bin\qsvgicon.dll"
-"" - "z:\resource\qt\plugins\iconengines\qsvgicon.qtplugin"
-"" - "z:\sys\bin\qmlfolderlistmodelplugin.dll"
-"" - "z:\resource\qt\imports\Qt\labs\folderlistmodel\qmlfolderlistmodelplugin.qtplugin"
-"" - "z:\resource\qt\imports\Qt\labs\folderlistmodel\qmldir"
-"" - "z:\sys\bin\qmlgesturesplugin.dll"
-"" - "z:\resource\qt\imports\Qt\labs\gestures\qmlgesturesplugin.qtplugin"
-"" - "z:\resource\qt\imports\Qt\labs\gestures\qmldir"
-"" - "z:\sys\bin\qmlparticlesplugin.dll"
-"" - "z:\resource\qt\imports\Qt\labs\particles\qmlparticlesplugin.qtplugin"
-"" - "z:\resource\qt\imports\Qt\labs\particles\qmldir"
-
diff --git a/config.profiles/symbian/qt_stub.sis b/config.profiles/symbian/qt_stub.sis
new file mode 100644
index 0000000000..30d91a984a
--- /dev/null
+++ b/config.profiles/symbian/qt_stub.sis
Binary files differ
diff --git a/configure b/configure
index 0de4ab0667..0be1497d1c 100755
--- a/configure
+++ b/configure
@@ -699,7 +699,7 @@ CFG_FONTCONFIG=auto
CFG_QWS_FREETYPE=auto
CFG_LIBFREETYPE=auto
CFG_SQL_AVAILABLE=
-QT_DEFAULT_BUILD_PARTS="libs examples demos"
+QT_DEFAULT_BUILD_PARTS="libs examples demos tests"
CFG_BUILD_PARTS=""
CFG_NOBUILD_PARTS=""
CFG_RELEASE_QMAKE=no
@@ -712,6 +712,7 @@ CFG_DECLARATIVE=auto
CFG_DECLARATIVE_DEBUG=yes
CFG_WEBKIT=auto # (yes|no|auto|debug)
CFG_JAVASCRIPTCORE_JIT=auto
+CFG_LOCATION=auto
CFG_GFX_AVAILABLE="linuxfb transformed qvfb vnc multiscreen directfb"
CFG_GFX_ON="linuxfb multiscreen"
@@ -2145,6 +2146,17 @@ while [ "$#" -gt 0 ]; do
[ "$VAL" = "auto" ] && VAL="yes"
CFG_WEBKIT="$VAL"
;;
+ location)
+ if [ "$VAL" = "yes" ]; then
+ CFG_LOCATION="yes"
+ else
+ if [ "$VAL" = "no" ]; then
+ CFG_LOCATION="no"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ fi
+ ;;
javascript-jit)
if [ "$VAL" = "yes" ] || [ "$VAL" = "auto" ] || [ "$VAL" = "no" ]; then
CFG_JAVASCRIPTCORE_JIT="$VAL"
@@ -3726,6 +3738,7 @@ Usage: $relconf [-h] [-prefix <dir>] [-prefix-install] [-bindir <dir>] [-libdir
[-no-javascript-jit] [-javascript-jit]
[-no-script] [-script] [-no-scripttools] [-scripttools]
[-no-declarative] [-declarative] [-no-declarative-debug] [-declarative-debug]
+ [-no-location] [-location]
[additional platform specific options (see below)]
@@ -3897,6 +3910,9 @@ fi
-no-declarative-debug ..... Do not build the declarative debugging support.
+ -declarative-debug ....... Build the declarative debugging support.
+ -no-location ....... Do not build the QtLocation module.
+ + -location .......... Build the QtLocation module.
+
-platform target ... The operating system and compiler you are building
on ($PLATFORM).
@@ -7659,6 +7675,22 @@ else
QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_DECLARATIVE"
fi
+if [ "$CFG_LOCATION" = "auto" ]; then
+ CFG_LOCATION="$CFG_GUI"
+fi
+
+if [ "$CFG_LOCATION" = "yes" ] && [ "$CFG_GUI" = "no" ]; then
+ echo "QtLocation requested, but it can't be built without QtGui"
+ exit 1
+fi
+
+#Disable QtLocation until ready
+CFG_LOCATION="no"
+
+if [ "$CFG_LOCATION" = "no" ]; then
+ QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_LOCATION"
+fi
+
if [ "$CFG_EXCEPTIONS" = "no" ]; then
case "$COMPILER" in
g++*)
@@ -8679,6 +8711,7 @@ echo "Declarative module ..... $CFG_DECLARATIVE"
if [ "$CFG_DECLARATIVE" = "yes" ]; then
echo "Declarative debugging ...$CFG_DECLARATIVE_DEBUG"
fi
+echo "Location module ........ $CFG_LOCATION"
echo "Support for S60 ........ $CFG_S60"
echo "Symbian DEF files ...... $CFG_SYMBIAN_DEFFILES"
echo "STL support ............ $CFG_STL"
diff --git a/dist/changes-4.8.0 b/dist/changes-4.8.0
index fa50f24963..b8cc62600e 100644
--- a/dist/changes-4.8.0
+++ b/dist/changes-4.8.0
@@ -97,9 +97,17 @@ Qt for Windows CE
- Assistant
-
- Designer
-
+ * [QTBUG-18631] Enabled the use of promoted QWidgets in the buddy editor.
+ * [QTBUG-18120] Fixed saving of the Z-order.
+ * [QTBUG-13683] Fixed saving of QGridLayout and QFormLayout
+ by QFormBuilder.
+ * [QTBUG-10890] Added a filter to the rich text editor dialog.
+ that simplifies the HTML markup generated.
+ * [QTBUG-7777] Added support for QIcon::fromTheme.
+ * [QTBUG-7169] Fixed QtUiTools to be built with the correct
+ lib-infix.
+ * [QTBUG-3120] Added support for alignment of box layout items.
- Linguist
- Linguist GUI
diff --git a/doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp b/doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp
index cf40f9a05a..5919c01085 100644
--- a/doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp
+++ b/doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp
@@ -86,38 +86,3 @@ beginMoveRows(parent, 2, 2, parent, 0);
//! [9]
beginMoveRows(parent, 2, 2, parent, 4);
//! [9]
-
-
-//! [10]
-class CustomDataProxy : public QSortFilterProxyModel
-{
- Q_OBJECT
-public:
- CustomDataProxy(QObject *parent)
- : QSortFilterProxyModel(parent)
- {
- }
-
- ...
-
- QVariant data(const QModelIndex &index, int role)
- {
- if (role != Qt::BackgroundRole)
- return QSortFilterProxyModel::data(index, role);
-
- if (m_customData.contains(index.row()))
- return m_customData.value(index.row());
- return QSortFilterProxyModel::data(index, role);
- }
-
-private slots:
- void resetInternalData()
- {
- m_customData.clear();
- }
-
-private:
- QHash<int, QVariant> m_customData;
-};
-//! [10]
-
diff --git a/mkspecs/common/symbian/template.applite b/mkspecs/common/symbian/template.applite
new file mode 100644
index 0000000000..73a1999023
--- /dev/null
+++ b/mkspecs/common/symbian/template.applite
@@ -0,0 +1 @@
+// This is an auto-generated lite registration file \ No newline at end of file
diff --git a/mkspecs/features/module.prf b/mkspecs/features/module.prf
index 248f7f516a..85639f0345 100644
--- a/mkspecs/features/module.prf
+++ b/mkspecs/features/module.prf
@@ -1,7 +1,7 @@
!isEmpty(MODULE_PRI) {
pritarget.path = $$[QT_INSTALL_DATA]/mkspecs/modules
pritarget.files = $$MODULE_PRI
- INSTALLS = pritarget
+ INSTALLS += pritarget
} else {
warning("Project $$basename(_PRO_FILE_) is a module, but has not defined MODULE_PRI, which is required for Qt to expose the module to other projects")
}
diff --git a/mkspecs/features/symbian/sis_targets.prf b/mkspecs/features/symbian/sis_targets.prf
index d0fe881003..f3452b7091 100644
--- a/mkspecs/features/symbian/sis_targets.prf
+++ b/mkspecs/features/symbian/sis_targets.prf
@@ -26,7 +26,11 @@ equals(GENERATE_SIS_TARGETS, true) {
qtPrepareTool(QMAKE_CREATEPACKAGE, createpackage)
- CREATEPACKAGE_DIR = $$OBJECTS_DIR/createpackage_tmp
+ sis_objects_dir = $$OBJECTS_DIR
+ isEmpty(sis_objects_dir):sis_objects_dir = .
+
+ CREATEPACKAGE_DIR = $$sis_objects_dir/createpackage_tmp
+
QMAKE_CLEAN += $$CREATEPACKAGE_DIR/*
symbian-abld|symbian-sbsv2 {
diff --git a/mkspecs/features/symbian/symbian_appbooster.prf b/mkspecs/features/symbian/symbian_appbooster.prf
new file mode 100644
index 0000000000..080f4d0a50
--- /dev/null
+++ b/mkspecs/features/symbian/symbian_appbooster.prf
@@ -0,0 +1,32 @@
+contains(TEMPLATE, ".*app") {
+ baseTarget = $$symbianRemoveSpecialCharacters($$basename(TARGET))
+
+ symbian-abld|symbian-sbsv2 {
+ LITE_REG_TARGET = $$_PRO_FILE_PWD_
+ } else {
+ contains(DESTDIR, "/.*") {
+ LITE_REG_TARGET = $$DESTDIR
+ } else:isEmpty(DESTDIR) {
+ LITE_REG_TARGET = $$OUT_PWD
+ } else {
+ LITE_REG_TARGET = $$OUT_PWD/$$DESTDIR
+ }
+ }
+
+ LITE_REG_TARGET = $${LITE_REG_TARGET}/$${baseTarget}.applite
+ LITE_REG_TEMPLATE = $$[QT_INSTALL_DATA]/mkspecs/common/symbian/template.applite
+
+ lite_reg_copy.input = LITE_REG_TEMPLATE
+ lite_reg_copy.output = $$LITE_REG_TARGET
+ lite_reg_copy.variable_out = PRE_TARGETDEPS
+ lite_reg_copy.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
+ lite_reg_copy.CONFIG += no_link
+ QMAKE_EXTRA_COMPILERS += lite_reg_copy
+
+ isEmpty(LITE_IMPORT_DIR): LITE_IMPORT_DIR = /private/20034884/import/apps
+ lite_deployment.sources += $$LITE_REG_TARGET
+ lite_deployment.path = $$LITE_IMPORT_DIR
+ DEPLOYMENT += lite_deployment
+
+ LIBS += -lqDeclarativeBooster.dll
+}
diff --git a/mkspecs/hurd-g++/qmake.conf b/mkspecs/hurd-g++/qmake.conf
index d89f2e4383..09a72fa0d7 100644
--- a/mkspecs/hurd-g++/qmake.conf
+++ b/mkspecs/hurd-g++/qmake.conf
@@ -1,90 +1,74 @@
#
# qmake configuration for hurd-g++
#
-# Submitted by uch@nop.or.jp as "gnu-g++".
-# Renamed to "hurd-g++" because people were confusing GNU/Hurd with GNU/Linux.
-#
MAKEFILE_GENERATOR = UNIX
TARGET_PLATFORM = unix
TEMPLATE = app
+CONFIG += qt warn_on release incremental link_prl gdb_dwarf_index
QT += core gui
-CONFIG += qt warn_on release link_prl
-
-QMAKE_CC = gcc
-QMAKE_LEX = flex
-QMAKE_LEXFLAGS =
-QMAKE_YACC = yacc
-QMAKE_YACCFLAGS = -d
-QMAKE_CFLAGS = -pipe
-QMAKE_CFLAGS_DEPS = -M
-QMAKE_CFLAGS_WARN_ON = -Wall -W
-QMAKE_CFLAGS_WARN_OFF = -w
-QMAKE_CFLAGS_RELEASE = -O2
-QMAKE_CFLAGS_DEBUG = -g
-QMAKE_CFLAGS_SHLIB = -fPIC
-QMAKE_CFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_SHLIB
-QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
-QMAKE_CFLAGS_THREAD = -D_REENTRANT
+QMAKE_INCREMENTAL_STYLE = sublib
-QMAKE_CXX = g++
-QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
-QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS
-QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
-QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
-QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
-QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
-QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB
-QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB
-QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
-QMAKE_CXXFLAGS_THREAD = $$QMAKE_CXXFLAGS_THREAD
+QMAKE_CFLAGS_THREAD += -D_REENTRANT
+QMAKE_CXXFLAGS_THREAD += $$QMAKE_CFLAGS_THREAD
-QMAKE_INCDIR =
-QMAKE_LIBDIR =
-QMAKE_INCDIR_X11 = /usr/X11R6/include
-QMAKE_LIBDIR_X11 = /usr/X11R6/lib
-QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS]
-QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS]
-QMAKE_INCDIR_OPENGL = /usr/X11R6/include
-QMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+QMAKE_INCDIR =
+QMAKE_LIBDIR =
+QMAKE_INCDIR_X11 = /usr/X11R6/include
+QMAKE_LIBDIR_X11 = /usr/X11R6/lib
+QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS]
+QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS]
+QMAKE_INCDIR_OPENGL = /usr/X11R6/include
+QMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+QMAKE_INCDIR_OPENGL_ES1 = $$QMAKE_INCDIR_OPENGL
+QMAKE_LIBDIR_OPENGL_ES1 = $$QMAKE_LIBDIR_OPENGL
+QMAKE_INCDIR_OPENGL_ES2 = $$QMAKE_INCDIR_OPENGL
+QMAKE_LIBDIR_OPENGL_ES2 = $$QMAKE_LIBDIR_OPENGL
+QMAKE_INCDIR_EGL =
+QMAKE_LIBDIR_EGL =
+QMAKE_INCDIR_OPENVG =
+QMAKE_LIBDIR_OPENVG =
-QMAKE_LINK = g++
-QMAKE_LINK_SHLIB = g++
-QMAKE_LINK_C = gcc
-QMAKE_LINK_C_SHLIB = gcc
-QMAKE_LFLAGS = -Wl,-rpath=/lib:/usr/X11R6/lib:$$[QT_INSTALL_LIBS]
-QMAKE_LFLAGS_RELEASE =
-QMAKE_LFLAGS_DEBUG =
-QMAKE_LFLAGS_SHLIB = -shared
-QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB
-QMAKE_LFLAGS_SONAME = -Wl,-soname,
+QMAKE_LIBS =
+QMAKE_LIBS_DYNLOAD = -ldl
+QMAKE_LIBS_X11 = -lXext -lX11 -lm
+QMAKE_LIBS_X11SM = -lSM -lICE
+QMAKE_LIBS_NIS = -lnsl
+QMAKE_LIBS_EGL = -lEGL
+QMAKE_LIBS_OPENGL = -lGL
+QMAKE_LIBS_OPENGL_QT = -lGL
+QMAKE_LIBS_OPENGL_ES1 = -lGLES_CM
+QMAKE_LIBS_OPENGL_ES2 = -lGLESv2
+QMAKE_LIBS_OPENVG = -lOpenVG
+QMAKE_LIBS_THREAD = -lpthread
-QMAKE_LIBS = -lpthread # This is tricky but needed
-QMAKE_LIBS_DYNLOAD = -ldl
-QMAKE_LIBS_X11 = -lXext -lX11 -lm
-QMAKE_LIBS_X11SM = -lSM -lICE
-QMAKE_LIBS_NIS = -lnsl
-QMAKE_LIBS_QT_THREAD = -lqt-mt
-QMAKE_LIBS_THREAD =
+QMAKE_MOC = $$[QT_INSTALL_BINS]/moc
+QMAKE_UIC = $$[QT_INSTALL_BINS]/uic
-QMAKE_LIBS_OPENGL = -lGL
-QMAKE_LIBS_OPENGL_QT = -lGL
+QMAKE_AR = ar cqs
+QMAKE_OBJCOPY = objcopy
+QMAKE_RANLIB =
-QMAKE_MOC = $$[QT_INSTALL_BINS]/moc
-QMAKE_UIC = $$[QT_INSTALL_BINS]/uic
+QMAKE_TAR = tar -cf
+QMAKE_GZIP = gzip -9f
-QMAKE_AR = ar cqs
-QMAKE_OBJCOPY = objcopy
-QMAKE_RANLIB =
+QMAKE_COPY = cp -f
+QMAKE_COPY_FILE = $(COPY)
+QMAKE_COPY_DIR = $(COPY) -r
+QMAKE_MOVE = mv -f
+QMAKE_DEL_FILE = rm -f
+QMAKE_DEL_DIR = rmdir
+QMAKE_STRIP = strip
+QMAKE_STRIPFLAGS_LIB += --strip-unneeded
+QMAKE_CHK_DIR_EXISTS = test -d
+QMAKE_MKDIR = mkdir -p
+QMAKE_INSTALL_FILE = install -m 644 -p
+QMAKE_INSTALL_PROGRAM = install -m 755 -p
-QMAKE_TAR = tar -cf
-QMAKE_GZIP = gzip -9f
-
-QMAKE_COPY = cp -f
-QMAKE_MOVE = mv -f
-QMAKE_DEL_FILE = rm -f
-QMAKE_DEL_DIR = rmdir
-QMAKE_CHK_DIR_EXISTS = test -d
-QMAKE_MKDIR = mkdir -p
include(../common/unix.conf)
+include(../common/gcc-base-unix.conf)
+include(../common/g++-unix.conf)
load(qt_config)
+
+# This is tricky but needed
+QMAKE_LIBS += $$QMAKE_LIBS_THREAD
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 47ae384ba9..69dffba990 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -2527,7 +2527,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
t << " " << targets.at(target-1)->target << "-" << targetSuffixes.at(suffix) << "-ordered ";
if(project->isEmpty("QMAKE_NOFORCE"))
t << " FORCE";
- writeSubMakeCall(t, out_directory_cdin, makefilein, out_directory_cdout);
+ writeSubMakeCall(t, out_directory_cdin, makefilein + " " + s, out_directory_cdout);
}
t << subtarget->target << "-" << targetSuffixes.at(suffix) << ": " << mkfile;
if(!subtarget->depends.isEmpty())
@@ -2535,7 +2535,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
"-"+targetSuffixes.at(suffix));
if(project->isEmpty("QMAKE_NOFORCE"))
t << " FORCE";
- writeSubMakeCall(t, out_directory_cdin, makefilein, out_directory_cdout);
+ writeSubMakeCall(t, out_directory_cdin, makefilein + " " + s, out_directory_cdout);
}
}
t << endl;
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index 9f144929ed..82f2366349 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -96,7 +96,8 @@ UnixMakefileGenerator::writeMakefile(QTextStream &t)
}
if (project->values("TEMPLATE").first() == "app" ||
- project->values("TEMPLATE").first() == "lib") {
+ project->values("TEMPLATE").first() == "lib" ||
+ project->values("TEMPLATE").first() == "aux") {
if(Option::mkfile::do_stub_makefile && MakefileGenerator::writeStubMakefile(t))
return true;
writeMakeParts(t);
@@ -1017,6 +1018,9 @@ void UnixMakefileGenerator::init2()
if(project->isEmpty("QMAKE_FRAMEWORK_VERSION"))
project->values("QMAKE_FRAMEWORK_VERSION").append(project->values("VER_MAJ").first());
+ if (project->values("TEMPLATE").first() == "aux")
+ return;
+
if (!project->values("QMAKE_APP_FLAG").isEmpty()) {
if(!project->isEmpty("QMAKE_BUNDLE")) {
QString bundle_loc = project->first("QMAKE_BUNDLE_LOCATION");
diff --git a/qmake/generators/win32/borland_bmake.cpp b/qmake/generators/win32/borland_bmake.cpp
index 585a0f4982..1f7de00c2e 100644
--- a/qmake/generators/win32/borland_bmake.cpp
+++ b/qmake/generators/win32/borland_bmake.cpp
@@ -68,7 +68,8 @@ BorlandMakefileGenerator::writeMakefile(QTextStream &t)
}
if(project->first("TEMPLATE") == "app" ||
- project->first("TEMPLATE") == "lib") {
+ project->first("TEMPLATE") == "lib" ||
+ project->first("TEMPLATE") == "aux") {
writeBorlandParts(t);
return MakefileGenerator::writeMakefile(t);
}
@@ -136,6 +137,11 @@ BorlandMakefileGenerator::init()
void BorlandMakefileGenerator::writeBuildRulesPart(QTextStream &t)
{
+ if (project->first("TEMPLATE") == "aux") {
+ t << "first:" << endl;
+ return;
+ }
+
t << "first: all" << endl;
t << "all: " << fileFixify(Option::output.fileName()) << " " << varGlue("ALL_DEPS"," "," "," ") << " $(DESTDIR_TARGET)" << endl << endl;
t << "$(DESTDIR_TARGET): " << var("PRE_TARGETDEPS") << " $(OBJECTS) " << var("POST_TARGETDEPS");
diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp
index 462920e06c..0d15cfbad2 100644
--- a/qmake/generators/win32/mingw_make.cpp
+++ b/qmake/generators/win32/mingw_make.cpp
@@ -141,7 +141,8 @@ bool MingwMakefileGenerator::writeMakefile(QTextStream &t)
}
if(project->first("TEMPLATE") == "app" ||
- project->first("TEMPLATE") == "lib") {
+ project->first("TEMPLATE") == "lib" ||
+ project->first("TEMPLATE") == "aux") {
if(project->isActiveConfig("create_pc") && project->first("TEMPLATE") == "lib")
writePkgConfigFile();
@@ -436,6 +437,11 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t)
void MingwMakefileGenerator::writeBuildRulesPart(QTextStream &t)
{
+ if (project->first("TEMPLATE") == "aux") {
+ t << "first:" << endl;
+ return;
+ }
+
t << "first: all" << endl;
t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName())) << " " << valGlue(escapeDependencyPaths(project->values("ALL_DEPS"))," "," "," ") << " $(DESTDIR_TARGET)" << endl << endl;
t << "$(DESTDIR_TARGET): " << var("PRE_TARGETDEPS") << " $(OBJECTS) " << var("POST_TARGETDEPS");
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index e0e2fe0e79..52eaaceda1 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -70,7 +70,8 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
}
if(project->first("TEMPLATE") == "app" ||
- project->first("TEMPLATE") == "lib") {
+ project->first("TEMPLATE") == "lib" ||
+ project->first("TEMPLATE") == "aux") {
#if 0
if(Option::mkfile::do_stub_makefile)
return MakefileGenerator::writeStubMakefile(t);
@@ -341,6 +342,11 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t)
void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t)
{
+ if (project->first("TEMPLATE") == "aux") {
+ t << "first:" << endl;
+ return;
+ }
+
t << "first: all" << endl;
t << "all: " << fileFixify(Option::output.fileName()) << " " << varGlue("ALL_DEPS"," "," "," ") << "$(DESTDIR_TARGET)" << endl << endl;
t << "$(DESTDIR_TARGET): " << var("PRE_TARGETDEPS") << " $(OBJECTS) " << var("POST_TARGETDEPS");
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index 56f3bfdb94..580778736c 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -208,6 +208,7 @@ const char _slnExtSections[] = "\n\tGlobalSection(ExtensibilityGlobals) = pos
VcprojGenerator::VcprojGenerator()
: Win32MakefileGenerator(),
init_flag(false),
+ is64Bit(false),
projectWriter(0)
{
}
@@ -597,14 +598,16 @@ nextfile:
}
}
t << _slnGlobalBeg;
+
+ QString slnConf = _slnSolutionConf;
if (!project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH")) {
- QString slnConfCE = _slnSolutionConf;
- QString platform = QString("|") + project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")";
- slnConfCE.replace(QString("|Win32"), platform);
- t << slnConfCE;
- } else {
- t << _slnSolutionConf;
+ QString slnPlatform = QString("|") + project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")";
+ slnConf.replace(QString("|Win32"), slnPlatform);
+ } else if (is64Bit) {
+ slnConf.replace(QString("|Win32"), "|x64");
}
+ t << slnConf;
+
t << _slnProjDepBeg;
// Restore previous after_user_var options
@@ -621,7 +624,7 @@ nextfile:
t << _slnProjDepEnd;
t << _slnProjConfBeg;
for(QList<VcsolutionDepend*>::Iterator it = solution_cleanup.begin(); it != solution_cleanup.end(); ++it) {
- QString platform = "Win32";
+ QString platform = is64Bit ? "x64" : "Win32";
if (!project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH"))
platform = project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")";
t << "\n\t\t" << (*it)->uuid << QString(_slnProjDbgConfTag1).arg(platform) << platform;
@@ -661,6 +664,7 @@ void VcprojGenerator::init()
if (init_flag)
return;
init_flag = true;
+ is64Bit = (project->first("QMAKE_TARGET.arch") == "x86_64");
projectWriter = createProjectWriter();
if(project->first("TEMPLATE") == "vcsubdirs") //too much work for subdirs
@@ -831,7 +835,7 @@ void VcprojGenerator::initProject()
vcProject.Keyword = project->first("VCPROJ_KEYWORD");
if (project->isEmpty("CE_SDK") || project->isEmpty("CE_ARCH")) {
- vcProject.PlatformName = (vcProject.Configuration.idl.TargetEnvironment == midlTargetWin64 ? "Win64" : "Win32");
+ vcProject.PlatformName = (is64Bit ? "x64" : "Win32");
} else {
vcProject.PlatformName = project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")";
}
@@ -895,7 +899,7 @@ void VcprojGenerator::initConfiguration()
conf.Name = isDebug ? "Debug" : "Release";
conf.ConfigurationName = conf.Name;
if (project->isEmpty("CE_SDK") || project->isEmpty("CE_ARCH")) {
- conf.Name += (conf.idl.TargetEnvironment == midlTargetWin64 ? "|Win64" : "|Win32");
+ conf.Name += (is64Bit ? "|x64" : "|Win32");
} else {
conf.Name += "|" + project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")";
}
diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h
index afe8f9ff21..c7f5c1b432 100644
--- a/qmake/generators/win32/msvc_vcproj.h
+++ b/qmake/generators/win32/msvc_vcproj.h
@@ -57,6 +57,7 @@ struct QUuid;
class VcprojGenerator : public Win32MakefileGenerator
{
bool init_flag;
+ bool is64Bit;
bool writeVcprojParts(QTextStream &);
bool writeMakefile(QTextStream &);
diff --git a/qmake/generators/win32/msvc_vcxproj.cpp b/qmake/generators/win32/msvc_vcxproj.cpp
index 1e7c4b7a93..5b75cfa354 100644
--- a/qmake/generators/win32/msvc_vcxproj.cpp
+++ b/qmake/generators/win32/msvc_vcxproj.cpp
@@ -41,26 +41,9 @@
#include "msvc_vcxproj.h"
#include "msbuild_objectmodel.h"
-#include <qdir.h>
-#include <qdiriterator.h>
-#include <quuid.h>
-
-
-QT_BEGIN_NAMESPACE
-// Filter GUIDs (Do NOT change these!) ------------------------------
-const char _GUIDSourceFiles[] = "{4FC737F1-C7A5-4376-A066-2A32D752A2FF}";
-const char _GUIDHeaderFiles[] = "{93995380-89BD-4b04-88EB-625FBE52EBFB}";
-const char _GUIDGeneratedFiles[] = "{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}";
-const char _GUIDResourceFiles[] = "{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}";
-const char _GUIDLexYaccFiles[] = "{E12AE0D2-192F-4d59-BD23-7D3FA58D3183}";
-const char _GUIDTranslationFiles[] = "{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}";
-const char _GUIDFormFiles[] = "{99349809-55BA-4b9d-BF79-8FDBB0286EB3}";
-const char _GUIDExtraCompilerFiles[] = "{E0D8C965-CC5F-43d7-AD63-FAEF0BBC0F85}";
-QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
-
VcxprojGenerator::VcxprojGenerator() : VcprojGenerator()
{
}
@@ -71,4 +54,3 @@ VCProjectWriter *VcxprojGenerator::createProjectWriter()
}
QT_END_NAMESPACE
-
diff --git a/qmake/generators/win32/msvc_vcxproj.h b/qmake/generators/win32/msvc_vcxproj.h
index 3283cc7493..90f665217e 100644
--- a/qmake/generators/win32/msvc_vcxproj.h
+++ b/qmake/generators/win32/msvc_vcxproj.h
@@ -42,8 +42,6 @@
#ifndef MSVC_VCXPROJ_H
#define MSVC_VCXPROJ_H
-#include "winmakefile.h"
-#include "msbuild_objectmodel.h"
#include "msvc_vcproj.h"
QT_BEGIN_NAMESPACE
@@ -52,19 +50,11 @@ class VcxprojGenerator : public VcprojGenerator
{
public:
VcxprojGenerator();
- ~VcxprojGenerator();
protected:
virtual VCProjectWriter *createProjectWriter();
-
-private:
- friend class VCFilter;
-
};
-inline VcxprojGenerator::~VcxprojGenerator()
-{ }
-
QT_END_NAMESPACE
#endif // MSVC_VCXPROJ_H
diff --git a/qtbase.pro b/qtbase.pro
index 7e334501ae..375308a5cc 100644
--- a/qtbase.pro
+++ b/qtbase.pro
@@ -7,12 +7,19 @@ TEMPLATE = subdirs
cross_compile: CONFIG += nostrip
+module_qtbase_tests.subdir = tests
+module_qtbase_tests.target = module-qtbase-tests
+module_qtbase_tests.depends = module_qtbase_src
+module_qtbase_tests.CONFIG = no_default_target no_default_install
+
#process the projects
for(PROJECT, $$list($$lower($$unique(QT_BUILD_PARTS)))) {
isEqual(PROJECT, examples) {
SUBDIRS += examples
} else:isEqual(PROJECT, demos) {
SUBDIRS += demos
+ } else:isEqual(PROJECT, tests) {
+ module_qtbase_tests.CONFIG -= no_default_target
} else:isEqual(PROJECT, libs) {
include(src/src.pro)
} else:isEqual(PROJECT, qmake) {
@@ -22,10 +29,6 @@ for(PROJECT, $$list($$lower($$unique(QT_BUILD_PARTS)))) {
}
}
-module_qtbase_tests.subdir = tests
-module_qtbase_tests.target = module-qtbase-tests
-module_qtbase_tests.depends = module_qtbase_src
-module_qtbase_tests.CONFIG = no_default_target no_default_install
SUBDIRS += module_qtbase_tests
!symbian: confclean.depends += clean
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
index c202e1f52b..3410782453 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
@@ -655,6 +655,7 @@ void HB_GetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength,
const HB_ScriptItem *items, hb_uint32 numItems,
HB_CharAttributes *attributes)
{
+ memset(attributes, 0, stringLength * sizeof(HB_CharAttributes));
calcLineBreaks(string, stringLength, attributes);
for (hb_uint32 i = 0; i < numItems; ++i) {
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index 7d74de8e44..d43ca51bc1 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -580,6 +580,8 @@ qint64 QAnimationDriver::elapsed() const
QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer)
: QAnimationDriver(0), m_unified_timer(timer)
{
+ connect(this, SIGNAL(started()), this, SLOT(startTimer()));
+ connect(this, SIGNAL(stopped()), this, SLOT(stopTimer()));
}
void QDefaultAnimationDriver::timerEvent(QTimerEvent *e)
@@ -589,12 +591,12 @@ void QDefaultAnimationDriver::timerEvent(QTimerEvent *e)
advance();
}
-void QDefaultAnimationDriver::started()
+void QDefaultAnimationDriver::startTimer()
{
m_timer.start(m_unified_timer->timingInterval, this);
}
-void QDefaultAnimationDriver::stopped()
+void QDefaultAnimationDriver::stopTimer()
{
m_timer.stop();
}
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
index de26987721..3389414995 100644
--- a/src/corelib/animation/qabstractanimation_p.h
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -124,8 +124,9 @@ public:
QDefaultAnimationDriver(QUnifiedTimer *timer);
void timerEvent(QTimerEvent *e);
- void started();
- void stopped();
+private Q_SLOTS:
+ void startTimer();
+ void stopTimer();
private:
QBasicTimer m_timer;
diff --git a/src/corelib/concurrent/qtconcurrentfilter.h b/src/corelib/concurrent/qtconcurrentfilter.h
index e392212b12..63dcc4b192 100644
--- a/src/corelib/concurrent/qtconcurrentfilter.h
+++ b/src/corelib/concurrent/qtconcurrentfilter.h
@@ -115,19 +115,7 @@ ThreadEngineStarter<void> filterInternal(Sequence &sequence, KeepFunctor keep, T
template <typename Sequence, typename KeepFunctor>
QFuture<void> filter(Sequence &sequence, KeepFunctor keep)
{
- return filterInternal(sequence, keep, &Sequence::push_back);
-}
-
-template <typename Sequence, typename T>
-QFuture<void> filter(Sequence &sequence, bool (keep)(T))
-{
- return filterInternal(sequence, FunctionWrapper1<bool, T>(keep), &Sequence::push_back);
-}
-
-template <typename Sequence, typename C>
-QFuture<void> filter(Sequence &sequence, bool (C::*keep)() const)
-{
- return filterInternal(sequence, ConstMemberFunctionWrapper<bool, C>(keep), &Sequence::push_back);
+ return filterInternal(sequence, QtPrivate::createFunctionWrapper(keep), &Sequence::push_back);
}
// filteredReduced() on sequences
@@ -137,103 +125,20 @@ QFuture<ResultType> filteredReduced(const Sequence &sequence,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startFilteredReduced<ResultType>(sequence, keep, reduce, options);
- }
-
-template <typename ResultType, typename Sequence, typename T, typename ReduceFunctor>
-QFuture<ResultType> filteredReduced(const Sequence &sequence,
- bool (filter)(T),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<ResultType>(sequence,
- FunctionWrapper1<bool, T>(filter),
- reduce,
- options);
+ return startFilteredReduced<ResultType>(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options);
}
-template <typename ResultType, typename Sequence, typename C, typename ReduceFunctor>
-QFuture<ResultType> filteredReduced(const Sequence &sequence,
- bool (C::*filter)() const,
+template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return filteredReduced<ResultType>(sequence,
- ConstMemberFunctionWrapper<bool, C>(filter),
- reduce,
- options);
-}
-
-template <typename Sequence, typename KeepFunctor, typename T, typename U, typename V>
-QFuture<U> filteredReduced(const Sequence &sequence,
- KeepFunctor keep,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<U>(sequence,
- keep,
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
-QFuture<C> filteredReduced(const Sequence &sequence,
- KeepFunctor keep,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<C>(sequence,
- keep,
- MemberFunctionWrapper1<T, C, U>(reduce),
- options);
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename W>
-QFuture<V> filteredReduced(const Sequence &sequence,
- bool (keep)(T),
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<V>(sequence,
- FunctionWrapper1<bool, T>(keep),
- FunctionWrapper2<U, V &, W>(reduce),
- options);
-}
-
-template <typename Sequence, typename C, typename T, typename U, typename V>
-QFuture<U> filteredReduced(const Sequence &sequence,
- bool (C::*keep)() const,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<U>(sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename T, typename U, typename C, typename V>
-QFuture<C> filteredReduced(const Sequence &sequence,
- bool (keep)(T),
- U (C::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<C>(sequence,
- FunctionWrapper1<bool, T>(keep),
- MemberFunctionWrapper1<U, C, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename C, typename T, typename D, typename U>
-QFuture<D> filteredReduced(const Sequence &sequence,
- bool (C::*keep)() const,
- T (D::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<D>(sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- MemberFunctionWrapper1<T, D, U>(reduce),
- options);
+ return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (sequence,
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
// filteredReduced() on iterators
@@ -244,184 +149,42 @@ QFuture<ResultType> filteredReduced(Iterator begin,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startFilteredReduced<ResultType>(begin, end, keep, reduce, options);
-}
-
-template <typename ResultType, typename Iterator, typename T, typename ReduceFunctor>
-QFuture<ResultType> filteredReduced(Iterator begin,
- Iterator end,
- bool (filter)(T),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<ResultType>(begin,
- end,
- FunctionWrapper1<bool, T>(filter),
- reduce,
- options);
+ return startFilteredReduced<ResultType>(begin, end, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options);
}
-template <typename ResultType, typename Iterator, typename C, typename ReduceFunctor>
-QFuture<ResultType> filteredReduced(Iterator begin,
+template <typename Iterator, typename KeepFunctor, typename ReduceFunctor>
+QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filteredReduced(Iterator begin,
Iterator end,
- bool (C::*filter)() const,
+ KeepFunctor keep,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return filteredReduced<ResultType>(begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(filter),
- reduce,
- options);
-}
-
-template <typename Iterator, typename KeepFunctor, typename T, typename U, typename V>
-QFuture<U> filteredReduced(Iterator begin,
- Iterator end,
- KeepFunctor keep,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<U>(begin,
- end,
- keep,
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename KeepFunctor, typename T, typename C, typename U>
-QFuture<C> filteredReduced(Iterator begin,
- Iterator end,
- KeepFunctor keep,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<C>(begin,
- end,
- keep,
- MemberFunctionWrapper1<T, C, U>(reduce),
- options);
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename W>
-QFuture<V> filteredReduced(Iterator begin,
- Iterator end,
- bool (keep)(T),
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<V>(begin,
- end,
- FunctionWrapper1<bool, T>(keep),
- FunctionWrapper2<U, V &, W>(reduce),
- options);
-}
-
-template <typename Iterator, typename C, typename T, typename U, typename V>
-QFuture<U> filteredReduced(Iterator begin,
- Iterator end,
- bool (C::*keep)() const,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<U>(begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(keep),
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename T, typename U, typename C, typename V>
-QFuture<C> filteredReduced(Iterator begin,
- Iterator end,
- bool (keep)(T),
- U (C::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<C>(begin,
- end,
- FunctionWrapper1<bool, T>(keep),
- MemberFunctionWrapper1<U, C, V>(reduce),
- options);
+ return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
-template <typename Iterator, typename C, typename T, typename D, typename U>
-QFuture<D> filteredReduced(Iterator begin,
- Iterator end,
- bool (C::*keep)() const,
- T (D::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<D>(begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(keep),
- MemberFunctionWrapper1<T, D, U>(reduce),
- options);
-}
-
-
// filtered() on sequences
template <typename Sequence, typename KeepFunctor>
QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, KeepFunctor keep)
{
- return startFiltered(sequence, keep);
-}
-
-template <typename Sequence, typename T>
-QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, bool (keep)(T))
-{
- return startFiltered(sequence, FunctionWrapper1<bool, T>(keep));
-}
-
-template <typename Sequence, typename C>
-QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, bool (C::*keep)() const)
-{
- return startFiltered(sequence, ConstMemberFunctionWrapper<bool, C>(keep));
+ return startFiltered(sequence, QtPrivate::createFunctionWrapper(keep));
}
// filtered() on iterators
template <typename Iterator, typename KeepFunctor>
QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin, Iterator end, KeepFunctor keep)
{
- return startFiltered(begin, end, keep);
+ return startFiltered(begin, end, QtPrivate::createFunctionWrapper(keep));
}
-template <typename Iterator, typename T>
-QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin, Iterator end, bool (keep)(T))
-{
- return startFiltered(begin, end, FunctionWrapper1<bool, T>(keep));
-}
-
-template <typename Iterator, typename C>
-QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin,
- Iterator end,
- bool (C::*keep)() const)
-{
- return startFiltered(begin, end, ConstMemberFunctionWrapper<bool, C>(keep));
-}
-
-
// blocking filter() on sequences
template <typename Sequence, typename KeepFunctor>
void blockingFilter(Sequence &sequence, KeepFunctor keep)
{
- filterInternal(sequence, keep, &Sequence::push_back).startBlocking();
-}
-
-template <typename Sequence, typename T>
-void blockingFilter(Sequence &sequence, bool (keep)(T))
-{
- filterInternal(sequence, FunctionWrapper1<bool, T>(keep), &Sequence::push_back)
- .startBlocking();
-}
-
-template <typename Sequence, typename C>
-void blockingFilter(Sequence &sequence, bool (C::*keep)() const)
-{
- filterInternal(sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- &Sequence::push_back)
- .startBlocking();
+ filterInternal(sequence, QtPrivate::createFunctionWrapper(keep), &Sequence::push_back).startBlocking();
}
// blocking filteredReduced() on sequences
@@ -431,111 +194,20 @@ ResultType blockingFilteredReduced(const Sequence &sequence,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startFilteredReduced<ResultType>(sequence, keep, reduce, options)
+ return startFilteredReduced<ResultType>(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options)
.startBlocking();
}
-template <typename ResultType, typename Sequence, typename T, typename ReduceFunctor>
-ResultType blockingFilteredReduced(const Sequence &sequence,
- bool (filter)(T),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<ResultType>
- (sequence,
- FunctionWrapper1<bool, T>(filter),
- reduce,
- options);
-}
-
-template <typename ResultType, typename Sequence, typename C, typename ReduceFunctor>
-ResultType blockingFilteredReduced(const Sequence &sequence,
- bool (C::*filter)() const,
+template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFilteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return blockingFilteredReduced<ResultType>
- (sequence,
- ConstMemberFunctionWrapper<bool, C>(filter),
- reduce,
- options);
-}
-
-template <typename Sequence, typename KeepFunctor, typename T, typename U, typename V>
-U blockingFilteredReduced(const Sequence &sequence,
- KeepFunctor keep,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<U>
- (sequence,
- keep,
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
-C blockingFilteredReduced(const Sequence &sequence,
- KeepFunctor keep,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<C>
+ return blockingFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
(sequence,
- keep,
- MemberFunctionWrapper1<T, C, U>(reduce),
- options);
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename W>
-V blockingFilteredReduced(const Sequence &sequence,
- bool (keep)(T),
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<V>
- (sequence,
- FunctionWrapper1<bool, T>(keep),
- FunctionWrapper2<U, V &, W>(reduce),
- options);
-}
-
-template <typename Sequence, typename C, typename T, typename U, typename V>
-U blockingFilteredReduced(const Sequence &sequence,
- bool (C::*keep)() const,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<U>
- (sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename T, typename U, typename C, typename V>
-C blockingFilteredReduced(const Sequence &sequence,
- bool (keep)(T),
- U (C::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<C>
- (sequence,
- FunctionWrapper1<bool, T>(keep),
- MemberFunctionWrapper1<U, C, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename C, typename T, typename D, typename U>
-D blockingFilteredReduced(const Sequence &sequence,
- bool (C::*keep)() const,
- T (D::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<D>
- (sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- MemberFunctionWrapper1<T, D, U>(reduce),
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
options);
}
@@ -547,150 +219,34 @@ ResultType blockingFilteredReduced(Iterator begin,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startFilteredReduced<ResultType>(begin, end, keep, reduce, options)
+ return startFilteredReduced<ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
+ options)
.startBlocking();
}
-template <typename ResultType, typename Iterator, typename T, typename ReduceFunctor>
-ResultType blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (filter)(T),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<ResultType>
- (begin,
- end,
- FunctionWrapper1<bool, T>(filter),
- reduce,
- options);
-}
-
-template <typename ResultType, typename Iterator, typename C, typename ReduceFunctor>
-ResultType blockingFilteredReduced(Iterator begin,
+template <typename Iterator, typename KeepFunctor, typename ReduceFunctor>
+typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFilteredReduced(Iterator begin,
Iterator end,
- bool (C::*filter)() const,
+ KeepFunctor keep,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return blockingFilteredReduced<ResultType>
- (begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(filter),
- reduce,
- options);
-}
-
-template <typename Iterator, typename KeepFunctor, typename T, typename U, typename V>
-U blockingFilteredReduced(Iterator begin,
- Iterator end,
- KeepFunctor keep,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<U>
- (begin,
- end,
- keep,
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename KeepFunctor, typename T, typename C, typename U>
-C blockingFilteredReduced(Iterator begin,
- Iterator end,
- KeepFunctor keep,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<C>
- (begin,
- end,
- keep,
- MemberFunctionWrapper1<T, C, U>(reduce),
- options);
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename W>
-V blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (keep)(T),
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<V>
- (begin,
- end,
- FunctionWrapper1<bool, T>(keep),
- FunctionWrapper2<U, V &, W>(reduce),
- options);
-}
-
-template <typename Iterator, typename C, typename T, typename U, typename V>
-U blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (C::*keep)() const,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<U>
- (begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(keep),
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename T, typename U, typename C, typename V>
-C blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (keep)(T),
- U (C::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<C>
- (begin,
- end,
- FunctionWrapper1<bool, T>(keep),
- MemberFunctionWrapper1<U, C, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename C, typename T, typename D, typename U>
-D blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (C::*keep)() const,
- T (D::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<D>
- (begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(keep),
- MemberFunctionWrapper1<T, D, U>(reduce),
- options);
+ return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
+ options)
+ .startBlocking();
}
// blocking filtered() on sequences
template <typename Sequence, typename KeepFunctor>
Sequence blockingFiltered(const Sequence &sequence, KeepFunctor keep)
{
- return blockingFilteredReduced(sequence, keep, &Sequence::push_back, OrderedReduce);
-}
-
-template <typename Sequence, typename T>
-Sequence blockingFiltered(const Sequence &sequence, bool (keep)(T))
-{
- return blockingFilteredReduced(sequence, keep, &Sequence::push_back, OrderedReduce);
-}
-
-template <typename Sequence, typename C>
-Sequence blockingFiltered(const Sequence &sequence, bool (C::*filter)() const)
-{
- return blockingFilteredReduced(sequence,
- filter,
- &Sequence::push_back,
- OrderedReduce);
+ return blockingFilteredReduced(sequence, QtPrivate::createFunctionWrapper(keep), &Sequence::push_back, OrderedReduce);
}
// blocking filtered() on iterators
@@ -699,27 +255,7 @@ OutputSequence blockingFiltered(Iterator begin, Iterator end, KeepFunctor keep)
{
return blockingFilteredReduced(begin,
end,
- keep,
- &OutputSequence::push_back,
- OrderedReduce);
-}
-
-template <typename OutputSequence, typename Iterator, typename T>
-OutputSequence blockingFiltered(Iterator begin, Iterator end, bool (keep)(T))
-{
- return blockingFilteredReduced(begin,
- end,
- keep,
- &OutputSequence::push_back,
- OrderedReduce);
-}
-
-template <typename OutputSequence, typename Iterator, typename C>
-OutputSequence blockingFiltered(Iterator begin, Iterator end, bool (C::*filter)() const)
-{
- return blockingFilteredReduced(begin,
- end,
- filter,
+ QtPrivate::createFunctionWrapper(keep),
&OutputSequence::push_back,
OrderedReduce);
}
diff --git a/src/corelib/concurrent/qtconcurrentfunctionwrappers.h b/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
index f31f7d2877..98506a597a 100644
--- a/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
+++ b/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
@@ -163,6 +163,125 @@ private:
} // namespace QtConcurrent.
+namespace QtPrivate {
+
+template <typename T>
+const T& createFunctionWrapper(const T& t)
+{
+ return t;
+}
+
+template <typename T, typename U>
+QtConcurrent::FunctionWrapper1<T, U> createFunctionWrapper(T (*func)(U))
+{
+ return QtConcurrent::FunctionWrapper1<T, U>(func);
+}
+
+template <typename T, typename C>
+QtConcurrent::MemberFunctionWrapper<T, C> createFunctionWrapper(T (C::*func)())
+{
+ return QtConcurrent::MemberFunctionWrapper<T, C>(func);
+}
+
+template <typename T, typename C, typename U>
+QtConcurrent::MemberFunctionWrapper1<T, C, U> createFunctionWrapper(T (C::*func)(U))
+{
+ return QtConcurrent::MemberFunctionWrapper1<T, C, U>(func);
+}
+
+template <typename T, typename C>
+QtConcurrent::ConstMemberFunctionWrapper<T, C> createFunctionWrapper(T (C::*func)() const)
+{
+ return QtConcurrent::ConstMemberFunctionWrapper<T, C>(func);
+}
+
+
+template<typename T>
+void *lazyResultType_helper(int, typename T::result_type * = 0);
+template<typename T>
+char lazyResultType_helper(double);
+
+template <typename Functor, bool foo = sizeof(lazyResultType_helper<Functor>(0)) != sizeof(void*)>
+struct LazyResultType { typedef typename Functor::result_type Type; };
+template <typename Functor>
+struct LazyResultType<Functor, true> { typedef void Type; };
+
+
+template <class T>
+struct ReduceResultType;
+
+template <class U, class V>
+struct ReduceResultType<void(*)(U&,V)>
+{
+ typedef U ResultType;
+};
+
+template <class T, class C, class U>
+struct ReduceResultType<T(C::*)(U)>
+{
+ typedef C ResultType;
+};
+
+template <class InputSequence, class MapFunctor>
+struct MapResultType
+{
+ typedef typename LazyResultType<MapFunctor>::Type ResultType;
+};
+
+template <class U, class V>
+struct MapResultType<void, U (*)(V)>
+{
+ typedef U ResultType;
+};
+
+template <class T, class C>
+struct MapResultType<void, T(C::*)() const>
+{
+ typedef T ResultType;
+};
+
+#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
+
+template <template <typename> class InputSequence, typename MapFunctor, typename T>
+struct MapResultType<InputSequence<T>, MapFunctor>
+{
+ typedef InputSequence<typename LazyResultType<MapFunctor>::Type> ResultType;
+};
+
+template <template <typename> class InputSequence, class T, class U, class V>
+struct MapResultType<InputSequence<T>, U (*)(V)>
+{
+ typedef InputSequence<U> ResultType;
+};
+
+template <template <typename> class InputSequence, class T, class U, class C>
+struct MapResultType<InputSequence<T>, U(C::*)() const>
+{
+ typedef InputSequence<U> ResultType;
+};
+
+#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER
+
+template <class MapFunctor>
+struct MapResultType<QStringList, MapFunctor>
+{
+ typedef QList<typename LazyResultType<MapFunctor>::Type> ResultType;
+};
+
+template <class U, class V>
+struct MapResultType<QStringList, U (*)(V)>
+{
+ typedef QList<U> ResultType;
+};
+
+template <class U, class C>
+struct MapResultType<QStringList, U(C::*)() const>
+{
+ typedef QList<U> ResultType;
+};
+
+} // namespace QtPrivate.
+
#endif //qdoc
QT_END_NAMESPACE
diff --git a/src/corelib/concurrent/qtconcurrentmap.h b/src/corelib/concurrent/qtconcurrentmap.h
index 80edf7e136..a857ab5917 100644
--- a/src/corelib/concurrent/qtconcurrentmap.h
+++ b/src/corelib/concurrent/qtconcurrentmap.h
@@ -110,38 +110,14 @@ namespace QtConcurrent {
template <typename Sequence, typename MapFunctor>
QFuture<void> map(Sequence &sequence, MapFunctor map)
{
- return startMap(sequence.begin(), sequence.end(), map);
-}
-
-template <typename Sequence, typename T, typename U>
-QFuture<void> map(Sequence &sequence, T (map)(U))
-{
- return startMap(sequence.begin(), sequence.end(), FunctionWrapper1<T, U>(map));
-}
-
-template <typename Sequence, typename T, typename C>
-QFuture<void> map(Sequence &sequence, T (C::*map)())
-{
- return startMap(sequence.begin(), sequence.end(), MemberFunctionWrapper<T, C>(map));
+ return startMap(sequence.begin(), sequence.end(), QtPrivate::createFunctionWrapper(map));
}
// map() on iterators
template <typename Iterator, typename MapFunctor>
QFuture<void> map(Iterator begin, Iterator end, MapFunctor map)
{
- return startMap(begin, end, map);
-}
-
-template <typename Iterator, typename T, typename U>
-QFuture<void> map(Iterator begin, Iterator end, T (map)(U))
-{
- return startMap(begin, end, FunctionWrapper1<T, U>(map));
-}
-
-template <typename Iterator, typename T, typename C>
-QFuture<void> map(Iterator begin, Iterator end, T (C::*map)())
-{
- return startMap(begin, end, MemberFunctionWrapper<T, C>(map));
+ return startMap(begin, end, QtPrivate::createFunctionWrapper(map));
}
// mappedReduced() for sequences.
@@ -151,88 +127,24 @@ QFuture<ResultType> mappedReduced(const Sequence &sequence,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startMappedReduced<typename MapFunctor::result_type, ResultType>
- (sequence, map, reduce, options);
-}
-
-template <typename Sequence, typename MapFunctor, typename T, typename U, typename V>
-QFuture<U> mappedReduced(const Sequence &sequence,
- MapFunctor map,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<typename MapFunctor::result_type, U>
- (sequence, map, FunctionWrapper2<T, U &, V>(reduce), options);
-}
-
-template <typename Sequence, typename MapFunctor, typename T, typename C, typename U>
-QFuture<C> mappedReduced(const Sequence &sequence,
- MapFunctor map,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<typename MapFunctor::result_type, C>
- (sequence, map, MemberFunctionWrapper1<T, C, U>(reduce), options);
-}
-
-template <typename ResultType, typename Sequence, typename T, typename U, typename ReduceFunctor>
-QFuture<ResultType> mappedReduced(const Sequence &sequence,
- T (map)(U),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, ResultType>
- (sequence, FunctionWrapper1<T, U>(map), reduce, options);
+ return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>
+ (sequence,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
-template <typename ResultType, typename Sequence, typename T, typename C, typename ReduceFunctor>
-QFuture<ResultType> mappedReduced(const Sequence &sequence,
- T (C::*map)() const,
+template <typename Sequence, typename MapFunctor, typename ReduceFunctor>
+QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedReduced(const Sequence &sequence,
+ MapFunctor map,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startMappedReduced<T, ResultType>
- (sequence, ConstMemberFunctionWrapper<T, C>(map), reduce, options);
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename W, typename X>
-QFuture<W> mappedReduced(const Sequence &sequence,
- T (map)(U),
- V (reduce)(W &, X),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, W>
- (sequence, FunctionWrapper1<T, U>(map), FunctionWrapper2<V, W &, X>(reduce), options);
-}
-
-template <typename Sequence, typename T, typename C, typename U, typename V, typename W>
-QFuture<V> mappedReduced(const Sequence &sequence,
- T (C::*map)() const,
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, V> (sequence, ConstMemberFunctionWrapper<T, C>(map),
- FunctionWrapper2<U, V &, W>(reduce), options);
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename C, typename W>
-QFuture<C> mappedReduced(const Sequence &sequence,
- T (map)(U),
- V (C::*reduce)(W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, C> (sequence, FunctionWrapper1<T, U>(map),
- MemberFunctionWrapper1<V, C, W>(reduce), options);
-}
-
-template <typename Sequence, typename T, typename C, typename U,typename D, typename V>
-QFuture<D> mappedReduced(const Sequence &sequence,
- T (C::*map)() const,
- U (D::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, D>(sequence, ConstMemberFunctionWrapper<T, C>(map),
- MemberFunctionWrapper1<U, D, V>(reduce), options);
+ return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (sequence,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
// mappedReduced() for iterators
@@ -243,295 +155,85 @@ QFuture<ResultType> mappedReduced(Iterator begin,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startMappedReduced<ResultType, typename MapFunctor::result_type>
- (begin, end, map, reduce, options);
-}
-
-template <typename Iterator, typename MapFunctor, typename T, typename U, typename V>
-QFuture<U> mappedReduced(Iterator begin,
- Iterator end,
- MapFunctor map,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<typename MapFunctor::result_type, U>
- (begin, end, map, FunctionWrapper2<T, U &, V>(reduce), options);
-}
-
-template <typename Iterator, typename MapFunctor, typename T, typename C, typename U>
-QFuture<C> mappedReduced(Iterator begin,
- Iterator end,
- MapFunctor map,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<typename MapFunctor::result_type, C>
- (begin, end, map, MemberFunctionWrapper1<T, C, U>(reduce), options);
+ return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
-template <typename ResultType, typename Iterator, typename T, typename U, typename ReduceFunctor>
-QFuture<ResultType> mappedReduced(Iterator begin,
+template <typename Iterator, typename MapFunctor, typename ReduceFunctor>
+QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedReduced(Iterator begin,
Iterator end,
- T (map)(U),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, ResultType>
- (begin, end, FunctionWrapper1<T, U>(map), reduce, options);
-}
-
-template <typename ResultType, typename Iterator, typename T, typename C, typename ReduceFunctor>
-QFuture<ResultType> mappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
+ MapFunctor map,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startMappedReduced<T, ResultType>
- (begin, end, ConstMemberFunctionWrapper<T, C>(map), reduce, options);
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename W, typename X>
-QFuture<W> mappedReduced(Iterator begin,
- Iterator end,
- T (map)(U),
- V (reduce)(W &, X),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, W>
- (begin, end, FunctionWrapper1<T, U>(map), FunctionWrapper2<V, W &, X>(reduce), options);
-}
-
-template <typename Iterator, typename T, typename C, typename U, typename V, typename W>
-QFuture<V> mappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, V>(begin, end, ConstMemberFunctionWrapper<T, C>(map),
- FunctionWrapper2<U, V &, W>(reduce), options);
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename C, typename W>
-QFuture<C> mappedReduced(Iterator begin,
- Iterator end,
- T (map)(U),
- V (C::*reduce)(W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, C>
- (begin, end, FunctionWrapper1<T, U>(map), MemberFunctionWrapper1<V, C, W>(reduce), options);
-}
-
-template <typename Iterator, typename T, typename C, typename U,typename D, typename V>
-QFuture<D> mappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
- U (D::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, D>(begin, end, ConstMemberFunctionWrapper<T, C>(map),
- MemberFunctionWrapper1<U, D, V>(reduce), options);
+ return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
// mapped() for sequences
template <typename Sequence, typename MapFunctor>
-QFuture<typename MapFunctor::result_type> mapped(const Sequence &sequence, MapFunctor map)
+QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> mapped(const Sequence &sequence, MapFunctor map)
{
- return startMapped<typename MapFunctor::result_type>(sequence, map);
-}
-
-template <typename Sequence, typename T, typename U>
-QFuture<T> mapped(const Sequence &sequence, T (map)(U))
-{
- return startMapped<T>(sequence, FunctionWrapper1<T, U>(map));
-}
-
-template <typename Sequence, typename T, typename C>
-QFuture<T> mapped(const Sequence &sequence, T (C::*map)() const)
-{
- return startMapped<T>(sequence, ConstMemberFunctionWrapper<T, C>(map));
+ return startMapped<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType>(sequence, QtPrivate::createFunctionWrapper(map));
}
// mapped() for iterator ranges.
template <typename Iterator, typename MapFunctor>
-QFuture<typename MapFunctor::result_type> mapped(Iterator begin, Iterator end, MapFunctor map)
-{
- return startMapped<Q_TYPENAME MapFunctor::result_type>(begin, end, map);
-}
-
-template <typename Iterator, typename T, typename U>
-QFuture<T> mapped(Iterator begin, Iterator end, T (map)(U))
+QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> mapped(Iterator begin, Iterator end, MapFunctor map)
{
- return startMapped<T>(begin, end, FunctionWrapper1<T, U>(map));
+ return startMapped<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType>(begin, end, QtPrivate::createFunctionWrapper(map));
}
-template <typename Iterator, typename T, typename C>
-QFuture<T> mapped(Iterator begin, Iterator end, T (C::*map)() const)
-{
- return startMapped<T>(begin, end, ConstMemberFunctionWrapper<T, C>(map));
-}
-
-
+// blockingMap() for sequences
template <typename Sequence, typename MapFunctor>
void blockingMap(Sequence &sequence, MapFunctor map)
{
- startMap(sequence.begin(), sequence.end(), map).startBlocking();
-}
-
-template <typename Sequence, typename T, typename U>
-void blockingMap(Sequence &sequence, T (map)(U))
-{
- startMap(sequence.begin(), sequence.end(), QtConcurrent::FunctionWrapper1<T, U>(map)).startBlocking();
-}
-
-template <typename Sequence, typename T, typename C>
-void blockingMap(Sequence &sequence, T (C::*map)())
-{
- startMap(sequence.begin(), sequence.end(), QtConcurrent::MemberFunctionWrapper<T, C>(map)).startBlocking();
+ startMap(sequence.begin(), sequence.end(), QtPrivate::createFunctionWrapper(map)).startBlocking();
}
+// blockingMap() for iterator ranges
template <typename Iterator, typename MapFunctor>
void blockingMap(Iterator begin, Iterator end, MapFunctor map)
{
- startMap(begin, end, map).startBlocking();
-}
-
-template <typename Iterator, typename T, typename U>
-void blockingMap(Iterator begin, Iterator end, T (map)(U))
-{
- startMap(begin, end, QtConcurrent::FunctionWrapper1<T, U>(map)).startBlocking();
-}
-
-template <typename Iterator, typename T, typename C>
-void blockingMap(Iterator begin, Iterator end, T (C::*map)())
-{
- startMap(begin, end, QtConcurrent::MemberFunctionWrapper<T, C>(map)).startBlocking();
+ startMap(begin, end, QtPrivate::createFunctionWrapper(map)).startBlocking();
}
+// blockingMappedReduced() for sequences
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
ResultType blockingMappedReduced(const Sequence &sequence,
MapFunctor map,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, ResultType>
- (sequence, map, reduce, options).startBlocking();
-}
-
-template <typename Sequence, typename MapFunctor, typename T, typename U, typename V>
-U blockingMappedReduced(const Sequence &sequence,
- MapFunctor map,
- T (reduce)(U &, V),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, U>
- (sequence,
- map,
- QtConcurrent::FunctionWrapper2<T, U &, V>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename MapFunctor, typename T, typename C, typename U>
-C blockingMappedReduced(const Sequence &sequence,
- MapFunctor map,
- T (C::*reduce)(U),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, C>
- (sequence,
- map,
- QtConcurrent::MemberFunctionWrapper1<T, C, U>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename ResultType, typename Sequence, typename T, typename U, typename ReduceFunctor>
-ResultType blockingMappedReduced(const Sequence &sequence,
- T (map)(U),
- ReduceFunctor reduce,
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, ResultType>
+ return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>
(sequence,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- reduce,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
options)
.startBlocking();
}
-template <typename ResultType, typename Sequence, typename T, typename C, typename ReduceFunctor>
-ResultType blockingMappedReduced(const Sequence &sequence,
- T (C::*map)() const,
+template <typename MapFunctor, typename ReduceFunctor, typename Sequence>
+typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedReduced(const Sequence &sequence,
+ MapFunctor map,
ReduceFunctor reduce,
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, ResultType>
- (sequence,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- reduce,
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename W, typename X>
-W blockingMappedReduced(const Sequence &sequence,
- T (map)(U),
- V (reduce)(W &, X),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, W>
- (sequence,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- QtConcurrent::FunctionWrapper2<V, W &, X>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename T, typename C, typename U, typename V, typename W>
-V blockingMappedReduced(const Sequence &sequence,
- T (C::*map)() const,
- U (reduce)(V &, W),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, V>
- (sequence,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- QtConcurrent::FunctionWrapper2<U, V &, W>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename C, typename W>
-C blockingMappedReduced(const Sequence &sequence,
- T (map)(U),
- V (C::*reduce)(W),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, C>
- (sequence,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- QtConcurrent::MemberFunctionWrapper1<V, C, W>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename T, typename C, typename U,typename D, typename V>
-D blockingMappedReduced(const Sequence &sequence,
- T (C::*map)() const,
- U (D::*reduce)(V),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return QtConcurrent::startMappedReduced<T, D>
+ return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
(sequence,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- QtConcurrent::MemberFunctionWrapper1<U, D, V>(reduce),
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
options)
.startBlocking();
}
+// blockingMappedReduced() for iterator ranges
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
ResultType blockingMappedReduced(Iterator begin,
Iterator end,
@@ -539,134 +241,25 @@ ResultType blockingMappedReduced(Iterator begin,
ReduceFunctor reduce,
QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, ResultType>
- (begin, end, map, reduce, options).startBlocking();
-}
-
-template <typename Iterator, typename MapFunctor, typename T, typename U, typename V>
-U blockingMappedReduced(Iterator begin,
- Iterator end,
- MapFunctor map,
- T (reduce)(U &, V),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, U>
- (begin,
- end,
- map,
- QtConcurrent::FunctionWrapper2<T, U &, V>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename MapFunctor, typename T, typename C, typename U>
-C blockingMappedReduced(Iterator begin,
- Iterator end,
- MapFunctor map,
- T (C::*reduce)(U),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, C>
- (begin,
- end,
- map,
- QtConcurrent::MemberFunctionWrapper1<T, C, U>(reduce),
+ return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
options)
.startBlocking();
}
-template <typename ResultType, typename Iterator, typename T, typename U, typename ReduceFunctor>
-ResultType blockingMappedReduced(Iterator begin,
+template <typename Iterator, typename MapFunctor, typename ReduceFunctor>
+typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedReduced(Iterator begin,
Iterator end,
- T (map)(U),
- ReduceFunctor reduce,
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, ResultType>
- (begin,
- end,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- reduce,
- options)
- .startBlocking();
-}
-
-template <typename ResultType, typename Iterator, typename T, typename C, typename ReduceFunctor>
-ResultType blockingMappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
+ MapFunctor map,
ReduceFunctor reduce,
QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
{
- return QtConcurrent::startMappedReduced<T, ResultType>
- (begin,
- end,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- reduce,
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename W, typename X>
-W blockingMappedReduced(Iterator begin,
- Iterator end,
- T (map)(U),
- V (reduce)(W &, X),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, W>
- (begin,
- end,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- QtConcurrent::FunctionWrapper2<V, W &, X>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename T, typename C, typename U, typename V, typename W>
-V blockingMappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
- U (reduce)(V &, W),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, V>
- (begin,
- end,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- QtConcurrent::FunctionWrapper2<U, V &, W>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename C, typename W>
-C blockingMappedReduced(Iterator begin,
- Iterator end,
- T (map)(U),
- V (C::*reduce)(W),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, C>
- (begin,
- end,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- QtConcurrent::MemberFunctionWrapper1<V, C, W>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename T, typename C, typename U,typename D, typename V>
-D blockingMappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
- U (D::*reduce)(V),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, D>
- (begin,
- end,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- QtConcurrent::MemberFunctionWrapper1<U, D, V>(reduce),
+ return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
options)
.startBlocking();
}
@@ -675,97 +268,44 @@ D blockingMappedReduced(Iterator begin,
template <typename OutputSequence, typename InputSequence, typename MapFunctor>
OutputSequence blockingMapped(const InputSequence &sequence, MapFunctor map)
{
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <typename OutputSequence, typename InputSequence, typename T, typename U>
-OutputSequence blockingMapped(const InputSequence &sequence, T (map)(U))
-{
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <typename OutputSequence, typename InputSequence, typename T, typename C>
-OutputSequence blockingMapped(const InputSequence &sequence, T (C::*map)() const)
-{
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
-
-// overloads for changing the container value type:
-template <template <typename> class Sequence, typename MapFunctor, typename T>
-Sequence<typename MapFunctor::result_type> blockingMapped(const Sequence<T> &sequence, MapFunctor map)
-{
- typedef Sequence<typename MapFunctor::result_type> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <template <typename> class Sequence, typename T, typename U, typename V>
-Sequence<U> blockingMapped(const Sequence<T> &sequence, U (map)(V))
-{
- typedef Sequence<U> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <template <typename> class Sequence, typename T, typename U, typename C>
-Sequence<U> blockingMapped(const Sequence<T> &sequence, U (C::*map)() const)
-{
- typedef Sequence<U> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER
-
-// overloads for changing the container value type from a QStringList:
-template <typename MapFunctor>
-QList<typename MapFunctor::result_type> blockingMapped(const QStringList &sequence, MapFunctor map)
-{
- typedef QList<typename MapFunctor::result_type> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <typename U, typename V>
-QList<U> blockingMapped(const QStringList &sequence, U (map)(V))
-{
- typedef QList<U> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
+ return blockingMappedReduced<OutputSequence>
+ (sequence,
+ QtPrivate::createFunctionWrapper(map),
+ &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
}
-template <typename U, typename C>
-QList<U> blockingMapped(const QStringList &sequence, U (C::*map)() const)
+template <typename MapFunctor, typename InputSequence>
+typename QtPrivate::MapResultType<InputSequence, MapFunctor>::ResultType blockingMapped(const InputSequence &sequence, MapFunctor map)
{
- typedef QList<U> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
+ typedef typename QtPrivate::MapResultType<InputSequence, MapFunctor>::ResultType OutputSequence;
+ return blockingMappedReduced<OutputSequence>
+ (sequence,
+ QtPrivate::createFunctionWrapper(map),
+ &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
}
// mapped() for iterator ranges
template <typename Sequence, typename Iterator, typename MapFunctor>
Sequence blockingMapped(Iterator begin, Iterator end, MapFunctor map)
{
- return blockingMappedReduced(begin, end, map, &Sequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <typename Sequence, typename Iterator, typename T, typename U>
-Sequence blockingMapped(Iterator begin, Iterator end, T (map)(U))
-{
- return blockingMappedReduced(begin, end, map, &Sequence::push_back,
- QtConcurrent::OrderedReduce);
+ return blockingMappedReduced<Sequence>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ &Sequence::push_back,
+ QtConcurrent::OrderedReduce);
}
-template <typename Sequence, typename Iterator, typename T, typename C>
-Sequence blockingMapped(Iterator begin, Iterator end, T (C::*map)() const)
-{
- return blockingMappedReduced(begin, end, map, &Sequence::push_back,
- QtConcurrent::OrderedReduce);
+template <typename Iterator, typename MapFunctor>
+typename QtPrivate::MapResultType<Iterator, MapFunctor>::ResultType blockingMapped(Iterator begin, Iterator end, MapFunctor map)
+{
+ typedef typename QtPrivate::MapResultType<Iterator, MapFunctor>::ResultType OutputSequence;
+ return blockingMappedReduced<OutputSequence>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
}
} // namespace QtConcurrent
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 49f5f989fb..35edcdb1a1 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1368,6 +1368,16 @@ class QDataStream;
# else
# define Q_DBUS_EXPORT Q_DECL_IMPORT
# endif
+# if defined(QT_BUILD_LOCATION_LIB)
+# define Q_LOCATION_EXPORT Q_DECL_EXPORT
+# else
+# define Q_LOCATION_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_SENSORS_LIB)
+# define Q_SENSORS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_SENSORS_EXPORT Q_DECL_IMPORT
+# endif
# define Q_TEMPLATEDLL
# elif defined(QT_DLL) /* use a Qt DLL library */
# define Q_CORE_EXPORT Q_DECL_IMPORT
@@ -1386,6 +1396,8 @@ class QDataStream;
# define Q_SCRIPTTOOLS_EXPORT Q_DECL_IMPORT
# define Q_COMPAT_EXPORT Q_DECL_IMPORT
# define Q_DBUS_EXPORT Q_DECL_IMPORT
+# define Q_LOCATION_EXPORT Q_DECL_IMPORT
+# define Q_SENSORS_EXPORT Q_DECL_IMPORT
# define Q_TEMPLATEDLL
# endif
# define Q_NO_DECLARED_NOT_DEFINED
@@ -1415,6 +1427,8 @@ class QDataStream;
# define Q_SCRIPTTOOLS_EXPORT Q_DECL_EXPORT
# define Q_COMPAT_EXPORT Q_DECL_EXPORT
# define Q_DBUS_EXPORT Q_DECL_EXPORT
+# define Q_LOCATION_EXPORT Q_DECL_EXPORT
+# define Q_SENSORS_EXPORT Q_DECL_EXPORT
# else
# define Q_CORE_EXPORT
# define Q_GUI_EXPORT
@@ -1430,6 +1444,8 @@ class QDataStream;
# define Q_SCRIPTTOOLS_EXPORT
# define Q_COMPAT_EXPORT
# define Q_DBUS_EXPORT
+# define Q_LOCATION_EXPORT
+# define Q_SENSORS_EXPORT
# endif
#endif
@@ -1843,6 +1859,10 @@ inline QT3_SUPPORT void qSuppressObsoleteWarnings(bool = true) {}
inline QT3_SUPPORT void qObsolete(const char *, const char * = 0, const char * = 0) {}
#endif
+#if !defined(Q_UNIMPLEMENTED)
+# define Q_UNIMPLEMENTED() qWarning("%s:%d: %s: Unimplemented code.", __FILE__, __LINE__, Q_FUNC_INFO)
+#endif
+
#if defined(QT_NO_THREAD)
template <typename T>
@@ -2587,26 +2607,28 @@ Q_CORE_EXPORT int qt_symbian_exception2Error(const std::exception& ex);
*/
/* Qt modules */
-#define QT_MODULE_CORE 0x00001
-#define QT_MODULE_GUI 0x00002
-#define QT_MODULE_NETWORK 0x00004
-#define QT_MODULE_OPENGL 0x00008
-#define QT_MODULE_SQL 0x00010
-#define QT_MODULE_XML 0x00020
-#define QT_MODULE_QT3SUPPORTLIGHT 0x00040
-#define QT_MODULE_QT3SUPPORT 0x00080
-#define QT_MODULE_SVG 0x00100
-#define QT_MODULE_ACTIVEQT 0x00200
-#define QT_MODULE_GRAPHICSVIEW 0x00400
-#define QT_MODULE_SCRIPT 0x00800
-#define QT_MODULE_XMLPATTERNS 0x01000
-#define QT_MODULE_HELP 0x02000
-#define QT_MODULE_TEST 0x04000
-#define QT_MODULE_DBUS 0x08000
-#define QT_MODULE_SCRIPTTOOLS 0x10000
-#define QT_MODULE_OPENVG 0x20000
-#define QT_MODULE_MULTIMEDIA 0x40000
-#define QT_MODULE_DECLARATIVE 0x80000
+#define QT_MODULE_CORE 0x000001
+#define QT_MODULE_GUI 0x000002
+#define QT_MODULE_NETWORK 0x000004
+#define QT_MODULE_OPENGL 0x000008
+#define QT_MODULE_SQL 0x000010
+#define QT_MODULE_XML 0x000020
+#define QT_MODULE_QT3SUPPORTLIGHT 0x000040
+#define QT_MODULE_QT3SUPPORT 0x000080
+#define QT_MODULE_SVG 0x000100
+#define QT_MODULE_ACTIVEQT 0x000200
+#define QT_MODULE_GRAPHICSVIEW 0x000400
+#define QT_MODULE_SCRIPT 0x000800
+#define QT_MODULE_XMLPATTERNS 0x001000
+#define QT_MODULE_HELP 0x002000
+#define QT_MODULE_TEST 0x004000
+#define QT_MODULE_DBUS 0x008000
+#define QT_MODULE_SCRIPTTOOLS 0x010000
+#define QT_MODULE_OPENVG 0x020000
+#define QT_MODULE_MULTIMEDIA 0x040000
+#define QT_MODULE_DECLARATIVE 0x080000
+#define QT_MODULE_LOCATION 0x100000
+#define QT_MODULE_SENSORS 0x200000
/* Qt editions */
#define QT_EDITION_CONSOLE (QT_MODULE_CORE \
@@ -2642,6 +2664,8 @@ Q_CORE_EXPORT int qt_symbian_exception2Error(const std::exception& ex);
| QT_MODULE_HELP \
| QT_MODULE_TEST \
| QT_MODULE_DBUS \
+ | QT_MODULE_LOCATION \
+ | QT_MODULE_SENSORS \
| QT_MODULE_ACTIVEQT)
#define QT_EDITION_DESKTOP (QT_EDITION_OPENSOURCE)
#define QT_EDITION_UNIVERSAL QT_EDITION_DESKTOP
@@ -2721,6 +2745,12 @@ QT_LICENSED_MODULE(Test)
#if (QT_EDITION & QT_MODULE_DBUS)
QT_LICENSED_MODULE(DBus)
#endif
+#if (QT_EDITION & QT_MODULE_LOCATION)
+QT_LICENSED_MODULE(Location)
+#endif
+#if (QT_EDITION & QT_MODULE_SENSORS)
+QT_LICENSED_MODULE(Sensors)
+#endif
#define QT_MODULE(x) \
typedef QtValidLicenseFor##x##Module Qt##x##Module;
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index c9ebaa48bc..030b8456c4 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -356,6 +356,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
const QByteArray &path = entry.nativeFilePath();
nativeFilePath = path.constData();
nativeFilePathLength = path.size();
+ Q_UNUSED(nativeFilePathLength);
}
bool entryExists = true; // innocent until proven otherwise
@@ -638,7 +639,7 @@ QFileSystemEntry QFileSystemEngine::currentPath()
#if defined(__GLIBC__) && !defined(PATH_MAX)
char *currentName = ::get_current_dir_name();
if (currentName) {
- result = QFile::decodeName(QByteArray(currentName));
+ result = QFileSystemEntry(QByteArray(currentName), QFileSystemEntry::FromNativePath());
::free(currentName);
}
#else
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index a45225f3f7..c2234e9667 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -143,55 +143,13 @@ QT_BEGIN_NAMESPACE
\sa QProcess, QProcess::systemEnvironment(), QProcess::setProcessEnvironment()
*/
-#ifdef Q_OS_WIN
-static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name)
-{ return name.toUpper(); }
-static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name)
-{ return QString::fromLocal8Bit(name).toUpper(); }
-static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name)
-{ return name; }
-static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value)
-{ return value; }
-static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value)
-{ return QString::fromLocal8Bit(value); }
-static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value)
-{ return value; }
-static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value)
-{ return value.toLocal8Bit(); }
-#else
-static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name)
-{ return name; }
-static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name)
-{ return name.toLocal8Bit(); }
-static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name)
-{ return QString::fromLocal8Bit(name); }
-static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value)
-{ return value; }
-static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value)
-{ return value.toLocal8Bit(); }
-static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value)
-{ return QString::fromLocal8Bit(value); }
-static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value)
-{ return value; }
-#endif
-
-template<> void QSharedDataPointer<QProcessEnvironmentPrivate>::detach()
-{
- if (d && d->ref == 1)
- return;
- QProcessEnvironmentPrivate *x = (d ? new QProcessEnvironmentPrivate(*d)
- : new QProcessEnvironmentPrivate);
- x->ref.ref();
- if (d && !d->ref.deref())
- delete d;
- d = x;
-}
QStringList QProcessEnvironmentPrivate::toList() const
{
QStringList result;
- QHash<Unit, Unit>::ConstIterator it = hash.constBegin(),
- end = hash.constEnd();
+ result.reserve(hash.size());
+ Hash::ConstIterator it = hash.constBegin(),
+ end = hash.constEnd();
for ( ; it != end; ++it) {
QString data = nameToString(it.key());
QString value = valueToString(it.value());
@@ -224,19 +182,27 @@ QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list
QStringList QProcessEnvironmentPrivate::keys() const
{
QStringList result;
- QHash<Unit, Unit>::ConstIterator it = hash.constBegin(),
- end = hash.constEnd();
+ result.reserve(hash.size());
+ Hash::ConstIterator it = hash.constBegin(),
+ end = hash.constEnd();
for ( ; it != end; ++it)
result << nameToString(it.key());
return result;
}
-void QProcessEnvironmentPrivate::insert(const Hash &h)
+void QProcessEnvironmentPrivate::insert(const QProcessEnvironmentPrivate &other)
{
- QHash<Unit, Unit>::ConstIterator it = h.constBegin(),
- end = h.constEnd();
+ Hash::ConstIterator it = other.hash.constBegin(),
+ end = other.hash.constEnd();
for ( ; it != end; ++it)
hash.insert(it.key(), it.value());
+
+#ifdef Q_OS_UNIX
+ QHash<QString, Key>::ConstIterator nit = other.nameMap.constBegin(),
+ nend = other.nameMap.constEnd();
+ for ( ; nit != nend; ++nit)
+ nameMap.insert(nit.key(), nit.value());
+#endif
}
/*!
@@ -317,6 +283,8 @@ void QProcessEnvironment::clear()
{
if (d)
d->hash.clear();
+ // Unix: Don't clear d->nameMap, as the environment is likely to be
+ // re-populated with the same keys again.
}
/*!
@@ -331,7 +299,7 @@ void QProcessEnvironment::clear()
*/
bool QProcessEnvironment::contains(const QString &name) const
{
- return d ? d->hash.contains(prepareName(name)) : false;
+ return d ? d->hash.contains(d->prepareName(name)) : false;
}
/*!
@@ -353,7 +321,7 @@ bool QProcessEnvironment::contains(const QString &name) const
void QProcessEnvironment::insert(const QString &name, const QString &value)
{
// d detaches from null
- d->hash.insert(prepareName(name), prepareValue(value));
+ d->hash.insert(d->prepareName(name), d->prepareValue(value));
}
/*!
@@ -370,7 +338,7 @@ void QProcessEnvironment::insert(const QString &name, const QString &value)
void QProcessEnvironment::remove(const QString &name)
{
if (d)
- d->hash.remove(prepareName(name));
+ d->hash.remove(d->prepareName(name));
}
/*!
@@ -389,11 +357,11 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa
if (!d)
return defaultValue;
- QProcessEnvironmentPrivate::Hash::ConstIterator it = d->hash.constFind(prepareName(name));
+ QProcessEnvironmentPrivate::Hash::ConstIterator it = d->hash.constFind(d->prepareName(name));
if (it == d->hash.constEnd())
return defaultValue;
- return valueToString(it.value());
+ return d->valueToString(it.value());
}
/*!
@@ -438,7 +406,7 @@ void QProcessEnvironment::insert(const QProcessEnvironment &e)
return;
// d detaches from null
- d->insert(e.d->hash);
+ d->insert(*e.d);
}
void QProcessPrivate::Channel::clear()
@@ -2321,6 +2289,8 @@ QStringList QProcess::systemEnvironment()
}
/*!
+ \fn QProcessEnvironment QProcessEnvironment::systemEnvironment()
+
\since 4.6
\brief The systemEnvironment function returns the environment of
@@ -2336,21 +2306,6 @@ QStringList QProcess::systemEnvironment()
\sa QProcess::systemEnvironment()
*/
-QProcessEnvironment QProcessEnvironment::systemEnvironment()
-{
- QProcessEnvironment env;
- const char *entry;
- for (int count = 0; (entry = environ[count]); ++count) {
- const char *equal = strchr(entry, '=');
- if (!equal)
- continue;
-
- QByteArray name(entry, equal - entry);
- QByteArray value(equal + 1);
- env.insert(QString::fromLocal8Bit(name), QString::fromLocal8Bit(value));
- }
- return env;
-}
/*!
\typedef Q_PID
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index 7bfcb311f9..54d49361be 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -81,23 +81,119 @@ class QTimer;
class RProcess;
#endif
+#ifdef Q_OS_WIN
+class QProcEnvKey : public QString
+{
+public:
+ QProcEnvKey() {}
+ explicit QProcEnvKey(const QString &other) : QString(other) {}
+ QProcEnvKey(const QProcEnvKey &other) : QString(other) {}
+ bool operator==(const QProcEnvKey &other) const { return !compare(other, Qt::CaseInsensitive); }
+};
+inline uint qHash(const QProcEnvKey &key) { return qHash(key.toCaseFolded()); }
+
+typedef QString QProcEnvValue;
+#else
+class QProcEnvKey
+{
+public:
+ QProcEnvKey() : hash(0) {}
+ explicit QProcEnvKey(const QByteArray &other) : key(other), hash(qHash(key)) {}
+ QProcEnvKey(const QProcEnvKey &other) { *this = other; }
+ bool operator==(const QProcEnvKey &other) const { return key == other.key; }
+
+ QByteArray key;
+ uint hash;
+};
+inline uint qHash(const QProcEnvKey &key) { return key.hash; }
+
+class QProcEnvValue
+{
+public:
+ QProcEnvValue() {}
+ QProcEnvValue(const QProcEnvValue &other) { *this = other; }
+ explicit QProcEnvValue(const QString &value) : stringValue(value) {}
+ explicit QProcEnvValue(const QByteArray &value) : byteValue(value) {}
+ bool operator==(const QProcEnvValue &other) const
+ {
+ return byteValue.isEmpty() && other.byteValue.isEmpty()
+ ? stringValue == other.stringValue
+ : bytes() == other.bytes();
+ }
+ QByteArray bytes() const
+ {
+ if (byteValue.isEmpty() && !stringValue.isEmpty())
+ byteValue = stringValue.toLocal8Bit();
+ return byteValue;
+ }
+ QString string() const
+ {
+ if (stringValue.isEmpty() && !byteValue.isEmpty())
+ stringValue = QString::fromLocal8Bit(byteValue);
+ return stringValue;
+ }
+
+ mutable QByteArray byteValue;
+ mutable QString stringValue;
+};
+Q_DECLARE_TYPEINFO(QProcEnvValue, Q_MOVABLE_TYPE);
+#endif
+Q_DECLARE_TYPEINFO(QProcEnvKey, Q_MOVABLE_TYPE);
+
class QProcessEnvironmentPrivate: public QSharedData
{
public:
+ typedef QProcEnvKey Key;
+ typedef QProcEnvValue Value;
#ifdef Q_OS_WIN
- typedef QString Unit;
+ inline Key prepareName(const QString &name) const { return Key(name); }
+ inline QString nameToString(const Key &name) const { return name; }
+ inline Value prepareValue(const QString &value) const { return value; }
+ inline QString valueToString(const Value &value) const { return value; }
#else
- typedef QByteArray Unit;
+ inline Key prepareName(const QString &name) const
+ {
+ Key &ent = nameMap[name];
+ if (ent.key.isEmpty())
+ ent = Key(name.toLocal8Bit());
+ return ent;
+ }
+ inline QString nameToString(const Key &name) const
+ {
+ const QString sname = QString::fromLocal8Bit(name.key);
+ nameMap[sname] = name;
+ return sname;
+ }
+ inline Value prepareValue(const QString &value) const { return Value(value); }
+ inline QString valueToString(const Value &value) const { return value.string(); }
#endif
- typedef QHash<Unit, Unit> Hash;
+
+ typedef QHash<Key, Value> Hash;
Hash hash;
+#ifdef Q_OS_UNIX
+ typedef QHash<QString, Key> NameHash;
+ mutable NameHash nameMap;
+#endif
+
static QProcessEnvironment fromList(const QStringList &list);
QStringList toList() const;
QStringList keys() const;
- void insert(const Hash &hash);
+ void insert(const QProcessEnvironmentPrivate &other);
};
+template<> Q_INLINE_TEMPLATE void QSharedDataPointer<QProcessEnvironmentPrivate>::detach()
+{
+ if (d && d->ref == 1)
+ return;
+ QProcessEnvironmentPrivate *x = (d ? new QProcessEnvironmentPrivate(*d)
+ : new QProcessEnvironmentPrivate);
+ x->ref.ref();
+ if (d && !d->ref.deref())
+ delete d;
+ d = x;
+}
+
class QProcessPrivate : public QIODevicePrivate
{
public:
diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp
index 8a74c7b4a2..2ce7a00082 100644
--- a/src/corelib/io/qprocess_symbian.cpp
+++ b/src/corelib/io/qprocess_symbian.cpp
@@ -1062,6 +1062,11 @@ void QProcessPrivate::initializeProcessManager()
(void) processManager();
}
+QProcessEnvironment QProcessEnvironment::systemEnvironment()
+{
+ return QProcessEnvironment();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_PROCESS
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index f53742b815..207ac92c72 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -467,7 +467,35 @@ bool QProcessPrivate::createChannel(Channel &channel)
}
}
-static char **_q_dupEnvironment(const QHash<QByteArray, QByteArray> &environment, int *envc)
+QT_BEGIN_INCLUDE_NAMESPACE
+#if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES)
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#else
+ extern char **environ;
+#endif
+QT_END_INCLUDE_NAMESPACE
+
+QProcessEnvironment QProcessEnvironment::systemEnvironment()
+{
+ QProcessEnvironment env;
+#if !defined(Q_OS_MAC) || !defined(QT_NO_CORESERVICES)
+ const char *entry;
+ for (int count = 0; (entry = environ[count]); ++count) {
+ const char *equal = strchr(entry, '=');
+ if (!equal)
+ continue;
+
+ QByteArray name(entry, equal - entry);
+ QByteArray value(equal + 1);
+ env.d->hash.insert(QProcessEnvironmentPrivate::Key(name),
+ QProcessEnvironmentPrivate::Value(value));
+ }
+#endif
+ return env;
+}
+
+static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environment, int *envc)
{
*envc = 0;
if (environment.isEmpty())
@@ -483,17 +511,17 @@ static char **_q_dupEnvironment(const QHash<QByteArray, QByteArray> &environment
#endif
const QByteArray envLibraryPath = qgetenv(libraryPath);
bool needToAddLibraryPath = !envLibraryPath.isEmpty() &&
- !environment.contains(libraryPath);
+ !environment.contains(QProcessEnvironmentPrivate::Key(QByteArray(libraryPath)));
char **envp = new char *[environment.count() + 2];
envp[environment.count()] = 0;
envp[environment.count() + 1] = 0;
- QHash<QByteArray, QByteArray>::ConstIterator it = environment.constBegin();
- const QHash<QByteArray, QByteArray>::ConstIterator end = environment.constEnd();
+ QProcessEnvironmentPrivate::Hash::ConstIterator it = environment.constBegin();
+ const QProcessEnvironmentPrivate::Hash::ConstIterator end = environment.constEnd();
for ( ; it != end; ++it) {
- QByteArray key = it.key();
- QByteArray value = it.value();
+ QByteArray key = it.key().key;
+ QByteArray value = it.value().bytes();
key.reserve(key.length() + 1 + value.length());
key.append('=');
key.append(value);
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 625ed9853f..bb23954614 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -278,29 +278,55 @@ static QString qt_create_commandline(const QString &program, const QStringList &
return args;
}
-static QByteArray qt_create_environment(const QHash<QString, QString> &environment)
+QProcessEnvironment QProcessEnvironment::systemEnvironment()
+{
+ QProcessEnvironment env;
+#if !defined(Q_OS_WINCE)
+ // Calls to setenv() affect the low-level environment as well.
+ // This is not the case the other way round.
+ if (wchar_t *envStrings = GetEnvironmentStringsW()) {
+ for (const wchar_t *entry = envStrings; *entry; ) {
+ int entryLen = wcslen(entry);
+ if (const wchar_t *equal = wcschr(entry, L'=')) {
+ int nameLen = equal - entry;
+ QString name = QString::fromWCharArray(entry, nameLen);
+ QString value = QString::fromWCharArray(equal + 1, entryLen - nameLen - 1);
+ env.d->hash.insert(QProcessEnvironmentPrivate::Key(name), value);
+ }
+ entry += entryLen + 1;
+ }
+ FreeEnvironmentStringsW(envStrings);
+ }
+#endif
+ return env;
+}
+
+#if !defined(Q_OS_WINCE)
+static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Hash &environment)
{
QByteArray envlist;
if (!environment.isEmpty()) {
- QHash<QString, QString> copy = environment;
+ QProcessEnvironmentPrivate::Hash copy = environment;
// add PATH if necessary (for DLL loading)
- if (!copy.contains(QLatin1String("PATH"))) {
+ QProcessEnvironmentPrivate::Key pathKey(QLatin1String("PATH"));
+ if (!copy.contains(pathKey)) {
QByteArray path = qgetenv("PATH");
if (!path.isEmpty())
- copy.insert(QLatin1String("PATH"), QString::fromLocal8Bit(path));
+ copy.insert(pathKey, QString::fromLocal8Bit(path));
}
// add systemroot if needed
- if (!copy.contains(QLatin1String("SYSTEMROOT"))) {
- QByteArray systemRoot = qgetenv("SYSTEMROOT");
+ QProcessEnvironmentPrivate::Key rootKey(QLatin1String("SystemRoot"));
+ if (!copy.contains(rootKey)) {
+ QByteArray systemRoot = qgetenv("SystemRoot");
if (!systemRoot.isEmpty())
- copy.insert(QLatin1String("SYSTEMROOT"), QString::fromLocal8Bit(systemRoot));
+ copy.insert(rootKey, QString::fromLocal8Bit(systemRoot));
}
int pos = 0;
- QHash<QString, QString>::ConstIterator it = copy.constBegin(),
- end = copy.constEnd();
+ QProcessEnvironmentPrivate::Hash::ConstIterator it = copy.constBegin(),
+ end = copy.constEnd();
static const wchar_t equal = L'=';
static const wchar_t nul = L'\0';
@@ -335,6 +361,7 @@ static QByteArray qt_create_environment(const QHash<QString, QString> &environme
}
return envlist;
}
+#endif
void QProcessPrivate::startProcess()
{
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index b084ca5d62..f43fb31856 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -981,23 +981,6 @@ QStringList QSettingsPrivate::splitArgs(const QString &s, int idx)
// ************************************************************************
// QConfFileSettingsPrivate
-/*
- If we don't have the permission to read the file, returns false.
- If the file doesn't exist, returns true.
-*/
-static bool checkAccess(const QString &name)
-{
- QFileInfo fileInfo(name);
-
- if (fileInfo.exists()) {
- QFile file(name);
- // if the file exists but we can't open it, report an error
- return file.open(QFile::ReadOnly);
- } else {
- return true;
- }
-}
-
void QConfFileSettingsPrivate::initFormat()
{
extension = (format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini");
@@ -1026,18 +1009,13 @@ void QConfFileSettingsPrivate::initFormat()
void QConfFileSettingsPrivate::initAccess()
{
- bool readAccess = false;
if (confFiles[spec]) {
- readAccess = checkAccess(confFiles[spec]->name);
if (format > QSettings::IniFormat) {
if (!readFunc)
- readAccess = false;
+ setStatus(QSettings::AccessError);
}
}
- if (!readAccess)
- setStatus(QSettings::AccessError);
-
sync(); // loads the files the first time
}
@@ -1432,7 +1410,7 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
We can often optimize the read-only case, if the file on disk
hasn't changed.
*/
- if (readOnly) {
+ if (readOnly && confFile->size > 0) {
QFileInfo fileInfo(confFile->name);
if (confFile->size == fileInfo.size() && confFile->timeStamp == fileInfo.lastModified())
return;
@@ -1455,6 +1433,9 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
if (!file.isOpen())
file.open(QFile::ReadOnly);
+ if (!createFile && !file.isOpen())
+ setStatus(QSettings::AccessError);
+
#ifdef Q_OS_WIN
HANDLE readSemaphore = 0;
HANDLE writeSemaphore = 0;
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 36609a3a1c..c323d44de7 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -270,6 +270,17 @@ bool QCoreApplicationPrivate::is_app_closing = false;
Q_CORE_EXPORT bool qt_locale_initialized = false;
+/*
+ Create an instance of Trolltech.conf. This ensures that the settings will not
+ be thrown out of QSetting's cache for unused settings.
+ */
+Q_GLOBAL_STATIC_WITH_ARGS(QSettings, staticTrolltechConf, (QSettings::UserScope, QLatin1String("Trolltech")))
+
+QSettings *QCoreApplicationPrivate::trolltechConf()
+{
+ return staticTrolltechConf();
+}
+
Q_CORE_EXPORT uint qGlobalPostedEventsCount()
{
QThreadData *currentThreadData = QThreadData::current();
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index fdceab4724..5079e4681c 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -55,6 +55,7 @@
#include "QtCore/qcoreapplication.h"
#include "QtCore/qtranslator.h"
+#include "QtCore/qsettings.h"
#include "private/qobject_p.h"
#ifdef Q_OS_SYMBIAN
@@ -141,6 +142,7 @@ public:
#if defined(QT3_SUPPORT)
static bool useQt3Support;
#endif
+ static QSettings *trolltechConf();
};
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 80e927bcc9..d9aac00cf1 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -52,6 +52,7 @@
#include <qmap.h>
#include <qsettings.h>
#include <qdatetime.h>
+#include <private/qcoreapplication_p.h>
#ifdef Q_OS_MAC
# include <private/qcore_mac_p.h>
#endif
@@ -408,12 +409,6 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB
typedef QMap<QString, QLibraryPrivate*> LibraryMap;
struct LibraryData {
- LibraryData() : settings(0) { }
- ~LibraryData() {
- delete settings;
- }
-
- QSettings *settings;
LibraryMap libraryMap;
QSet<QLibraryPrivate*> loadedLibs;
};
@@ -711,11 +706,7 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
QStringList reg;
#ifndef QT_NO_SETTINGS
if (!settings) {
- settings = libraryData()->settings;
- if (!settings) {
- settings = new QSettings(QSettings::UserScope, QLatin1String("Trolltech"));
- libraryData()->settings = settings;
- }
+ settings = QCoreApplicationPrivate::trolltechConf();
}
reg = settings->value(regkey).toStringList();
#endif
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index 11e20604e2..b584ae5690 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -107,18 +107,21 @@ bool QMutexPrivate::wait(int timeout)
// lock acquired without waiting
return true;
}
- bool returnValue;
+ kern_return_t r;
if (timeout < 0) {
- returnValue = semaphore_wait(mach_semaphore) == KERN_SUCCESS;
+ do {
+ r = semaphore_wait(mach_semaphore);
+ } while (r == KERN_ABORTED);
+ if (r != KERN_SUCCESS)
+ qWarning("QMutex: infinite wait failed, error %d", r);
} else {
mach_timespec_t ts;
ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
ts.tv_sec = (timeout / 1000);
- kern_return_t r = semaphore_timedwait(mach_semaphore, ts);
- returnValue = r == KERN_SUCCESS;
+ r = semaphore_timedwait(mach_semaphore, ts);
}
contenders.deref();
- return returnValue;
+ return r == KERN_SUCCESS;
}
void QMutexPrivate::wakeUp()
diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp
index 5d8b5cbf0d..665aadd3a4 100644
--- a/src/corelib/thread/qthread_symbian.cpp
+++ b/src/corelib/thread/qthread_symbian.cpp
@@ -329,6 +329,8 @@ void *QThreadPrivate::start(void *arg)
data->quitNow = thr->d_func()->exited;
}
+ CTrapCleanup *cleanup = CTrapCleanup::New();
+
// ### TODO: allow the user to create a custom event dispatcher
createEventDispatcher(data);
@@ -337,6 +339,8 @@ void *QThreadPrivate::start(void *arg)
QThreadPrivate::finish(arg);
+ delete cleanup;
+
return 0;
}
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index bab6cf85de..bdade1d24e 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -300,7 +300,7 @@ void QThreadPrivate::createEventDispatcher(QThreadData *data)
#ifndef QT_NO_THREAD
-unsigned int __stdcall QThreadPrivate::start(void *arg)
+unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg)
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadData *data = QThreadData::get2(thr);
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index a3a8884374..d9a054ae77 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -2460,7 +2460,11 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
If the \a format is Qt::ISODate, the string format corresponds
to the ISO 8601 extended specification for representations of
- dates and times, taking the form YYYY-MM-DDTHH:MM:SS.
+ dates and times, taking the form YYYY-MM-DDTHH:MM:SS[Z|[+|-]HH:MM],
+ depending on the timeSpec() of the QDateTime. If the timeSpec()
+ is Qt::UTC, Z will be appended to the string; if the timeSpec() is
+ Qt::OffsetFromUTC the offset in hours and minutes from UTC will
+ be appended to the string.
If the \a format is Qt::SystemLocaleShortDate or
Qt::SystemLocaleLongDate, the string format depends on the locale
@@ -2497,6 +2501,21 @@ QString QDateTime::toString(Qt::DateFormat f) const
return QString(); // failed to convert
buf += QLatin1Char('T');
buf += d->time.toString(Qt::ISODate);
+ switch (d->spec) {
+ case QDateTimePrivate::UTC:
+ buf += QLatin1Char('Z');
+ break;
+ case QDateTimePrivate::OffsetFromUTC: {
+ int sign = d->utcOffset >= 0 ? 1: -1;
+ buf += QString::fromLatin1("%1%2:%3").
+ arg(sign == 1 ? QLatin1Char('+') : QLatin1Char('-')).
+ arg(d->utcOffset * sign / SECS_PER_HOUR, 2, 10, QLatin1Char('0')).
+ arg((d->utcOffset / 60) % 60, 2, 10, QLatin1Char('0'));
+ break;
+ }
+ default:
+ break;
+ }
}
#ifndef QT_NO_TEXTDATE
else if (f == Qt::TextDate) {
diff --git a/src/corelib/tools/qelapsedtimer_symbian.cpp b/src/corelib/tools/qelapsedtimer_symbian.cpp
index b831e03208..3667b05315 100644
--- a/src/corelib/tools/qelapsedtimer_symbian.cpp
+++ b/src/corelib/tools/qelapsedtimer_symbian.cpp
@@ -95,7 +95,7 @@ qint64 QElapsedTimer::restart()
qint64 oldt1 = t1;
t1 = getMicrosecondFromTick();
t2 = 0;
- return t1 - oldt1;
+ return (t1 - oldt1) / 1000;
}
qint64 QElapsedTimer::nsecsElapsed() const
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 5c4085af41..c8ed94b35f 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -2782,8 +2782,6 @@ bool QLocalePrivate::numberToCLocale(const QString &num,
if (idx == l)
return false;
- const QChar _group = group();
-
while (idx < l) {
const QChar &in = uc[idx];
diff --git a/src/corelib/tools/qlocale_symbian.cpp b/src/corelib/tools/qlocale_symbian.cpp
index 09d74d0136..5dca7b7537 100644
--- a/src/corelib/tools/qlocale_symbian.cpp
+++ b/src/corelib/tools/qlocale_symbian.cpp
@@ -44,6 +44,7 @@
#include <QTime>
#include <QVariant>
#include <QThread>
+#include <QStringList>
#include <e32std.h>
#include <e32const.h>
@@ -86,6 +87,7 @@ static TPtrC defaultFormatSpec(TExtendedLocale&)
struct symbianToISO {
int symbian_language;
char iso_name[8];
+ char uilanguage[8];
};
@@ -94,77 +96,80 @@ struct symbianToISO {
NOTE: This array should be sorted by the first column!
*/
static const symbianToISO symbian_to_iso_list[] = {
- { ELangEnglish, "en_GB" }, // 1
- { ELangFrench, "fr_FR" }, // 2
- { ELangGerman, "de_DE" }, // 3
- { ELangSpanish, "es_ES" }, // 4
- { ELangItalian, "it_IT" }, // 5
- { ELangSwedish, "sv_SE" }, // 6
- { ELangDanish, "da_DK" }, // 7
- { ELangNorwegian, "no_NO" }, // 8
- { ELangFinnish, "fi_FI" }, // 9
- { ELangAmerican, "en_US" }, // 10
- { ELangPortuguese, "pt_PT" }, // 13
- { ELangTurkish, "tr_TR" }, // 14
- { ELangIcelandic, "is_IS" }, // 15
- { ELangRussian, "ru_RU" }, // 16
- { ELangHungarian, "hu_HU" }, // 17
- { ELangDutch, "nl_NL" }, // 18
- { ELangBelgianFlemish, "nl_BE" }, // 19
- { ELangCzech, "cs_CZ" }, // 25
- { ELangSlovak, "sk_SK" }, // 26
- { ELangPolish, "pl_PL" }, // 27
- { ELangSlovenian, "sl_SI" }, // 28
- { ELangTaiwanChinese, "zh_TW" }, // 29
- { ELangHongKongChinese, "zh_HK" }, // 30
- { ELangPrcChinese, "zh_CN" }, // 31
- { ELangJapanese, "ja_JP" }, // 32
- { ELangThai, "th_TH" }, // 33
- { ELangArabic, "ar_AE" }, // 37
- { ELangTagalog, "tl_PH" }, // 39
- { ELangBulgarian, "bg_BG" }, // 42
- { ELangCatalan, "ca_ES" }, // 44
- { ELangCroatian, "hr_HR" }, // 45
- { ELangEstonian, "et_EE" }, // 49
- { ELangFarsi, "fa_IR" }, // 50
- { ELangCanadianFrench, "fr_CA" }, // 51
- { ELangGreek, "el_GR" }, // 54
- { ELangHebrew, "he_IL" }, // 57
- { ELangHindi, "hi_IN" }, // 58
- { ELangIndonesian, "id_ID" }, // 59
- { ELangKorean, "ko_KO" }, // 65
- { ELangLatvian, "lv_LV" }, // 67
- { ELangLithuanian, "lt_LT" }, // 68
- { ELangMalay, "ms_MY" }, // 70
- { ELangNorwegianNynorsk, "nn_NO" }, // 75
- { ELangBrazilianPortuguese, "pt_BR" }, // 76
- { ELangRomanian, "ro_RO" }, // 78
- { ELangSerbian, "sr_RS" }, // 79
- { ELangLatinAmericanSpanish,"es_419" }, // 83
- { ELangUkrainian, "uk_UA" }, // 93
- { ELangUrdu, "ur_PK" }, // 94 - India/Pakistan
- { ELangVietnamese, "vi_VN" }, // 96
+ { ELangEnglish, "en_GB", "en" }, // 1
+ { ELangFrench, "fr_FR", "fr" }, // 2
+ { ELangGerman, "de_DE", "de" }, // 3
+ { ELangSpanish, "es_ES", "es" }, // 4
+ { ELangItalian, "it_IT", "it" }, // 5
+ { ELangSwedish, "sv_SE", "sv" }, // 6
+ { ELangDanish, "da_DK", "da" }, // 7
+ { ELangNorwegian, "nb_NO", "nb" }, // 8
+ { ELangFinnish, "fi_FI", "fi" }, // 9
+ { ELangAmerican, "en_US", "en-US" }, // 10
+ { ELangPortuguese, "pt_PT", "pt" }, // 13
+ { ELangTurkish, "tr_TR", "tr" }, // 14
+ { ELangIcelandic, "is_IS", "is" }, // 15
+ { ELangRussian, "ru_RU", "ru" }, // 16
+ { ELangHungarian, "hu_HU", "hu" }, // 17
+ { ELangDutch, "nl_NL", "nl" }, // 18
+ { ELangCzech, "cs_CZ", "cs" }, // 25
+ { ELangSlovak, "sk_SK", "sk" }, // 26
+ { ELangPolish, "pl_PL", "pl" }, // 27
+ { ELangSlovenian, "sl_SI", "sl" }, // 28
+ { ELangTaiwanChinese, "zh_TW", "zh-TW" }, // 29
+ { ELangHongKongChinese, "zh_HK", "zh-HK" }, // 30
+ { ELangPrcChinese, "zh_CN", "zh" }, // 31
+ { ELangJapanese, "ja_JP", "ja" }, // 32
+ { ELangThai, "th_TH", "th" }, // 33
+ { ELangArabic, "ar_AE", "ar" }, // 37
+ { ELangTagalog, "tl_PH", "tl" }, // 39
+ { ELangBulgarian, "bg_BG", "bg" }, // 42
+ { ELangCatalan, "ca_ES", "ca" }, // 44
+ { ELangCroatian, "hr_HR", "hr" }, // 45
+ { ELangEstonian, "et_EE", "et" }, // 49
+ { ELangFarsi, "fa_IR", "fa" }, // 50
+ { ELangCanadianFrench, "fr_CA", "fr-CA" }, // 51
+ { ELangGreek, "el_GR", "el" }, // 54
+ { ELangHebrew, "he_IL", "he" }, // 57
+ { ELangHindi, "hi_IN", "hi" }, // 58
+ { ELangIndonesian, "id_ID", "id" }, // 59
+ { 63/*ELangKazakh*/, "kk_KZ", "kk" }, // 63
+ { ELangKorean, "ko_KO", "ko" }, // 65
+ { ELangLatvian, "lv_LV", "lv" }, // 67
+ { ELangLithuanian, "lt_LT", "lt" }, // 68
+ { ELangMalay, "ms_MY", "ms" }, // 70
+ { ELangNorwegianNynorsk, "nn_NO", "nn" }, // 75
+ { ELangBrazilianPortuguese, "pt_BR", "pt-BR" }, // 76
+ { ELangRomanian, "ro_RO", "ro" }, // 78
+ { ELangSerbian, "sr_RS", "sr" }, // 79
+ { ELangLatinAmericanSpanish,"es_419", "es-419" },// 83
+ { ELangUkrainian, "uk_UA", "uk" }, // 93
+ { ELangUrdu, "ur_PK", "ur" }, // 94 - India/Pakistan
+ { ELangVietnamese, "vi_VN", "vi" }, // 96
#ifdef __E32LANG_H__
// 5.0
- { ELangBasque, "eu_ES" }, // 102
- { ELangGalician, "gl_ES" }, // 103
+ { ELangBasque, "eu_ES", "eu" }, // 102
+ { ELangGalician, "gl_ES", "gl" }, // 103
#endif
#if !defined(__SERIES60_31__)
- { ELangEnglish_Apac, "en" }, // 129
- { ELangEnglish_Taiwan, "en_TW" }, // 157 ### Not supported by CLDR
- { ELangEnglish_HongKong, "en_HK" }, // 158
- { ELangEnglish_Prc, "en_CN" }, // 159 ### Not supported by CLDR
- { ELangEnglish_Japan, "en_JP"}, // 160 ### Not supported by CLDR
- { ELangEnglish_Thailand, "en_TH" }, // 161 ### Not supported by CLDR
- { ELangMalay_Apac, "ms" }, // 326
+ { ELangEnglish_Apac, "en_GB", "en" }, // 129
+ { ELangEnglish_Taiwan, "en_TW", "en-TW" }, // 157 ### Not supported by CLDR
+ { ELangEnglish_HongKong, "en_HK", "en-HK" }, // 158
+ { ELangEnglish_Prc, "en_CN", "en-CN" }, // 159 ### Not supported by CLDR
+ { ELangEnglish_Japan, "en_JP", "en" }, // 160 ### Not supported by CLDR
+ { ELangEnglish_Thailand, "en_TH", "en" }, // 161 ### Not supported by CLDR
+ { 230/*ELangEnglish_India*/,"en_IN", "en" }, // 230
+ { ELangMalay_Apac, "ms_MY", "ms" }, // 326
#endif
- { 327/*ELangIndonesian_Apac*/,"id_ID" } // 327 - appeared in Symbian^3
+ { 327/*ELangIndonesian_Apac*/, "id_ID", "id" } // 327 - appeared in Symbian^3
};
-/*!
- Returns ISO name corresponding to the Symbian locale code \a sys_fmt.
-*/
-QByteArray qt_symbianLocaleName(int code)
+enum LocaleNameType {
+ ISO,
+ UILanguage
+};
+
+QByteArray qt_resolveSymbianLocaleName(int code, LocaleNameType type)
{
//Number of Symbian to ISO locale mappings
static const int symbian_to_iso_count
@@ -174,8 +179,11 @@ QByteArray qt_symbianLocaleName(int code)
if (cmp < 0)
return 0;
- if (cmp == 0)
- return symbian_to_iso_list[0].iso_name;
+ if (cmp == 0) {
+ if (type == ISO)
+ return symbian_to_iso_list[0].iso_name;
+ return symbian_to_iso_list[0].uilanguage;
+ }
int begin = 0;
int end = symbian_to_iso_count;
@@ -185,17 +193,27 @@ QByteArray qt_symbianLocaleName(int code)
const symbianToISO *elt = symbian_to_iso_list + mid;
int cmp = code - elt->symbian_language;
- if (cmp < 0)
+ if (cmp < 0) {
end = mid;
- else if (cmp > 0)
+ } else if (cmp > 0) {
begin = mid;
- else
- return elt->iso_name;
+ } else {
+ if (type == ISO)
+ return elt->iso_name;
+ return elt->uilanguage;
+ }
}
return 0;
}
+/*!
+ Returns ISO name corresponding to the Symbian locale code \a sys_fmt.
+*/
+QByteArray qt_symbianLocaleName(int code)
+{
+ return qt_resolveSymbianLocaleName(code, ISO);
+}
// order is: normal, abbr, nmode, nmode+abbr
static const char *us_locale_dep[] = {
@@ -822,6 +840,13 @@ QLocale QSystemLocale::fallbackLocale() const
return QLocale(locale);
}
+static QStringList symbianUILanguages()
+{
+ TLanguage lang = User::Language();
+ QString s = QLatin1String(qt_resolveSymbianLocaleName(lang, UILanguage));
+ return QStringList(s);
+}
+
QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
{
switch(type) {
@@ -889,6 +914,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
return qt_TDes2QString(TAmPmName(TAmPm(EAm)));
case PMText:
return qt_TDes2QString(TAmPmName(TAmPm(EPm)));
+ case UILanguages:
+ return QVariant(symbianUILanguages());
default:
break;
}
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 66cfa744df..6418a8cbd4 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -695,9 +695,9 @@ inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLat
inline int QString::length() const
{ return d->size; }
inline const QChar QString::at(int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; }
inline const QChar QString::operator[](int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; }
inline const QChar QString::operator[](uint i) const
{ Q_ASSERT(i < uint(size())); return d->data[i]; }
inline bool QString::isEmpty() const
diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp
index 34bc406309..47319d4ff4 100644
--- a/src/corelib/tools/qtextboundaryfinder.cpp
+++ b/src/corelib/tools/qtextboundaryfinder.cpp
@@ -199,11 +199,11 @@ QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &o
chars = other.chars;
length = other.length;
pos = other.pos;
- freePrivate = true;
QTextBoundaryFinderPrivate *newD = (QTextBoundaryFinderPrivate *)
- realloc(d, length*sizeof(HB_CharAttributes));
+ realloc(freePrivate ? d : 0, length*sizeof(HB_CharAttributes));
Q_CHECK_PTR(newD);
+ freePrivate = true;
d = newD;
memcpy(d, other.d, length*sizeof(HB_CharAttributes));
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 9418642752..6f068dc4b0 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -574,8 +574,9 @@ void QVector<T>::append(const T &t)
{
if (d->ref != 1 || d->size + 1 > d->alloc) {
const T copy(t);
- realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T),
- QTypeInfo<T>::isStatic));
+ realloc(d->size, (d->size + 1 > d->alloc) ?
+ QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T), QTypeInfo<T>::isStatic)
+ : d->alloc);
if (QTypeInfo<T>::isComplex)
new (p->array + d->size) T(copy);
else
diff --git a/src/gui/guikernel/qclipboard.h b/src/gui/guikernel/qclipboard.h
index 0a9e28ac8c..989ba19c2c 100644
--- a/src/gui/guikernel/qclipboard.h
+++ b/src/gui/guikernel/qclipboard.h
@@ -113,6 +113,7 @@ protected:
friend class QBaseApplication;
friend class QDragManager;
friend class QMimeSource;
+ friend class QPlatformClipboard;
private:
Q_DISABLE_COPY(QClipboard)
diff --git a/src/gui/guikernel/qplatformclipboard_qpa.cpp b/src/gui/guikernel/qplatformclipboard_qpa.cpp
index 957a4dfd2e..302df683bd 100644
--- a/src/gui/guikernel/qplatformclipboard_qpa.cpp
+++ b/src/gui/guikernel/qplatformclipboard_qpa.cpp
@@ -42,6 +42,8 @@
#ifndef QT_NO_CLIPBOARD
+#include <QtGui/private/qapplication_p.h>
+
QT_BEGIN_NAMESPACE
class QClipboardData
@@ -81,7 +83,7 @@ QPlatformClipboard::~QPlatformClipboard()
}
-const QMimeData *QPlatformClipboard::mimeData(QClipboard::Mode mode) const
+QMimeData *QPlatformClipboard::mimeData(QClipboard::Mode mode)
{
//we know its clipboard
Q_UNUSED(mode);
@@ -100,6 +102,11 @@ bool QPlatformClipboard::supportsMode(QClipboard::Mode mode) const
return mode == QClipboard::Clipboard;
}
+void QPlatformClipboard::emitChanged(QClipboard::Mode mode)
+{
+ QApplication::clipboard()->emitChanged(mode);
+}
+
QT_END_NAMESPACE
#endif //QT_NO_CLIPBOARD
diff --git a/src/gui/guikernel/qplatformclipboard_qpa.h b/src/gui/guikernel/qplatformclipboard_qpa.h
index 3381c062b8..e1be8aa22f 100644
--- a/src/gui/guikernel/qplatformclipboard_qpa.h
+++ b/src/gui/guikernel/qplatformclipboard_qpa.h
@@ -59,9 +59,10 @@ class Q_GUI_EXPORT QPlatformClipboard
public:
virtual ~QPlatformClipboard();
- virtual const QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard ) const;
+ virtual QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard);
virtual void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);
virtual bool supportsMode(QClipboard::Mode mode) const;
+ void emitChanged(QClipboard::Mode mode);
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index da0a10409a..21640ca4bb 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1156,12 +1156,8 @@ Qt::HANDLE QPixmap::handle() const
{
#if defined(Q_WS_X11)
const QPixmapData *pd = pixmapData();
- if (pd) {
- if (pd->classId() == QPixmapData::X11Class)
- return static_cast<const QX11PixmapData*>(pd)->handle();
- else
- qWarning("QPixmap::handle(): Pixmap is not an X11 class pixmap");
- }
+ if (pd && pd->classId() == QPixmapData::X11Class)
+ return static_cast<const QX11PixmapData*>(pd)->handle();
#endif
return 0;
}
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index aec03bc544..b5320dd6cb 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -810,6 +810,22 @@ const QGradient *QBrush::gradient() const
return 0;
}
+Q_GUI_EXPORT bool qt_isExtendedRadialGradient(const QBrush &brush)
+{
+ if (brush.style() == Qt::RadialGradientPattern) {
+ const QGradient *g = brush.gradient();
+ const QRadialGradient *rg = static_cast<const QRadialGradient *>(g);
+
+ if (!qFuzzyIsNull(rg->focalRadius()))
+ return true;
+
+ QPointF delta = rg->focalPoint() - rg->center();
+ if (delta.x() * delta.x() + delta.y() * delta.y() > rg->radius() * rg->radius())
+ return true;
+ }
+
+ return false;
+}
/*!
Returns true if the brush is fully opaque otherwise false. A brush
@@ -819,6 +835,7 @@ const QGradient *QBrush::gradient() const
\i The alpha component of the color() is 255.
\i Its texture() does not have an alpha channel and is not a QBitmap.
\i The colors in the gradient() all have an alpha component that is 255.
+ \i It is an extended radial gradient.
\endlist
*/
@@ -830,6 +847,9 @@ bool QBrush::isOpaque() const
if (d->style == Qt::SolidPattern)
return opaqueColor;
+ if (qt_isExtendedRadialGradient(*this))
+ return false;
+
if (d->style == Qt::LinearGradientPattern
|| d->style == Qt::RadialGradientPattern
|| d->style == Qt::ConicalGradientPattern) {
@@ -1179,8 +1199,10 @@ QDataStream &operator>>(QDataStream &s, QBrush &b)
\list
\o \e Linear gradients interpolate colors between start and end points.
- \o \e Radial gradients interpolate colors between a focal point and end
- points on a circle surrounding it.
+ \o \e Simple radial gradients interpolate colors between a focal point
+ and end points on a circle surrounding it.
+ \o \e Extended radial gradients interpolate colors between a center and
+ a focal circle.
\o \e Conical gradients interpolate colors around a center point.
\endlist
@@ -1476,8 +1498,6 @@ void QGradient::setInterpolationMode(InterpolationMode mode)
dummy = p;
}
-#undef Q_DUMMY_ACCESSOR
-
/*!
\fn bool QGradient::operator!=(const QGradient &gradient) const
\since 4.2
@@ -1511,7 +1531,7 @@ bool QGradient::operator==(const QGradient &gradient) const
|| m_data.radial.cy != gradient.m_data.radial.cy
|| m_data.radial.fx != gradient.m_data.radial.fx
|| m_data.radial.fy != gradient.m_data.radial.fy
- || m_data.radial.radius != gradient.m_data.radial.radius)
+ || m_data.radial.cradius != gradient.m_data.radial.cradius)
return false;
} else { // m_type == ConicalGradient
if (m_data.conical.cx != gradient.m_data.conical.cx
@@ -1717,10 +1737,17 @@ void QLinearGradient::setFinalStop(const QPointF &stop)
\brief The QRadialGradient class is used in combination with QBrush to
specify a radial gradient brush.
- Radial gradients interpolate colors between a focal point and end
- points on a circle surrounding it. Outside the end points the
- gradient is either padded, reflected or repeated depending on the
- currently set \l {QGradient::Spread}{spread} method:
+ Qt supports both simple and extended radial gradients.
+
+ Simple radial gradients interpolate colors between a focal point and end
+ points on a circle surrounding it. Extended radial gradients interpolate
+ colors between a focal circle and a center circle. Points outside the cone
+ defined by the two circles will be transparent. For simple radial gradients
+ the focal point is adjusted to lie inside the center circle, whereas the
+ focal point can have any position in an extended radial gradient.
+
+ Outside the end points the gradient is either padded, reflected or repeated
+ depending on the currently set \l {QGradient::Spread}{spread} method:
\table
\row
@@ -1765,9 +1792,14 @@ static QPointF qt_radial_gradient_adapt_focal_point(const QPointF &center,
}
/*!
- Constructs a radial gradient with the given \a center, \a
+ Constructs a simple radial gradient with the given \a center, \a
radius and \a focalPoint.
+ \note If the given focal point is outside the circle defined by the
+ center (\a cx, \a cy) and the \a radius it will be re-adjusted to
+ the intersection between the line from the center to the focal point
+ and the circle.
+
\sa QGradient::setColorAt(), QGradient::setStops()
*/
@@ -1777,7 +1809,7 @@ QRadialGradient::QRadialGradient(const QPointF &center, qreal radius, const QPoi
m_spread = PadSpread;
m_data.radial.cx = center.x();
m_data.radial.cy = center.y();
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(center, radius, focalPoint);
m_data.radial.fx = adapted_focal.x();
@@ -1785,7 +1817,7 @@ QRadialGradient::QRadialGradient(const QPointF &center, qreal radius, const QPoi
}
/*!
- Constructs a radial gradient with the given \a center, \a
+ Constructs a simple radial gradient with the given \a center, \a
radius and the focal point in the circle center.
\sa QGradient::setColorAt(), QGradient::setStops()
@@ -1796,16 +1828,21 @@ QRadialGradient::QRadialGradient(const QPointF &center, qreal radius)
m_spread = PadSpread;
m_data.radial.cx = center.x();
m_data.radial.cy = center.y();
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
m_data.radial.fx = center.x();
m_data.radial.fy = center.y();
}
/*!
- Constructs a radial gradient with the given center (\a cx, \a cy),
+ Constructs a simple radial gradient with the given center (\a cx, \a cy),
\a radius and focal point (\a fx, \a fy).
+ \note If the given focal point is outside the circle defined by the
+ center (\a cx, \a cy) and the \a radius it will be re-adjusted to
+ the intersection between the line from the center to the focal point
+ and the circle.
+
\sa QGradient::setColorAt(), QGradient::setStops()
*/
@@ -1815,7 +1852,7 @@ QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius, qreal fx, qre
m_spread = PadSpread;
m_data.radial.cx = cx;
m_data.radial.cy = cy;
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(QPointF(cx, cy),
radius,
@@ -1826,7 +1863,7 @@ QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius, qreal fx, qre
}
/*!
- Constructs a radial gradient with the center at (\a cx, \a cy) and the
+ Constructs a simple radial gradient with the center at (\a cx, \a cy) and the
specified \a radius. The focal point lies at the center of the circle.
\sa QGradient::setColorAt(), QGradient::setStops()
@@ -1837,14 +1874,14 @@ QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius)
m_spread = PadSpread;
m_data.radial.cx = cx;
m_data.radial.cy = cy;
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
m_data.radial.fx = cx;
m_data.radial.fy = cy;
}
/*!
- Constructs a radial gradient with the center and focal point at
+ Constructs a simple radial gradient with the center and focal point at
(0, 0) with a radius of 1.
*/
QRadialGradient::QRadialGradient()
@@ -1853,11 +1890,51 @@ QRadialGradient::QRadialGradient()
m_spread = PadSpread;
m_data.radial.cx = 0;
m_data.radial.cy = 0;
- m_data.radial.radius = 1;
+ m_data.radial.cradius = 1;
m_data.radial.fx = 0;
m_data.radial.fy = 0;
}
+/*!
+ \since 4.8
+
+ Constructs an extended radial gradient with the given \a center, \a
+ centerRadius, \a focalPoint, and \a focalRadius.
+*/
+QRadialGradient::QRadialGradient(const QPointF &center, qreal centerRadius, const QPointF &focalPoint, qreal focalRadius)
+{
+ m_type = RadialGradient;
+ m_spread = PadSpread;
+ m_data.radial.cx = center.x();
+ m_data.radial.cy = center.y();
+ m_data.radial.cradius = centerRadius;
+
+ m_data.radial.fx = focalPoint.x();
+ m_data.radial.fy = focalPoint.y();
+ setFocalRadius(focalRadius);
+}
+
+/*!
+ \since 4.8
+
+ Constructs an extended radial gradient with the given \a center, \a
+ centerRadius, \a focalPoint, and \a focalRadius.
+ Constructs a radial gradient with the given center (\a cx, \a cy),
+ center radius \a centerRadius, focal point (\a fx, \a fy), and
+ focal radius \a focalRadius.
+*/
+QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal centerRadius, qreal fx, qreal fy, qreal focalRadius)
+{
+ m_type = RadialGradient;
+ m_spread = PadSpread;
+ m_data.radial.cx = cx;
+ m_data.radial.cy = cy;
+ m_data.radial.cradius = centerRadius;
+
+ m_data.radial.fx = fx;
+ m_data.radial.fy = fy;
+ setFocalRadius(focalRadius);
+}
/*!
Returns the center of this radial gradient in logical coordinates.
@@ -1902,13 +1979,15 @@ void QRadialGradient::setCenter(const QPointF &center)
/*!
Returns the radius of this radial gradient in logical coordinates.
+ Equivalent to centerRadius()
+
\sa QGradient::stops()
*/
qreal QRadialGradient::radius() const
{
Q_ASSERT(m_type == RadialGradient);
- return m_data.radial.radius;
+ return m_data.radial.cradius;
}
@@ -1917,13 +1996,81 @@ qreal QRadialGradient::radius() const
Sets the radius of this radial gradient in logical coordinates
to \a radius
+
+ Equivalent to setCenterRadius()
*/
void QRadialGradient::setRadius(qreal radius)
{
Q_ASSERT(m_type == RadialGradient);
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
+}
+
+/*!
+ \since 4.8
+
+ Returns the center radius of this radial gradient in logical
+ coordinates.
+
+ \sa QGradient::stops()
+*/
+qreal QRadialGradient::centerRadius() const
+{
+ Q_ASSERT(m_type == RadialGradient);
+ return m_data.radial.cradius;
+}
+
+/*
+ \since 4.8
+
+ Sets the center radius of this radial gradient in logical coordinates
+ to \a radius
+*/
+void QRadialGradient::setCenterRadius(qreal radius)
+{
+ Q_ASSERT(m_type == RadialGradient);
+ m_data.radial.cradius = radius;
+}
+
+/*!
+ \since 4.8
+
+ Returns the focal radius of this radial gradient in logical
+ coordinates.
+
+ \sa QGradient::stops()
+*/
+qreal QRadialGradient::focalRadius() const
+{
+ Q_ASSERT(m_type == RadialGradient);
+ Q_DUMMY_ACCESSOR
+
+ // mask away low three bits
+ union { float f; quint32 i; } u;
+ u.i = i & ~0x07;
+ return u.f;
}
+/*
+ \since 4.8
+
+ Sets the focal radius of this radial gradient in logical coordinates
+ to \a radius
+*/
+void QRadialGradient::setFocalRadius(qreal radius)
+{
+ Q_ASSERT(m_type == RadialGradient);
+ Q_DUMMY_ACCESSOR
+
+ // Since there's no QGradientData, we only have the dummy void * to
+ // store additional data in. The three lowest bits are already
+ // taken, thus we cut the three lowest bits from the significand
+ // and store the radius as a float.
+ union { float f; quint32 i; } u;
+ u.f = float(radius);
+ // add 0x04 to round up when we drop the three lowest bits
+ i |= (u.i + 0x04) & ~0x07;
+ dummy = p;
+}
/*!
Returns the focal point of this radial gradient in logical
@@ -2163,4 +2310,6 @@ void QConicalGradient::setAngle(qreal angle)
\sa setTransform()
*/
+#undef Q_DUMMY_ACCESSOR
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index 89be376ad9..e399a4e3ae 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -245,6 +245,7 @@ private:
friend class QLinearGradient;
friend class QRadialGradient;
friend class QConicalGradient;
+ friend class QBrush;
Type m_type;
Spread m_spread;
@@ -254,7 +255,7 @@ private:
qreal x1, y1, x2, y2;
} linear;
struct {
- qreal cx, cy, fx, fy, radius;
+ qreal cx, cy, fx, fy, cradius;
} radial;
struct {
qreal cx, cy, angle;
@@ -293,6 +294,9 @@ public:
QRadialGradient(const QPointF &center, qreal radius);
QRadialGradient(qreal cx, qreal cy, qreal radius);
+ QRadialGradient(const QPointF &center, qreal centerRadius, const QPointF &focalPoint, qreal focalRadius);
+ QRadialGradient(qreal cx, qreal cy, qreal centerRadius, qreal fx, qreal fy, qreal focalRadius);
+
QPointF center() const;
void setCenter(const QPointF &center);
inline void setCenter(qreal x, qreal y) { setCenter(QPointF(x, y)); }
@@ -303,6 +307,12 @@ public:
qreal radius() const;
void setRadius(qreal radius);
+
+ qreal centerRadius() const;
+ void setCenterRadius(qreal radius);
+
+ qreal focalRadius() const;
+ void setFocalRadius(qreal radius);
};
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 333b433bb5..5e23f5f6fd 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -75,43 +75,9 @@ enum {
fixed_scale = 1 << 16,
half_point = 1 << 15
};
-static const int buffer_size = 2048;
-
-struct LinearGradientValues
-{
- qreal dx;
- qreal dy;
- qreal l;
- qreal off;
-};
-
-struct RadialGradientValues
-{
- qreal dx;
- qreal dy;
- qreal a;
-};
-
-struct Operator;
-typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
-typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length);
-typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
-
-struct Operator
-{
- QPainter::CompositionMode mode;
- DestFetchProc dest_fetch;
- DestStoreProc dest_store;
- SourceFetchProc src_fetch;
- CompositionFunctionSolid funcSolid;
- CompositionFunction func;
- union {
- LinearGradientValues linear;
- RadialGradientValues radial;
-// TextureValues texture;
- };
-};
+// must be multiple of 4 for easier SIMD implementations
+static const int buffer_size = 2048;
/*
Destination fetch. This is simple as we don't have to do bounds checks or
@@ -1346,64 +1312,13 @@ static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
},
};
-
-static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos)
-{
- int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5));
-
- // calculate the actual offset.
- if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) {
- if (data->spread == QGradient::RepeatSpread) {
- ipos = ipos % GRADIENT_STOPTABLE_SIZE;
- ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos;
-
- } else if (data->spread == QGradient::ReflectSpread) {
- const int limit = GRADIENT_STOPTABLE_SIZE * 2 - 1;
- ipos = ipos % limit;
- ipos = ipos < 0 ? limit + ipos : ipos;
- ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos;
-
- } else {
- if (ipos < 0) ipos = 0;
- else if (ipos >= GRADIENT_STOPTABLE_SIZE) ipos = GRADIENT_STOPTABLE_SIZE-1;
- }
- }
-
- Q_ASSERT(ipos >= 0);
- Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE);
-
- return data->colorTable[ipos];
-}
-
#define FIXPT_BITS 8
#define FIXPT_SIZE (1<<FIXPT_BITS)
static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos)
{
int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS;
-
- // calculate the actual offset.
- if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) {
- if (data->spread == QGradient::RepeatSpread) {
- ipos = ipos % GRADIENT_STOPTABLE_SIZE;
- ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos;
-
- } else if (data->spread == QGradient::ReflectSpread) {
- const int limit = GRADIENT_STOPTABLE_SIZE * 2 - 1;
- ipos = ipos % limit;
- ipos = ipos < 0 ? limit + ipos : ipos;
- ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos;
-
- } else {
- if (ipos < 0) ipos = 0;
- else if (ipos >= GRADIENT_STOPTABLE_SIZE) ipos = GRADIENT_STOPTABLE_SIZE-1;
- }
- }
-
- Q_ASSERT(ipos >= 0);
- Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE);
-
- return data->colorTable[ipos];
+ return data->colorTable[qt_gradient_clamp(data, ipos)];
}
static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const QSpanData *data)
@@ -1419,8 +1334,8 @@ static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const Q
}
}
-static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length)
+static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
{
const uint *b = buffer;
qreal t, inc;
@@ -1487,110 +1402,65 @@ static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator
return b;
}
-static inline qreal determinant(qreal a, qreal b, qreal c)
-{
- return (b * b) - (4 * a * c);
-}
-
-// function to evaluate real roots
-static inline qreal realRoots(qreal a, qreal b, qreal detSqrt)
-{
- return (-b + detSqrt)/(2 * a);
-}
-
-static inline qreal qSafeSqrt(qreal x)
-{
- return x > 0 ? qSqrt(x) : 0;
-}
-
static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data)
{
v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x;
v->dy = data->gradient.radial.center.y - data->gradient.radial.focal.y;
- v->a = data->gradient.radial.radius*data->gradient.radial.radius - v->dx*v->dx - v->dy*v->dy;
-}
-
-static const uint * QT_FASTCALL fetchRadialGradient(uint *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length)
-{
- const uint *b = buffer;
- qreal rx = data->m21 * (y + qreal(0.5))
- + data->dx + data->m11 * (x + qreal(0.5));
- qreal ry = data->m22 * (y + qreal(0.5))
- + data->dy + data->m12 * (x + qreal(0.5));
- bool affine = !data->m13 && !data->m23;
- //qreal r = data->gradient.radial.radius;
-
- const uint *end = buffer + length;
- if (affine) {
- rx -= data->gradient.radial.focal.x;
- ry -= data->gradient.radial.focal.y;
-
- qreal inv_a = 1 / qreal(2 * op->radial.a);
-
- const qreal delta_rx = data->m11;
- const qreal delta_ry = data->m12;
- qreal b = 2*(rx * op->radial.dx + ry * op->radial.dy);
- qreal delta_b = 2*(delta_rx * op->radial.dx + delta_ry * op->radial.dy);
- const qreal b_delta_b = 2 * b * delta_b;
- const qreal delta_b_delta_b = 2 * delta_b * delta_b;
+ v->dr = data->gradient.radial.center.radius - data->gradient.radial.focal.radius;
+ v->sqrfr = data->gradient.radial.focal.radius * data->gradient.radial.focal.radius;
- const qreal bb = b * b;
- const qreal delta_bb = delta_b * delta_b;
+ v->a = v->dr * v->dr - v->dx*v->dx - v->dy*v->dy;
+ v->inv2a = 1 / (2 * v->a);
- b *= inv_a;
- delta_b *= inv_a;
-
- const qreal rxrxryry = rx * rx + ry * ry;
- const qreal delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry;
- const qreal rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry);
- const qreal delta_rx_plus_ry = 2 * delta_rxrxryry;
-
- inv_a *= inv_a;
+ v->extended = !qFuzzyIsNull(data->gradient.radial.focal.radius) || v->a <= 0;
+}
- qreal det = (bb + 4 * op->radial.a * rxrxryry) * inv_a;
- qreal delta_det = (b_delta_b + delta_bb + 4 * op->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a;
- const qreal delta_delta_det = (delta_b_delta_b + 4 * op->radial.a * delta_rx_plus_ry) * inv_a;
+class RadialFetchPlain
+{
+public:
+ static inline void fetch(uint *buffer, uint *end, const Operator *op, const QSpanData *data, qreal det,
+ qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b)
+ {
+ if (op->radial.extended) {
+ while (buffer < end) {
+ quint32 result = 0;
+ if (det >= 0) {
+ qreal w = qSqrt(det) - b;
+ if (data->gradient.radial.focal.radius + op->radial.dr * w >= 0)
+ result = qt_gradient_pixel(&data->gradient, w);
+ }
- while (buffer < end) {
- *buffer = qt_gradient_pixel(&data->gradient, qSafeSqrt(det) - b);
+ *buffer = result;
- det += delta_det;
- delta_det += delta_delta_det;
- b += delta_b;
+ det += delta_det;
+ delta_det += delta_delta_det;
+ b += delta_b;
- ++buffer;
- }
- } else {
- qreal rw = data->m23 * (y + qreal(0.5))
- + data->m33 + data->m13 * (x + qreal(0.5));
- if (!rw)
- rw = 1;
- while (buffer < end) {
- qreal gx = rx/rw - data->gradient.radial.focal.x;
- qreal gy = ry/rw - data->gradient.radial.focal.y;
- qreal b = 2*(gx*op->radial.dx + gy*op->radial.dy);
- qreal det = determinant(op->radial.a, b , -(gx*gx + gy*gy));
- qreal s = realRoots(op->radial.a, b, qSafeSqrt(det));
-
- *buffer = qt_gradient_pixel(&data->gradient, s);
+ ++buffer;
+ }
+ } else {
+ while (buffer < end) {
+ *buffer++ = qt_gradient_pixel(&data->gradient, qSqrt(det) - b);
- rx += data->m11;
- ry += data->m12;
- rw += data->m13;
- if (!rw) {
- rw += data->m13;
+ det += delta_det;
+ delta_det += delta_delta_det;
+ b += delta_b;
}
- ++buffer;
}
}
+};
- return b;
+const uint * QT_FASTCALL qt_fetch_radial_gradient_plain(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_radial_gradient_template<RadialFetchPlain>(buffer, op, data, y, x, length);
}
-static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
+static SourceFetchProc qt_fetch_radial_gradient = qt_fetch_radial_gradient_plain;
+
+static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
{
const uint *b = buffer;
qreal rx = data->m21 * (y + qreal(0.5))
@@ -3347,16 +3217,16 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
case QSpanData::LinearGradient:
solidSource = !data->gradient.alphaColor;
getLinearGradientValues(&op.linear, data);
- op.src_fetch = fetchLinearGradient;
+ op.src_fetch = qt_fetch_linear_gradient;
break;
case QSpanData::RadialGradient:
solidSource = !data->gradient.alphaColor;
getRadialGradientValues(&op.radial, data);
- op.src_fetch = fetchRadialGradient;
+ op.src_fetch = qt_fetch_radial_gradient;
break;
case QSpanData::ConicalGradient:
solidSource = !data->gradient.alphaColor;
- op.src_fetch = fetchConicalGradient;
+ op.src_fetch = qt_fetch_conical_gradient;
break;
case QSpanData::Texture:
op.src_fetch = sourceFetch[getBlendType(data)][data->texture.format];
@@ -7278,6 +7148,11 @@ void qInitDrawhelperAsm()
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
+
+ extern const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length);
+
+ qt_fetch_radial_gradient = qt_fetch_radial_gradient_sse2;
}
#ifdef QT_HAVE_SSSE3
@@ -7373,6 +7248,11 @@ void qInitDrawhelperAsm()
qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon;
qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon;
qt_memfill32 = qt_memfill32_neon;
+
+ extern const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length);
+
+ qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
}
#endif
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index debca37486..e673dd9861 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -955,6 +955,46 @@ void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h,
}
}
+class QSimdNeon
+{
+public:
+ typedef int32x4_t Int32x4;
+ typedef float32x4_t Float32x4;
+
+ union Vect_buffer_i { Int32x4 v; int i[4]; };
+ union Vect_buffer_f { Float32x4 v; float f[4]; };
+
+ static inline Float32x4 v_dup(float x) { return vdupq_n_f32(x); }
+ static inline Int32x4 v_dup(int x) { return vdupq_n_s32(x); }
+ static inline Int32x4 v_dup(uint x) { return vdupq_n_s32(x); }
+
+ static inline Float32x4 v_add(Float32x4 a, Float32x4 b) { return vaddq_f32(a, b); }
+ static inline Int32x4 v_add(Int32x4 a, Int32x4 b) { return vaddq_s32(a, b); }
+
+ static inline Float32x4 v_max(Float32x4 a, Float32x4 b) { return vmaxq_f32(a, b); }
+ static inline Float32x4 v_min(Float32x4 a, Float32x4 b) { return vminq_f32(a, b); }
+ static inline Int32x4 v_min_16(Int32x4 a, Int32x4 b) { return vminq_s32(a, b); }
+
+ static inline Int32x4 v_and(Int32x4 a, Int32x4 b) { return vandq_s32(a, b); }
+
+ static inline Float32x4 v_sub(Float32x4 a, Float32x4 b) { return vsubq_f32(a, b); }
+ static inline Int32x4 v_sub(Int32x4 a, Int32x4 b) { return vsubq_s32(a, b); }
+
+ static inline Float32x4 v_mul(Float32x4 a, Float32x4 b) { return vmulq_f32(a, b); }
+
+ static inline Float32x4 v_sqrt(Float32x4 x) { Float32x4 y = vrsqrteq_f32(x); y = vmulq_f32(y, vrsqrtsq_f32(x, vmulq_f32(y, y))); return vmulq_f32(x, y); }
+
+ static inline Int32x4 v_toInt(Float32x4 x) { return vcvtq_s32_f32(x); }
+
+ static inline Int32x4 v_greaterOrEqual(Float32x4 a, Float32x4 b) { return vcge_f32(a, b); }
+};
+
+const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdNeon> >(buffer, op, data, y, x, length);
+}
+
QT_END_NAMESPACE
#endif // QT_HAVE_NEON
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index a16a9bec51..758b0c88cb 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -63,6 +63,7 @@
#endif
#include "private/qrasterdefs_p.h"
#include <private/qsimd_p.h>
+#include <private/qmath_p.h>
QT_BEGIN_NAMESPACE
@@ -170,6 +171,44 @@ void qBlendTexture(int count, const QSpan *spans, void *userData);
typedef void (QT_FASTCALL *CompositionFunction)(uint *dest, const uint *src, int length, uint const_alpha);
typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha);
+struct LinearGradientValues
+{
+ qreal dx;
+ qreal dy;
+ qreal l;
+ qreal off;
+};
+
+struct RadialGradientValues
+{
+ qreal dx;
+ qreal dy;
+ qreal dr;
+ qreal sqrfr;
+ qreal a;
+ qreal inv2a;
+ bool extended;
+};
+
+struct Operator;
+typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
+typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length);
+typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
+
+struct Operator
+{
+ QPainter::CompositionMode mode;
+ DestFetchProc dest_fetch;
+ DestStoreProc dest_store;
+ SourceFetchProc src_fetch;
+ CompositionFunctionSolid funcSolid;
+ CompositionFunction func;
+ union {
+ LinearGradientValues linear;
+ RadialGradientValues radial;
+ };
+};
+
void qInitDrawhelperAsm();
class QRasterPaintEngine;
@@ -196,12 +235,13 @@ struct QRadialGradientData
struct {
qreal x;
qreal y;
+ qreal radius;
} center;
struct {
qreal x;
qreal y;
+ qreal radius;
} focal;
- qreal radius;
};
struct QConicalGradientData
@@ -224,6 +264,7 @@ struct QGradientData
};
#define GRADIENT_STOPTABLE_SIZE 1024
+#define GRADIENT_STOPTABLE_SIZE_SHIFT 10
uint* colorTable; //[GRADIENT_STOPTABLE_SIZE];
@@ -293,6 +334,218 @@ struct QSpanData
void adjustSpanMethods();
};
+static inline uint qt_gradient_clamp(const QGradientData *data, int ipos)
+{
+ if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) {
+ if (data->spread == QGradient::RepeatSpread) {
+ ipos = ipos % GRADIENT_STOPTABLE_SIZE;
+ ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos;
+ } else if (data->spread == QGradient::ReflectSpread) {
+ const int limit = GRADIENT_STOPTABLE_SIZE * 2;
+ ipos = ipos % limit;
+ ipos = ipos < 0 ? limit + ipos : ipos;
+ ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - 1 - ipos : ipos;
+ } else {
+ if (ipos < 0)
+ ipos = 0;
+ else if (ipos >= GRADIENT_STOPTABLE_SIZE)
+ ipos = GRADIENT_STOPTABLE_SIZE-1;
+ }
+ }
+
+ Q_ASSERT(ipos >= 0);
+ Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE);
+
+ return ipos;
+}
+
+static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos)
+{
+ int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5));
+ return data->colorTable[qt_gradient_clamp(data, ipos)];
+}
+
+static inline qreal qRadialDeterminant(qreal a, qreal b, qreal c)
+{
+ return (b * b) - (4 * a * c);
+}
+
+template <class RadialFetchFunc>
+const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ // avoid division by zero
+ if (qFuzzyIsNull(op->radial.a)) {
+ extern void (*qt_memfill32)(quint32 *dest, quint32 value, int count);
+ qt_memfill32(buffer, 0, length);
+ return buffer;
+ }
+
+ const uint *b = buffer;
+ qreal rx = data->m21 * (y + qreal(0.5))
+ + data->dx + data->m11 * (x + qreal(0.5));
+ qreal ry = data->m22 * (y + qreal(0.5))
+ + data->dy + data->m12 * (x + qreal(0.5));
+ bool affine = !data->m13 && !data->m23;
+
+ uint *end = buffer + length;
+ if (affine) {
+ rx -= data->gradient.radial.focal.x;
+ ry -= data->gradient.radial.focal.y;
+
+ qreal inv_a = 1 / qreal(2 * op->radial.a);
+
+ const qreal delta_rx = data->m11;
+ const qreal delta_ry = data->m12;
+
+ qreal b = 2*(op->radial.dr*data->gradient.radial.focal.radius + rx * op->radial.dx + ry * op->radial.dy);
+ qreal delta_b = 2*(delta_rx * op->radial.dx + delta_ry * op->radial.dy);
+ const qreal b_delta_b = 2 * b * delta_b;
+ const qreal delta_b_delta_b = 2 * delta_b * delta_b;
+
+ const qreal bb = b * b;
+ const qreal delta_bb = delta_b * delta_b;
+
+ b *= inv_a;
+ delta_b *= inv_a;
+
+ const qreal rxrxryry = rx * rx + ry * ry;
+ const qreal delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry;
+ const qreal rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry);
+ const qreal delta_rx_plus_ry = 2 * delta_rxrxryry;
+
+ inv_a *= inv_a;
+
+ qreal det = (bb - 4 * op->radial.a * (op->radial.sqrfr - rxrxryry)) * inv_a;
+ qreal delta_det = (b_delta_b + delta_bb + 4 * op->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a;
+ const qreal delta_delta_det = (delta_b_delta_b + 4 * op->radial.a * delta_rx_plus_ry) * inv_a;
+
+ RadialFetchFunc::fetch(buffer, end, op, data, det, delta_det, delta_delta_det, b, delta_b);
+ } else {
+ qreal rw = data->m23 * (y + qreal(0.5))
+ + data->m33 + data->m13 * (x + qreal(0.5));
+
+ while (buffer < end) {
+ if (rw == 0) {
+ *buffer = 0;
+ } else {
+ qreal invRw = 1 / rw;
+ qreal gx = rx * invRw - data->gradient.radial.focal.x;
+ qreal gy = ry * invRw - data->gradient.radial.focal.y;
+ qreal b = 2*(op->radial.dr*data->gradient.radial.focal.radius + gx*op->radial.dx + gy*op->radial.dy);
+ qreal det = qRadialDeterminant(op->radial.a, b, op->radial.sqrfr - (gx*gx + gy*gy));
+
+ quint32 result = 0;
+ if (det >= 0) {
+ qreal detSqrt = qSqrt(det);
+
+ qreal s0 = (-b - detSqrt) * op->radial.inv2a;
+ qreal s1 = (-b + detSqrt) * op->radial.inv2a;
+
+ qreal s = qMax(s0, s1);
+
+ if (data->gradient.radial.focal.radius + op->radial.dr * s >= 0)
+ result = qt_gradient_pixel(&data->gradient, s);
+ }
+
+ *buffer = result;
+ }
+
+ rx += data->m11;
+ ry += data->m12;
+ rw += data->m13;
+
+ ++buffer;
+ }
+ }
+
+ return b;
+}
+
+template <class Simd>
+class QRadialFetchSimd
+{
+public:
+ static void fetch(uint *buffer, uint *end, const Operator *op, const QSpanData *data, qreal det,
+ qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b)
+ {
+ typename Simd::Vect_buffer_f det_vec;
+ typename Simd::Vect_buffer_f delta_det4_vec;
+ typename Simd::Vect_buffer_f b_vec;
+
+ for (int i = 0; i < 4; ++i) {
+ det_vec.f[i] = det;
+ delta_det4_vec.f[i] = 4 * delta_det;
+ b_vec.f[i] = b;
+
+ det += delta_det;
+ delta_det += delta_delta_det;
+ b += delta_b;
+ }
+
+ const typename Simd::Float32x4 v_delta_delta_det16 = Simd::v_dup(16 * delta_delta_det);
+ const typename Simd::Float32x4 v_delta_delta_det6 = Simd::v_dup(6 * delta_delta_det);
+ const typename Simd::Float32x4 v_delta_b4 = Simd::v_dup(4 * delta_b);
+
+ const typename Simd::Float32x4 v_r0 = Simd::v_dup(data->gradient.radial.focal.radius);
+ const typename Simd::Float32x4 v_dr = Simd::v_dup(op->radial.dr);
+
+ const typename Simd::Float32x4 v_min = Simd::v_dup(0.0f);
+ const typename Simd::Float32x4 v_max = Simd::v_dup(float(GRADIENT_STOPTABLE_SIZE-1));
+ const typename Simd::Float32x4 v_half = Simd::v_dup(0.5f);
+
+ const typename Simd::Int32x4 v_repeat_mask = Simd::v_dup(~(uint(0xffffff) << GRADIENT_STOPTABLE_SIZE_SHIFT));
+ const typename Simd::Int32x4 v_reflect_mask = Simd::v_dup(~(uint(0xffffff) << (GRADIENT_STOPTABLE_SIZE_SHIFT+1)));
+
+ const typename Simd::Int32x4 v_reflect_limit = Simd::v_dup(2 * GRADIENT_STOPTABLE_SIZE - 1);
+
+ const int extended_mask = op->radial.extended ? 0x0 : ~0x0;
+
+#define FETCH_RADIAL_LOOP_PROLOGUE \
+ while (buffer < end) { \
+ typename Simd::Vect_buffer_i v_buffer_mask; \
+ v_buffer_mask.v = Simd::v_greaterOrEqual(det_vec.v, v_min); \
+ const typename Simd::Float32x4 v_index_local = Simd::v_sub(Simd::v_sqrt(Simd::v_max(v_min, det_vec.v)), b_vec.v); \
+ const typename Simd::Float32x4 v_index = Simd::v_add(Simd::v_mul(v_index_local, v_max), v_half); \
+ v_buffer_mask.v = Simd::v_and(v_buffer_mask.v, Simd::v_greaterOrEqual(Simd::v_add(v_r0, Simd::v_mul(v_dr, v_index_local)), v_min)); \
+ typename Simd::Vect_buffer_i index_vec;
+#define FETCH_RADIAL_LOOP_CLAMP_REPEAT \
+ index_vec.v = Simd::v_and(v_repeat_mask, Simd::v_toInt(v_index));
+#define FETCH_RADIAL_LOOP_CLAMP_REFLECT \
+ const typename Simd::Int32x4 v_index_i = Simd::v_and(v_reflect_mask, Simd::v_toInt(v_index)); \
+ const typename Simd::Int32x4 v_index_i_inv = Simd::v_sub(v_reflect_limit, v_index_i); \
+ index_vec.v = Simd::v_min_16(v_index_i, v_index_i_inv);
+#define FETCH_RADIAL_LOOP_CLAMP_PAD \
+ index_vec.v = Simd::v_toInt(Simd::v_min(v_max, Simd::v_max(v_min, v_index)));
+#define FETCH_RADIAL_LOOP_EPILOGUE \
+ det_vec.v = Simd::v_add(Simd::v_add(det_vec.v, delta_det4_vec.v), v_delta_delta_det6); \
+ delta_det4_vec.v = Simd::v_add(delta_det4_vec.v, v_delta_delta_det16); \
+ b_vec.v = Simd::v_add(b_vec.v, v_delta_b4); \
+ for (int i = 0; i < 4; ++i) \
+ *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]]; \
+ }
+
+#define FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP) \
+ FETCH_RADIAL_LOOP_PROLOGUE \
+ FETCH_RADIAL_LOOP_CLAMP \
+ FETCH_RADIAL_LOOP_EPILOGUE
+
+ switch (data->gradient.spread) {
+ case QGradient::RepeatSpread:
+ FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_REPEAT)
+ break;
+ case QGradient::ReflectSpread:
+ FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_REFLECT)
+ break;
+ case QGradient::PadSpread:
+ FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_PAD)
+ break;
+ default:
+ Q_ASSERT(false);
+ }
+ }
+};
+
#if defined(Q_CC_RVCT)
# pragma push
# pragma arm
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index aad6bc9254..75bb619d09 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -112,8 +112,6 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
// First, align dest to 16 bytes:
ALIGNMENT_PROLOGUE_16BYTES(dst, x, w) {
- quint32 s = src[x];
- s = BYTE_MUL(s, const_alpha);
dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha);
}
@@ -127,8 +125,6 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
}
}
for (; x<w; ++x) {
- quint32 s = src[x];
- s = BYTE_MUL(s, const_alpha);
dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha);
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
@@ -491,6 +487,58 @@ void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y,
}
}
+class QSimdSse2
+{
+public:
+ typedef __m128i Int32x4;
+ typedef __m128 Float32x4;
+
+ union Vect_buffer_i { Int32x4 v; int i[4]; };
+ union Vect_buffer_f { Float32x4 v; float f[4]; };
+
+ static inline Float32x4 v_dup(float x) { return _mm_set1_ps(x); }
+ static inline Float32x4 v_dup(double x) { return _mm_set1_ps(x); }
+ static inline Int32x4 v_dup(int x) { return _mm_set1_epi32(x); }
+ static inline Int32x4 v_dup(uint x) { return _mm_set1_epi32(x); }
+
+ static inline Float32x4 v_add(Float32x4 a, Float32x4 b) { return _mm_add_ps(a, b); }
+ static inline Int32x4 v_add(Int32x4 a, Int32x4 b) { return _mm_add_epi32(a, b); }
+
+ static inline Float32x4 v_max(Float32x4 a, Float32x4 b) { return _mm_max_ps(a, b); }
+ static inline Float32x4 v_min(Float32x4 a, Float32x4 b) { return _mm_min_ps(a, b); }
+ static inline Int32x4 v_min_16(Int32x4 a, Int32x4 b) { return _mm_min_epi16(a, b); }
+
+ static inline Int32x4 v_and(Int32x4 a, Int32x4 b) { return _mm_and_si128(a, b); }
+
+ static inline Float32x4 v_sub(Float32x4 a, Float32x4 b) { return _mm_sub_ps(a, b); }
+ static inline Int32x4 v_sub(Int32x4 a, Int32x4 b) { return _mm_sub_epi32(a, b); }
+
+ static inline Float32x4 v_mul(Float32x4 a, Float32x4 b) { return _mm_mul_ps(a, b); }
+
+ static inline Float32x4 v_sqrt(Float32x4 x) { return _mm_sqrt_ps(x); }
+
+ static inline Int32x4 v_toInt(Float32x4 x) { return _mm_cvttps_epi32(x); }
+
+ // pre-VS 2008 doesn't have cast intrinsics, whereas 2008 and later requires it
+#if defined(Q_CC_MSVC) && _MSC_VER < 1500
+ static inline Int32x4 v_greaterOrEqual(Float32x4 a, Float32x4 b)
+ {
+ union Convert { Int32x4 vi; Float32x4 vf; } convert;
+ convert.vf = _mm_cmpgt_ps(a, b);
+ return convert.vi;
+ }
+#else
+ static inline Int32x4 v_greaterOrEqual(Float32x4 a, Float32x4 b) { return _mm_castps_si128(_mm_cmpgt_ps(a, b)); }
+#endif
+};
+
+const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdSse2> >(buffer, op, data, y, x, length);
+}
+
+
QT_END_NAMESPACE
#endif // QT_HAVE_SSE2
diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp
index 7870defd22..6f6cd6f66b 100644
--- a/src/gui/painting/qpaintbuffer.cpp
+++ b/src/gui/painting/qpaintbuffer.cpp
@@ -535,16 +535,6 @@ QString QPaintBuffer::commandDescription(int command) const
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: {
@@ -1778,12 +1768,12 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
rawFontD->fontEngine = fontD->engineForScript(QUnicodeTables::Common);
rawFontD->fontEngine->ref.ref();
- QGlyphs glyphs;
- glyphs.setFont(rawFont);
+ QGlyphRun glyphs;
+ glyphs.setRawFont(rawFont);
glyphs.setGlyphIndexes(glyphIndexes);
glyphs.setPositions(positions);
- painter->drawGlyphs(QPointF(), glyphs);
+ painter->drawGlyphRun(QPointF(), glyphs);
break;
}
#endif
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 9c86172753..8fc2dbab1a 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -4814,6 +4814,84 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
+ if (stopCount == 2) {
+ uint first_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity);
+ uint second_color = ARGB_COMBINE_ALPHA(stops[1].second.rgba(), opacity);
+
+ qreal first_stop = stops[0].first;
+ qreal second_stop = stops[1].first;
+
+ if (second_stop < first_stop) {
+ qSwap(first_color, second_color);
+ qSwap(first_stop, second_stop);
+ }
+
+ if (colorInterpolation) {
+ first_color = PREMUL(first_color);
+ second_color = PREMUL(second_color);
+ }
+
+ int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1));
+ int second_index = qRound(second_stop * (GRADIENT_STOPTABLE_SIZE-1));
+
+ uint red_first = qRed(first_color) << 16;
+ uint green_first = qGreen(first_color) << 16;
+ uint blue_first = qBlue(first_color) << 16;
+ uint alpha_first = qAlpha(first_color) << 16;
+
+ uint red_second = qRed(second_color) << 16;
+ uint green_second = qGreen(second_color) << 16;
+ uint blue_second = qBlue(second_color) << 16;
+ uint alpha_second = qAlpha(second_color) << 16;
+
+ int i = 0;
+ for (; i <= qMin(GRADIENT_STOPTABLE_SIZE, first_index); ++i) {
+ if (colorInterpolation)
+ colorTable[i] = first_color;
+ else
+ colorTable[i] = PREMUL(first_color);
+ }
+
+ if (i < second_index) {
+ qreal reciprocal = qreal(1) / (second_index - first_index);
+
+ int red_delta = qRound(int(red_second - red_first) * reciprocal);
+ int green_delta = qRound(int(green_second - green_first) * reciprocal);
+ int blue_delta = qRound(int(blue_second - blue_first) * reciprocal);
+ int alpha_delta = qRound(int(alpha_second - alpha_first) * reciprocal);
+
+ // rounding
+ red_first += 1 << 15;
+ green_first += 1 << 15;
+ blue_first += 1 << 15;
+ alpha_first += 1 << 15;
+
+ for (; i < qMin(GRADIENT_STOPTABLE_SIZE, second_index); ++i) {
+ red_first += red_delta;
+ green_first += green_delta;
+ blue_first += blue_delta;
+ alpha_first += alpha_delta;
+
+ const uint color = ((alpha_first << 8) & 0xff000000) | (red_first & 0xff0000)
+ | ((green_first >> 8) & 0xff00) | (blue_first >> 16);
+
+ if (colorInterpolation)
+ colorTable[i] = color;
+ else
+ colorTable[i] = PREMUL(color);
+ }
+ }
+
+ for (; i < GRADIENT_STOPTABLE_SIZE; ++i) {
+ if (colorInterpolation)
+ colorTable[i] = second_color;
+ else
+ colorTable[i] = PREMUL(second_color);
+ }
+
+ return;
+ }
+
uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity);
if (stopCount == 1) {
current_color = PREMUL(current_color);
@@ -4982,10 +5060,11 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
QPointF center = g->center();
radialData.center.x = center.x();
radialData.center.y = center.y();
+ radialData.center.radius = g->centerRadius();
QPointF focal = g->focalPoint();
radialData.focal.x = focal.x();
radialData.focal.y = focal.y();
- radialData.radius = g->radius();
+ radialData.focal.radius = g->focalRadius();
}
break;
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 509fb77d25..7f601eb755 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -1012,4 +1012,50 @@ void QPaintEngineEx::updateState(const QPaintEngineState &)
// do nothing...
}
+Q_GUI_EXPORT QPainterPath qt_painterPathFromVectorPath(const QVectorPath &path)
+{
+ const qreal *points = path.points();
+ const QPainterPath::ElementType *types = path.elements();
+
+ QPainterPath p;
+ if (types) {
+ int id = 0;
+ for (int i=0; i<path.elementCount(); ++i) {
+ switch(types[i]) {
+ case QPainterPath::MoveToElement:
+ p.moveTo(QPointF(points[id], points[id+1]));
+ id+=2;
+ break;
+ case QPainterPath::LineToElement:
+ p.lineTo(QPointF(points[id], points[id+1]));
+ id+=2;
+ break;
+ case QPainterPath::CurveToElement: {
+ QPointF p1(points[id], points[id+1]);
+ QPointF p2(points[id+2], points[id+3]);
+ QPointF p3(points[id+4], points[id+5]);
+ p.cubicTo(p1, p2, p3);
+ id+=6;
+ break;
+ }
+ case QPainterPath::CurveToDataElement:
+ ;
+ break;
+ }
+ }
+ } else {
+ p.moveTo(QPointF(points[0], points[1]));
+ int id = 2;
+ for (int i=1; i<path.elementCount(); ++i) {
+ p.lineTo(QPointF(points[id], points[id+1]));
+ id+=2;
+ }
+ }
+ if (path.hints() & QVectorPath::WindingFill)
+ p.setFillRule(Qt::WindingFill);
+
+ return p;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index f974186f58..64e84e5310 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -59,7 +59,7 @@
#include "qthread.h"
#include "qvarlengtharray.h"
#include "qstatictext.h"
-#include "qglyphs.h"
+#include "qglyphrun.h"
#include <private/qfontengine_p.h>
#include <private/qpaintengine_p.h>
@@ -69,7 +69,7 @@
#include <private/qpaintengine_raster_p.h>
#include <private/qmath_p.h>
#include <private/qstatictext_p.h>
-#include <private/qglyphs_p.h>
+#include <private/qglyphrun_p.h>
#include <private/qhexstring_p.h>
#include <private/qguiapplication_p.h>
#include <private/qrawfont_p.h>
@@ -477,8 +477,12 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio
q->save();
state->matrix = QTransform();
- state->dirtyFlags |= QPaintEngine::DirtyTransform;
- updateState(state);
+ if (extended) {
+ extended->transformChanged();
+ } else {
+ state->dirtyFlags |= QPaintEngine::DirtyTransform;
+ updateState(state);
+ }
engine->drawImage(absPathRect,
image,
QRectF(0, 0, absPathRect.width(), absPathRect.height()),
@@ -661,11 +665,14 @@ void QPainterPrivate::updateInvMatrix()
invMatrix = state->matrix.inverted();
}
+extern bool qt_isExtendedRadialGradient(const QBrush &brush);
+
void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
{
bool alpha = false;
bool linearGradient = false;
bool radialGradient = false;
+ bool extendedRadialGradient = false;
bool conicalGradient = false;
bool patternBrush = false;
bool xform = false;
@@ -697,6 +704,7 @@ void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
(brushStyle == Qt::LinearGradientPattern));
radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
(brushStyle == Qt::RadialGradientPattern));
+ extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
(brushStyle == Qt::ConicalGradientPattern));
patternBrush = (((penBrushStyle > Qt::SolidPattern
@@ -780,7 +788,7 @@ void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
// Radial gradient emulation
- if (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill))
+ if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
else
s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
@@ -5664,19 +5672,19 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
\since 4.8
- \sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes()
+ \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
*/
#if !defined(QT_NO_RAWFONT)
-void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
+void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
{
Q_D(QPainter);
- QRawFont font = glyphs.font();
+ QRawFont font = glyphRun.rawFont();
if (!font.isValid())
return;
- QVector<quint32> glyphIndexes = glyphs.glyphIndexes();
- QVector<QPointF> glyphPositions = glyphs.positions();
+ QVector<quint32> glyphIndexes = glyphRun.glyphIndexes();
+ QVector<QPointF> glyphPositions = glyphRun.positions();
int count = qMin(glyphIndexes.size(), glyphPositions.size());
QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
@@ -5685,6 +5693,13 @@ void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
d->extended != 0
? qt_paintengine_supports_transformations(d->extended->type())
: qt_paintengine_supports_transformations(d->engine->type());
+
+ // If the matrix is not affine, the paint engine will fall back to
+ // drawing the glyphs as paths, which in turn means we should not
+ // preprocess the glyph positions
+ if (!d->state->matrix.isAffine())
+ paintEngineSupportsTransformations = true;
+
for (int i=0; i<count; ++i) {
QPointF processedPosition = position + glyphPositions.at(i);
if (!paintEngineSupportsTransformations)
@@ -5692,8 +5707,8 @@ void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
}
- d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count, font, glyphs.overline(),
- glyphs.underline(), glyphs.strikeOut());
+ d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count, font, glyphRun.overline(),
+ glyphRun.underline(), glyphRun.strikeOut());
}
void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount,
@@ -5728,7 +5743,7 @@ void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, in
QFixed width = rightMost - leftMost;
- if (extended != 0) {
+ if (extended != 0 && state->matrix.isAffine()) {
QStaticTextItem staticTextItem;
staticTextItem.color = state->pen.color();
staticTextItem.font = state->font;
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 0be3dfcbb3..7420801998 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -78,7 +78,7 @@ class QTextItem;
class QMatrix;
class QTransform;
class QStaticText;
-class QGlyphs;
+class QGlyphRun;
class QPainterPrivateDeleter;
@@ -399,7 +399,7 @@ public:
Qt::LayoutDirection layoutDirection() const;
#if !defined(QT_NO_RAWFONT)
- void drawGlyphs(const QPointF &position, const QGlyphs &glyphs);
+ void drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun);
#endif
void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText);
@@ -480,6 +480,7 @@ private:
friend class QPaintEngine;
friend class QPaintEngineExPrivate;
friend class QOpenGLPaintEngine;
+ friend class QVGPaintEngine;
friend class QX11PaintEngine;
friend class QX11PaintEnginePrivate;
friend class QWin32PaintEngine;
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 27aed3226f..9fbac13f47 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1126,6 +1126,7 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString &
QTextEngine *eng = layout.engine();
layout.beginLayout();
QTextLine line = layout.createLine();
+ Q_UNUSED(line);
layout.endLayout();
const QScriptLine &sl = eng->lines[0];
if (!sl.length || !eng->layoutData)
diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp
index b7f51606da..353869f3a4 100644
--- a/src/gui/painting/qprintengine_pdf.cpp
+++ b/src/gui/painting/qprintengine_pdf.cpp
@@ -534,7 +534,10 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_n
QImage image = img;
QImage::Format format = image.format();
- if (image.depth() == 1 && *bitmap && img.colorTable().size() == 0) {
+ if (image.depth() == 1 && *bitmap && img.colorTable().size() == 2
+ && img.colorTable().at(0) == QColor(Qt::black).rgba()
+ && img.colorTable().at(1) == QColor(Qt::white).rgba())
+ {
if (format == QImage::Format_MonoLSB)
image = image.convertToFormat(QImage::Format_Mono);
format = QImage::Format_Mono;
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index fca46b45f7..dd723edc45 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -552,6 +552,7 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine
// // line to the beginning of the arc segment, (should not be needed).
// emitLineTo(qt_real_to_fixed(curve_start.x()), qt_real_to_fixed(curve_start.y()));
+ Q_UNUSED(curve_start);
for (int i=0; i<point_count; i+=3) {
emitCubicTo(qt_real_to_fixed(curves[i].x()),
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 58bcca87b7..4dae2a3784 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -803,106 +803,6 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
return load_flags;
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const
-{
- Glyph *g = set->getGlyph(glyph);
- if (g && g->format == format)
- return g;
-
- bool hsubpixel = false;
- int vfactor = 1;
- int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor);
-
- // apply our matrix to this, but note that the metrics will not be affected by this.
- FT_Face face = lockFace();
- FT_Matrix matrix = this->matrix;
- FT_Matrix_Multiply(&set->transformationMatrix, &matrix);
- FT_Set_Transform(face, &matrix, 0);
- freetype->matrix = matrix;
-
- bool transform = matrix.xx != 0x10000 || matrix.yy != 0x10000 || matrix.xy != 0 || matrix.yx != 0;
- if (transform)
- load_flags |= FT_LOAD_NO_BITMAP;
-
- FT_Error err = FT_Load_Glyph(face, glyph, load_flags);
- if (err && (load_flags & FT_LOAD_NO_BITMAP)) {
- load_flags &= ~FT_LOAD_NO_BITMAP;
- err = FT_Load_Glyph(face, glyph, load_flags);
- }
- if (err == FT_Err_Too_Few_Arguments) {
- // this is an error in the bytecode interpreter, just try to run without it
- load_flags |= FT_LOAD_FORCE_AUTOHINT;
- err = FT_Load_Glyph(face, glyph, load_flags);
- }
- if (err != FT_Err_Ok)
- qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
-
- unlockFace();
- if (set->outline_drawing)
- return 0;
-
- if (!g) {
- g = new Glyph;
- g->uploadedToServer = false;
- g->data = 0;
- }
-
- FT_GlyphSlot slot = face->glyph;
- if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(slot);
- int left = slot->metrics.horiBearingX;
- int right = slot->metrics.horiBearingX + slot->metrics.width;
- int top = slot->metrics.horiBearingY;
- int bottom = slot->metrics.horiBearingY - slot->metrics.height;
- if (transform && slot->format != FT_GLYPH_FORMAT_BITMAP) { // freetype doesn't apply the transformation on the metrics
- int l, r, t, b;
- FT_Vector vector;
- vector.x = left;
- vector.y = top;
- FT_Vector_Transform(&vector, &matrix);
- l = r = vector.x;
- t = b = vector.y;
- vector.x = right;
- vector.y = top;
- FT_Vector_Transform(&vector, &matrix);
- if (l > vector.x) l = vector.x;
- if (r < vector.x) r = vector.x;
- if (t < vector.y) t = vector.y;
- if (b > vector.y) b = vector.y;
- vector.x = right;
- vector.y = bottom;
- FT_Vector_Transform(&vector, &matrix);
- if (l > vector.x) l = vector.x;
- if (r < vector.x) r = vector.x;
- if (t < vector.y) t = vector.y;
- if (b > vector.y) b = vector.y;
- vector.x = left;
- vector.y = bottom;
- FT_Vector_Transform(&vector, &matrix);
- if (l > vector.x) l = vector.x;
- if (r < vector.x) r = vector.x;
- if (t < vector.y) t = vector.y;
- if (b > vector.y) b = vector.y;
- left = l;
- right = r;
- top = t;
- bottom = b;
- }
- left = FLOOR(left);
- right = CEIL(right);
- bottom = FLOOR(bottom);
- top = CEIL(top);
-
- g->linearAdvance = face->glyph->linearHoriAdvance >> 10;
- g->width = TRUNC(right-left);
- g->height = TRUNC(top-bottom);
- g->x = TRUNC(left);
- g->y = TRUNC(top);
- g->advance = TRUNC(ROUND(face->glyph->advance.x));
- g->format = Format_None;
-
- return g;
-}
-
QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
QFixed subPixelPosition,
GlyphFormat format,
@@ -1697,7 +1597,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
FT_Face face = 0;
bool design = (default_hint_style == HintNone ||
default_hint_style == HintLight ||
- (flags & HB_ShaperFlag_UseDesignMetrics));
+ (flags & HB_ShaperFlag_UseDesignMetrics)) && FT_IS_SCALABLE(freetype->face);
for (int i = 0; i < glyphs->numGlyphs; i++) {
Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
if (g) {
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 2c335f3cd3..41064715b1 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -343,7 +343,6 @@ protected:
private:
friend class QFontEngineFTRawFont;
- QFontEngineFT::Glyph *loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const;
int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
GlyphFormat defaultFormat;
diff --git a/src/gui/text/qglyphs.cpp b/src/gui/text/qglyphrun.cpp
index cfea6ece93..ea527886cd 100644
--- a/src/gui/text/qglyphs.cpp
+++ b/src/gui/text/qglyphrun.cpp
@@ -43,14 +43,14 @@
#if !defined(QT_NO_RAWFONT)
-#include "qglyphs.h"
-#include "qglyphs_p.h"
+#include "qglyphrun.h"
+#include "qglyphrun_p.h"
QT_BEGIN_NAMESPACE
/*!
- \class QGlyphs
- \brief The QGlyphs class provides direct access to the internal glyphs in a font.
+ \class QGlyphRun
+ \brief The QGlyphRun class provides direct access to the internal glyphs in a font.
\since 4.8
\ingroup text
@@ -67,42 +67,43 @@ QT_BEGIN_NAMESPACE
Under certain circumstances, it can be useful as an application developer to have more low-level
control over which glyphs in a specific font are drawn to the screen. This could for instance
be the case in applications that use an external font engine and text shaper together with Qt.
- QGlyphs provides an interface to the raw data needed to get text on the screen. It
+ QGlyphRun provides an interface to the raw data needed to get text on the screen. It
contains a list of glyph indexes, a position for each glyph and a font.
It is the user's responsibility to ensure that the selected font actually contains the
provided glyph indexes.
- QTextLayout::glyphs() or QTextFragment::glyphs() can be used to convert unicode encoded text
- into a list of QGlyphs objects, and QPainter::drawGlyphs() can be used to draw the glyphs.
+ QTextLayout::glyphRuns() or QTextFragment::glyphRuns() can be used to convert unicode encoded
+ text into a list of QGlyphRun objects, and QPainter::drawGlyphRun() can be used to draw the
+ glyphs.
\note Please note that QRawFont is considered local to the thread in which it is constructed.
- This in turn means that a new QRawFont will have to be created and set on the QGlyphs if it is
- moved to a different thread. If the QGlyphs contains a reference to a QRawFont from a different
+ This in turn means that a new QRawFont will have to be created and set on the QGlyphRun if it is
+ moved to a different thread. If the QGlyphRun contains a reference to a QRawFont from a different
thread than the current, it will not be possible to draw the glyphs using a QPainter, as the
QRawFont is considered invalid and inaccessible in this case.
*/
/*!
- Constructs an empty QGlyphs object.
+ Constructs an empty QGlyphRun object.
*/
-QGlyphs::QGlyphs() : d(new QGlyphsPrivate)
+QGlyphRun::QGlyphRun() : d(new QGlyphRunPrivate)
{
}
/*!
- Constructs a QGlyphs object which is a copy of \a other.
+ Constructs a QGlyphRun object which is a copy of \a other.
*/
-QGlyphs::QGlyphs(const QGlyphs &other)
+QGlyphRun::QGlyphRun(const QGlyphRun &other)
{
d = other.d;
}
/*!
- Destroys the QGlyphs.
+ Destroys the QGlyphRun.
*/
-QGlyphs::~QGlyphs()
+QGlyphRun::~QGlyphRun()
{
// Required for QExplicitlySharedDataPointer
}
@@ -110,26 +111,26 @@ QGlyphs::~QGlyphs()
/*!
\internal
*/
-void QGlyphs::detach()
+void QGlyphRun::detach()
{
if (d->ref != 1)
d.detach();
}
/*!
- Assigns \a other to this QGlyphs object.
+ Assigns \a other to this QGlyphRun object.
*/
-QGlyphs &QGlyphs::operator=(const QGlyphs &other)
+QGlyphRun &QGlyphRun::operator=(const QGlyphRun &other)
{
d = other.d;
return *this;
}
/*!
- Compares \a other to this QGlyphs object. Returns true if the list of glyph indexes,
+ Compares \a other to this QGlyphRun object. Returns true if the list of glyph indexes,
the list of positions and the font are all equal, otherwise returns false.
*/
-bool QGlyphs::operator==(const QGlyphs &other) const
+bool QGlyphRun::operator==(const QGlyphRun &other) const
{
return ((d == other.d)
|| (d->glyphIndexes == other.d->glyphIndexes
@@ -137,14 +138,14 @@ bool QGlyphs::operator==(const QGlyphs &other) const
&& d->overline == other.d->overline
&& d->underline == other.d->underline
&& d->strikeOut == other.d->strikeOut
- && d->font == other.d->font));
+ && d->rawFont == other.d->rawFont));
}
/*!
- Compares \a other to this QGlyphs object. Returns true if any of the list of glyph
+ Compares \a other to this QGlyphRun object. Returns true if any of the list of glyph
indexes, the list of positions or the font are different, otherwise returns false.
*/
-bool QGlyphs::operator!=(const QGlyphs &other) const
+bool QGlyphRun::operator!=(const QGlyphRun &other) const
{
return !(*this == other);
}
@@ -152,13 +153,13 @@ bool QGlyphs::operator!=(const QGlyphs &other) const
/*!
\internal
- Adds together the lists of glyph indexes and positions in \a other and this QGlyphs
- object and returns the result. The font in the returned QGlyphs will be the same as in
- this QGlyphs object.
+ Adds together the lists of glyph indexes and positions in \a other and this QGlyphRun
+ object and returns the result. The font in the returned QGlyphRun will be the same as in
+ this QGlyphRun object.
*/
-QGlyphs QGlyphs::operator+(const QGlyphs &other) const
+QGlyphRun QGlyphRun::operator+(const QGlyphRun &other) const
{
- QGlyphs ret(*this);
+ QGlyphRun ret(*this);
ret += other;
return ret;
}
@@ -166,10 +167,10 @@ QGlyphs QGlyphs::operator+(const QGlyphs &other) const
/*!
\internal
- Appends the glyph indexes and positions in \a other to this QGlyphs object and returns
+ Appends the glyph indexes and positions in \a other to this QGlyphRun object and returns
a reference to the current object.
*/
-QGlyphs &QGlyphs::operator+=(const QGlyphs &other)
+QGlyphRun &QGlyphRun::operator+=(const QGlyphRun &other)
{
detach();
@@ -180,41 +181,41 @@ QGlyphs &QGlyphs::operator+=(const QGlyphs &other)
}
/*!
- Returns the font selected for this QGlyphs object.
+ Returns the font selected for this QGlyphRun object.
- \sa setFont()
+ \sa setRawFont()
*/
-QRawFont QGlyphs::font() const
+QRawFont QGlyphRun::rawFont() const
{
- return d->font;
+ return d->rawFont;
}
/*!
Sets the font in which to look up the glyph indexes to \a font.
- \sa font(), setGlyphIndexes()
+ \sa rawFont(), setGlyphIndexes()
*/
-void QGlyphs::setFont(const QRawFont &font)
+void QGlyphRun::setRawFont(const QRawFont &rawFont)
{
detach();
- d->font = font;
+ d->rawFont = rawFont;
}
/*!
- Returns the glyph indexes for this QGlyphs object.
+ Returns the glyph indexes for this QGlyphRun object.
\sa setGlyphIndexes(), setPositions()
*/
-QVector<quint32> QGlyphs::glyphIndexes() const
+QVector<quint32> QGlyphRun::glyphIndexes() const
{
return d->glyphIndexes;
}
/*!
- Set the glyph indexes for this QGlyphs object to \a glyphIndexes. The glyph indexes must
+ Set the glyph indexes for this QGlyphRun object to \a glyphIndexes. The glyph indexes must
be valid for the selected font.
*/
-void QGlyphs::setGlyphIndexes(const QVector<quint32> &glyphIndexes)
+void QGlyphRun::setGlyphIndexes(const QVector<quint32> &glyphIndexes)
{
detach();
d->glyphIndexes = glyphIndexes;
@@ -223,7 +224,7 @@ void QGlyphs::setGlyphIndexes(const QVector<quint32> &glyphIndexes)
/*!
Returns the position of the edge of the baseline for each glyph in this set of glyph indexes.
*/
-QVector<QPointF> QGlyphs::positions() const
+QVector<QPointF> QGlyphRun::positions() const
{
return d->glyphPositions;
}
@@ -232,87 +233,87 @@ QVector<QPointF> QGlyphs::positions() const
Sets the positions of the edge of the baseline for each glyph in this set of glyph indexes to
\a positions.
*/
-void QGlyphs::setPositions(const QVector<QPointF> &positions)
+void QGlyphRun::setPositions(const QVector<QPointF> &positions)
{
detach();
d->glyphPositions = positions;
}
/*!
- Clears all data in the QGlyphs object.
+ Clears all data in the QGlyphRun object.
*/
-void QGlyphs::clear()
+void QGlyphRun::clear()
{
detach();
d->glyphPositions = QVector<QPointF>();
d->glyphIndexes = QVector<quint32>();
- d->font = QRawFont();
+ d->rawFont = QRawFont();
d->strikeOut = false;
d->overline = false;
d->underline = false;
}
/*!
- Returns true if this QGlyphs should be painted with an overline decoration.
+ Returns true if this QGlyphRun should be painted with an overline decoration.
\sa setOverline()
*/
-bool QGlyphs::overline() const
+bool QGlyphRun::overline() const
{
return d->overline;
}
/*!
- Indicates that this QGlyphs should be painted with an overline decoration if \a overline is true.
- Otherwise the QGlyphs should be painted with no overline decoration.
+ Indicates that this QGlyphRun should be painted with an overline decoration if \a overline is true.
+ Otherwise the QGlyphRun should be painted with no overline decoration.
\sa overline()
*/
-void QGlyphs::setOverline(bool overline)
+void QGlyphRun::setOverline(bool overline)
{
detach();
d->overline = overline;
}
/*!
- Returns true if this QGlyphs should be painted with an underline decoration.
+ Returns true if this QGlyphRun should be painted with an underline decoration.
\sa setUnderline()
*/
-bool QGlyphs::underline() const
+bool QGlyphRun::underline() const
{
return d->underline;
}
/*!
- Indicates that this QGlyphs should be painted with an underline decoration if \a underline is
- true. Otherwise the QGlyphs should be painted with no underline decoration.
+ Indicates that this QGlyphRun should be painted with an underline decoration if \a underline is
+ true. Otherwise the QGlyphRun should be painted with no underline decoration.
\sa underline()
*/
-void QGlyphs::setUnderline(bool underline)
+void QGlyphRun::setUnderline(bool underline)
{
detach();
d->underline = underline;
}
/*!
- Returns true if this QGlyphs should be painted with a strike out decoration.
+ Returns true if this QGlyphRun should be painted with a strike out decoration.
\sa setStrikeOut()
*/
-bool QGlyphs::strikeOut() const
+bool QGlyphRun::strikeOut() const
{
return d->strikeOut;
}
/*!
- Indicates that this QGlyphs should be painted with an strike out decoration if \a strikeOut is
- true. Otherwise the QGlyphs should be painted with no strike out decoration.
+ Indicates that this QGlyphRun should be painted with an strike out decoration if \a strikeOut is
+ true. Otherwise the QGlyphRun should be painted with no strike out decoration.
\sa strikeOut()
*/
-void QGlyphs::setStrikeOut(bool strikeOut)
+void QGlyphRun::setStrikeOut(bool strikeOut)
{
detach();
d->strikeOut = strikeOut;
diff --git a/src/gui/text/qglyphs.h b/src/gui/text/qglyphrun.h
index 4d7dcaf554..dcc166ea3e 100644
--- a/src/gui/text/qglyphs.h
+++ b/src/gui/text/qglyphrun.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QGLYPHS_H
-#define QGLYPHS_H
+#ifndef QGLYPHRUN_H
+#define QGLYPHRUN_H
#include <QtCore/qsharedpointer.h>
#include <QtCore/qvector.h>
@@ -55,16 +55,16 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-class QGlyphsPrivate;
-class Q_GUI_EXPORT QGlyphs
+class QGlyphRunPrivate;
+class Q_GUI_EXPORT QGlyphRun
{
public:
- QGlyphs();
- QGlyphs(const QGlyphs &other);
- ~QGlyphs();
+ QGlyphRun();
+ QGlyphRun(const QGlyphRun &other);
+ ~QGlyphRun();
- QRawFont font() const;
- void setFont(const QRawFont &font);
+ QRawFont rawFont() const;
+ void setRawFont(const QRawFont &rawFont);
QVector<quint32> glyphIndexes() const;
void setGlyphIndexes(const QVector<quint32> &glyphIndexes);
@@ -74,9 +74,9 @@ public:
void clear();
- QGlyphs &operator=(const QGlyphs &other);
- bool operator==(const QGlyphs &other) const;
- bool operator!=(const QGlyphs &other) const;
+ QGlyphRun &operator=(const QGlyphRun &other);
+ bool operator==(const QGlyphRun &other) const;
+ bool operator!=(const QGlyphRun &other) const;
void setOverline(bool overline);
bool overline() const;
@@ -88,14 +88,14 @@ public:
bool strikeOut() const;
private:
- friend class QGlyphsPrivate;
+ friend class QGlyphRunPrivate;
friend class QTextLine;
- QGlyphs operator+(const QGlyphs &other) const;
- QGlyphs &operator+=(const QGlyphs &other);
+ QGlyphRun operator+(const QGlyphRun &other) const;
+ QGlyphRun &operator+=(const QGlyphRun &other);
void detach();
- QExplicitlySharedDataPointer<QGlyphsPrivate> d;
+ QExplicitlySharedDataPointer<QGlyphRunPrivate> d;
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qglyphs_p.h b/src/gui/text/qglyphrun_p.h
index 944f777d4a..4aa01d6bda 100644
--- a/src/gui/text/qglyphs_p.h
+++ b/src/gui/text/qglyphrun_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QGLYPHS_P_H
-#define QGLYPHS_P_H
+#ifndef QGLYPHRUN_P_H
+#define QGLYPHRUN_P_H
//
// W A R N I N G
@@ -53,7 +53,7 @@
// We mean it.
//
-#include "qglyphs.h"
+#include "qglyphrun.h"
#include "qrawfont.h"
#include <qfont.h>
@@ -64,21 +64,21 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-class QGlyphsPrivate: public QSharedData
+class QGlyphRunPrivate: public QSharedData
{
public:
- QGlyphsPrivate()
+ QGlyphRunPrivate()
: overline(false)
, underline(false)
, strikeOut(false)
{
}
- QGlyphsPrivate(const QGlyphsPrivate &other)
+ QGlyphRunPrivate(const QGlyphRunPrivate &other)
: QSharedData(other)
, glyphIndexes(other.glyphIndexes)
, glyphPositions(other.glyphPositions)
- , font(other.font)
+ , rawFont(other.rawFont)
, overline(other.overline)
, underline(other.underline)
, strikeOut(other.strikeOut)
@@ -87,7 +87,7 @@ public:
QVector<quint32> glyphIndexes;
QVector<QPointF> glyphPositions;
- QRawFont font;
+ QRawFont rawFont;
uint overline : 1;
uint underline : 1;
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index 1bce909b0e..29394e9b7a 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -78,7 +78,7 @@ QT_BEGIN_NAMESPACE
A QRawFont object represents a single, physical instance of a given font in a given pixel size.
I.e. in the typical case it represents a set of TrueType or OpenType font tables and uses a
user specified pixel size to convert metrics into logical pixel units. In can be used in
- combination with the QGlyphs class to draw specific glyph indexes at specific positions, and
+ combination with the QGlyphRun class to draw specific glyph indexes at specific positions, and
also have accessors to some relevant data in the physical font.
QRawFont only provides support for the main font technologies: GDI and DirectWrite on Windows
@@ -87,9 +87,9 @@ QT_BEGIN_NAMESPACE
QRawFont can be constructed in a number of ways:
\list
- \o \l It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The
- returned QGlyphs objects will contain QRawFont objects which represent the actual fonts
- used to render each portion of the text.
+ \o \l It can be constructed by calling QTextLayout::glyphRuns() or QTextFragment::glyphRuns().
+ The returned QGlyphRun objects will contain QRawFont objects which represent the actual
+ fonts used to render each portion of the text.
\o \l It can be constructed by passing a QFont object to QRawFont::fromFont(). The function
will return a QRawFont object representing the font that will be selected as response to
the QFont query and the selected writing system.
@@ -234,7 +234,7 @@ void QRawFont::loadFromData(const QByteArray &fontData,
the pixel in the rasterization of the glyph. Otherwise, the image will be in the format of
QImage::Format_A8 and each pixel will contain the opacity of the pixel in the rasterization.
- \sa pathForGlyph(), QPainter::drawGlyphs()
+ \sa pathForGlyph(), QPainter::drawGlyphRun()
*/
QImage QRawFont::alphaMapForGlyph(quint32 glyphIndex, AntialiasingType antialiasingType,
const QTransform &transform) const
@@ -302,6 +302,58 @@ qreal QRawFont::descent() const
}
/*!
+ Returns the xHeight of this QRawFont in pixel units.
+
+ \sa QFontMetricsF::xHeight()
+*/
+qreal QRawFont::xHeight() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->xHeight().toReal();
+}
+
+/*!
+ Returns the leading of this QRawFont in pixel units.
+
+ \sa QFontMetricsF::leading()
+*/
+qreal QRawFont::leading() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->leading().toReal();
+}
+
+/*!
+ Returns the average character width of this QRawFont in pixel units.
+
+ \sa QFontMetricsF::averageCharWidth()
+*/
+qreal QRawFont::averageCharWidth() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->averageCharWidth().toReal();
+}
+
+/*!
+ Returns the width of the widest character in the font.
+
+ \sa QFontMetricsF::maxWidth()
+*/
+qreal QRawFont::maxCharWidth() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->maxCharWidth();
+}
+
+/*!
Returns the pixel size set for this QRawFont. The pixel size affects how glyphs are
rasterized, the size of glyphs returned by pathForGlyph(), and is used to convert
internal metrics from design units to logical pixel units.
@@ -374,9 +426,9 @@ int QRawFont::weight() const
underlying font. Note that in cases where there are other tables in the font that affect the
shaping of the text, the returned glyph indexes will not correctly represent the rendering
of the text. To get the correctly shaped text, you can use QTextLayout to lay out and shape the
- text, and then call QTextLayout::glyphs() to get the set of glyph index list and QRawFont pairs.
+ text, and then call QTextLayout::glyphRuns() to get the set of glyph index list and QRawFont pairs.
- \sa advancesForGlyphIndexes(), QGlyphs, QTextLayout::glyphs(), QTextFragment::glyphs()
+ \sa advancesForGlyphIndexes(), QGlyphRun, QTextLayout::glyphRuns(), QTextFragment::glyphRuns()
*/
QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const
{
@@ -535,17 +587,17 @@ QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writ
layout.beginLayout();
QTextLine line = layout.createLine();
layout.endLayout();
- QList<QGlyphs> list = layout.glyphs();
+ QList<QGlyphRun> list = layout.glyphRuns();
if (list.size()) {
// Pick the one matches the family name we originally requested,
// if none of them match, just pick the first one
for (int i = 0; i < list.size(); i++) {
- QGlyphs glyphs = list.at(i);
- QRawFont rawfont = glyphs.font();
+ QGlyphRun glyphs = list.at(i);
+ QRawFont rawfont = glyphs.rawFont();
if (rawfont.familyName() == font.family())
return rawfont;
}
- return list.at(0).font();
+ return list.at(0).rawFont();
}
return QRawFont();
#else
diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h
index 56aeefc8ff..900c07a7dd 100644
--- a/src/gui/text/qrawfont.h
+++ b/src/gui/text/qrawfont.h
@@ -103,6 +103,10 @@ public:
qreal ascent() const;
qreal descent() const;
+ qreal leading() const;
+ qreal xHeight() const;
+ qreal averageCharWidth() const;
+ qreal maxCharWidth() const;
qreal unitsPerEm() const;
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 450f7e100a..e6d5070340 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -3090,6 +3090,7 @@ void QTextDocumentLayoutPrivate::ensureLayouted(QFixed y) const
if (currentLazyLayoutPosition == -1)
return;
const QSizeF oldSize = q->dynamicDocumentSize();
+ Q_UNUSED(oldSize);
if (checkPoints.isEmpty())
layoutStep();
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 551ef69203..271af7ae82 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -50,8 +50,8 @@
#include "qtextdocument_p.h"
#include "qtextformat_p.h"
#include "qpainterpath.h"
-#include "qglyphs.h"
-#include "qglyphs_p.h"
+#include "qglyphrun.h"
+#include "qglyphrun_p.h"
#include "qrawfont.h"
#include "qrawfont_p.h"
#include <limits.h>
@@ -992,12 +992,12 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip)
\since 4.8
- \sa draw(), QPainter::drawGlyphs()
+ \sa draw(), QPainter::drawGlyphRun()
*/
#if !defined(QT_NO_RAWFONT)
-QList<QGlyphs> QTextLayout::glyphs() const
+QList<QGlyphRun> QTextLayout::glyphRuns() const
{
- QList<QGlyphs> glyphs;
+ QList<QGlyphRun> glyphs;
for (int i=0; i<d->lines.size(); ++i)
glyphs += QTextLine(i, d).glyphs(-1, -1);
@@ -1209,8 +1209,6 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
d->itemize();
QPointF position = pos + d->position;
- QFixed pos_x = QFixed::fromReal(position.x());
- QFixed pos_y = QFixed::fromReal(position.y());
cursorPosition = qBound(0, cursorPosition, d->layoutData->string.length());
int line = d->lineNumberForTextPosition(cursorPosition);
@@ -2093,15 +2091,15 @@ namespace {
\since 4.8
- \sa QTextLayout::glyphs()
+ \sa QTextLayout::glyphRuns()
*/
#if !defined(QT_NO_RAWFONT)
-QList<QGlyphs> QTextLine::glyphs(int from, int length) const
+QList<QGlyphRun> QTextLine::glyphs(int from, int length) const
{
const QScriptLine &line = eng->lines[i];
if (line.length == 0)
- return QList<QGlyphs>();
+ return QList<QGlyphRun>();
QHash<QFontEngine *, GlyphInfo> glyphLayoutHash;
@@ -2166,7 +2164,7 @@ QList<QGlyphs> QTextLine::glyphs(int from, int length) const
}
}
- QHash<QPair<QFontEngine *, int>, QGlyphs> glyphsHash;
+ QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphsHash;
QList<QFontEngine *> keys = glyphLayoutHash.uniqueKeys();
for (int i=0; i<keys.size(); ++i) {
@@ -2223,14 +2221,14 @@ QList<QGlyphs> QTextLine::glyphs(int from, int length) const
positions.append(positionsArray.at(i).toPointF() + pos);
}
- QGlyphs glyphIndexes;
+ QGlyphRun glyphIndexes;
glyphIndexes.setGlyphIndexes(glyphs);
glyphIndexes.setPositions(positions);
glyphIndexes.setOverline(flags.testFlag(QTextItem::Overline));
glyphIndexes.setUnderline(flags.testFlag(QTextItem::Underline));
glyphIndexes.setStrikeOut(flags.testFlag(QTextItem::StrikeOut));
- glyphIndexes.setFont(font);
+ glyphIndexes.setRawFont(font);
QPair<QFontEngine *, int> key(fontEngine, int(flags));
if (!glyphsHash.contains(key))
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index 6aa81f9e7c..8fe488a95a 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -49,7 +49,7 @@
#include <QtCore/qobject.h>
#include <QtGui/qevent.h>
#include <QtGui/qtextformat.h>
-#include <QtGui/qglyphs.h>
+#include <QtGui/qglyphrun.h>
#include <QtGui/qtextcursor.h>
QT_BEGIN_HEADER
@@ -174,7 +174,7 @@ public:
qreal maximumWidth() const;
#if !defined(QT_NO_RAWFONT)
- QList<QGlyphs> glyphs() const;
+ QList<QGlyphRun> glyphRuns() const;
#endif
QTextEngine *engine() const { return d; }
@@ -249,7 +249,7 @@ private:
void layout_helper(int numGlyphs);
#if !defined(QT_NO_RAWFONT)
- QList<QGlyphs> glyphs(int from, int length) const;
+ QList<QGlyphRun> glyphs(int from, int length) const;
#endif
friend class QTextLayout;
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index 5c1c8b9edc..8dabcc771b 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -1664,25 +1664,25 @@ QTextBlock::iterator &QTextBlock::iterator::operator--()
Returns the glyphs of this text fragment. The positions of the glyphs are
relative to the position of the QTextBlock's layout.
- \sa QGlyphs, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphs()
+ \sa QGlyphRun, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphRun()
*/
#if !defined(QT_NO_RAWFONT)
-QList<QGlyphs> QTextFragment::glyphs() const
+QList<QGlyphRun> QTextFragment::glyphRuns() const
{
if (!p || !n)
- return QList<QGlyphs>();
+ return QList<QGlyphRun>();
int pos = position();
int len = length();
if (len == 0)
- return QList<QGlyphs>();
+ return QList<QGlyphRun>();
int blockNode = p->blockMap().findNode(pos);
const QTextBlockData *blockData = p->blockMap().fragment(blockNode);
QTextLayout *layout = blockData->layout;
- QList<QGlyphs> ret;
+ QList<QGlyphRun> ret;
for (int i=0; i<layout->lineCount(); ++i) {
QTextLine textLine = layout->lineAt(i);
ret += textLine.glyphs(pos, len);
diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h
index ad8e6579dc..1588349a3f 100644
--- a/src/gui/text/qtextobject.h
+++ b/src/gui/text/qtextobject.h
@@ -44,7 +44,7 @@
#include <QtCore/qobject.h>
#include <QtGui/qtextformat.h>
-#include <QtGui/qglyphs.h>
+#include <QtGui/qglyphrun.h>
QT_BEGIN_HEADER
@@ -317,7 +317,7 @@ public:
QString text() const;
#if !defined(QT_NO_RAWFONT)
- QList<QGlyphs> glyphs() const;
+ QList<QGlyphRun> glyphRuns() const;
#endif
private:
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index 24f9c5f0e4..6357dec1d2 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -38,10 +38,10 @@ HEADERS += \
text/qtextodfwriter_p.h \
text/qstatictext_p.h \
text/qstatictext.h \
- text/qglyphs.h \
- text/qglyphs_p.h \
text/qrawfont.h \
- text/qrawfont_p.h
+ text/qrawfont_p.h \
+ text/qglyphrun.h \
+ text/qglyphrun_p.h
SOURCES += \
text/qfont.cpp \
@@ -71,8 +71,8 @@ SOURCES += \
text/qzip.cpp \
text/qtextodfwriter.cpp \
text/qstatictext.cpp \
- text/qglyphs.cpp \
- text/qrawfont.cpp
+ text/qrawfont.cpp \
+ text/qglyphrun.cpp
win32 {
SOURCES += \
diff --git a/src/network/access/access.pri b/src/network/access/access.pri
index 5ead3ad37f..0f901b873d 100644
--- a/src/network/access/access.pri
+++ b/src/network/access/access.pri
@@ -14,7 +14,6 @@ HEADERS += \
access/qnetworkaccesscache_p.h \
access/qnetworkaccessbackend_p.h \
access/qnetworkaccessdebugpipebackend_p.h \
- access/qnetworkaccesshttpbackend_p.h \
access/qnetworkaccessfilebackend_p.h \
access/qnetworkaccesscachebackend_p.h \
access/qnetworkaccessftpbackend_p.h \
@@ -29,6 +28,7 @@ HEADERS += \
access/qnetworkreply_p.h \
access/qnetworkreplyimpl_p.h \
access/qnetworkreplydataimpl_p.h \
+ access/qnetworkreplyhttpimpl_p.h \
access/qnetworkreplyfileimpl_p.h \
access/qabstractnetworkcache_p.h \
access/qabstractnetworkcache.h \
@@ -54,13 +54,13 @@ SOURCES += \
access/qnetworkaccessfilebackend.cpp \
access/qnetworkaccesscachebackend.cpp \
access/qnetworkaccessftpbackend.cpp \
- access/qnetworkaccesshttpbackend.cpp \
access/qnetworkcookie.cpp \
access/qnetworkcookiejar.cpp \
access/qnetworkrequest.cpp \
access/qnetworkreply.cpp \
access/qnetworkreplyimpl.cpp \
access/qnetworkreplydataimpl.cpp \
+ access/qnetworkreplyhttpimpl.cpp \
access/qnetworkreplyfileimpl.cpp \
access/qabstractnetworkcache.cpp \
access/qnetworkdiskcache.cpp \
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 83156c6a35..a47155906f 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -117,7 +117,6 @@ QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
void QHttpNetworkConnectionPrivate::init()
{
- Q_Q(QHttpNetworkConnection);
for (int i = 0; i < channelCount; i++) {
channels[i].setConnection(this->q_func());
channels[i].ssl = encrypt;
@@ -520,6 +519,15 @@ bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket)
return false;
}
+QHttpNetworkRequest QHttpNetworkConnectionPrivate::predictNextRequest()
+{
+ if (!highPriorityQueue.isEmpty())
+ return highPriorityQueue.last().first;
+ if (!lowPriorityQueue.isEmpty())
+ return lowPriorityQueue.last().first;
+ return QHttpNetworkRequest();
+}
+
// this is called from _q_startNextRequest and when a request has been sent down a socket from the channel
void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket)
{
diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h
index adb779f473..329d3626fa 100644
--- a/src/network/access/qhttpnetworkconnection_p.h
+++ b/src/network/access/qhttpnetworkconnection_p.h
@@ -169,6 +169,7 @@ public:
void requeueRequest(const HttpMessagePair &pair); // e.g. after pipeline broke
bool dequeueRequest(QAbstractSocket *socket);
void prepareRequest(HttpMessagePair &request);
+ QHttpNetworkRequest predictNextRequest();
void fillPipeline(QAbstractSocket *socket);
bool fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel);
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 6fbc6f8056..f44010100f 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -579,6 +579,17 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
connectHost = connection->d_func()->networkProxy.hostName();
connectPort = connection->d_func()->networkProxy.port();
}
+ if (socket->proxy().type() == QNetworkProxy::HttpProxy) {
+ // Make user-agent field available to HTTP proxy socket engine (QTBUG-17223)
+ QByteArray value;
+ // ensureConnection is called before any request has been assigned, but can also be called again if reconnecting
+ if (request.url().isEmpty())
+ value = connection->d_func()->predictNextRequest().headerField("user-agent");
+ else
+ value = request.headerField("user-agent");
+ if (!value.isEmpty())
+ socket->setProperty("_q_user-agent", value);
+ }
#endif
if (ssl) {
#ifndef QT_NO_OPENSSL
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 6220abed02..a0042f436b 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -41,6 +41,7 @@
#include "qnetworkaccessbackend_p.h"
#include "qnetworkaccessmanager_p.h"
+#include "qnetworkconfigmanager.h"
#include "qnetworkrequest.h"
#include "qnetworkreply.h"
#include "qnetworkreply_p.h"
@@ -315,13 +316,13 @@ void QNetworkAccessBackend::error(QNetworkReply::NetworkError code, const QStrin
void QNetworkAccessBackend::proxyAuthenticationRequired(const QNetworkProxy &proxy,
QAuthenticator *authenticator)
{
- manager->proxyAuthenticationRequired(this, proxy, authenticator);
+ manager->proxyAuthenticationRequired(proxy, synchronous, authenticator, &reply->lastProxyAuthentication);
}
#endif
void QNetworkAccessBackend::authenticationRequired(QAuthenticator *authenticator)
{
- manager->authenticationRequired(this, authenticator);
+ manager->authenticationRequired(authenticator, reply->q_func(), synchronous, reply->url, &reply->urlForLastAuthentication);
}
void QNetworkAccessBackend::metaDataChanged()
@@ -343,8 +344,6 @@ void QNetworkAccessBackend::sslErrors(const QList<QSslError> &errors)
#endif
}
-#ifndef QT_NO_BEARERMANAGEMENT
-
/*!
Starts the backend. Returns true if the backend is started. Returns false if the backend
could not be started due to an unopened or roaming session. The caller should recall this
@@ -352,31 +351,62 @@ void QNetworkAccessBackend::sslErrors(const QList<QSslError> &errors)
*/
bool QNetworkAccessBackend::start()
{
- if (!manager->networkSession) {
- open();
- return true;
- }
-
- // This is not ideal.
- const QString host = reply->url.host();
- if (host == QLatin1String("localhost") ||
- QHostAddress(host) == QHostAddress::LocalHost ||
- QHostAddress(host) == QHostAddress::LocalHostIPv6) {
- // Don't need an open session for localhost access.
- open();
- return true;
+#ifndef QT_NO_BEARERMANAGEMENT
+ // For bearer, check if session start is required
+ if (manager->networkSession) {
+ // session required
+ if (manager->networkSession->isOpen() &&
+ manager->networkSession->state() == QNetworkSession::Connected) {
+ // Session is already open and ready to use.
+ // copy network session down to the backend
+ setProperty("_q_networksession", QVariant::fromValue(manager->networkSession));
+ } else {
+ // Session not ready, but can skip for loopback connections
+
+ // This is not ideal.
+ const QString host = reply->url.host();
+
+ if (host == QLatin1String("localhost") ||
+ QHostAddress(host) == QHostAddress::LocalHost ||
+ QHostAddress(host) == QHostAddress::LocalHostIPv6) {
+ // Don't need an open session for localhost access.
+ } else {
+ // need to wait for session to be opened
+ return false;
+ }
+ }
}
+#endif
- if (manager->networkSession->isOpen() &&
- manager->networkSession->state() == QNetworkSession::Connected) {
- //copy network session down to the backend
- setProperty("_q_networksession", QVariant::fromValue(manager->networkSession));
- open();
- return true;
+#ifndef QT_NO_NETWORKPROXY
+#ifndef QT_NO_BEARERMANAGEMENT
+ // Get the proxy settings from the network session (in the case of service networks,
+ // the proxy settings change depending which AP was activated)
+ QNetworkSession *session = manager->networkSession.data();
+ QNetworkConfiguration config;
+ if (session) {
+ QNetworkConfigurationManager configManager;
+ // The active configuration tells us what IAP is in use
+ QVariant v = session->sessionProperty(QLatin1String("ActiveConfiguration"));
+ if (v.isValid())
+ config = configManager.configurationFromIdentifier(qvariant_cast<QString>(v));
+ // Fallback to using the configuration if no active configuration
+ if (!config.isValid())
+ config = session->configuration();
+ // or unspecified configuration if that is no good either
+ if (!config.isValid())
+ config = QNetworkConfiguration();
}
+ reply->proxyList = manager->queryProxy(QNetworkProxyQuery(config, url()));
+#else // QT_NO_BEARERMANAGEMENT
+ // Without bearer management, the proxy depends only on the url
+ reply->proxyList = manager->queryProxy(QNetworkProxyQuery(url()));
+#endif
+#endif
- return false;
+ // now start the request
+ open();
+ return true;
}
-#endif
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkaccesscachebackend.cpp b/src/network/access/qnetworkaccesscachebackend.cpp
index 13f4cd9cbb..c585848c98 100644
--- a/src/network/access/qnetworkaccesscachebackend.cpp
+++ b/src/network/access/qnetworkaccesscachebackend.cpp
@@ -66,6 +66,7 @@ void QNetworkAccessCacheBackend::open()
QString msg = QCoreApplication::translate("QNetworkAccessCacheBackend", "Error opening %1")
.arg(this->url().toString());
error(QNetworkReply::ContentNotFoundError, msg);
+ } else {
setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true);
}
finished();
@@ -85,14 +86,18 @@ bool QNetworkAccessCacheBackend::sendCacheContents()
QNetworkCacheMetaData::AttributesMap attributes = item.attributes();
setAttribute(QNetworkRequest::HttpStatusCodeAttribute, attributes.value(QNetworkRequest::HttpStatusCodeAttribute));
setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute));
- setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true);
// set the raw headers
QNetworkCacheMetaData::RawHeaderList rawHeaders = item.rawHeaders();
QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(),
end = rawHeaders.constEnd();
- for ( ; it != end; ++it)
+ for ( ; it != end; ++it) {
+ if (it->first.toLower() == "cache-control" &&
+ it->second.toLower().contains("must-revalidate")) {
+ return false;
+ }
setRawHeader(it->first, it->second);
+ }
// handle a possible redirect
QVariant redirectionTarget = attributes.value(QNetworkRequest::RedirectionTargetAttribute);
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index c61911445b..a45c2de0b2 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -262,13 +262,11 @@ bool QNetworkAccessHttpBackend::loadFromCacheIfAllowed(QHttpNetworkRequest &http
if (lastModified.isValid())
httpRequest.setHeaderField("If-Modified-Since", QNetworkHeadersPrivate::toHttpDate(lastModified));
- if (CacheLoadControlAttribute == QNetworkRequest::PreferNetwork) {
- it = cacheHeaders.findRawHeader("Cache-Control");
- if (it != cacheHeaders.rawHeaders.constEnd()) {
- QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
- if (cacheControl.contains("must-revalidate"))
- return false;
- }
+ it = cacheHeaders.findRawHeader("Cache-Control");
+ if (it != cacheHeaders.rawHeaders.constEnd()) {
+ QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
+ if (cacheControl.contains("must-revalidate"))
+ return false;
}
QDateTime currentDateTime = QDateTime::currentDateTime();
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 5a7521e33e..dbaa2d1082 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -67,13 +67,12 @@
#include "QtNetwork/qhttpmultipart.h"
#include "qhttpmultipart_p.h"
+#include "qnetworkreplyhttpimpl_p.h"
+
#include "qthread.h"
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_HTTP
-Q_GLOBAL_STATIC(QNetworkAccessHttpBackendFactory, httpBackend)
-#endif // QT_NO_HTTP
Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend)
#ifndef QT_NO_FTP
Q_GLOBAL_STATIC(QNetworkAccessFtpBackendFactory, ftpBackend)
@@ -85,10 +84,6 @@ Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend)
static void ensureInitialized()
{
-#ifndef QT_NO_HTTP
- (void) httpBackend();
-#endif // QT_NO_HTTP
-
#ifndef QT_NO_FTP
(void) ftpBackend();
#endif
@@ -356,6 +351,17 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
ensureInitialized();
qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
+#ifndef QT_NO_NETWORKPROXY
+ qRegisterMetaType<QNetworkProxy>("QNetworkProxy");
+#endif
+#ifndef QT_NO_OPENSSL
+ qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
+ qRegisterMetaType<QSslConfiguration>("QSslConfiguration");
+#endif
+ qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >("QList<QPair<QByteArray,QByteArray> >");
+ qRegisterMetaType<QHttpNetworkRequest>("QHttpNetworkRequest");
+ qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
+ qRegisterMetaType<QSharedPointer<char> >("QSharedPointer<char>");
}
/*!
@@ -861,7 +867,7 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess
device will be uploaded to the server; in that case, data must be open for
reading and must remain valid until the finished() signal is emitted for this reply.
- \note This feature is currently available for HTTP only.
+ \note This feature is currently available for HTTP(S) only.
\sa get(), post(), put(), deleteResource()
*/
@@ -967,6 +973,18 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
}
}
+#ifndef QT_NO_HTTP
+ // Since Qt 5 we use the new QNetworkReplyHttpImpl
+ if (scheme == QLatin1String("http") || scheme == QLatin1String("https") ) {
+ QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
+#ifndef QT_NO_BEARERMANAGEMENT
+ connect(this, SIGNAL(networkSessionConnected()),
+ reply, SLOT(_q_networkSessionConnected()));
+#endif
+ return reply;
+ }
+#endif // QT_NO_HTTP
+
// first step: create the reply
QUrl url = request.url();
QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
@@ -986,10 +1004,6 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
// third step: find a backend
priv->backend = d->findBackend(op, request);
-#ifndef QT_NO_NETWORKPROXY
- QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url()));
- priv->proxyList = proxyList;
-#endif
if (priv->backend) {
priv->backend->setParent(reply);
priv->backend->reply = priv;
@@ -1055,42 +1069,43 @@ void QNetworkAccessManagerPrivate::createCookieJar() const
}
}
-void QNetworkAccessManagerPrivate::authenticationRequired(QNetworkAccessBackend *backend,
- QAuthenticator *authenticator)
+void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authenticator,
+ QNetworkReply *reply,
+ bool synchronous,
+ QUrl &url,
+ QUrl *urlForLastAuthentication)
{
Q_Q(QNetworkAccessManager);
- // FIXME: Add support for domains (i.e., the leading path)
- QUrl url = backend->reply->url;
-
// don't try the cache for the same URL twice in a row
// being called twice for the same URL means the authentication failed
// also called when last URL is empty, e.g. on first call
- if (backend->reply->urlForLastAuthentication.isEmpty()
- || url != backend->reply->urlForLastAuthentication) {
+ if (urlForLastAuthentication->isEmpty()
+ || url != *urlForLastAuthentication) {
QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
if (!cred.isNull()) {
authenticator->setUser(cred.user);
authenticator->setPassword(cred.password);
- backend->reply->urlForLastAuthentication = url;
+ *urlForLastAuthentication = url;
return;
}
}
// if we emit a signal here in synchronous mode, the user might spin
// an event loop, which might recurse and lead to problems
- if (backend->isSynchronous())
+ if (synchronous)
return;
- backend->reply->urlForLastAuthentication = url;
- emit q->authenticationRequired(backend->reply->q_func(), authenticator);
+ *urlForLastAuthentication = url;
+ emit q->authenticationRequired(reply, authenticator);
authenticationManager->cacheCredentials(url, authenticator);
}
#ifndef QT_NO_NETWORKPROXY
-void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(QNetworkAccessBackend *backend,
- const QNetworkProxy &proxy,
- QAuthenticator *authenticator)
+void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy,
+ bool synchronous,
+ QAuthenticator *authenticator,
+ QNetworkProxy *lastProxyAuthentication)
{
Q_Q(QNetworkAccessManager);
// ### FIXME Tracking of successful authentications
@@ -1100,7 +1115,7 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(QNetworkAccessBac
// proxyAuthenticationRequired gets emitted again
// possible solution: some tracking inside the authenticator
// or a new function proxyAuthenticationSucceeded(true|false)
- if (proxy != backend->reply->lastProxyAuthentication) {
+ if (proxy != *lastProxyAuthentication) {
QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
if (!cred.isNull()) {
authenticator->setUser(cred.user);
@@ -1111,10 +1126,10 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(QNetworkAccessBac
// if we emit a signal here in synchronous mode, the user might spin
// an event loop, which might recurse and lead to problems
- if (backend->isSynchronous())
+ if (synchronous)
return;
- backend->reply->lastProxyAuthentication = proxy;
+ *lastProxyAuthentication = proxy;
emit q->proxyAuthenticationRequired(proxy, authenticator);
authenticationManager->cacheProxyCredentials(proxy, authenticator);
}
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 47760b210b..b22be91a96 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -160,6 +160,7 @@ protected:
private:
friend class QNetworkReplyImplPrivate;
friend class QNetworkAccessHttpBackend;
+ friend class QNetworkReplyHttpImpl;
Q_DECLARE_PRIVATE(QNetworkAccessManager)
Q_PRIVATE_SLOT(d_func(), void _q_replyFinished())
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index f64cc4dc79..f5e13e3a09 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -94,14 +94,20 @@ public:
QNetworkReply *postProcess(QNetworkReply *reply);
void createCookieJar() const;
- void authenticationRequired(QNetworkAccessBackend *backend, QAuthenticator *authenticator);
+ void authenticationRequired(QAuthenticator *authenticator,
+ QNetworkReply *reply,
+ bool synchronous,
+ QUrl &url,
+ QUrl *urlForLastAuthentication);
void cacheCredentials(const QUrl &url, const QAuthenticator *auth);
QNetworkAuthenticationCredential *fetchCachedCredentials(const QUrl &url,
const QAuthenticator *auth = 0);
#ifndef QT_NO_NETWORKPROXY
- void proxyAuthenticationRequired(QNetworkAccessBackend *backend, const QNetworkProxy &proxy,
- QAuthenticator *authenticator);
+ void proxyAuthenticationRequired(const QNetworkProxy &proxy,
+ bool synchronous,
+ QAuthenticator *authenticator,
+ QNetworkProxy *lastProxyAuthentication);
void cacheProxyCredentials(const QNetworkProxy &proxy, const QAuthenticator *auth);
QNetworkAuthenticationCredential *fetchCachedProxyCredentials(const QNetworkProxy &proxy,
const QAuthenticator *auth = 0);
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index 52eb3453b8..eec850797b 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -395,8 +395,8 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
// qdtext = <any TEXT except <">>
// quoted-pair = "\" CHAR
- // If its NAME=VALUE, retain the value as is
- // refer to ttp://bugreports.qt.nokia.com/browse/QTBUG-17746
+ // If it is NAME=VALUE, retain the value as is
+ // refer to http://bugreports.qt.nokia.com/browse/QTBUG-17746
if (isNameValue)
second += '"';
++i;
@@ -432,7 +432,9 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
position = i;
for ( ; i < length; ++i) {
register char c = text.at(i);
- if (c == ',' || c == ';' || isLWS(c))
+ // for name value pairs, we want to parse until reaching the next ';'
+ // and not break when reaching a space char
+ if (c == ',' || c == ';' || ((isNameValue && (c == '\n' || c == '\r')) || (!isNameValue && isLWS(c))))
break;
}
@@ -487,7 +489,6 @@ QByteArray QNetworkCookie::toRawForm(RawForm form) const
result += '=';
if ((d->value.contains(';') ||
d->value.contains(',') ||
- d->value.contains(' ') ||
d->value.contains('"')) &&
(!d->value.startsWith('"') &&
!d->value.endsWith('"'))) {
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
new file mode 100644
index 0000000000..cd6d8fb87e
--- /dev/null
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -0,0 +1,1983 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define QNETWORKACCESSHTTPBACKEND_DEBUG
+
+#include "qnetworkreplyhttpimpl_p.h"
+#include "qnetworkaccessmanager_p.h"
+#include "qnetworkaccesscache_p.h"
+#include "qabstractnetworkcache.h"
+#include "qnetworkrequest.h"
+#include "qnetworkreply.h"
+#include "qnetworkrequest_p.h"
+#include "qnetworkcookie_p.h"
+#include "QtCore/qdatetime.h"
+#include "QtCore/qelapsedtimer.h"
+#include "QtNetwork/qsslconfiguration.h"
+#include "qhttpthreaddelegate_p.h"
+#include "qthread.h"
+#include "QtCore/qcoreapplication.h"
+
+#include "qnetworkcookiejar.h"
+
+#ifndef QT_NO_HTTP
+
+#include <string.h> // for strchr
+
+Q_DECLARE_METATYPE(QSharedPointer<char>)
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkProxy;
+
+static inline bool isSeparator(register char c)
+{
+ static const char separators[] = "()<>@,;:\\\"/[]?={}";
+ return isLWS(c) || strchr(separators, c) != 0;
+}
+
+// ### merge with nextField in cookiejar.cpp
+static QHash<QByteArray, QByteArray> parseHttpOptionHeader(const QByteArray &header)
+{
+ // The HTTP header is of the form:
+ // header = #1(directives)
+ // directives = token | value-directive
+ // value-directive = token "=" (token | quoted-string)
+ QHash<QByteArray, QByteArray> result;
+
+ int pos = 0;
+ while (true) {
+ // skip spaces
+ pos = nextNonWhitespace(header, pos);
+ if (pos == header.length())
+ return result; // end of parsing
+
+ // pos points to a non-whitespace
+ int comma = header.indexOf(',', pos);
+ int equal = header.indexOf('=', pos);
+ if (comma == pos || equal == pos)
+ // huh? Broken header.
+ return result;
+
+ // The key name is delimited by either a comma, an equal sign or the end
+ // of the header, whichever comes first
+ int end = comma;
+ if (end == -1)
+ end = header.length();
+ if (equal != -1 && end > equal)
+ end = equal; // equal sign comes before comma/end
+ QByteArray key = QByteArray(header.constData() + pos, end - pos).trimmed().toLower();
+ pos = end + 1;
+
+ if (uint(equal) < uint(comma)) {
+ // case: token "=" (token | quoted-string)
+ // skip spaces
+ pos = nextNonWhitespace(header, pos);
+ if (pos == header.length())
+ // huh? Broken header
+ return result;
+
+ QByteArray value;
+ value.reserve(header.length() - pos);
+ if (header.at(pos) == '"') {
+ // case: quoted-string
+ // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
+ // qdtext = <any TEXT except <">>
+ // quoted-pair = "\" CHAR
+ ++pos;
+ while (pos < header.length()) {
+ register char c = header.at(pos);
+ if (c == '"') {
+ // end of quoted text
+ break;
+ } else if (c == '\\') {
+ ++pos;
+ if (pos >= header.length())
+ // broken header
+ return result;
+ c = header.at(pos);
+ }
+
+ value += c;
+ ++pos;
+ }
+ } else {
+ // case: token
+ while (pos < header.length()) {
+ register char c = header.at(pos);
+ if (isSeparator(c))
+ break;
+ value += c;
+ ++pos;
+ }
+ }
+
+ result.insert(key, value);
+
+ // find the comma now:
+ comma = header.indexOf(',', pos);
+ if (comma == -1)
+ return result; // end of parsing
+ pos = comma + 1;
+ } else {
+ // case: token
+ // key is already set
+ result.insert(key, QByteArray());
+ }
+ }
+}
+
+QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager* const manager,
+ const QNetworkRequest& request,
+ QNetworkAccessManager::Operation& operation,
+ QIODevice* outgoingData)
+ : QNetworkReply(*new QNetworkReplyHttpImplPrivate, manager)
+{
+ Q_D(QNetworkReplyHttpImpl);
+ d->manager = manager;
+ d->managerPrivate = manager->d_func();
+ d->request = request;
+ d->operation = operation;
+ d->outgoingData = outgoingData;
+ d->url = request.url();
+#ifndef QT_NO_OPENSSL
+ d->sslConfiguration = request.sslConfiguration();
+#endif
+
+ // FIXME Later maybe set to Unbuffered, especially if it is zerocopy or from cache?
+ QIODevice::open(QIODevice::ReadOnly);
+
+
+ // Internal code that does a HTTP reply for the synchronous Ajax
+ // in QtWebKit.
+ QVariant synchronousHttpAttribute = request.attribute(
+ static_cast<QNetworkRequest::Attribute>(QNetworkRequest::SynchronousRequestAttribute));
+ if (synchronousHttpAttribute.isValid()) {
+ d->synchronous = synchronousHttpAttribute.toBool();
+ if (d->synchronous && outgoingData) {
+ // The synchronous HTTP is a corner case, we will put all upload data in one big QByteArray in the outgoingDataBuffer.
+ // Yes, this is not the most efficient thing to do, but on the other hand synchronous XHR needs to die anyway.
+ d->outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+ qint64 previousDataSize = 0;
+ do {
+ previousDataSize = d->outgoingDataBuffer->size();
+ d->outgoingDataBuffer->append(d->outgoingData->readAll());
+ } while (d->outgoingDataBuffer->size() != previousDataSize);
+ d->_q_startOperation();
+ return;
+ }
+ }
+
+
+ if (outgoingData) {
+ // there is data to be uploaded, e.g. HTTP POST.
+
+ if (!d->outgoingData->isSequential()) {
+ // fixed size non-sequential (random-access)
+ // just start the operation
+ QMetaObject::invokeMethod(this, "_q_startOperation", Qt::QueuedConnection);
+ // FIXME make direct call?
+ } else {
+ bool bufferingDisallowed =
+ request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute,
+ false).toBool();
+
+ if (bufferingDisallowed) {
+ // if a valid content-length header for the request was supplied, we can disable buffering
+ // if not, we will buffer anyway
+ if (request.header(QNetworkRequest::ContentLengthHeader).isValid()) {
+ QMetaObject::invokeMethod(this, "_q_startOperation", Qt::QueuedConnection);
+ // FIXME make direct call?
+ } else {
+ d->state = d->Buffering;
+ QMetaObject::invokeMethod(this, "_q_bufferOutgoingData", Qt::QueuedConnection);
+ }
+ } else {
+ // _q_startOperation will be called when the buffering has finished.
+ d->state = d->Buffering;
+ QMetaObject::invokeMethod(this, "_q_bufferOutgoingData", Qt::QueuedConnection);
+ }
+ }
+ } else {
+ // No outgoing data (POST, ..)
+ d->_q_startOperation();
+ }
+}
+
+QNetworkReplyHttpImpl::~QNetworkReplyHttpImpl()
+{
+ // Most work is done in private destructor
+}
+
+void QNetworkReplyHttpImpl::close()
+{
+ Q_D(QNetworkReplyHttpImpl);
+
+ if (d->state == QNetworkReplyHttpImplPrivate::Aborted ||
+ d->state == QNetworkReplyHttpImplPrivate::Finished)
+ return;
+
+ // According to the documentation close only stops the download
+ // by closing we can ignore the download part and continue uploading.
+ QNetworkReply::close();
+
+ // call finished which will emit signals
+ // FIXME shouldn't this be emitted Queued?
+ d->error(OperationCanceledError, tr("Operation canceled"));
+ d->finished();
+}
+
+void QNetworkReplyHttpImpl::abort()
+{
+ Q_D(QNetworkReplyHttpImpl);
+ // FIXME
+ if (d->state == QNetworkReplyHttpImplPrivate::Finished || d->state == QNetworkReplyHttpImplPrivate::Aborted)
+ return;
+
+ QNetworkReply::close();
+
+ if (d->state != QNetworkReplyHttpImplPrivate::Finished) {
+ // call finished which will emit signals
+ // FIXME shouldn't this be emitted Queued?
+ d->error(OperationCanceledError, tr("Operation canceled"));
+ d->finished();
+ }
+
+ d->state = QNetworkReplyHttpImplPrivate::Aborted;
+
+ emit abortHttpRequest();
+}
+
+qint64 QNetworkReplyHttpImpl::bytesAvailable() const
+{
+ Q_D(const QNetworkReplyHttpImpl);
+
+ // if we load from cache device
+ if (d->cacheLoadDevice) {
+ return QNetworkReply::bytesAvailable() + d->cacheLoadDevice->bytesAvailable() + d->downloadMultiBuffer.byteAmount();
+ }
+
+ // zerocopy buffer
+ if (d->downloadZerocopyBuffer) {
+ return QNetworkReply::bytesAvailable() + d->downloadBufferCurrentSize - d->downloadBufferReadPosition;
+ }
+
+ // normal buffer
+ return QNetworkReply::bytesAvailable() + d->downloadMultiBuffer.byteAmount();
+}
+
+bool QNetworkReplyHttpImpl::isSequential () const
+{
+ // FIXME In the cache of a cached load or the zero-copy buffer we could actually be non-sequential.
+ // FIXME however this requires us to implement stuff like seek() too.
+ return true;
+}
+
+qint64 QNetworkReplyHttpImpl::size() const
+{
+ // FIXME At some point, this could return a proper value, e.g. if we're non-sequential.
+ return QNetworkReply::size();
+}
+
+qint64 QNetworkReplyHttpImpl::readData(char* data, qint64 maxlen)
+{
+ Q_D(QNetworkReplyHttpImpl);
+
+ // cacheload device
+ if (d->cacheLoadDevice) {
+ // FIXME bytesdownloaded, position etc?
+
+ // There is something already in the buffer we buffered before because the user did not read()
+ // anything, so we read there first:
+ if (!d->downloadMultiBuffer.isEmpty()) {
+ return d->downloadMultiBuffer.read(data, maxlen);
+ }
+
+ qint64 ret = d->cacheLoadDevice->read(data, maxlen);
+ return ret;
+ }
+
+ // zerocopy buffer
+ if (d->downloadZerocopyBuffer) {
+ // FIXME bytesdownloaded, position etc?
+
+ qint64 howMuch = qMin(maxlen, (d->downloadBufferCurrentSize - d->downloadBufferReadPosition));
+ memcpy(data, d->downloadZerocopyBuffer + d->downloadBufferReadPosition, howMuch);
+ d->downloadBufferReadPosition += howMuch;
+ return howMuch;
+
+ }
+
+ // normal buffer
+ if (d->downloadMultiBuffer.isEmpty()) {
+ if (d->state == d->Finished || d->state == d->Aborted)
+ return -1;
+ return 0;
+ }
+
+ if (maxlen == 1) {
+ // optimization for getChar()
+ *data = d->downloadMultiBuffer.getChar();
+ return 1;
+ }
+
+ maxlen = qMin<qint64>(maxlen, d->downloadMultiBuffer.byteAmount());
+ return d->downloadMultiBuffer.read(data, maxlen);
+}
+
+void QNetworkReplyHttpImpl::setReadBufferSize(qint64 size)
+{
+ // FIXME, unsupported right now
+ return;
+}
+
+bool QNetworkReplyHttpImpl::canReadLine () const
+{
+ Q_D(const QNetworkReplyHttpImpl);
+
+ if (QNetworkReply::canReadLine())
+ return true;
+
+ if (d->cacheLoadDevice)
+ return d->cacheLoadDevice->canReadLine() || d->downloadMultiBuffer.canReadLine();
+
+ // FIXME zerocopy buffer?
+
+ return d->downloadMultiBuffer.canReadLine();
+}
+
+#ifndef QT_NO_OPENSSL
+void QNetworkReplyHttpImpl::ignoreSslErrors()
+{
+ Q_D(QNetworkReplyHttpImpl);
+
+ d->pendingIgnoreAllSslErrors = true;
+}
+
+void QNetworkReplyHttpImpl::ignoreSslErrorsImplementation(const QList<QSslError> &errors)
+{
+ Q_D(QNetworkReplyHttpImpl);
+
+ // the pending list is set if QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
+ // is called before QNetworkAccessManager::get() (or post(), etc.)
+ d->pendingIgnoreSslErrorsList = errors;
+}
+
+void QNetworkReplyHttpImpl::setSslConfigurationImplementation(const QSslConfiguration &newconfig)
+{
+ // Setting a SSL configuration on a reply is not supported. The user needs to set
+ // her/his QSslConfiguration on the QNetworkRequest.
+ Q_UNUSED(newconfig);
+}
+
+QSslConfiguration QNetworkReplyHttpImpl::sslConfigurationImplementation() const
+{
+ Q_D(const QNetworkReplyHttpImpl);
+ return d->sslConfiguration;
+}
+#endif
+
+QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
+ : QNetworkReplyPrivate()
+ , manager(0)
+ , managerPrivate(0)
+ , synchronous(false)
+ , state(Idle)
+ , statusCode(0)
+ , outgoingData(0)
+ , bytesUploaded(-1)
+ , cacheLoadDevice(0)
+ , loadingFromCache(false)
+ , cacheSaveDevice(0)
+ , cacheEnabled(false)
+ , resumeOffset(0)
+ , preMigrationDownloaded(-1)
+ , bytesDownloaded(0)
+ , lastBytesDownloaded(-1)
+ , downloadBufferReadPosition(0)
+ , downloadBufferCurrentSize(0)
+ , downloadBufferMaximumSize(0)
+ , downloadZerocopyBuffer(0)
+ , pendingDownloadDataEmissions(new QAtomicInt())
+ , pendingDownloadProgressEmissions(new QAtomicInt())
+ #ifndef QT_NO_OPENSSL
+ , pendingIgnoreAllSslErrors(false)
+ #endif
+
+{
+}
+
+QNetworkReplyHttpImplPrivate::~QNetworkReplyHttpImplPrivate()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+ // This will do nothing if the request was already finished or aborted
+ emit q->abortHttpRequest();
+}
+
+/*
+ For a given httpRequest
+ 1) If AlwaysNetwork, return
+ 2) If we have a cache entry for this url populate headers so the server can return 304
+ 3) Calculate if response_is_fresh and if so send the cache and set loadedFromCache to true
+ */
+bool QNetworkReplyHttpImplPrivate::loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest)
+{
+ QNetworkRequest::CacheLoadControl CacheLoadControlAttribute =
+ (QNetworkRequest::CacheLoadControl)request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt();
+ if (CacheLoadControlAttribute == QNetworkRequest::AlwaysNetwork) {
+ // If the request does not already specify preferred cache-control
+ // force reload from the network and tell any caching proxy servers to reload too
+ if (!request.rawHeaderList().contains("Cache-Control")) {
+ httpRequest.setHeaderField("Cache-Control", "no-cache");
+ httpRequest.setHeaderField("Pragma", "no-cache");
+ }
+ return false;
+ }
+
+ // The disk cache API does not currently support partial content retrieval.
+ // That is why we don't use the disk cache for any such requests.
+ if (request.hasRawHeader("Range"))
+ return false;
+
+ QAbstractNetworkCache *nc = managerPrivate->networkCache;
+ if (!nc)
+ return false; // no local cache
+
+ QNetworkCacheMetaData metaData = nc->metaData(request.url());
+ if (!metaData.isValid())
+ return false; // not in cache
+
+ if (!metaData.saveToDisk())
+ return false;
+
+ QNetworkHeadersPrivate cacheHeaders;
+ QNetworkHeadersPrivate::RawHeadersList::ConstIterator it;
+ cacheHeaders.setAllRawHeaders(metaData.rawHeaders());
+
+ it = cacheHeaders.findRawHeader("etag");
+ if (it != cacheHeaders.rawHeaders.constEnd())
+ httpRequest.setHeaderField("If-None-Match", it->second);
+
+ QDateTime lastModified = metaData.lastModified();
+ if (lastModified.isValid())
+ httpRequest.setHeaderField("If-Modified-Since", QNetworkHeadersPrivate::toHttpDate(lastModified));
+
+ it = cacheHeaders.findRawHeader("Cache-Control");
+ if (it != cacheHeaders.rawHeaders.constEnd()) {
+ QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
+ if (cacheControl.contains("must-revalidate"))
+ return false;
+ }
+
+ QDateTime currentDateTime = QDateTime::currentDateTime();
+ QDateTime expirationDate = metaData.expirationDate();
+
+#if 0
+ /*
+ * age_value
+ * is the value of Age: header received by the cache with
+ * this response.
+ * date_value
+ * is the value of the origin server's Date: header
+ * request_time
+ * is the (local) time when the cache made the request
+ * that resulted in this cached response
+ * response_time
+ * is the (local) time when the cache received the
+ * response
+ * now
+ * is the current (local) time
+ */
+ int age_value = 0;
+ it = cacheHeaders.findRawHeader("age");
+ if (it != cacheHeaders.rawHeaders.constEnd())
+ age_value = it->second.toInt();
+
+ QDateTime dateHeader;
+ int date_value = 0;
+ it = cacheHeaders.findRawHeader("date");
+ if (it != cacheHeaders.rawHeaders.constEnd()) {
+ dateHeader = QNetworkHeadersPrivate::fromHttpDate(it->second);
+ date_value = dateHeader.toTime_t();
+ }
+
+ int now = currentDateTime.toUTC().toTime_t();
+ int request_time = now;
+ int response_time = now;
+
+ // Algorithm from RFC 2616 section 13.2.3
+ int apparent_age = qMax(0, response_time - date_value);
+ int corrected_received_age = qMax(apparent_age, age_value);
+ int response_delay = response_time - request_time;
+ int corrected_initial_age = corrected_received_age + response_delay;
+ int resident_time = now - response_time;
+ int current_age = corrected_initial_age + resident_time;
+
+ // RFC 2616 13.2.4 Expiration Calculations
+ if (!expirationDate.isValid()) {
+ if (lastModified.isValid()) {
+ int diff = currentDateTime.secsTo(lastModified);
+ expirationDate = lastModified;
+ expirationDate.addSecs(diff / 10);
+ if (httpRequest.headerField("Warning").isEmpty()) {
+ QDateTime dt;
+ dt.setTime_t(current_age);
+ if (dt.daysTo(currentDateTime) > 1)
+ httpRequest.setHeaderField("Warning", "113");
+ }
+ }
+ }
+
+ // the cache-saving code below sets the expirationDate with date+max_age
+ // if "max-age" is present, or to Expires otherwise
+ int freshness_lifetime = dateHeader.secsTo(expirationDate);
+ bool response_is_fresh = (freshness_lifetime > current_age);
+#else
+ bool response_is_fresh = currentDateTime.secsTo(expirationDate) >= 0;
+#endif
+
+ if (!response_is_fresh)
+ return false;
+
+#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
+ qDebug() << "response_is_fresh" << CacheLoadControlAttribute;
+#endif
+ return sendCacheContents(metaData);
+}
+
+QHttpNetworkRequest::Priority QNetworkReplyHttpImplPrivate::convert(const QNetworkRequest::Priority& prio)
+{
+ switch (prio) {
+ case QNetworkRequest::LowPriority:
+ return QHttpNetworkRequest::LowPriority;
+ case QNetworkRequest::HighPriority:
+ return QHttpNetworkRequest::HighPriority;
+ case QNetworkRequest::NormalPriority:
+ default:
+ return QHttpNetworkRequest::NormalPriority;
+ }
+}
+
+void QNetworkReplyHttpImplPrivate::postRequest()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ QThread *thread = 0;
+ if (synchronous) {
+ // A synchronous HTTP request uses its own thread
+ thread = new QThread();
+ QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
+ thread->start();
+ } else if (!managerPrivate->httpThread) {
+ // We use the manager-global thread.
+ // At some point we could switch to having multiple threads if it makes sense.
+ managerPrivate->httpThread = new QThread();
+ QObject::connect(managerPrivate->httpThread, SIGNAL(finished()), managerPrivate->httpThread, SLOT(deleteLater()));
+ managerPrivate->httpThread->start();
+
+ thread = managerPrivate->httpThread;
+ } else {
+ // Asynchronous request, thread already exists
+ thread = managerPrivate->httpThread;
+ }
+
+ QUrl url = request.url();
+ httpRequest.setUrl(url);
+
+ bool ssl = url.scheme().toLower() == QLatin1String("https");
+ q->setAttribute(QNetworkRequest::ConnectionEncryptedAttribute, ssl);
+ httpRequest.setSsl(ssl);
+
+
+#ifndef QT_NO_NETWORKPROXY
+ QNetworkProxy transparentProxy, cacheProxy;
+
+ // FIXME the proxy stuff should be done in the HTTP thread
+ foreach (const QNetworkProxy &p, managerPrivate->queryProxy(QNetworkProxyQuery(request.url()))) {
+ //foreach (const QNetworkProxy &p, proxyList()) {
+ // use the first proxy that works
+ // for non-encrypted connections, any transparent or HTTP proxy
+ // for encrypted, only transparent proxies
+ if (!ssl
+ && (p.capabilities() & QNetworkProxy::CachingCapability)
+ && (p.type() == QNetworkProxy::HttpProxy ||
+ p.type() == QNetworkProxy::HttpCachingProxy)) {
+ cacheProxy = p;
+ transparentProxy = QNetworkProxy::NoProxy;
+ break;
+ }
+ if (p.isTransparentProxy()) {
+ transparentProxy = p;
+ cacheProxy = QNetworkProxy::NoProxy;
+ break;
+ }
+ }
+
+ // check if at least one of the proxies
+ if (transparentProxy.type() == QNetworkProxy::DefaultProxy &&
+ cacheProxy.type() == QNetworkProxy::DefaultProxy) {
+ // unsuitable proxies
+ QMetaObject::invokeMethod(q, "_q_error", synchronous ? Qt::DirectConnection : Qt::QueuedConnection,
+ Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProxyNotFoundError),
+ Q_ARG(QString, q->tr("No suitable proxy found")));
+ QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection);
+ return;
+ }
+#endif
+
+
+ bool loadedFromCache = false;
+ httpRequest.setPriority(convert(request.priority()));
+
+ switch (operation) {
+ case QNetworkAccessManager::GetOperation:
+ httpRequest.setOperation(QHttpNetworkRequest::Get);
+ loadedFromCache = loadFromCacheIfAllowed(httpRequest);
+ break;
+
+ case QNetworkAccessManager::HeadOperation:
+ httpRequest.setOperation(QHttpNetworkRequest::Head);
+ loadedFromCache = loadFromCacheIfAllowed(httpRequest);
+ break;
+
+ case QNetworkAccessManager::PostOperation:
+ invalidateCache();
+ httpRequest.setOperation(QHttpNetworkRequest::Post);
+ createUploadByteDevice();
+ break;
+
+ case QNetworkAccessManager::PutOperation:
+ invalidateCache();
+ httpRequest.setOperation(QHttpNetworkRequest::Put);
+ createUploadByteDevice();
+ break;
+
+ case QNetworkAccessManager::DeleteOperation:
+ invalidateCache();
+ httpRequest.setOperation(QHttpNetworkRequest::Delete);
+ break;
+
+ case QNetworkAccessManager::CustomOperation:
+ invalidateCache(); // for safety reasons, we don't know what the operation does
+ httpRequest.setOperation(QHttpNetworkRequest::Custom);
+ createUploadByteDevice();
+ httpRequest.setCustomVerb(request.attribute(
+ QNetworkRequest::CustomVerbAttribute).toByteArray());
+ break;
+
+ default:
+ break; // can't happen
+ }
+
+ if (loadedFromCache) {
+ return; // no need to send the request! :)
+ }
+
+ QList<QByteArray> headers = request.rawHeaderList();
+ if (resumeOffset != 0) {
+ if (headers.contains("Range")) {
+ // Need to adjust resume offset for user specified range
+
+ headers.removeOne("Range");
+
+ // We've already verified that requestRange starts with "bytes=", see canResume.
+ QByteArray requestRange = request.rawHeader("Range").mid(6);
+
+ int index = requestRange.indexOf('-');
+
+ quint64 requestStartOffset = requestRange.left(index).toULongLong();
+ quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong();
+
+ requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) +
+ '-' + QByteArray::number(requestEndOffset);
+
+ httpRequest.setHeaderField("Range", requestRange);
+ } else {
+ httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-');
+ }
+ }
+
+ foreach (const QByteArray &header, headers)
+ httpRequest.setHeaderField(header, request.rawHeader(header));
+
+ if (request.attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true)
+ httpRequest.setPipeliningAllowed(true);
+
+ if (static_cast<QNetworkRequest::LoadControl>
+ (request.attribute(QNetworkRequest::AuthenticationReuseAttribute,
+ QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Manual)
+ httpRequest.setWithCredentials(false);
+
+
+ // Create the HTTP thread delegate
+ QHttpThreadDelegate *delegate = new QHttpThreadDelegate;
+
+ // For the synchronous HTTP, this is the normal way the delegate gets deleted
+ // For the asynchronous HTTP this is a safety measure, the delegate deletes itself when HTTP is finished
+ QObject::connect(thread, SIGNAL(finished()), delegate, SLOT(deleteLater()));
+
+ // Set the properties it needs
+ delegate->httpRequest = httpRequest;
+#ifndef QT_NO_NETWORKPROXY
+ delegate->cacheProxy = cacheProxy;
+ delegate->transparentProxy = transparentProxy;
+#endif
+ delegate->ssl = ssl;
+#ifndef QT_NO_OPENSSL
+ if (ssl)
+ delegate->incomingSslConfiguration = request.sslConfiguration();
+#endif
+
+ // Do we use synchronous HTTP?
+ delegate->synchronous = synchronous;
+
+ // The authentication manager is used to avoid the BlockingQueuedConnection communication
+ // from HTTP thread to user thread in some cases.
+ delegate->authenticationManager = managerPrivate->authenticationManager;
+
+ if (!synchronous) {
+ // Tell our zerocopy policy to the delegate
+ delegate->downloadBufferMaximumSize =
+ request.attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute).toLongLong();
+
+ // These atomic integers are used for signal compression
+ delegate->pendingDownloadData = pendingDownloadDataEmissions;
+ delegate->pendingDownloadProgress = pendingDownloadProgressEmissions;
+
+ // Connect the signals of the delegate to us
+ QObject::connect(delegate, SIGNAL(downloadData(QByteArray)),
+ q, SLOT(replyDownloadData(QByteArray)),
+ Qt::QueuedConnection);
+ QObject::connect(delegate, SIGNAL(downloadFinished()),
+ q, SLOT(replyFinished()),
+ Qt::QueuedConnection);
+ QObject::connect(delegate, SIGNAL(downloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64)),
+ q, SLOT(replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64)),
+ Qt::QueuedConnection);
+ QObject::connect(delegate, SIGNAL(downloadProgress(qint64,qint64)),
+ q, SLOT(replyDownloadProgressSlot(qint64,qint64)),
+ Qt::QueuedConnection);
+ QObject::connect(delegate, SIGNAL(error(QNetworkReply::NetworkError,QString)),
+ q, SLOT(httpError(QNetworkReply::NetworkError, const QString)),
+ Qt::QueuedConnection);
+#ifndef QT_NO_OPENSSL
+ QObject::connect(delegate, SIGNAL(sslConfigurationChanged(QSslConfiguration)),
+ q, SLOT(replySslConfigurationChanged(QSslConfiguration)),
+ Qt::QueuedConnection);
+#endif
+ // Those need to report back, therefire BlockingQueuedConnection
+ QObject::connect(delegate, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
+ q, SLOT(httpAuthenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
+ Qt::BlockingQueuedConnection);
+#ifndef QT_NO_NETWORKPROXY
+ QObject::connect(delegate, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ q, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ Qt::BlockingQueuedConnection);
+#endif
+#ifndef QT_NO_OPENSSL
+ QObject::connect(delegate, SIGNAL(sslErrors(QList<QSslError>,bool*,QList<QSslError>*)),
+ q, SLOT(replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *)),
+ Qt::BlockingQueuedConnection);
+#endif
+ // This signal we will use to start the request.
+ QObject::connect(q, SIGNAL(startHttpRequest()), delegate, SLOT(startRequest()));
+ QObject::connect(q, SIGNAL(abortHttpRequest()), delegate, SLOT(abortRequest()));
+
+ if (uploadByteDevice) {
+ QNonContiguousByteDeviceThreadForwardImpl *forwardUploadDevice =
+ new QNonContiguousByteDeviceThreadForwardImpl(uploadByteDevice->atEnd(), uploadByteDevice->size());
+ if (uploadByteDevice->isResetDisabled())
+ forwardUploadDevice->disableReset();
+ forwardUploadDevice->setParent(delegate); // needed to make sure it is moved on moveToThread()
+ delegate->httpRequest.setUploadByteDevice(forwardUploadDevice);
+
+ // From main thread to user thread:
+ QObject::connect(q, SIGNAL(haveUploadData(QByteArray, bool, qint64)),
+ forwardUploadDevice, SLOT(haveDataSlot(QByteArray, bool, qint64)), Qt::QueuedConnection);
+ QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()),
+ forwardUploadDevice, SIGNAL(readyRead()),
+ Qt::QueuedConnection);
+
+ // From http thread to user thread:
+ QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)),
+ q, SLOT(wantUploadDataSlot(qint64)));
+ QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)),
+ q, SLOT(sentUploadDataSlot(qint64)));
+ QObject::connect(forwardUploadDevice, SIGNAL(resetData(bool*)),
+ q, SLOT(resetUploadDataSlot(bool*)),
+ Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued!
+ }
+ } else if (synchronous) {
+ QObject::connect(q, SIGNAL(startHttpRequestSynchronously()), delegate, SLOT(startRequestSynchronously()), Qt::BlockingQueuedConnection);
+
+ if (uploadByteDevice) {
+ // For the synchronous HTTP use case the use thread (this one here) is blocked
+ // so we cannot use the asynchronous upload architecture.
+ // We therefore won't use the QNonContiguousByteDeviceThreadForwardImpl but directly
+ // use the uploadByteDevice provided to us by the QNetworkReplyImpl.
+ // The code that is in start() makes sure it is safe to use from a thread
+ // since it only wraps a QRingBuffer
+ delegate->httpRequest.setUploadByteDevice(uploadByteDevice.data());
+ }
+ }
+
+
+ // Move the delegate to the http thread
+ delegate->moveToThread(thread);
+ // This call automatically moves the uploadDevice too for the asynchronous case.
+
+ // Send an signal to the delegate so it starts working in the other thread
+ if (synchronous) {
+ emit q->startHttpRequestSynchronously(); // This one is BlockingQueuedConnection, so it will return when all work is done
+
+ if (delegate->incomingErrorCode != QNetworkReply::NoError) {
+ replyDownloadMetaData
+ (delegate->incomingHeaders,
+ delegate->incomingStatusCode,
+ delegate->incomingReasonPhrase,
+ delegate->isPipeliningUsed,
+ QSharedPointer<char>(),
+ delegate->incomingContentLength);
+ httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail);
+ } else {
+ replyDownloadMetaData
+ (delegate->incomingHeaders,
+ delegate->incomingStatusCode,
+ delegate->incomingReasonPhrase,
+ delegate->isPipeliningUsed,
+ QSharedPointer<char>(),
+ delegate->incomingContentLength);
+ replyDownloadData(delegate->synchronousDownloadData);
+ }
+
+ // End the thread. It will delete itself from the finished() signal
+ thread->quit();
+
+ finished();
+ } else {
+ emit q->startHttpRequest(); // Signal to the HTTP thread and go back to user.
+ }
+}
+
+void QNetworkReplyHttpImplPrivate::invalidateCache()
+{
+ QAbstractNetworkCache *nc = managerPrivate->networkCache;
+ if (nc)
+ nc->remove(request.url());
+}
+
+void QNetworkReplyHttpImplPrivate::initCacheSaveDevice()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ // The disk cache does not support partial content, so don't even try to
+ // save any such content into the cache.
+ if (q->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 206) {
+ cacheEnabled = false;
+ return;
+ }
+
+ // save the meta data
+ QNetworkCacheMetaData metaData;
+ metaData.setUrl(url);
+ metaData = fetchCacheMetaData(metaData);
+
+ // save the redirect request also in the cache
+ QVariant redirectionTarget = q->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirectionTarget.isValid()) {
+ QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes();
+ attributes.insert(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget);
+ metaData.setAttributes(attributes);
+ }
+
+ cacheSaveDevice = managerPrivate->networkCache->prepare(metaData);
+
+ if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) {
+ if (cacheSaveDevice && !cacheSaveDevice->isOpen())
+ qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- "
+ "class %s probably needs to be fixed",
+ managerPrivate->networkCache->metaObject()->className());
+
+ managerPrivate->networkCache->remove(url);
+ cacheSaveDevice = 0;
+ cacheEnabled = false;
+ }
+}
+
+void QNetworkReplyHttpImplPrivate::replyDownloadData(QByteArray d)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ // If we're closed just ignore this data
+ if (!q->isOpen())
+ return;
+
+ int pendingSignals = (int)pendingDownloadDataEmissions->fetchAndAddAcquire(-1) - 1;
+
+ if (pendingSignals > 0) {
+ // Some more signal emissions to this slot are pending.
+ // Instead of writing the downstream data, we wait
+ // and do it in the next call we get
+ // (signal comppression)
+ pendingDownloadData.append(d);
+ return;
+ }
+
+ pendingDownloadData.append(d);
+ d.clear();
+ // We need to usa a copy for calling writeDownstreamData as we could
+ // possibly recurse into this this function when we call
+ // appendDownstreamDataSignalEmissions because the user might call
+ // processEvents() or spin an event loop when this occur.
+ QByteDataBuffer pendingDownloadDataCopy = pendingDownloadData;
+ pendingDownloadData.clear();
+
+ if (cacheEnabled && !cacheSaveDevice) {
+ initCacheSaveDevice();
+ }
+
+ qint64 bytesWritten = 0;
+ for (int i = 0; i < pendingDownloadDataCopy.bufferCount(); i++) {
+ QByteArray const &item = pendingDownloadDataCopy[i];
+
+ if (cacheSaveDevice)
+ cacheSaveDevice->write(item.constData(), item.size());
+ downloadMultiBuffer.append(item);
+
+ bytesWritten += item.size();
+ }
+ pendingDownloadDataCopy.clear();
+
+ bytesDownloaded += bytesWritten;
+ lastBytesDownloaded = bytesDownloaded;
+
+
+ QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
+ if (preMigrationDownloaded != Q_INT64_C(-1))
+ totalSize = totalSize.toLongLong() + preMigrationDownloaded;
+
+ emit q->readyRead();
+ // emit readyRead before downloadProgress incase this will cause events to be
+ // processed and we get into a recursive call (as in QProgressDialog).
+ emit q->downloadProgress(bytesDownloaded,
+ totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
+
+}
+
+void QNetworkReplyHttpImplPrivate::replyFinished()
+{
+ // We are already loading from cache, we still however
+ // got this signal because it was posted already
+ if (loadingFromCache)
+ return;
+
+ finished();
+}
+
+void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+ switch (statusCode) {
+ case 301: // Moved Permanently
+ case 302: // Found
+ case 303: // See Other
+ case 307: // Temporary Redirect
+ // What do we do about the caching of the HTML note?
+ // The response to a 303 MUST NOT be cached, while the response to
+ // all of the others is cacheable if the headers indicate it to be
+ QByteArray header = q->rawHeader("location");
+ QUrl url = QUrl::fromEncoded(header);
+ if (!url.isValid())
+ url = QUrl(QLatin1String(header));
+ // FIXME?
+ //redirectionRequested(url);
+ q->setAttribute(QNetworkRequest::RedirectionTargetAttribute, url);
+ }
+}
+
+void QNetworkReplyHttpImplPrivate::replyDownloadMetaData
+ (QList<QPair<QByteArray,QByteArray> > hm,
+ int sc,QString rp,bool pu,
+ QSharedPointer<char> db,
+ qint64 contentLength)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ statusCode = sc;
+ reasonPhrase = rp;
+
+ // Download buffer
+ if (!db.isNull()) {
+ //setDownloadBuffer(db, contentLength);
+ downloadBufferPointer = db;
+ downloadZerocopyBuffer = downloadBufferPointer.data();
+ downloadBufferCurrentSize = 0;
+ downloadBufferMaximumSize = contentLength;
+ q->setAttribute(QNetworkRequest::DownloadBufferAttribute, qVariantFromValue<QSharedPointer<char> > (downloadBufferPointer));
+ }
+
+ q->setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, pu);
+
+ // reconstruct the HTTP header
+ QList<QPair<QByteArray, QByteArray> > headerMap = hm;
+ QList<QPair<QByteArray, QByteArray> >::ConstIterator it = headerMap.constBegin(),
+ end = headerMap.constEnd();
+ QByteArray header;
+
+ for (; it != end; ++it) {
+ QByteArray value = q->rawHeader(it->first);
+ if (!value.isEmpty()) {
+ if (qstricmp(it->first.constData(), "set-cookie") == 0)
+ value += '\n';
+ else
+ value += ", ";
+ }
+ value += it->second;
+ q->setRawHeader(it->first, value);
+ }
+
+ q->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
+ q->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase);
+
+ // is it a redirection?
+ checkForRedirect(statusCode);
+
+ if (statusCode >= 500 && statusCode < 600) {
+ QAbstractNetworkCache *nc = managerPrivate->networkCache;
+ if (nc) {
+ QNetworkCacheMetaData metaData = nc->metaData(request.url());
+ QNetworkHeadersPrivate cacheHeaders;
+ cacheHeaders.setAllRawHeaders(metaData.rawHeaders());
+ QNetworkHeadersPrivate::RawHeadersList::ConstIterator it;
+ it = cacheHeaders.findRawHeader("Cache-Control");
+ bool mustReValidate = false;
+ if (it != cacheHeaders.rawHeaders.constEnd()) {
+ QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
+ if (cacheControl.contains("must-revalidate"))
+ mustReValidate = true;
+ }
+ if (!mustReValidate && sendCacheContents(metaData))
+ return;
+ }
+ }
+
+ if (statusCode == 304) {
+#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
+ qDebug() << "Received a 304 from" << url();
+#endif
+ QAbstractNetworkCache *nc = managerPrivate->networkCache;
+ if (nc) {
+ QNetworkCacheMetaData oldMetaData = nc->metaData(request.url());
+ QNetworkCacheMetaData metaData = fetchCacheMetaData(oldMetaData);
+ if (oldMetaData != metaData)
+ nc->updateMetaData(metaData);
+ if (sendCacheContents(metaData))
+ return;
+ }
+ }
+
+
+ if (statusCode != 304 && statusCode != 303) {
+ if (!isCachingEnabled())
+ setCachingEnabled(true);
+ }
+
+ metaDataChanged();
+}
+
+void QNetworkReplyHttpImplPrivate::replyDownloadProgressSlot(qint64 bytesReceived, qint64 bytesTotal)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ // If we're closed just ignore this data
+ if (!q->isOpen())
+ return;
+
+ // we can be sure here that there is a download buffer
+
+ int pendingSignals = (int)pendingDownloadProgressEmissions->fetchAndAddAcquire(-1) - 1;
+ if (pendingSignals > 0) {
+ // Let's ignore this signal and look at the next one coming in
+ // (signal comppression)
+ return;
+ }
+
+ if (!q->isOpen())
+ return;
+
+ if (cacheEnabled && bytesReceived == bytesTotal) {
+ // Write everything in one go if we use a download buffer. might be more performant.
+ initCacheSaveDevice();
+ // need to check again if cache enabled and device exists
+ if (cacheSaveDevice && cacheEnabled)
+ cacheSaveDevice->write(downloadZerocopyBuffer, bytesTotal);
+ // FIXME where is it closed?
+ }
+
+ bytesDownloaded = bytesReceived;
+ lastBytesDownloaded = bytesReceived;
+
+ downloadBufferCurrentSize = bytesReceived;
+
+ // Only emit readyRead when actual data is there
+ // emit readyRead before downloadProgress incase this will cause events to be
+ // processed and we get into a recursive call (as in QProgressDialog).
+ if (bytesDownloaded > 0)
+ emit q->readyRead();
+ emit q->downloadProgress(bytesDownloaded, bytesTotal);
+}
+
+void QNetworkReplyHttpImplPrivate::httpAuthenticationRequired(const QHttpNetworkRequest &,
+ QAuthenticator *auth)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+ managerPrivate->authenticationRequired(auth, q_func(), synchronous, url, &urlForLastAuthentication);
+}
+
+#ifndef QT_NO_NETWORKPROXY
+void QNetworkReplyHttpImplPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy,
+ QAuthenticator *authenticator)
+{
+ managerPrivate->proxyAuthenticationRequired(proxy, synchronous, authenticator, &lastProxyAuthentication);
+}
+#endif
+
+void QNetworkReplyHttpImplPrivate::httpError(QNetworkReply::NetworkError errorCode,
+ const QString &errorString)
+{
+#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
+ qDebug() << "http error!" << errorCode << errorString;
+#endif
+
+ // FIXME?
+ error(errorCode, errorString);
+}
+
+#ifndef QT_NO_OPENSSL
+void QNetworkReplyHttpImplPrivate::replySslErrors(
+ const QList<QSslError> &list, bool *ignoreAll, QList<QSslError> *toBeIgnored)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+ emit q->sslErrors(list);
+ // Check if the callback set any ignore and return this here to http thread
+ if (pendingIgnoreAllSslErrors)
+ *ignoreAll = true;
+ if (!pendingIgnoreSslErrorsList.isEmpty())
+ *toBeIgnored = pendingIgnoreSslErrorsList;
+}
+
+void QNetworkReplyHttpImplPrivate::replySslConfigurationChanged(const QSslConfiguration &sslConfiguration)
+{
+ // Receiving the used SSL configuration from the HTTP thread
+ this->sslConfiguration = sslConfiguration;
+}
+#endif
+
+// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
+void QNetworkReplyHttpImplPrivate::resetUploadDataSlot(bool *r)
+{
+ *r = uploadByteDevice->reset();
+}
+
+// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
+void QNetworkReplyHttpImplPrivate::sentUploadDataSlot(qint64 amount)
+{
+ uploadByteDevice->advanceReadPointer(amount);
+}
+
+// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
+void QNetworkReplyHttpImplPrivate::wantUploadDataSlot(qint64 maxSize)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ // call readPointer
+ qint64 currentUploadDataLength = 0;
+ char *data = const_cast<char*>(uploadByteDevice->readPointer(maxSize, currentUploadDataLength));
+ // Let's make a copy of this data
+ QByteArray dataArray(data, currentUploadDataLength);
+
+ // Communicate back to HTTP thread
+ emit q->haveUploadData(dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size());
+}
+
+/*
+ A simple web page that can be used to test us: http://www.procata.com/cachetest/
+ */
+bool QNetworkReplyHttpImplPrivate::sendCacheContents(const QNetworkCacheMetaData &metaData)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ setCachingEnabled(false);
+ if (!metaData.isValid())
+ return false;
+
+ QAbstractNetworkCache *nc = managerPrivate->networkCache;
+ Q_ASSERT(nc);
+ QIODevice *contents = nc->data(url);
+ if (!contents) {
+#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
+ qDebug() << "Can not send cache, the contents are 0" << url;
+#endif
+ return false;
+ }
+ contents->setParent(q);
+
+ QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes();
+ int status = attributes.value(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ if (status < 100)
+ status = 200; // fake it
+
+ q->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, status);
+ q->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute));
+ q->setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true);
+
+ QNetworkCacheMetaData::RawHeaderList rawHeaders = metaData.rawHeaders();
+ QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(),
+ end = rawHeaders.constEnd();
+ for ( ; it != end; ++it)
+ setRawHeader(it->first, it->second);
+
+ checkForRedirect(status);
+
+ cacheLoadDevice = contents;
+ q->connect(cacheLoadDevice, SIGNAL(readyRead()), SLOT(_q_cacheLoadReadyRead()));
+ q->connect(cacheLoadDevice, SIGNAL(readChannelFinished()), SLOT(_q_cacheLoadReadyRead()));
+
+ // This needs to be emitted in the event loop because it can be reached at
+ // the direct code path of qnam.get(...) before the user has a chance
+ // to connect any signals.
+ QMetaObject::invokeMethod(q, "metaDataChanged", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(q, "_q_cacheLoadReadyRead", Qt::QueuedConnection);
+
+
+#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
+ qDebug() << "Successfully sent cache:" << url << contents->size() << "bytes";
+#endif
+
+ // Set the following flag so we can ignore some signals from HTTP thread
+ // that would still come
+ loadingFromCache = true;
+ return true;
+}
+
+QNetworkCacheMetaData QNetworkReplyHttpImplPrivate::fetchCacheMetaData(const QNetworkCacheMetaData &oldMetaData) const
+{
+ Q_Q(const QNetworkReplyHttpImpl);
+
+ QNetworkCacheMetaData metaData = oldMetaData;
+
+ QNetworkHeadersPrivate cacheHeaders;
+ cacheHeaders.setAllRawHeaders(metaData.rawHeaders());
+ QNetworkHeadersPrivate::RawHeadersList::ConstIterator it;
+
+ QList<QByteArray> newHeaders = q->rawHeaderList();
+ foreach (QByteArray header, newHeaders) {
+ QByteArray originalHeader = header;
+ header = header.toLower();
+ bool hop_by_hop =
+ (header == "connection"
+ || header == "keep-alive"
+ || header == "proxy-authenticate"
+ || header == "proxy-authorization"
+ || header == "te"
+ || header == "trailers"
+ || header == "transfer-encoding"
+ || header == "upgrade");
+ if (hop_by_hop)
+ continue;
+
+ // for 4.6.0, we were planning to not store the date header in the
+ // cached resource; through that we planned to reduce the number
+ // of writes to disk when using a QNetworkDiskCache (i.e. don't
+ // write to disk when only the date changes).
+ // However, without the date we cannot calculate the age of the page
+ // anymore.
+ //if (header == "date")
+ //continue;
+
+ // Don't store Warning 1xx headers
+ if (header == "warning") {
+ QByteArray v = q->rawHeader(header);
+ if (v.length() == 3
+ && v[0] == '1'
+ && v[1] >= '0' && v[1] <= '9'
+ && v[2] >= '0' && v[2] <= '9')
+ continue;
+ }
+
+ it = cacheHeaders.findRawHeader(header);
+ if (it != cacheHeaders.rawHeaders.constEnd()) {
+ // Match the behavior of Firefox and assume Cache-Control: "no-transform"
+ if (header == "content-encoding"
+ || header == "content-range"
+ || header == "content-type")
+ continue;
+
+ // For MS servers that send "Content-Length: 0" on 304 responses
+ // ignore this too
+ if (header == "content-length")
+ continue;
+ }
+
+#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
+ QByteArray n = rawHeader(header);
+ QByteArray o;
+ if (it != cacheHeaders.rawHeaders.constEnd())
+ o = (*it).second;
+ if (n != o && header != "date") {
+ qDebug() << "replacing" << header;
+ qDebug() << "new" << n;
+ qDebug() << "old" << o;
+ }
+#endif
+ cacheHeaders.setRawHeader(originalHeader, q->rawHeader(header));
+ }
+ metaData.setRawHeaders(cacheHeaders.rawHeaders);
+
+ bool checkExpired = true;
+
+ QHash<QByteArray, QByteArray> cacheControl;
+ it = cacheHeaders.findRawHeader("Cache-Control");
+ if (it != cacheHeaders.rawHeaders.constEnd()) {
+ cacheControl = parseHttpOptionHeader(it->second);
+ QByteArray maxAge = cacheControl.value("max-age");
+ if (!maxAge.isEmpty()) {
+ checkExpired = false;
+ QDateTime dt = QDateTime::currentDateTime();
+ dt = dt.addSecs(maxAge.toInt());
+ metaData.setExpirationDate(dt);
+ }
+ }
+ if (checkExpired) {
+ it = cacheHeaders.findRawHeader("expires");
+ if (it != cacheHeaders.rawHeaders.constEnd()) {
+ QDateTime expiredDateTime = QNetworkHeadersPrivate::fromHttpDate(it->second);
+ metaData.setExpirationDate(expiredDateTime);
+ }
+ }
+
+ it = cacheHeaders.findRawHeader("last-modified");
+ if (it != cacheHeaders.rawHeaders.constEnd())
+ metaData.setLastModified(QNetworkHeadersPrivate::fromHttpDate(it->second));
+
+ bool canDiskCache;
+ // only cache GET replies by default, all other replies (POST, PUT, DELETE)
+ // are not cacheable by default (according to RFC 2616 section 9)
+ if (httpRequest.operation() == QHttpNetworkRequest::Get) {
+
+ canDiskCache = true;
+ // 14.32
+ // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client
+ // had sent "Cache-Control: no-cache".
+ it = cacheHeaders.findRawHeader("pragma");
+ if (it != cacheHeaders.rawHeaders.constEnd()
+ && it->second == "no-cache")
+ canDiskCache = false;
+
+ // HTTP/1.1. Check the Cache-Control header
+ if (cacheControl.contains("no-cache"))
+ canDiskCache = false;
+ else if (cacheControl.contains("no-store"))
+ canDiskCache = false;
+
+ // responses to POST might be cacheable
+ } else if (httpRequest.operation() == QHttpNetworkRequest::Post) {
+
+ canDiskCache = false;
+ // some pages contain "expires:" and "cache-control: no-cache" field,
+ // so we only might cache POST requests if we get "cache-control: max-age ..."
+ if (cacheControl.contains("max-age"))
+ canDiskCache = true;
+
+ // responses to PUT and DELETE are not cacheable
+ } else {
+ canDiskCache = false;
+ }
+
+ metaData.setSaveToDisk(canDiskCache);
+ QNetworkCacheMetaData::AttributesMap attributes;
+ if (statusCode != 304) {
+ // update the status code
+ attributes.insert(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
+ attributes.insert(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase);
+ } else {
+ // this is a redirection, keep the attributes intact
+ attributes = oldMetaData.attributes();
+ }
+ metaData.setAttributes(attributes);
+ return metaData;
+}
+
+bool QNetworkReplyHttpImplPrivate::canResume() const
+{
+ Q_Q(const QNetworkReplyHttpImpl);
+
+ // Only GET operation supports resuming.
+ if (operation != QNetworkAccessManager::GetOperation)
+ return false;
+
+ // Can only resume if server/resource supports Range header.
+ QByteArray acceptRangesheaderName("Accept-Ranges");
+ if (!q->hasRawHeader(acceptRangesheaderName) || q->rawHeader(acceptRangesheaderName) == "none")
+ return false;
+
+ // We only support resuming for byte ranges.
+ if (request.hasRawHeader("Range")) {
+ QByteArray range = request.rawHeader("Range");
+ if (!range.startsWith("bytes="))
+ return false;
+ }
+
+ // If we're using a download buffer then we don't support resuming/migration
+ // right now. Too much trouble.
+ if (downloadZerocopyBuffer)
+ return false;
+
+ return true;
+}
+
+void QNetworkReplyHttpImplPrivate::setResumeOffset(quint64 offset)
+{
+ resumeOffset = offset;
+}
+
+/*!
+ Starts the backend. Returns true if the backend is started. Returns false if the backend
+ could not be started due to an unopened or roaming session. The caller should recall this
+ function once the session has been opened or the roaming process has finished.
+*/
+bool QNetworkReplyHttpImplPrivate::start()
+{
+ if (!managerPrivate->networkSession) {
+ postRequest();
+ return true;
+ }
+
+ // This is not ideal.
+ const QString host = url.host();
+ if (host == QLatin1String("localhost") ||
+ QHostAddress(host) == QHostAddress::LocalHost ||
+ QHostAddress(host) == QHostAddress::LocalHostIPv6) {
+ // Don't need an open session for localhost access.
+ postRequest();
+ return true;
+ }
+
+ if (managerPrivate->networkSession->isOpen() &&
+ managerPrivate->networkSession->state() == QNetworkSession::Connected) {
+ postRequest();
+ return true;
+ }
+
+ return false;
+}
+
+void QNetworkReplyHttpImplPrivate::_q_startOperation()
+{
+ // ensure this function is only being called once
+ if (state == Working) {
+ qDebug("QNetworkReplyImpl::_q_startOperation was called more than once");
+ return;
+ }
+ state = Working;
+
+#ifndef QT_NO_BEARERMANAGEMENT
+ if (!start()) { // ### we should call that method even if bearer is not used
+ // backend failed to start because the session state is not Connected.
+ // QNetworkAccessManager will call reply->backend->start() again for us when the session
+ // state changes.
+ state = WaitingForSession;
+
+ QNetworkSession *session = managerPrivate->networkSession.data();
+
+ if (session) {
+ Q_Q(QNetworkReplyHttpImpl);
+
+ QObject::connect(session, SIGNAL(error(QNetworkSession::SessionError)),
+ q, SLOT(_q_networkSessionFailed()));
+
+ if (!session->isOpen())
+ session->open();
+ } else {
+ qWarning("Backend is waiting for QNetworkSession to connect, but there is none!");
+ }
+
+ return;
+ }
+#endif
+
+ if (synchronous) {
+ state = Finished;
+ q_func()->setFinished(true);
+ } else {
+ if (state != Finished) {
+// if (operation == QNetworkAccessManager::GetOperation)
+// pendingNotifications.append(NotifyDownstreamReadyWrite);
+
+// handleNotifications();
+
+ }
+ }
+}
+
+void QNetworkReplyHttpImplPrivate::_q_cacheLoadReadyRead()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ if (state != Working)
+ return;
+ if (!cacheLoadDevice || !q->isOpen() || !cacheLoadDevice->bytesAvailable())
+ return;
+
+ // FIXME Optimize to use zerocopy download buffer if it is a QBuffer.
+ // Needs to be done where sendCacheContents() (?) of HTTP is emitting
+ // metaDataChanged ?
+
+
+ // FIXME
+ lastBytesDownloaded = bytesDownloaded;
+ QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
+
+ //pauseNotificationHandling();
+ // emit readyRead before downloadProgress incase this will cause events to be
+ // processed and we get into a recursive call (as in QProgressDialog).
+
+ // This readyRead() goes to the user. The user then may or may not read() anything.
+ emit q->readyRead();
+ emit q->downloadProgress(bytesDownloaded,
+ totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
+
+ // If there are still bytes available in the cacheLoadDevice then the user did not read
+ // in response to the readyRead() signal. This means we have to load from the cacheLoadDevice
+ // and buffer that stuff. This is needed to be able to properly emit finished() later.
+ while (cacheLoadDevice->bytesAvailable()) {
+ downloadMultiBuffer.append(cacheLoadDevice->readAll());
+ }
+
+ if (cacheLoadDevice->isSequential()) {
+ // check if end and we can read the EOF -1
+ char c;
+ qint64 actualCount = cacheLoadDevice->read(&c, 1);
+ if (actualCount < 0) {
+ cacheLoadDevice->deleteLater();
+ cacheLoadDevice = 0;
+ QMetaObject::invokeMethod(q, "_q_finished", Qt::QueuedConnection);
+ } else if (actualCount == 1) {
+ // This is most probably not happening since most QIODevice returned something proper for bytesAvailable()
+ // and had already been "emptied".
+ cacheLoadDevice->ungetChar(c);
+ }
+ } else if ((!cacheLoadDevice->isSequential() && cacheLoadDevice->atEnd())) {
+ // This codepath is in case the cache device is a QBuffer, e.g. from QNetworkDiskCache.
+ cacheLoadDevice->deleteLater();
+ cacheLoadDevice = 0;
+ QMetaObject::invokeMethod(q, "_q_finished", Qt::QueuedConnection);
+ }
+
+}
+
+
+void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingDataFinished()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ // make sure this is only called once, ever.
+ //_q_bufferOutgoingData may call it or the readChannelFinished emission
+ if (state != Buffering)
+ return;
+
+ // disconnect signals
+ QObject::disconnect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
+ QObject::disconnect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
+
+ // finally, start the request
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+}
+
+void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ if (!outgoingDataBuffer) {
+ // first call, create our buffer
+ outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer());
+
+ QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
+ QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
+ }
+
+ qint64 bytesBuffered = 0;
+ qint64 bytesToBuffer = 0;
+
+ // read data into our buffer
+ forever {
+ bytesToBuffer = outgoingData->bytesAvailable();
+ // unknown? just try 2 kB, this also ensures we always try to read the EOF
+ if (bytesToBuffer <= 0)
+ bytesToBuffer = 2*1024;
+
+ char *dst = outgoingDataBuffer->reserve(bytesToBuffer);
+ bytesBuffered = outgoingData->read(dst, bytesToBuffer);
+
+ if (bytesBuffered == -1) {
+ // EOF has been reached.
+ outgoingDataBuffer->chop(bytesToBuffer);
+
+ _q_bufferOutgoingDataFinished();
+ break;
+ } else if (bytesBuffered == 0) {
+ // nothing read right now, just wait until we get called again
+ outgoingDataBuffer->chop(bytesToBuffer);
+
+ break;
+ } else {
+ // don't break, try to read() again
+ outgoingDataBuffer->chop(bytesToBuffer - bytesBuffered);
+ }
+ }
+}
+
+#ifndef QT_NO_BEARERMANAGEMENT
+void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ if (!manager)
+ return;
+
+ QNetworkSession *session = managerPrivate->networkSession.data();
+ if (!session)
+ return;
+
+ if (session->state() != QNetworkSession::Connected)
+ return;
+
+ switch (state) {
+ case QNetworkReplyImplPrivate::Buffering:
+ case QNetworkReplyImplPrivate::Working:
+ case QNetworkReplyImplPrivate::Reconnecting:
+ // Migrate existing downloads to new network connection.
+ migrateBackend();
+ break;
+ case QNetworkReplyImplPrivate::WaitingForSession:
+ // Start waiting requests.
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+ break;
+ default:
+ ;
+ }
+}
+
+void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed()
+{
+ // Abort waiting and working replies.
+ if (state == WaitingForSession || state == Working) {
+ state = Working;
+ error(QNetworkReplyImpl::UnknownNetworkError,
+ QCoreApplication::translate("QNetworkReply", "Network session error."));
+ finished();
+ }
+}
+#endif
+
+
+// need to have this function since the reply is a private member variable
+// and the special backends need to access this.
+void QNetworkReplyHttpImplPrivate::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+ if (isFinished)
+ return;
+ emit q->uploadProgress(bytesSent, bytesTotal);
+}
+
+QNonContiguousByteDevice* QNetworkReplyHttpImplPrivate::createUploadByteDevice()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ if (outgoingDataBuffer)
+ uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(outgoingDataBuffer));
+ else if (outgoingData) {
+ uploadByteDevice = QSharedPointer<QNonContiguousByteDevice>(QNonContiguousByteDeviceFactory::create(outgoingData));
+ } else {
+ return 0;
+ }
+
+ bool bufferDisallowed =
+ request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute,
+ QVariant(false)) == QVariant(true);
+ if (bufferDisallowed)
+ uploadByteDevice->disableReset();
+
+ // We want signal emissions only for normal asynchronous uploads
+ if (!synchronous)
+ QObject::connect(uploadByteDevice.data(), SIGNAL(readProgress(qint64,qint64)),
+ q, SLOT(emitReplyUploadProgress(qint64,qint64)));
+
+ return uploadByteDevice.data();
+}
+
+void QNetworkReplyHttpImplPrivate::_q_finished()
+{
+ // This gets called queued, just forward to real call then
+ finished();
+}
+
+void QNetworkReplyHttpImplPrivate::finished()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ if (state == Finished || state == Aborted || state == WaitingForSession)
+ return;
+
+ //pauseNotificationHandling();
+ QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
+ if (preMigrationDownloaded != Q_INT64_C(-1))
+ totalSize = totalSize.toLongLong() + preMigrationDownloaded;
+
+ // FIXME why should it be 0
+ if (manager) {
+#ifndef QT_NO_BEARERMANAGEMENT
+ QNetworkSession *session = managerPrivate->networkSession.data();
+ if (session && session->state() == QNetworkSession::Roaming &&
+ state == Working && errorCode != QNetworkReply::OperationCanceledError) {
+ // only content with a known size will fail with a temporary network failure error
+ if (!totalSize.isNull()) {
+ if (bytesDownloaded != totalSize) {
+ if (migrateBackend()) {
+ // either we are migrating or the request is finished/aborted
+ if (state == Reconnecting || state == WaitingForSession) {
+ //resumeNotificationHandling();
+ return; // exit early if we are migrating.
+ }
+ } else {
+ error(QNetworkReply::TemporaryNetworkFailureError,
+ QNetworkReply::tr("Temporary network failure."));
+ }
+ }
+ }
+ }
+#endif
+ }
+ //resumeNotificationHandling();
+
+ state = Finished;
+ q->setFinished(true);
+
+ //pendingNotifications.clear();
+
+ //pauseNotificationHandling();
+ if (totalSize.isNull() || totalSize == -1) {
+ emit q->downloadProgress(bytesDownloaded, bytesDownloaded);
+ }
+
+ if (bytesUploaded == -1 && (outgoingData || outgoingDataBuffer))
+ emit q->uploadProgress(0, 0);
+ //resumeNotificationHandling();
+
+ // if we don't know the total size of or we received everything save the cache
+ if (totalSize.isNull() || totalSize == -1 || bytesDownloaded == totalSize)
+ completeCacheSave();
+
+ // note: might not be a good idea, since users could decide to delete us
+ // which would delete the backend too...
+ // maybe we should protect the backend
+ //pauseNotificationHandling();
+ emit q->readChannelFinished();
+ emit q->finished();
+ //resumeNotificationHandling();
+}
+
+void QNetworkReplyHttpImplPrivate::_q_error(QNetworkReplyImpl::NetworkError code, const QString &errorMessage)
+{
+ this->error(code, errorMessage);
+}
+
+
+void QNetworkReplyHttpImplPrivate::error(QNetworkReplyImpl::NetworkError code, const QString &errorMessage)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+ // Can't set and emit multiple errors.
+ if (errorCode != QNetworkReply::NoError) {
+ qWarning() << "QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once.";
+ return;
+ }
+
+ errorCode = code;
+ q->setErrorString(errorMessage);
+
+ // note: might not be a good idea, since users could decide to delete us
+ // which would delete the backend too...
+ // maybe we should protect the backend
+ emit q->error(code);
+}
+
+void QNetworkReplyHttpImplPrivate::metaDataChanged()
+{
+ // FIXME merge this with replyDownloadMetaData(); ?
+
+ Q_Q(QNetworkReplyHttpImpl);
+ // 1. do we have cookies?
+ // 2. are we allowed to set them?
+ if (cookedHeaders.contains(QNetworkRequest::SetCookieHeader) && manager
+ && (static_cast<QNetworkRequest::LoadControl>
+ (request.attribute(QNetworkRequest::CookieSaveControlAttribute,
+ QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Automatic)) {
+ QList<QNetworkCookie> cookies =
+ qvariant_cast<QList<QNetworkCookie> >(cookedHeaders.value(QNetworkRequest::SetCookieHeader));
+ QNetworkCookieJar *jar = manager->cookieJar();
+ if (jar)
+ jar->setCookiesFromUrl(cookies, url);
+ }
+ emit q->metaDataChanged();
+}
+
+/*
+ Migrates the backend of the QNetworkReply to a new network connection if required. Returns
+ true if the reply is migrated or it is not required; otherwise returns false.
+*/
+bool QNetworkReplyHttpImplPrivate::migrateBackend()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
+ // Network reply is already finished or aborted, don't need to migrate.
+ if (state == Finished || state == Aborted)
+ return true;
+
+ // Backend does not support resuming download.
+ if (!canResume())
+ return false;
+
+ // Request has outgoing data, not migrating.
+ if (outgoingData)
+ return false;
+
+ // Request is serviced from the cache, don't need to migrate.
+ if (cacheLoadDevice)
+ return true;
+
+ state = Reconnecting;
+
+// if (backend) {
+// delete backend;
+// backend = 0;
+// }
+
+ cookedHeaders.clear();
+ rawHeaders.clear();
+
+ preMigrationDownloaded = bytesDownloaded;
+
+// backend = manager->d_func()->findBackend(operation, request);
+
+// if (backend) {
+// backend->setParent(q);
+// backend->reply = this;
+// backend->setResumeOffset(bytesDownloaded);
+// }
+
+ // FIXME
+ Q_ASSERT(0);
+ // What probably needs to be done is an abort and then re-send?
+
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+
+ return true;
+}
+
+
+void QNetworkReplyHttpImplPrivate::createCache()
+{
+ // check if we can save and if we're allowed to
+ if (!managerPrivate->networkCache
+ || !request.attribute(QNetworkRequest::CacheSaveControlAttribute, true).toBool()
+ || request.attribute(QNetworkRequest::CacheLoadControlAttribute,
+ QNetworkRequest::PreferNetwork).toInt()
+ == QNetworkRequest::AlwaysNetwork)
+ return;
+ cacheEnabled = true;
+}
+
+bool QNetworkReplyHttpImplPrivate::isCachingEnabled() const
+{
+ return (cacheEnabled && managerPrivate->networkCache != 0);
+}
+
+void QNetworkReplyHttpImplPrivate::setCachingEnabled(bool enable)
+{
+ if (!enable && !cacheEnabled)
+ return; // nothing to do
+ if (enable && cacheEnabled)
+ return; // nothing to do either!
+
+ if (enable) {
+ if (bytesDownloaded) {
+ qDebug() << "x" << bytesDownloaded;
+ // refuse to enable in this case
+ qCritical("QNetworkReplyImpl: backend error: caching was enabled after some bytes had been written");
+ return;
+ }
+
+ createCache();
+ } else {
+ // someone told us to turn on, then back off?
+ // ok... but you should make up your mind
+ qDebug("QNetworkReplyImpl: setCachingEnabled(true) called after setCachingEnabled(false)");
+ managerPrivate->networkCache->remove(url);
+ cacheSaveDevice = 0;
+ cacheEnabled = false;
+ }
+}
+
+void QNetworkReplyHttpImplPrivate::completeCacheSave()
+{
+ if (cacheEnabled && errorCode != QNetworkReplyImpl::NoError) {
+ managerPrivate->networkCache->remove(url);
+ } else if (cacheEnabled && cacheSaveDevice) {
+ managerPrivate->networkCache->insert(cacheSaveDevice);
+ }
+ cacheSaveDevice = 0;
+ cacheEnabled = false;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_HTTP
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
new file mode 100644
index 0000000000..0420ffd313
--- /dev/null
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork 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 QNETWORKREPLYHTTPIMPL_P_H
+#define QNETWORKREPLYHTTPIMPL_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 Network Access API. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qnetworkrequest.h"
+#include "qnetworkreply.h"
+
+#include "QtCore/qpointer.h"
+#include "QtCore/qdatetime.h"
+#include "QtCore/qsharedpointer.h"
+#include "qatomic.h"
+
+#include <QtNetwork/QNetworkCacheMetaData>
+#include <private/qhttpnetworkrequest_p.h>
+#include <private/qbytedata_p.h>
+#include <private/qnetworkreply_p.h>
+#include <QtNetwork/QNetworkProxy>
+
+#ifndef QT_NO_OPENSSL
+#include <QtNetwork/QSslConfiguration>
+#endif
+
+#ifndef QT_NO_HTTP
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+class QNetworkReplyHttpImplPrivate;
+class QNetworkReplyHttpImpl: public QNetworkReply
+{
+ Q_OBJECT
+public:
+ QNetworkReplyHttpImpl(QNetworkAccessManager* const, const QNetworkRequest&, QNetworkAccessManager::Operation&, QIODevice* outgoingData);
+ virtual ~QNetworkReplyHttpImpl();
+
+ void close();
+ void abort();
+ qint64 bytesAvailable() const;
+ bool isSequential () const;
+ qint64 size() const;
+ qint64 readData(char*, qint64);
+ void setReadBufferSize(qint64 size);
+ bool canReadLine () const;
+
+#ifndef QT_NO_OPENSSL
+ void ignoreSslErrors();
+ // ### Qt5 Add proper virtual
+ Q_INVOKABLE void ignoreSslErrorsImplementation(const QList<QSslError> &errors);
+ // ### Qt5 Add proper virtual
+ Q_INVOKABLE void setSslConfigurationImplementation(const QSslConfiguration &configuration);
+ // ### Qt5 Add proper virtual
+ Q_INVOKABLE QSslConfiguration sslConfigurationImplementation() const;
+#endif
+
+ Q_DECLARE_PRIVATE(QNetworkReplyHttpImpl)
+ Q_PRIVATE_SLOT(d_func(), void _q_startOperation())
+ Q_PRIVATE_SLOT(d_func(), void _q_cacheLoadReadyRead())
+ Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
+ Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
+#ifndef QT_NO_BEARERMANAGEMENT
+ Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
+ Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
+#endif
+ Q_PRIVATE_SLOT(d_func(), void _q_finished())
+ Q_PRIVATE_SLOT(d_func(), void _q_error(QNetworkReply::NetworkError, const QString &))
+
+ // From reply
+ Q_PRIVATE_SLOT(d_func(), void replyDownloadData(QByteArray))
+ Q_PRIVATE_SLOT(d_func(), void replyFinished())
+ Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64))
+ Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64))
+ Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *))
+ Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &))
+#ifndef QT_NO_OPENSSL
+ Q_PRIVATE_SLOT(d_func(), void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *))
+ Q_PRIVATE_SLOT(d_func(), void replySslConfigurationChanged(const QSslConfiguration&))
+#endif
+ Q_PRIVATE_SLOT(d_func(), void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth))
+
+ Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
+ Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
+ Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64))
+ Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
+
+
+
+signals:
+ // To HTTP thread:
+ void startHttpRequest();
+ void abortHttpRequest();
+
+ void startHttpRequestSynchronously();
+
+ void haveUploadData(QByteArray dataArray, bool dataAtEnd, qint64 dataSize);
+};
+
+class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
+{
+public:
+
+ static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio);
+
+ enum State {
+ Idle, // The reply is idle.
+ Buffering, // The reply is buffering outgoing data.
+ Working, // The reply is uploading/downloading data.
+ Finished, // The reply has finished.
+ Aborted, // The reply has been aborted.
+ WaitingForSession, // The reply is waiting for the session to open before connecting.
+ Reconnecting // The reply will reconnect to once roaming has completed.
+ };
+
+ QNetworkReplyHttpImplPrivate();
+ ~QNetworkReplyHttpImplPrivate();
+
+ bool start();
+ void _q_startOperation();
+
+ void _q_cacheLoadReadyRead();
+
+ void _q_bufferOutgoingData();
+ void _q_bufferOutgoingDataFinished();
+
+#ifndef QT_NO_BEARERMANAGEMENT
+ void _q_networkSessionConnected();
+ void _q_networkSessionFailed();
+#endif
+ void _q_finished();
+
+
+ // FIXME
+ void finished();
+ void error(QNetworkReply::NetworkError code, const QString &errorString);
+ void _q_error(QNetworkReply::NetworkError code, const QString &errorString);
+ void metaDataChanged();
+
+ void redirectionRequested(const QUrl &target);
+ void checkForRedirect(const int statusCode);
+
+
+ // incoming from user
+ QNetworkAccessManager *manager;
+ QNetworkAccessManagerPrivate *managerPrivate;
+ QNetworkRequest request;
+ QNetworkAccessManager::Operation operation; // FIXME already in replyprivate?
+ QHttpNetworkRequest httpRequest; // There is also a copy in the HTTP thread
+ bool synchronous;
+
+ State state;
+
+ // from http thread
+ int statusCode;
+ QString reasonPhrase;
+
+ // upload
+ QNonContiguousByteDevice* createUploadByteDevice();
+ QSharedPointer<QNonContiguousByteDevice> uploadByteDevice;
+ QIODevice *outgoingData;
+ QSharedPointer<QRingBuffer> outgoingDataBuffer;
+ void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal); // dup?
+ qint64 bytesUploaded;
+
+
+ // cache
+ void createCache();
+ void completeCacheSave();
+ void setCachingEnabled(bool enable);
+ bool isCachingEnabled() const;
+ void initCacheSaveDevice();
+ QAbstractNetworkCache *networkCache() const;
+ QIODevice *cacheLoadDevice;
+ bool loadingFromCache;
+
+ QIODevice *cacheSaveDevice;
+ bool cacheEnabled; // is this for saving?
+
+
+ QUrl urlForLastAuthentication;
+#ifndef QT_NO_NETWORKPROXY
+ QNetworkProxy lastProxyAuthentication;
+ QList<QNetworkProxy> proxyList;
+#endif
+
+
+ bool migrateBackend();
+ bool canResume() const;
+ void setResumeOffset(quint64 offset);
+ quint64 resumeOffset;
+ qint64 preMigrationDownloaded;
+
+ // Used for normal downloading. For "zero copy" the downloadZerocopyBuffer is used
+ QByteDataBuffer downloadMultiBuffer;
+ QByteDataBuffer pendingDownloadData; // For signal compression
+ qint64 bytesDownloaded;
+ qint64 lastBytesDownloaded;
+ void setDownloadBuffer(QSharedPointer<char> sp, qint64 size);
+ char* getDownloadBuffer(qint64 size);
+
+ // only used when the "zero copy" style is used. Else downloadMultiBuffer is used.
+ // Please note that the whole "zero copy" download buffer API is private right now. Do not use it.
+ qint64 downloadBufferReadPosition;
+ qint64 downloadBufferCurrentSize;
+ qint64 downloadBufferMaximumSize;
+ QSharedPointer<char> downloadBufferPointer;
+ char* downloadZerocopyBuffer;
+
+ // Will be increased by HTTP thread:
+ QSharedPointer<QAtomicInt> pendingDownloadDataEmissions;
+ QSharedPointer<QAtomicInt> pendingDownloadProgressEmissions;
+
+
+#ifndef QT_NO_OPENSSL
+ QSslConfiguration sslConfiguration;
+ bool pendingIgnoreAllSslErrors;
+ QList<QSslError> pendingIgnoreSslErrorsList;
+#endif
+
+
+ bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest);
+ void invalidateCache();
+ bool sendCacheContents(const QNetworkCacheMetaData &metaData);
+ QNetworkCacheMetaData fetchCacheMetaData(const QNetworkCacheMetaData &metaData) const;
+
+
+ void postRequest();
+
+
+
+public:
+ // From HTTP thread:
+ void replyDownloadData(QByteArray);
+ void replyFinished();
+ void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64);
+ void replyDownloadProgressSlot(qint64,qint64);
+ void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
+ void httpError(QNetworkReply::NetworkError error, const QString &errorString);
+#ifndef QT_NO_OPENSSL
+ void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *);
+ void replySslConfigurationChanged(const QSslConfiguration&);
+#endif
+#ifndef QT_NO_NETWORKPROXY
+ void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth);
+#endif
+
+ // From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
+ void resetUploadDataSlot(bool *r);
+ void wantUploadDataSlot(qint64);
+ void sentUploadDataSlot(qint64);
+
+ Q_DECLARE_PUBLIC(QNetworkReplyHttpImpl)
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_HTTP
+
+#endif
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 9eb505d1b7..e50f3d627d 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -47,7 +47,6 @@
#include "QtCore/qdatetime.h"
#include "QtNetwork/qsslconfiguration.h"
#include "QtNetwork/qnetworksession.h"
-#include "qnetworkaccesshttpbackend_p.h"
#include "qnetworkaccessmanager_p.h"
#include <QtCore/QCoreApplication>
@@ -90,10 +89,10 @@ void QNetworkReplyImplPrivate::_q_startOperation()
return;
}
+ if (!backend->start()) {
#ifndef QT_NO_BEARERMANAGEMENT
- if (!backend->start()) { // ### we should call that method even if bearer is not used
// backend failed to start because the session state is not Connected.
- // QNetworkAccessManager will call reply->backend->start() again for us when the session
+ // QNetworkAccessManager will call _q_startOperation again for us when the session
// state changes.
state = WaitingForSession;
@@ -109,11 +108,20 @@ void QNetworkReplyImplPrivate::_q_startOperation()
session->open();
} else {
qWarning("Backend is waiting for QNetworkSession to connect, but there is none!");
+ state = Working;
+ error(QNetworkReplyImpl::UnknownNetworkError,
+ QCoreApplication::translate("QNetworkReply", "Network session error."));
+ finished();
}
-
+#else
+ qWarning("Backend start failed");
+ state = Working;
+ error(QNetworkReplyImpl::UnknownNetworkError,
+ QCoreApplication::translate("QNetworkReply", "backend start error."));
+ finished();
+#endif
return;
}
-#endif
if (backend && backend->isSynchronous()) {
state = Finished;
@@ -356,7 +364,7 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const
// for HTTP, we want to send out the request as fast as possible to the network, without
// invoking methods in a QueuedConnection
#ifndef QT_NO_HTTP
- if (qobject_cast<QNetworkAccessHttpBackend *>(backend) || (backend && backend->isSynchronous())) {
+ if (backend && backend->isSynchronous()) {
_q_startOperation();
} else {
QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
@@ -1043,11 +1051,7 @@ bool QNetworkReplyImplPrivate::migrateBackend()
}
#ifndef QT_NO_HTTP
- if (qobject_cast<QNetworkAccessHttpBackend *>(backend)) {
- _q_startOperation();
- } else {
- QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
- }
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
#else
QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
#endif // QT_NO_HTTP
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 338969a909..a9a1e49572 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -247,10 +247,13 @@ QT_BEGIN_NAMESPACE
\value AlwaysNetwork always load from network and do not
check if the cache has a valid entry (similar to the
- "Reload" feature in browsers)
+ "Reload" feature in browsers); in addition, force intermediate
+ caches to re-validate.
\value PreferNetwork default value; load from the network
- if the cached entry is older than the network entry
+ if the cached entry is older than the network entry. This will never
+ return stale data from the cache, but revalidate resources that
+ have become stale.
\value PreferCache load from cache if available,
otherwise load from network. Note that this can return possibly
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index e9b6703dd9..a948d917c4 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -385,8 +385,6 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
this, SLOT(configurationRemoved(QNetworkConfigurationPrivatePointer)));
connect(engine, SIGNAL(configurationChanged(QNetworkConfigurationPrivatePointer)),
this, SLOT(configurationChanged(QNetworkConfigurationPrivatePointer)));
-
- QMetaObject::invokeMethod(engine, "initialize");
}
}
@@ -410,8 +408,19 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
startPolling();
}
- if (firstUpdate)
+ if (firstUpdate) {
firstUpdate = false;
+ QList<QBearerEngine*> enginesToInitialize = sessionEngines; //shallow copy the list in case it is modified when we unlock mutex
+ Qt::ConnectionType connectionType;
+ if (QCoreApplicationPrivate::mainThread() == QThread::currentThread())
+ connectionType = Qt::DirectConnection;
+ else
+ connectionType = Qt::BlockingQueuedConnection;
+ locker.unlock();
+ foreach (QBearerEngine* engine, enginesToInitialize) {
+ QMetaObject::invokeMethod(engine, "initialize", connectionType);
+ }
+ }
}
void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index a16d4ca451..c86f510914 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -288,7 +288,7 @@ QHostInfo QHostInfoPrivate::fromName(const QString &name, QSharedPointer<QNetwor
#ifndef Q_OS_SYMBIAN
// This function has a special implementation for symbian right now in qhostinfo_symbian.cpp but not on other OS.
-QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer<QNetworkSession> networkSession)
+QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer<QNetworkSession>)
{
return QHostInfoAgent::fromName(hostName);
}
diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp
index 68ff95543a..14db913495 100644
--- a/src/network/kernel/qnetworkproxy.cpp
+++ b/src/network/kernel/qnetworkproxy.cpp
@@ -228,6 +228,10 @@
#include "qmutex.h"
#include "qurl.h"
+#ifndef QT_NO_BEARERMANAGEMENT
+#include <QtNetwork/QNetworkConfiguration>
+#endif
+
QT_BEGIN_NAMESPACE
class QSocks5SocketEngineHandler;
@@ -716,6 +720,9 @@ public:
QUrl remote;
int localPort;
QNetworkProxyQuery::QueryType type;
+#ifndef QT_NO_BEARERMANAGEMENT
+ QNetworkConfiguration config;
+#endif
};
template<> void QSharedDataPointer<QNetworkProxyQueryPrivate>::detach()
@@ -777,6 +784,11 @@ template<> void QSharedDataPointer<QNetworkProxyQueryPrivate>::detach()
like choosing an caching HTTP proxy for HTTP-based connections,
but a more powerful SOCKSv5 proxy for all others.
+ The network configuration specifies which configuration to use,
+ when bearer management is used. For example on a mobile phone
+ the proxy settings are likely to be different for the cellular
+ network vs WLAN.
+
Some of the criteria may not make sense in all of the types of
query. The following table lists the criteria that are most
commonly used, according to the type of query.
@@ -902,6 +914,68 @@ QNetworkProxyQuery::QNetworkProxyQuery(quint16 bindPort, const QString &protocol
d->type = queryType;
}
+#ifndef QT_NO_BEARERMANAGEMENT
+/*!
+ Constructs a QNetworkProxyQuery with the URL \a requestUrl and
+ sets the query type to \a queryType. The specified \a networkConfiguration
+ is used to resolve the proxy settings.
+
+ \sa protocolTag(), peerHostName(), peerPort(), networkConfiguration()
+*/
+QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
+ const QUrl &requestUrl, QueryType queryType)
+{
+ d->config = networkConfiguration;
+ d->remote = requestUrl;
+ d->type = queryType;
+}
+
+/*!
+ Constructs a QNetworkProxyQuery of type \a queryType and sets the
+ protocol tag to be \a protocolTag. This constructor is suitable
+ for QNetworkProxyQuery::TcpSocket queries, because it sets the
+ peer hostname to \a hostname and the peer's port number to \a
+ port. The specified \a networkConfiguration
+ is used to resolve the proxy settings.
+
+ \sa networkConfiguration()
+*/
+QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
+ const QString &hostname, int port,
+ const QString &protocolTag,
+ QueryType queryType)
+{
+ d->config = networkConfiguration;
+ d->remote.setScheme(protocolTag);
+ d->remote.setHost(hostname);
+ d->remote.setPort(port);
+ d->type = queryType;
+}
+
+/*!
+ Constructs a QNetworkProxyQuery of type \a queryType and sets the
+ protocol tag to be \a protocolTag. This constructor is suitable
+ for QNetworkProxyQuery::TcpSocket queries because it sets the
+ local port number to \a bindPort. The specified \a networkConfiguration
+ is used to resolve the proxy settings.
+
+ Note that \a bindPort is of type quint16 to indicate the exact
+ port number that is requested. The value of -1 (unknown) is not
+ allowed in this context.
+
+ \sa localPort(), networkConfiguration()
+*/
+QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
+ quint16 bindPort, const QString &protocolTag,
+ QueryType queryType)
+{
+ d->config = networkConfiguration;
+ d->remote.setScheme(protocolTag);
+ d->localPort = bindPort;
+ d->type = queryType;
+}
+#endif
+
/*!
Constructs a QNetworkProxyQuery object that is a copy of \a other.
*/
@@ -1116,6 +1190,30 @@ void QNetworkProxyQuery::setUrl(const QUrl &url)
d->remote = url;
}
+#ifndef QT_NO_BEARERMANAGEMENT
+QNetworkConfiguration QNetworkProxyQuery::networkConfiguration() const
+{
+ return d ? d->config : QNetworkConfiguration();
+}
+
+/*!
+ Sets the network configuration component of this QNetworkProxyQuery
+ object to be \a networkConfiguration. The network configuration can
+ be used to return different proxy settings based on the network in
+ use, for example WLAN vs cellular networks on a mobile phone.
+
+ In the case of "user choice" or "service network" configurations,
+ you should first start the QNetworkSession and obtain the active
+ configuration from its properties.
+
+ \sa networkConfiguration
+*/
+void QNetworkProxyQuery::setNetworkConfiguration(const QNetworkConfiguration &networkConfiguration)
+{
+ d->config = networkConfiguration;
+}
+#endif
+
/*!
\class QNetworkProxyFactory
\brief The QNetworkProxyFactory class provides fine-grained proxy selection.
diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h
index 26562d533f..e16b29e93a 100644
--- a/src/network/kernel/qnetworkproxy.h
+++ b/src/network/kernel/qnetworkproxy.h
@@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Network)
class QUrl;
+class QNetworkConfiguration;
class QNetworkProxyQueryPrivate;
class Q_NETWORK_EXPORT QNetworkProxyQuery
@@ -73,6 +74,16 @@ public:
QNetworkProxyQuery(quint16 bindPort, const QString &protocolTag = QString(),
QueryType queryType = TcpServer);
QNetworkProxyQuery(const QNetworkProxyQuery &other);
+#ifndef QT_NO_BEARERMANAGEMENT
+ QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
+ const QUrl &requestUrl, QueryType queryType = UrlRequest);
+ QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
+ const QString &hostname, int port, const QString &protocolTag = QString(),
+ QueryType queryType = TcpSocket);
+ QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
+ quint16 bindPort, const QString &protocolTag = QString(),
+ QueryType queryType = TcpServer);
+#endif
~QNetworkProxyQuery();
QNetworkProxyQuery &operator=(const QNetworkProxyQuery &other);
bool operator==(const QNetworkProxyQuery &other) const;
@@ -97,6 +108,11 @@ public:
QUrl url() const;
void setUrl(const QUrl &url);
+#ifndef QT_NO_BEARERMANAGEMENT
+ QNetworkConfiguration networkConfiguration() const;
+ void setNetworkConfiguration(const QNetworkConfiguration &networkConfiguration);
+#endif
+
private:
QSharedDataPointer<QNetworkProxyQueryPrivate> d;
};
diff --git a/src/network/kernel/qnetworkproxy_symbian.cpp b/src/network/kernel/qnetworkproxy_symbian.cpp
index 79dfb27396..4ba14c0465 100644
--- a/src/network/kernel/qnetworkproxy_symbian.cpp
+++ b/src/network/kernel/qnetworkproxy_symbian.cpp
@@ -58,6 +58,7 @@
#include <commsdattypeinfov1_1.h> // CCDIAPRecord, CCDProxiesRecord
#include <commsdattypesv1_1.h> // KCDTIdIAPRecord, KCDTIdProxiesRecord
#include <QtNetwork/QNetworkConfigurationManager>
+#include <QtNetwork/QNetworkConfiguration>
#include <QFlags>
using namespace CommsDat;
@@ -88,7 +89,7 @@ class SymbianProxyQuery
{
public:
static QNetworkConfiguration findCurrentConfiguration(QNetworkConfigurationManager& configurationManager);
- static SymbianIapId getIapId(QNetworkConfigurationManager& configurationManager);
+ static SymbianIapId getIapId(QNetworkConfigurationManager &configurationManager, const QNetworkProxyQuery &query);
static CCDIAPRecord *getIapRecordLC(TUint32 aIAPId, CMDBSession &aDb);
static CMDBRecordSet<CCDProxiesRecord> *prepareQueryLC(TUint32 serviceId, TDesC& serviceType);
static QList<QNetworkProxy> proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query);
@@ -137,11 +138,15 @@ QNetworkConfiguration SymbianProxyQuery::findCurrentConfiguration(QNetworkConfig
return currentConfig;
}
-SymbianIapId SymbianProxyQuery::getIapId(QNetworkConfigurationManager& configurationManager)
+SymbianIapId SymbianProxyQuery::getIapId(QNetworkConfigurationManager& configurationManager, const QNetworkProxyQuery &query)
{
SymbianIapId iapId;
- QNetworkConfiguration currentConfig = findCurrentConfiguration(configurationManager);
+ QNetworkConfiguration currentConfig = query.networkConfiguration();
+ if (!currentConfig.isValid()) {
+ //If config is not specified, then try to find out an active or default one
+ currentConfig = findCurrentConfiguration(configurationManager);
+ }
if (currentConfig.isValid()) {
// Note: the following code assumes that the identifier is in format
// I_xxxx where xxxx is the identifier of IAP. This is meant as a
@@ -249,7 +254,7 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
SymbianIapId iapId;
TInt error;
QNetworkConfigurationManager manager;
- iapId = SymbianProxyQuery::getIapId(manager);
+ iapId = SymbianProxyQuery::getIapId(manager, query);
if (iapId.isValid()) {
TRAP(error, proxies = SymbianProxyQuery::proxyQueryL(iapId.iapId(), query))
if (error != KErrNone) {
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index cfb141398c..d8d263370d 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -556,6 +556,10 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc
q->setErrorString(QAbstractSocket::tr("Operation on socket is not supported"));
return false;
}
+#ifndef QT_NO_NETWORKPROXY
+ //copy user agent to socket engine (if it has been set)
+ socketEngine->setProperty("_q_user-agent", q->property("_q_user-agent"));
+#endif
if (!socketEngine->initialize(q->socketType(), protocol)) {
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::initSocketLayer(%s, %s) failed (%s)",
diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp
index 7846056221..a8a11a71d4 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -501,7 +501,13 @@ void QHttpSocketEngine::slotSocketConnected()
data += path;
data += " HTTP/1.1\r\n";
data += "Proxy-Connection: keep-alive\r\n"
- "User-Agent: Mozilla/5.0\r\n"
+ "User-Agent: ";
+ QVariant v = property("_q_user-agent");
+ if (v.isValid())
+ data += v.toByteArray();
+ else
+ data += "Mozilla/5.0";
+ data += "\r\n"
"Host: " + peerAddress + "\r\n";
QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(d->authenticator);
//qDebug() << "slotSocketConnected: priv=" << priv << (priv ? (int)priv->method : -1);
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index c365635990..88b5aca434 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -1540,8 +1540,13 @@ qint64 QSocks5SocketEngine::write(const char *data, qint64 len)
// ### Handle this error.
}
- d->data->controlSocket->write(sealedBuf);
+ qint64 written = d->data->controlSocket->write(sealedBuf);
+ if (written <= 0) {
+ QSOCKS5_Q_DEBUG << "native write returned" << written;
+ return written;
+ }
d->data->controlSocket->waitForBytesWritten(0);
+ //NB: returning len rather than written for the OK case, because the "sealing" may increase the length
return len;
#ifndef QT_NO_UDPSOCKET
} else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) {
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 70d7dd8df1..ab4d7f1d76 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -233,7 +233,7 @@ void QSslConfiguration::setProtocol(QSsl::SslProtocol protocol)
client), and whether it should require that this certificate is valid.
The default mode is AutoVerifyPeer, which tells QSslSocket to use
- VerifyPeer for clients, QueryPeer for clients.
+ VerifyPeer for clients, QueryPeer for servers.
\sa setPeerVerifyMode()
*/
@@ -249,7 +249,7 @@ QSslSocket::PeerVerifyMode QSslConfiguration::peerVerifyMode() const
client), and whether it should require that this certificate is valid.
The default mode is AutoVerifyPeer, which tells QSslSocket to use
- VerifyPeer for clients, QueryPeer for clients.
+ VerifyPeer for clients, QueryPeer for servers.
\sa peerVerifyMode()
*/
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 0dbf4b5196..2695df1aef 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -1736,6 +1736,8 @@ void QSslSocket::connectToHostImplementation(const QString &hostName, quint16 po
}
#ifndef QT_NO_NETWORKPROXY
d->plainSocket->setProxy(proxy());
+ //copy user agent down to the plain socket (if it has been set)
+ d->plainSocket->setProperty("_q_user-agent", property("_q_user-agent"));
#endif
QIODevice::open(openMode);
d->plainSocket->connectToHost(hostName, port, openMode);
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index 8068aa8524..207ab3d07c 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -495,6 +495,8 @@ GLuint QGLEngineShaderManager::getUniformLocation(Uniform id)
"fmp",
"fmp2_m_radius2",
"inverse_2_fmp2_m_radius2",
+ "sqrfr",
+ "bradius",
"invertedTextureSize",
"brushTransform",
"brushTexture",
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
index 7cc9dc3bd4..bf2fe429c3 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -442,6 +442,8 @@ public:
Fmp,
Fmp2MRadius2,
Inverse2Fmp2MRadius2,
+ SqrFr,
+ BRadius,
InvertedTextureSize,
BrushTransform,
BrushTexture,
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
index fc8b9ef4db..9362c5812b 100644
--- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -241,6 +241,7 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\n\
uniform mediump vec2 halfViewportSize; \n\
uniform highp mat3 brushTransform; \n\
uniform highp vec2 fmp; \n\
+ uniform highp vec3 bradius; \n\
varying highp float b; \n\
varying highp vec2 A; \n\
void setPosition(void) \n\
@@ -253,7 +254,7 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\n\
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
A = hTexCoords.xy * invertedHTexCoordsZ; \n\
- b = 2.0 * dot(A, fmp); \n\
+ b = bradius.x + 2.0 * dot(A, fmp); \n\
}\n";
static const char* const qglslAffinePositionWithRadialGradientBrushVertexShader
@@ -263,13 +264,22 @@ static const char* const qglslRadialGradientBrushSrcFragmentShader = "\n\
uniform sampler2D brushTexture; \n\
uniform highp float fmp2_m_radius2; \n\
uniform highp float inverse_2_fmp2_m_radius2; \n\
+ uniform highp float sqrfr; \n\
varying highp float b; \n\
varying highp vec2 A; \n\
+ uniform highp vec3 bradius; \n\
lowp vec4 srcPixel() \n\
{ \n\
- highp float c = -dot(A, A); \n\
- highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \n\
- return texture2D(brushTexture, val); \n\
+ highp float c = sqrfr-dot(A, A); \n\
+ highp float det = b*b - 4.0*fmp2_m_radius2*c; \n\
+ lowp vec4 result = vec4(0.0); \n\
+ if (det >= 0.0) { \n\
+ highp float detSqrt = sqrt(det); \n\
+ highp float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\
+ if (bradius.y + w * bradius.z >= 0.0) \n\
+ result = texture2D(brushTexture, vec2(w, 0.5)); \n\
+ } \n\
+ return result; \n\
}\n";
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index a7c9411914..f702f13359 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -301,7 +301,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush.gradient());
QPointF realCenter = g->center();
QPointF realFocal = g->focalPoint();
- qreal realRadius = g->radius();
+ qreal realRadius = g->centerRadius() - g->focalRadius();
translationPoint = realFocal;
QPointF fmp = realCenter - realFocal;
@@ -311,6 +311,12 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Fmp2MRadius2), fmp2_m_radius2);
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Inverse2Fmp2MRadius2),
GLfloat(1.0 / (2.0*fmp2_m_radius2)));
+ shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::SqrFr),
+ GLfloat(g->focalRadius() * g->focalRadius()));
+ shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BRadius),
+ GLfloat(2 * (g->centerRadius() - g->focalRadius()) * g->focalRadius()),
+ g->focalRadius(),
+ g->centerRadius() - g->focalRadius());
QVector2D halfViewportSize(width*0.5, height*0.5);
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
index dffda118c5..53f838c641 100644
--- a/src/opengl/qpaintengine_opengl.cpp
+++ b/src/opengl/qpaintengine_opengl.cpp
@@ -2119,6 +2119,7 @@ void QOpenGLPaintEnginePrivate::fillPath(const QPainterPath &path)
updateGLMatrix();
}
+extern bool qt_isExtendedRadialGradient(const QBrush &brush);
static inline bool needsEmulation(Qt::BrushStyle style)
{
@@ -2129,9 +2130,11 @@ static inline bool needsEmulation(Qt::BrushStyle style)
void QOpenGLPaintEnginePrivate::updateUseEmulation()
{
- use_emulation = !use_fragment_programs
- && ((has_pen && needsEmulation(pen_brush_style))
- || (has_brush && needsEmulation(brush_style)));
+ use_emulation = (!use_fragment_programs
+ && ((has_pen && needsEmulation(pen_brush_style))
+ || (has_brush && needsEmulation(brush_style))))
+ || (has_pen && qt_isExtendedRadialGradient(cpen.brush()))
+ || (has_brush && qt_isExtendedRadialGradient(cbrush));
}
void QOpenGLPaintEngine::updatePen(const QPen &pen)
@@ -5447,50 +5450,7 @@ void QOpenGLPaintEngine::transformChanged()
updateMatrix(state()->matrix);
}
-static QPainterPath painterPathFromVectorPath(const QVectorPath &path)
-{
- const qreal *points = path.points();
- const QPainterPath::ElementType *types = path.elements();
-
- QPainterPath p;
- if (types) {
- int id = 0;
- for (int i=0; i<path.elementCount(); ++i) {
- switch(types[i]) {
- case QPainterPath::MoveToElement:
- p.moveTo(QPointF(points[id], points[id+1]));
- id+=2;
- break;
- case QPainterPath::LineToElement:
- p.lineTo(QPointF(points[id], points[id+1]));
- id+=2;
- break;
- case QPainterPath::CurveToElement: {
- QPointF p1(points[id], points[id+1]);
- QPointF p2(points[id+2], points[id+3]);
- QPointF p3(points[id+4], points[id+5]);
- p.cubicTo(p1, p2, p3);
- id+=6;
- break;
- }
- case QPainterPath::CurveToDataElement:
- ;
- break;
- }
- }
- } else {
- p.moveTo(QPointF(points[0], points[1]));
- int id = 2;
- for (int i=1; i<path.elementCount(); ++i) {
- p.lineTo(QPointF(points[id], points[id+1]));
- id+=2;
- }
- }
- if (path.hints() & QVectorPath::WindingFill)
- p.setFillRule(Qt::WindingFill);
-
- return p;
-}
+extern QPainterPath qt_painterPathFromVectorPath(const QVectorPath &path);
void QOpenGLPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
{
@@ -5499,11 +5459,11 @@ void QOpenGLPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
if (brush.style() == Qt::NoBrush)
return;
- if (!d->use_fragment_programs && needsEmulation(brush.style())) {
+ if ((!d->use_fragment_programs && needsEmulation(brush.style())) || qt_isExtendedRadialGradient(brush)) {
QPainter *p = painter();
QBrush oldBrush = p->brush();
p->setBrush(brush);
- qt_draw_helper(p->d_ptr.data(), painterPathFromVectorPath(path), QPainterPrivate::FillDraw);
+ qt_draw_helper(p->d_ptr.data(), qt_painterPathFromVectorPath(path), QPainterPrivate::FillDraw);
p->setBrush(oldBrush);
return;
}
@@ -5520,7 +5480,7 @@ void QOpenGLPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
drawRects(&r, 1);
updatePen(old_pen);
} else {
- d->fillPath(painterPathFromVectorPath(path));
+ d->fillPath(qt_painterPathFromVectorPath(path));
}
updateBrush(old_brush, state()->brushOrigin);
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index 52b424dcfe..62a631855f 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -97,7 +97,9 @@ QT_BEGIN_NAMESPACE
class QGLGlobalShareWidget
{
public:
- QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) {}
+ QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) {
+ created = true;
+ }
QGLWidget *shareWidget() {
if (!initializing && !widget && !cleanedUp) {
@@ -136,6 +138,7 @@ public:
}
static bool cleanedUp;
+ static bool created;
QGLPixmapData *firstPixmap;
int widgetRefCount;
@@ -146,6 +149,7 @@ private:
};
bool QGLGlobalShareWidget::cleanedUp = false;
+bool QGLGlobalShareWidget::created = false;
static void qt_cleanup_gl_share_widget();
Q_GLOBAL_STATIC_WITH_INITIALIZER(QGLGlobalShareWidget, _qt_gl_share_widget,
@@ -155,7 +159,8 @@ Q_GLOBAL_STATIC_WITH_INITIALIZER(QGLGlobalShareWidget, _qt_gl_share_widget,
static void qt_cleanup_gl_share_widget()
{
- _qt_gl_share_widget()->cleanup();
+ if (QGLGlobalShareWidget::created)
+ _qt_gl_share_widget()->cleanup();
}
QGLWidget* qt_gl_share_widget()
@@ -167,7 +172,8 @@ QGLWidget* qt_gl_share_widget()
void qt_destroy_gl_share_widget()
{
- _qt_gl_share_widget()->destroy();
+ if (QGLGlobalShareWidget::created)
+ _qt_gl_share_widget()->destroy();
}
const QGLContext *qt_gl_share_context()
@@ -554,6 +560,17 @@ void QGLWindowSurface::flush(QWindow *window, const QRegion &rgn, const QPoint &
if (!d_ptr->destructive_swap_buffers && !d_ptr->did_paint)
return;
+#ifdef Q_OS_SYMBIAN
+ if (window() != widget) {
+ // For performance reasons we don't support
+ // flushing native child widgets on Symbian.
+ // It breaks overlapping native child widget
+ // rendering in some cases but we prefer performance.
+ return;
+ }
+#endif
+
+
QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
Q_ASSERT(parent);
diff --git a/src/plugins/accessible/widgets/complexwidgets.cpp b/src/plugins/accessible/widgets/complexwidgets.cpp
index e6384133c0..85be0b0131 100644
--- a/src/plugins/accessible/widgets/complexwidgets.cpp
+++ b/src/plugins/accessible/widgets/complexwidgets.cpp
@@ -971,7 +971,11 @@ QString QAccessibleItemView::text(Text t, int child) const
return QAccessibleAbstractScrollArea::text(t, child);
QAccessibleItemRow item(itemView(), childIndex(child));
- return item.text(t, 1);
+ if (item.isValid()) {
+ return item.text(t, 1);
+ } else {
+ return QString();
+ }
} else {
return QAccessibleAbstractScrollArea::text(t, child);
}
diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
index 766760e299..c15232b368 100644
--- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
+++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
@@ -401,9 +401,14 @@ int QAccessibleStackedWidget::childCount() const
int QAccessibleStackedWidget::indexOfChild(const QAccessibleInterface *child) const
{
- if (!child || (stackedWidget()->currentWidget() != child->object()))
+ if (!child)
return -1;
- return 1;
+
+ QWidget* widget = qobject_cast<QWidget*>(child->object());
+ int index = stackedWidget()->indexOf(widget);
+ if (index >= 0) // one based counting of children
+ return index + 1;
+ return -1;
}
int QAccessibleStackedWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
@@ -413,9 +418,9 @@ int QAccessibleStackedWidget::navigate(RelationFlag relation, int entry, QAccess
QObject *targetObject = 0;
switch (relation) {
case Child:
- if (entry != 1)
+ if (entry < 1 || entry > stackedWidget()->count())
return -1;
- targetObject = stackedWidget()->currentWidget();
+ targetObject = stackedWidget()->widget(entry-1);
break;
default:
return QAccessibleWidgetEx::navigate(relation, entry, target);
@@ -1334,7 +1339,7 @@ QRect QAccessibleTextEdit::characterRect(int offset, CoordinateType coordType)
QRect r = edit->cursorRect(cursor);
if (cursor.movePosition(QTextCursor::NextCharacter)) {
- r.setWidth(edit->cursorRect(cursor).y() - r.y());
+ r.setWidth(edit->cursorRect(cursor).x() - r.x());
} else {
// we don't know the width of the character - maybe because we're at document end
// in that case, IAccessible2 tells us to return the width of a default character
@@ -1603,7 +1608,7 @@ void QAccessibleTextEdit::setAttributes(int startOffset, int endOffset, const QS
#ifndef QT_NO_MAINWINDOW
QAccessibleMainWindow::QAccessibleMainWindow(QWidget *widget)
- : QAccessibleWidgetEx(widget, Application) { }
+ : QAccessibleWidgetEx(widget, Window) { }
QVariant QAccessibleMainWindow::invokeMethodEx(QAccessible::Method /*method*/, int /*child*/, const QVariantList & /*params*/)
{
diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp
index 21d2d671f3..aa64630731 100644
--- a/src/plugins/accessible/widgets/simplewidgets.cpp
+++ b/src/plugins/accessible/widgets/simplewidgets.cpp
@@ -131,7 +131,7 @@ QString QAccessibleButton::actionText(int action, Text text, int child) const
/*! \reimp */
bool QAccessibleButton::doAction(int action, int child, const QVariantList &params)
{
- if (child || !widget()->isEnabled() || !widget()->isVisible())
+ if (child || !widget()->isEnabled())
return false;
switch (action) {
@@ -155,9 +155,6 @@ bool QAccessibleButton::doAction(int action, int child, const QVariantList &para
QString QAccessibleButton::text(Text t, int child) const
{
QString str;
- if (!widget()->isVisible())
- return str;
-
switch (t) {
case Accelerator:
{
@@ -227,6 +224,9 @@ QString QAccessibleButton::description(int actionIndex)
{
switch (actionIndex) {
case 0:
+ if (button()->isCheckable()) {
+ return QLatin1String("Toggles the button.");
+ }
return QLatin1String("Clicks the button.");
default:
return QString();
@@ -237,6 +237,13 @@ QString QAccessibleButton::name(int actionIndex)
{
switch (actionIndex) {
case 0:
+ if (button()->isCheckable()) {
+ if (button()->isChecked()) {
+ return QLatin1String("Uncheck");
+ } else {
+ return QLatin1String("Check");
+ }
+ }
return QLatin1String("Press");
default:
return QString();
@@ -247,6 +254,13 @@ QString QAccessibleButton::localizedName(int actionIndex)
{
switch (actionIndex) {
case 0:
+ if (button()->isCheckable()) {
+ if (button()->isChecked()) {
+ return tr("Uncheck");
+ } else {
+ return tr("Check");
+ }
+ }
return tr("Press");
default:
return QString();
@@ -380,9 +394,6 @@ QRect QAccessibleToolButton::rect(int child) const
QString QAccessibleToolButton::text(Text t, int child) const
{
QString str;
- if (!toolButton()->isVisible())
- return str;
-
switch (t) {
case Name:
str = toolButton()->text();
@@ -454,7 +465,7 @@ QString QAccessibleToolButton::actionText(int action, Text text, int child) cons
*/
bool QAccessibleToolButton::doAction(int action, int child, const QVariantList &params)
{
- if (!widget()->isEnabled() || !widget()->isVisible())
+ if (!widget()->isEnabled())
return false;
if (action == 1 || child == ButtonDropMenu) {
if(!child)
@@ -513,8 +524,6 @@ QAccessible::Role QAccessibleDisplay::role(int child) const
QString QAccessibleDisplay::text(Text t, int child) const
{
QString str;
- if (!widget()->isVisible())
- return str;
switch (t) {
case Name:
str = widget()->accessibleName();
@@ -674,8 +683,6 @@ QLineEdit *QAccessibleLineEdit::lineEdit() const
QString QAccessibleLineEdit::text(Text t, int child) const
{
QString str;
- if (!lineEdit()->isVisible())
- return str;
switch (t) {
case Value:
if (lineEdit()->echoMode() == QLineEdit::Normal)
@@ -692,8 +699,6 @@ QString QAccessibleLineEdit::text(Text t, int child) const
/*! \reimp */
void QAccessibleLineEdit::setText(Text t, int control, const QString &text)
{
- if (!lineEdit()->isVisible())
- return;
if (t != Value || control) {
QAccessibleWidgetEx::setText(t, control, text);
return;
diff --git a/src/plugins/bearer/corewlan/corewlan.pro b/src/plugins/bearer/corewlan/corewlan.pro
index ae5371a715..adc1625c3d 100644
--- a/src/plugins/bearer/corewlan/corewlan.pro
+++ b/src/plugins/bearer/corewlan/corewlan.pro
@@ -1,7 +1,7 @@
TARGET = qcorewlanbearer
include(../../qpluginbase.pri)
-QT = core network
+QT = core-private network-private
LIBS += -framework Foundation -framework SystemConfiguration
contains(QT_CONFIG, corewlan) {
diff --git a/src/plugins/platforms/minimal/minimal.pro b/src/plugins/platforms/minimal/minimal.pro
index 852d537793..5c8b55478a 100644
--- a/src/plugins/platforms/minimal/minimal.pro
+++ b/src/plugins/platforms/minimal/minimal.pro
@@ -2,6 +2,7 @@ TARGET = qminimal
include(../../qpluginbase.pri)
QT += gui-private core-private
+QT = core-private gui-private
DESTDIR = $$QT.gui.plugins/platforms
SOURCES = main.cpp \
diff --git a/src/plugins/platforms/wayland/qwaylandclipboard.cpp b/src/plugins/platforms/wayland/qwaylandclipboard.cpp
new file mode 100644
index 0000000000..47ca22865b
--- /dev/null
+++ b/src/plugins/platforms/wayland/qwaylandclipboard.cpp
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandclipboard.h"
+#include "qwaylanddisplay.h"
+#include "qwaylandinputdevice.h"
+#include <QtGui/QPlatformNativeInterface>
+#include <QtGui/QApplication>
+#include <QtCore/QMimeData>
+#include <QtCore/QStringList>
+#include <QtCore/QFile>
+#include <QtCore/QtDebug>
+#include <QtGui/private/qdnd_p.h>
+
+static QWaylandClipboard *clipboard;
+
+class QWaylandMimeData : public QInternalMimeData
+{
+public:
+ void clearAll();
+ void setFormats(const QStringList &formatList);
+ bool hasFormat_sys(const QString &mimeType) const;
+ QStringList formats_sys() const;
+ QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
+private:
+ QStringList mFormatList;
+};
+
+void QWaylandMimeData::clearAll()
+{
+ clear();
+ mFormatList.clear();
+}
+
+void QWaylandMimeData::setFormats(const QStringList &formatList)
+{
+ mFormatList = formatList;
+}
+
+bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const
+{
+ return formats().contains(mimeType);
+}
+
+QStringList QWaylandMimeData::formats_sys() const
+{
+ return mFormatList;
+}
+
+QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
+{
+ return clipboard->retrieveData(mimeType, type);
+}
+
+class QWaylandSelection
+{
+public:
+ QWaylandSelection(QWaylandDisplay *display, QMimeData *data);
+ ~QWaylandSelection();
+
+private:
+ static uint32_t getTime();
+ static void send(void *data, struct wl_selection *selection, const char *mime_type, int fd);
+ static void cancelled(void *data, struct wl_selection *selection);
+ static const struct wl_selection_listener selectionListener;
+
+ QMimeData *mMimeData;
+ struct wl_selection *mSelection;
+};
+
+const struct wl_selection_listener QWaylandSelection::selectionListener = {
+ QWaylandSelection::send,
+ QWaylandSelection::cancelled
+};
+
+uint32_t QWaylandSelection::getTime()
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+QWaylandSelection::QWaylandSelection(QWaylandDisplay *display, QMimeData *data)
+ : mMimeData(data), mSelection(0)
+{
+ struct wl_shell *shell = display->wl_shell();
+ mSelection = wl_shell_create_selection(shell);
+ wl_selection_add_listener(mSelection, &selectionListener, this);
+ foreach (const QString &format, data->formats())
+ wl_selection_offer(mSelection, format.toLatin1().constData());
+ wl_selection_activate(mSelection,
+ display->inputDevices().at(0)->wl_input_device(),
+ getTime());
+}
+
+QWaylandSelection::~QWaylandSelection()
+{
+ if (mSelection) {
+ clipboard->unregisterSelection(this);
+ wl_selection_destroy(mSelection);
+ }
+ delete mMimeData;
+}
+
+void QWaylandSelection::send(void *data,
+ struct wl_selection *selection,
+ const char *mime_type,
+ int fd)
+{
+ Q_UNUSED(selection);
+ QWaylandSelection *self = static_cast<QWaylandSelection *>(data);
+ QString mimeType = QString::fromLatin1(mime_type);
+ QByteArray content = self->mMimeData->data(mimeType);
+ if (!content.isEmpty()) {
+ QFile f;
+ if (f.open(fd, QIODevice::WriteOnly))
+ f.write(content);
+ }
+ close(fd);
+}
+
+void QWaylandSelection::cancelled(void *data, struct wl_selection *selection)
+{
+ Q_UNUSED(selection);
+ delete static_cast<QWaylandSelection *>(data);
+}
+
+QWaylandClipboard::QWaylandClipboard(QWaylandDisplay *display)
+ : mDisplay(display), mSelection(0), mMimeDataIn(0), mOffer(0)
+{
+ clipboard = this;
+}
+
+QWaylandClipboard::~QWaylandClipboard()
+{
+ if (mOffer)
+ wl_selection_offer_destroy(mOffer);
+ delete mMimeDataIn;
+ qDeleteAll(mSelections);
+}
+
+void QWaylandClipboard::unregisterSelection(QWaylandSelection *selection)
+{
+ mSelections.removeOne(selection);
+}
+
+void QWaylandClipboard::syncCallback(void *data)
+{
+ *static_cast<bool *>(data) = true;
+}
+
+void QWaylandClipboard::forceRoundtrip(struct wl_display *display)
+{
+ bool done = false;
+ wl_display_sync_callback(display, syncCallback, &done);
+ wl_display_iterate(display, WL_DISPLAY_WRITABLE);
+ while (!done)
+ wl_display_iterate(display, WL_DISPLAY_READABLE);
+}
+
+QVariant QWaylandClipboard::retrieveData(const QString &mimeType, QVariant::Type type) const
+{
+ Q_UNUSED(type);
+ if (mOfferedMimeTypes.isEmpty() || !mOffer)
+ return QVariant();
+ int pipefd[2];
+ if (pipe(pipefd) == -1) {
+ qWarning("QWaylandClipboard: pipe() failed");
+ return QVariant();
+ }
+ QByteArray mimeTypeBa = mimeType.toLatin1();
+ wl_selection_offer_receive(mOffer, mimeTypeBa.constData(), pipefd[1]);
+ QByteArray content;
+ forceRoundtrip(mDisplay->wl_display());
+ char buf[256];
+ int n;
+ close(pipefd[1]);
+ while ((n = read(pipefd[0], &buf, sizeof buf)) > 0)
+ content.append(buf, n);
+ close(pipefd[0]);
+ return content;
+}
+
+QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode)
+{
+ Q_ASSERT(mode == QClipboard::Clipboard);
+ if (!mMimeDataIn)
+ mMimeDataIn = new QWaylandMimeData;
+ mMimeDataIn->clearAll();
+ if (!mOfferedMimeTypes.isEmpty() && mOffer)
+ mMimeDataIn->setFormats(mOfferedMimeTypes);
+ return mMimeDataIn;
+}
+
+void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
+{
+ Q_ASSERT(mode == QClipboard::Clipboard);
+ if (!mDisplay->inputDevices().isEmpty()) {
+ if (!data)
+ data = new QMimeData;
+ mSelection = new QWaylandSelection(mDisplay, data);
+ } else {
+ qWarning("QWaylandClipboard::setMimeData: No input devices");
+ }
+}
+
+bool QWaylandClipboard::supportsMode(QClipboard::Mode mode) const
+{
+ return mode == QClipboard::Clipboard;
+}
+
+const struct wl_selection_offer_listener QWaylandClipboard::selectionOfferListener = {
+ QWaylandClipboard::offer,
+ QWaylandClipboard::keyboardFocus
+};
+
+void QWaylandClipboard::createSelectionOffer(uint32_t id)
+{
+ mOfferedMimeTypes.clear();
+ if (mOffer)
+ wl_selection_offer_destroy(mOffer);
+ mOffer = 0;
+ struct wl_selection_offer *offer = wl_selection_offer_create(mDisplay->wl_display(), id, 1);
+ wl_selection_offer_add_listener(offer, &selectionOfferListener, this);
+}
+
+void QWaylandClipboard::offer(void *data,
+ struct wl_selection_offer *selection_offer,
+ const char *type)
+{
+ Q_UNUSED(selection_offer);
+ QWaylandClipboard *self = static_cast<QWaylandClipboard *>(data);
+ self->mOfferedMimeTypes.append(QString::fromLatin1(type));
+}
+
+void QWaylandClipboard::keyboardFocus(void *data,
+ struct wl_selection_offer *selection_offer,
+ wl_input_device *input_device)
+{
+ QWaylandClipboard *self = static_cast<QWaylandClipboard *>(data);
+ if (!input_device) {
+ wl_selection_offer_destroy(selection_offer);
+ self->mOffer = 0;
+ return;
+ }
+ self->mOffer = selection_offer;
+ self->emitChanged(QClipboard::Clipboard);
+}
diff --git a/src/plugins/platforms/wayland/qwaylandclipboard.h b/src/plugins/platforms/wayland/qwaylandclipboard.h
new file mode 100644
index 0000000000..6a02254cae
--- /dev/null
+++ b/src/plugins/platforms/wayland/qwaylandclipboard.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDCLIPBOARD_H
+#define QWAYLANDCLIPBOARD_H
+
+#include <QtGui/QPlatformClipboard>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+class QWaylandDisplay;
+class QWaylandSelection;
+class QWaylandMimeData;
+struct wl_selection_offer;
+
+class QWaylandClipboard : public QPlatformClipboard
+{
+public:
+ QWaylandClipboard(QWaylandDisplay *display);
+ ~QWaylandClipboard();
+
+ QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard);
+ void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);
+ bool supportsMode(QClipboard::Mode mode) const;
+
+ void unregisterSelection(QWaylandSelection *selection);
+
+ void createSelectionOffer(uint32_t id);
+
+ QVariant retrieveData(const QString &mimeType, QVariant::Type type) const;
+
+private:
+ static void offer(void *data,
+ struct wl_selection_offer *selection_offer,
+ const char *type);
+ static void keyboardFocus(void *data,
+ struct wl_selection_offer *selection_offer,
+ struct wl_input_device *input_device);
+ static const struct wl_selection_offer_listener selectionOfferListener;
+
+ static void syncCallback(void *data);
+ static void forceRoundtrip(struct wl_display *display);
+
+ QWaylandDisplay *mDisplay;
+ QWaylandSelection *mSelection;
+ QWaylandMimeData *mMimeDataIn;
+ QList<QWaylandSelection *> mSelections;
+ QStringList mOfferedMimeTypes;
+ struct wl_selection_offer *mOffer;
+};
+
+#endif // QWAYLANDCLIPBOARD_H
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
index 3e8039fd9f..bd3f210533 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
@@ -45,13 +45,14 @@
#include "qwaylandscreen.h"
#include "qwaylandcursor.h"
#include "qwaylandinputdevice.h"
+#include "qwaylandclipboard.h"
#ifdef QT_WAYLAND_GL_SUPPORT
#include "gl_integration/qwaylandglintegration.h"
#endif
#include <QtCore/QAbstractEventDispatcher>
-#include <QtWidgets/QApplication>
+#include <QtGui/private/qguiapplication_p.h>
#include <unistd.h>
#include <fcntl.h>
@@ -249,7 +250,6 @@ void QWaylandDisplay::displayHandleGlobal(uint32_t id,
uint32_t version)
{
Q_UNUSED(version);
-
if (interface == "wl_output") {
struct wl_output *output = wl_output_create(mDisplay, id, 1);
wl_output_add_listener(output, &outputListener, this);
@@ -264,5 +264,9 @@ void QWaylandDisplay::displayHandleGlobal(uint32_t id,
QWaylandInputDevice *inputDevice =
new QWaylandInputDevice(mDisplay, id);
mInputDevices.append(inputDevice);
+ } else if (interface == "wl_selection_offer") {
+ QPlatformIntegration *plat = QGuiApplicationPrivate::platformIntegration();
+ QWaylandClipboard *clipboard = static_cast<QWaylandClipboard *>(plat->clipboard());
+ clipboard->createSelectionOffer(id);
}
}
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h
index a2cb1b28ad..0658956dc3 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.h
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.h
@@ -80,6 +80,7 @@ public:
void frameCallback(wl_display_frame_func_t func, struct wl_surface *surface, void *data);
struct wl_display *wl_display() const { return mDisplay; }
+ struct wl_shell *wl_shell() const { return mShell; }
QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h
index 3c83252c33..251259ba22 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.h
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h
@@ -60,6 +60,7 @@ public:
QWaylandInputDevice(struct wl_display *display, uint32_t id);
void attach(QWaylandBuffer *buffer, int x, int y);
void handleWindowDestroyed(QWaylandWindow *window);
+ struct wl_input_device *wl_input_device() const { return mInputDevice; }
private:
struct wl_display *mDisplay;
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp
index 8636865854..7df6c4a526 100644
--- a/src/plugins/platforms/wayland/qwaylandintegration.cpp
+++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp
@@ -45,6 +45,7 @@
#include "qwaylandshmsurface.h"
#include "qwaylandshmwindow.h"
#include "qwaylandnativeinterface.h"
+#include "qwaylandclipboard.h"
#include "qgenericunixfontdatabase.h"
@@ -64,6 +65,7 @@ QWaylandIntegration::QWaylandIntegration(bool useOpenGL)
, mDisplay(new QWaylandDisplay())
, mUseOpenGL(useOpenGL)
, mNativeInterface(new QWaylandNativeInterface)
+ , mClipboard(0)
{
}
@@ -130,3 +132,10 @@ bool QWaylandIntegration::hasOpenGL() const
return false;
#endif
}
+
+QPlatformClipboard *QWaylandIntegration::clipboard() const
+{
+ if (!mClipboard)
+ mClipboard = new QWaylandClipboard(mDisplay);
+ return mClipboard;
+}
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h
index 57e2d8b69b..f0bb27a4ed 100644
--- a/src/plugins/platforms/wayland/qwaylandintegration.h
+++ b/src/plugins/platforms/wayland/qwaylandintegration.h
@@ -65,6 +65,8 @@ public:
QPlatformNativeInterface *nativeInterface() const;
+ QPlatformClipboard *clipboard() const;
+
private:
bool hasOpenGL() const;
@@ -72,6 +74,7 @@ private:
QWaylandDisplay *mDisplay;
bool mUseOpenGL;
QPlatformNativeInterface *mNativeInterface;
+ mutable QPlatformClipboard *mClipboard;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro
index 8372d7ac6f..1a9368f13c 100644
--- a/src/plugins/platforms/wayland/wayland.pro
+++ b/src/plugins/platforms/wayland/wayland.pro
@@ -1,11 +1,15 @@
TARGET = qwayland
include(../../qpluginbase.pri)
+QT+=gui-private core-private opengl-private
+
DESTDIR = $$QT.gui.plugins/platforms
DEFINES += Q_PLATFORM_WAYLAND
DEFINES += $$QMAKE_DEFINES_WAYLAND
+QT += core-private gui-private opengl-private
+
SOURCES = main.cpp \
qwaylandintegration.cpp \
qwaylandnativeinterface.cpp \
@@ -15,7 +19,8 @@ SOURCES = main.cpp \
qwaylanddisplay.cpp \
qwaylandwindow.cpp \
qwaylandscreen.cpp \
- qwaylandshmwindow.cpp
+ qwaylandshmwindow.cpp \
+ qwaylandclipboard.cpp
HEADERS = qwaylandintegration.h \
qwaylandnativeinterface.h \
@@ -25,7 +30,8 @@ HEADERS = qwaylandintegration.h \
qwaylandscreen.h \
qwaylandshmsurface.h \
qwaylandbuffer.h \
- qwaylandshmwindow.h
+ qwaylandshmwindow.h \
+ qwaylandclipboard.h
INCLUDEPATH += $$QMAKE_INCDIR_WAYLAND
LIBS += $$QMAKE_LIBS_WAYLAND
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index 5640944ac3..7c0751f896 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -109,7 +109,6 @@ void QGLXContext::swapBuffers()
{
Q_XCB_NOOP(m_screen->connection());
glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), m_drawable);
- doneCurrent();
Q_XCB_NOOP(m_screen->connection());
}
diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro
index fffdb5d4b0..175bdd8451 100644
--- a/src/plugins/platforms/xcb/xcb.pro
+++ b/src/plugins/platforms/xcb/xcb.pro
@@ -3,6 +3,10 @@ TARGET = xcb
include(../../qpluginbase.pri)
QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms
+QT += core-private gui-private
+
+QT+=gui-private core-private
+
SOURCES = \
qxcbconnection.cpp \
qxcbintegration.cpp \
diff --git a/src/plugins/platforms/xlib/qxlibclipboard.cpp b/src/plugins/platforms/xlib/qxlibclipboard.cpp
index dfaf552121..fef6e3ae12 100644
--- a/src/plugins/platforms/xlib/qxlibclipboard.cpp
+++ b/src/plugins/platforms/xlib/qxlibclipboard.cpp
@@ -161,12 +161,11 @@ QXlibClipboard::QXlibClipboard(QXlibScreen *screen)
{
}
-const QMimeData * QXlibClipboard::mimeData(QClipboard::Mode mode) const
+QMimeData * QXlibClipboard::mimeData(QClipboard::Mode mode)
{
if (mode == QClipboard::Clipboard) {
if (!m_xClipboard) {
- QXlibClipboard *that = const_cast<QXlibClipboard *>(this);
- that->m_xClipboard = new QXlibClipboardMime(mode,that);
+ m_xClipboard = new QXlibClipboardMime(mode, this);
}
Window clipboardOwner = XGetSelectionOwner(screen()->display()->nativeDisplay(),QXlibStatic::atom(QXlibStatic::CLIPBOARD));
if (clipboardOwner == owner()) {
@@ -176,8 +175,7 @@ const QMimeData * QXlibClipboard::mimeData(QClipboard::Mode mode) const
}
} else if (mode == QClipboard::Selection) {
if (!m_xSelection) {
- QXlibClipboard *that = const_cast<QXlibClipboard *>(this);
- that->m_xSelection = new QXlibClipboardMime(mode,that);
+ m_xSelection = new QXlibClipboardMime(mode, this);
}
Window clipboardOwner = XGetSelectionOwner(screen()->display()->nativeDisplay(),XA_PRIMARY);
if (clipboardOwner == owner()) {
diff --git a/src/plugins/platforms/xlib/qxlibclipboard.h b/src/plugins/platforms/xlib/qxlibclipboard.h
index 15901b0d2a..d61340dd1c 100644
--- a/src/plugins/platforms/xlib/qxlibclipboard.h
+++ b/src/plugins/platforms/xlib/qxlibclipboard.h
@@ -51,7 +51,7 @@ class QXlibClipboard : public QPlatformClipboard
public:
QXlibClipboard(QXlibScreen *screen);
- const QMimeData *mimeData(QClipboard::Mode mode) const;
+ QMimeData *mimeData(QClipboard::Mode mode);
void setMimeData(QMimeData *data, QClipboard::Mode mode);
bool supportsMode(QClipboard::Mode mode) const;
diff --git a/src/plugins/platforms/xlib/qxlibstatic.h b/src/plugins/platforms/xlib/qxlibstatic.h
index 72cfaec54c..8517de0bc2 100644
--- a/src/plugins/platforms/xlib/qxlibstatic.h
+++ b/src/plugins/platforms/xlib/qxlibstatic.h
@@ -46,6 +46,9 @@
#include <QtCore/QDataStream>
#include <QtCore/QMetaType>
#include <QtCore/QVariant>
+// qcoreapplication_p.h includes qsettings.h which undefines Status
+// therefore it is included here before the X stuff.
+#include <QtCore/private/qcoreapplication_p.h>
#if defined(_XLIB_H_) // crude hack, but...
#error "cannot include <X11/Xlib.h> before this file"
diff --git a/src/plugins/platforms/xlib/xlib.pro b/src/plugins/platforms/xlib/xlib.pro
index ae02077100..902d379ee2 100644
--- a/src/plugins/platforms/xlib/xlib.pro
+++ b/src/plugins/platforms/xlib/xlib.pro
@@ -3,6 +3,8 @@ TARGET = qxlib
include(../../qpluginbase.pri)
DESTDIR = $$QT.gui.plugins/platforms
+QT += core-private gui-private opengl-private
+
SOURCES = \
main.cpp \
qxlibintegration.cpp \
diff --git a/src/qt_install.pri b/src/qt_install.pri
index 17b41af1ce..f5ad51f591 100644
--- a/src/qt_install.pri
+++ b/src/qt_install.pri
@@ -32,7 +32,7 @@ qt_install_headers {
INSTALLS += targ_headers
private_headers.files = $$SYNCQT.PRIVATE_HEADER_FILES
- private_headers.path = $$[QT_INSTALL_HEADERS]/$$TARGET/$$eval(QT.$${MODULE}.VERSION)/private
+ private_headers.path = $$[QT_INSTALL_HEADERS]/$$TARGET/$$eval(QT.$${MODULE}.VERSION)/$$TARGET/private
INSTALLS += private_headers
}
diff --git a/src/s60installs/eabi/QtOpenGLu.def b/src/s60installs/eabi/QtOpenGLu.def
index 44f7306d54..34b5266829 100644
--- a/src/s60installs/eabi/QtOpenGLu.def
+++ b/src/s60installs/eabi/QtOpenGLu.def
@@ -759,7 +759,7 @@ EXPORTS
_ZNK14QGLPaintDevice9isFlippedEv @ 758 NONAME
_ZNK16QGLWindowSurface8featuresEv @ 759 NONAME
_ZNK26QGLFramebufferObjectFormat6mipmapEv @ 760 NONAME
- _ZTI22QGLContextResourceBase @ 761 NONAME
+ _ZTI22QGLContextResourceBase @ 761 NONAME ABSENT
_ZTI27QGLContextGroupResourceBase @ 762 NONAME
_ZTV22QGLContextResourceBase @ 763 NONAME
_ZTV27QGLContextGroupResourceBase @ 764 NONAME
diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp
index 49e7f138ee..4250b61a01 100644
--- a/src/sql/drivers/mysql/qsql_mysql.cpp
+++ b/src/sql/drivers/mysql/qsql_mysql.cpp
@@ -1374,12 +1374,16 @@ QStringList QMYSQLDriver::tables(QSql::TableType type) const
} else {
QSqlQuery q(createResult());
if(type & QSql::Tables) {
- q.exec(QLatin1String("select table_name from information_schema.tables where table_type = 'BASE TABLE'"));
+ QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'BASE TABLE'");
+ q.exec(sql);
+
while(q.next())
tl.append(q.value(0).toString());
}
if(type & QSql::Views) {
- q.exec(QLatin1String("select table_name from information_schema.tables where table_type = 'VIEW'"));
+ QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'VIEW'");
+ q.exec(sql);
+
while(q.next())
tl.append(q.value(0).toString());
}
diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp
index d09c712b7b..b2f4f6d311 100644
--- a/src/tools/uic/cpp/cppwriteincludes.cpp
+++ b/src/tools/uic/cpp/cppwriteincludes.cpp
@@ -124,22 +124,6 @@ void WriteIncludes::acceptUI(DomUI *node)
add(QLatin1String("QButtonGroup")); // ### only if it is really necessary
add(QLatin1String("QHeaderView"));
- if (m_uic->hasExternalPixmap() && m_uic->pixmapFunction() == QLatin1String("qPixmapFromMimeSource")) {
-#ifdef QT_NO_QT3_SUPPORT
- qWarning("%s: Warning: The form file has external pixmaps or qPixmapFromMimeSource() set as a pixmap function. "
- "This requires Qt 3 support, which is disabled. The resulting code will not compile.",
- qPrintable(m_uic->option().messagePrefix()));
-#endif
- add(QLatin1String("Q3MimeSourceFactory"));
- }
-
- if (m_uic->databaseInfo()->connections().size()) {
- add(QLatin1String("QSqlDatabase"));
- add(QLatin1String("Q3SqlCursor"));
- add(QLatin1String("QSqlRecord"));
- add(QLatin1String("Q3SqlForm"));
- }
-
TreeWalker::acceptUI(node);
writeHeaders(m_globalIncludes, true);
@@ -241,10 +225,6 @@ void WriteIncludes::add(const QString &className, bool determineHeader, const QS
return;
}
- if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ListView")) ||
- m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3Table"))) {
- add(QLatin1String("Q3Header"));
- }
if (determineHeader)
insertIncludeForClass(className, header, global);
}
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 37d012c109..85c1b1d285 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -636,7 +636,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
const QString savedParentWidget = parentWidget;
- if (m_uic->isContainer(parentClass) || m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3ToolBar")))
+ if (m_uic->isContainer(parentClass))
parentWidget.clear();
if (m_widgetChain.size() != 1)
@@ -644,9 +644,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
parentWidget = savedParentWidget;
- if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ComboBox"))) {
- initializeComboBox3(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox"))) {
+ if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox"))) {
initializeComboBox(node);
} else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) {
initializeListWidget(node);
@@ -654,18 +652,6 @@ void WriteInitialization::acceptWidget(DomWidget *node)
initializeTreeWidget(node);
} else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableWidget"))) {
initializeTableWidget(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ListBox"))) {
- initializeQ3ListBox(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ListView"))) {
- initializeQ3ListView(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3IconView"))) {
- initializeQ3IconView(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3Table"))) {
- initializeQ3Table(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3DataTable"))) {
- initializeQ3SqlDataTable(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3DataBrowser"))) {
- initializeQ3SqlDataBrowser(node);
}
if (m_uic->isButton(className))
@@ -706,12 +692,9 @@ void WriteInitialization::acceptWidget(DomWidget *node)
id = pid->elementNumber();
}
- if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QMainWindow"))
- || m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3MainWindow"))) {
-
+ if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QMainWindow"))) {
if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QMenuBar"))) {
- if (!m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3MainWindow")))
- m_output << m_indent << parentWidget << "->setMenuBar(" << varName <<");\n";
+ m_output << m_indent << parentWidget << "->setMenuBar(" << varName <<");\n";
} else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBar"))) {
m_output << m_indent << parentWidget << "->addToolBar("
<< toolBarAreaStringFromDOMAttributes(attributes) << varName << ");\n";
@@ -733,8 +716,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
m_output << m_indent << parentWidget << "->addDockWidget(" << area << varName << ");\n";
} else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStatusBar"))) {
m_output << m_indent << parentWidget << "->setStatusBar(" << varName << ");\n";
- } else if (!m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3DockWindow"))
- && !m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ToolBar"))) {
+ } else {
m_output << m_indent << parentWidget << "->setCentralWidget(" << varName << ");\n";
}
}
@@ -747,8 +729,6 @@ void WriteInitialization::acceptWidget(DomWidget *node)
m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n";
} else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QToolBar"))) {
m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n";
- } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3WidgetStack"))) {
- m_output << m_indent << parentWidget << "->addWidget(" << varName << ", " << id << ");\n";
} else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QDockWidget"))) {
m_output << m_indent << parentWidget << "->setWidget(" << varName << ");\n";
} else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QScrollArea"))) {
@@ -809,15 +789,6 @@ void WriteInitialization::acceptWidget(DomWidget *node)
<< parentWidget << "->indexOf(" << varName << "), " << autoTrCall(pwhatsThis->elementString()) << ");\n";
}
#endif // QT_NO_WHATSTHIS
- } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3Wizard"))) {
- const DomProperty *ptitle = attributes.value(QLatin1String("title"));
- DomString *ptitleString = ptitle ? ptitle->elementString() : 0;
-
- m_output << m_indent << parentWidget << "->addPage(" << varName << ", " << noTrCall(ptitleString, pageDefaultString) << ");\n";
-
- autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget << "->setTitle("
- << varName << ", " << autoTrCall(ptitleString, pageDefaultString) << ");\n";
-
}
//
@@ -937,28 +908,6 @@ void WriteInitialization::acceptLayout(DomLayout *node)
bool isGroupBox = false;
- if (m_widgetChain.top()) {
- const QString parentWidget = m_widgetChain.top()->attributeClass();
-
- if (!m_layoutChain.top() && (m_uic->customWidgetsInfo()->extends(parentWidget, QLatin1String("Q3GroupBox"))
- || m_uic->customWidgetsInfo()->extends(parentWidget, QLatin1String("Q3ButtonGroup")))) {
- const QString parent = m_driver->findOrInsertWidget(m_widgetChain.top());
-
- isGroupBox = true;
- // special case for group box
-
- m_output << m_indent << parent << "->setColumnLayout(0, Qt::Vertical);\n";
- QString objectName = parent;
- objectName += QLatin1String("->layout()");
- int marginType = Use43UiFile;
- if (oldLayoutProperties)
- marginType = m_layoutMarginType;
-
- m_LayoutDefaultHandler.writeProperties(m_indent,
- objectName, properties, marginType, false, m_output);
- }
- }
-
m_output << m_indent << varName << " = new " << className << '(';
if (!m_layoutChain.top() && !isGroupBox)
@@ -966,24 +915,12 @@ void WriteInitialization::acceptLayout(DomLayout *node)
m_output << ");\n";
- if (isGroupBox) {
- const QString tempName = m_driver->unique(QLatin1String("boxlayout"));
- m_output << m_indent << "QBoxLayout *" << tempName << " = qobject_cast<QBoxLayout *>(" <<
- m_driver->findOrInsertWidget(m_widgetChain.top()) << "->layout());\n";
- m_output << m_indent << "if (" << tempName << ")\n";
- m_output << m_dindent << tempName << "->addLayout(" << varName << ");\n";
- }
-
- if (isGroupBox) {
- m_output << m_indent << varName << "->setAlignment(Qt::AlignTop);\n";
- } else {
- // Suppress margin on a read child layout
- const bool suppressMarginDefault = m_layoutChain.top();
- int marginType = Use43UiFile;
- if (oldLayoutProperties)
- marginType = m_layoutMarginType;
- m_LayoutDefaultHandler.writeProperties(m_indent, varName, properties, marginType, suppressMarginDefault, m_output);
- }
+ // Suppress margin on a read child layout
+ const bool suppressMarginDefault = m_layoutChain.top();
+ int marginType = Use43UiFile;
+ if (oldLayoutProperties)
+ marginType = m_layoutMarginType;
+ m_LayoutDefaultHandler.writeProperties(m_indent, varName, properties, marginType, suppressMarginDefault, m_output);
m_layoutMarginType = SubLayoutMargin;
@@ -1175,13 +1112,8 @@ void WriteInitialization::acceptActionRef(DomActionRef *node)
return;
} else if (m_driver->actionGroupByName(actionName)) {
return;
- } else if (DomWidget *w = m_driver->widgetByName(actionName)) {
+ } else if (const DomWidget *w = m_driver->widgetByName(actionName)) {
isMenu = m_uic->isMenu(w->attributeClass());
- bool inQ3ToolBar = m_uic->customWidgetsInfo()->extends(m_widgetChain.top()->attributeClass(), QLatin1String("Q3ToolBar"));
- if (!isMenu && inQ3ToolBar) {
- m_actionOut << m_indent << actionName << "->setParent(" << varName << ");\n";
- return;
- }
} else if (!(m_driver->actionByName(actionName) || isSeparator)) {
fprintf(stderr, "%s: Warning: action `%s' not declared\n",
qPrintable(m_option.messagePrefix()),
@@ -1217,8 +1149,6 @@ void WriteInitialization::writeProperties(const QString &varName,
}
}
- DomWidget *buttonGroupWidget = findWidget(QLatin1String("Q3ButtonGroup"));
-
QString indent;
if (!m_widgetChain.top()) {
indent = m_option.indent;
@@ -1244,11 +1174,6 @@ void WriteInitialization::writeProperties(const QString &varName,
const DomRect *r = p->elementRect();
m_output << m_indent << varName << "->resize(" << r->elementWidth() << ", " << r->elementHeight() << ");\n";
continue;
- } else if (propertyName == QLatin1String("buttonGroupId")) { // Q3ButtonGroup support
- if (buttonGroupWidget)
- m_output << m_indent << m_driver->findOrInsertWidget(buttonGroupWidget) << "->insert("
- << varName << ", " << p->elementNumber() << ");\n";
- continue;
} else if (propertyName == QLatin1String("currentRow") // QListWidget::currentRow
&& m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) {
m_delayedOut << m_indent << varName << "->setCurrentRow("
@@ -1568,16 +1493,7 @@ void WriteInitialization::writeProperties(const QString &varName,
}
}
if (leftMargin != -1 || topMargin != -1 || rightMargin != -1 || bottomMargin != -1) {
- QString objectName = varName;
- if (m_widgetChain.top()) {
- const QString parentWidget = m_widgetChain.top()->attributeClass();
-
- if (!m_layoutChain.top() && (m_uic->customWidgetsInfo()->extends(parentWidget, QLatin1String("Q3GroupBox"))
- || m_uic->customWidgetsInfo()->extends(parentWidget, QLatin1String("Q3ButtonGroup")))) {
- objectName = m_driver->findOrInsertWidget(m_widgetChain.top()) + QLatin1String("->layout()");
- }
- }
- m_output << m_indent << objectName << QLatin1String("->setContentsMargins(")
+ m_output << m_indent << varName << QLatin1String("->setContentsMargins(")
<< leftMargin << QLatin1String(", ")
<< topMargin << QLatin1String(", ")
<< rightMargin << QLatin1String(", ")
@@ -1934,199 +1850,6 @@ void WriteInitialization::acceptTabStops(DomTabStops *tabStops)
}
}
-void WriteInitialization::initializeQ3ListBox(DomWidget *w)
-{
- const QString varName = m_driver->findOrInsertWidget(w);
- const QString className = w->attributeClass();
-
- const QList<DomItem*> items = w->elementItem();
-
- if (items.isEmpty())
- return;
-
- m_refreshOut << m_indent << varName << "->clear();\n";
-
- for (int i=0; i<items.size(); ++i) {
- const DomItem *item = items.at(i);
-
- const DomPropertyMap properties = propertyMap(item->elementProperty());
- const DomProperty *text = properties.value(QLatin1String("text"));
- const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
- if (!(text || pixmap))
- continue;
-
- m_refreshOut << m_indent << varName << "->insertItem(";
- if (pixmap) {
- m_refreshOut << pixCall(pixmap);
-
- if (text)
- m_refreshOut << ", ";
- }
- if (text)
- m_refreshOut << trCall(text->elementString());
- m_refreshOut << ");\n";
- }
-}
-
-void WriteInitialization::initializeQ3IconView(DomWidget *w)
-{
- const QString varName = m_driver->findOrInsertWidget(w);
- const QString className = w->attributeClass();
-
- const QList<DomItem*> items = w->elementItem();
-
- if (items.isEmpty())
- return;
-
- m_refreshOut << m_indent << varName << "->clear();\n";
-
- for (int i=0; i<items.size(); ++i) {
- const DomItem *item = items.at(i);
-
- const DomPropertyMap properties = propertyMap(item->elementProperty());
- const DomProperty *text = properties.value(QLatin1String("text"));
- const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
- if (!(text || pixmap))
- continue;
-
- const QString itemName = m_driver->unique(QLatin1String("__item"));
- m_refreshOut << "\n";
- m_refreshOut << m_indent << "Q3IconViewItem *" << itemName << " = new Q3IconViewItem(" << varName << ");\n";
-
- if (pixmap) {
- m_refreshOut << m_indent << itemName << "->setPixmap(" << pixCall(pixmap) << ");\n";
- }
-
- if (text) {
- m_refreshOut << m_indent << itemName << "->setText(" << trCall(text->elementString()) << ");\n";
- }
- }
-}
-
-void WriteInitialization::initializeQ3ListView(DomWidget *w)
-{
- const QString varName = m_driver->findOrInsertWidget(w);
- const QString className = w->attributeClass();
-
- // columns
- const QList<DomColumn*> columns = w->elementColumn();
- for (int i=0; i<columns.size(); ++i) {
- const DomColumn *column = columns.at(i);
-
- const DomPropertyMap properties = propertyMap(column->elementProperty());
- const DomProperty *text = properties.value(QLatin1String("text"));
- const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
- const DomProperty *clickable = properties.value(QLatin1String("clickable"));
- const DomProperty *resizable = properties.value(QLatin1String("resizable"));
-
- const QString txt = trCall(text->elementString());
- m_output << m_indent << varName << "->addColumn(" << txt << ");\n";
- m_refreshOut << m_indent << varName << "->header()->setLabel(" << i << ", " << txt << ");\n";
-
- if (pixmap) {
- m_output << m_indent << varName << "->header()->setLabel("
- << varName << "->header()->count() - 1, " << pixCall(pixmap) << ", " << txt << ");\n";
- }
-
- if (clickable != 0) {
- m_output << m_indent << varName << "->header()->setClickEnabled(" << clickable->elementBool() << ", " << varName << "->header()->count() - 1);\n";
- }
-
- if (resizable != 0) {
- m_output << m_indent << varName << "->header()->setResizeEnabled(" << resizable->elementBool() << ", " << varName << "->header()->count() - 1);\n";
- }
- }
-
- if (w->elementItem().size()) {
- m_refreshOut << m_indent << varName << "->clear();\n";
-
- initializeQ3ListViewItems(className, varName, w->elementItem());
- }
-}
-
-void WriteInitialization::initializeQ3ListViewItems(const QString &className, const QString &varName, const QList<DomItem *> &items)
-{
- if (items.isEmpty())
- return;
-
- // items
- for (int i=0; i<items.size(); ++i) {
- const DomItem *item = items.at(i);
-
- const QString itemName = m_driver->unique(QLatin1String("__item"));
- m_refreshOut << "\n";
- m_refreshOut << m_indent << "Q3ListViewItem *" << itemName << " = new Q3ListViewItem(" << varName << ");\n";
-
- int textCount = 0, pixCount = 0;
- const DomPropertyList properties = item->elementProperty();
- for (int i=0; i<properties.size(); ++i) {
- const DomProperty *p = properties.at(i);
- if (p->attributeName() == QLatin1String("text"))
- m_refreshOut << m_indent << itemName << "->setText(" << textCount++ << ", "
- << trCall(p->elementString()) << ");\n";
-
- if (p->attributeName() == QLatin1String("pixmap"))
- m_refreshOut << m_indent << itemName << "->setPixmap(" << pixCount++ << ", "
- << pixCall(p) << ");\n";
- }
-
- if (item->elementItem().size()) {
- m_refreshOut << m_indent << itemName << "->setOpen(true);\n";
- initializeQ3ListViewItems(className, itemName, item->elementItem());
- }
- }
-}
-
-
-void WriteInitialization::initializeQ3Table(DomWidget *w)
-{
- const QString varName = m_driver->findOrInsertWidget(w);
- const QString className = w->attributeClass();
-
- // columns
- const QList<DomColumn*> columns = w->elementColumn();
-
- for (int i=0; i<columns.size(); ++i) {
- const DomColumn *column = columns.at(i);
-
- const DomPropertyMap properties = propertyMap(column->elementProperty());
- const DomProperty *text = properties.value(QLatin1String("text"));
- const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
-
- m_refreshOut << m_indent << varName << "->horizontalHeader()->setLabel(" << i << ", ";
- if (pixmap) {
- m_refreshOut << pixCall(pixmap) << ", ";
- }
- m_refreshOut << trCall(text->elementString()) << ");\n";
- }
-
- // rows
- const QList<DomRow*> rows = w->elementRow();
- for (int i=0; i<rows.size(); ++i) {
- const DomRow *row = rows.at(i);
-
- const DomPropertyMap properties = propertyMap(row->elementProperty());
- const DomProperty *text = properties.value(QLatin1String("text"));
- const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
-
- m_refreshOut << m_indent << varName << "->verticalHeader()->setLabel(" << i << ", ";
- if (pixmap) {
- m_refreshOut << pixCall(pixmap) << ", ";
- }
- m_refreshOut << trCall(text->elementString()) << ");\n";
- }
-
-
- //initializeQ3TableItems(className, varName, w->elementItem());
-}
-
-void WriteInitialization::initializeQ3TableItems(const QString &className, const QString &varName, const QList<DomItem *> &items)
-{
- Q_UNUSED(className);
- Q_UNUSED(varName);
- Q_UNUSED(items);
-}
-
QString WriteInitialization::iconCall(const DomProperty *icon)
{
if (icon->kind() == DomProperty::IconSet)
@@ -2194,26 +1917,6 @@ QString WriteInitialization::pixCall(const QString &t, const QString &text) cons
return type;
}
-void WriteInitialization::initializeComboBox3(DomWidget *w)
-{
- const QList<DomItem*> items = w->elementItem();
- if (items.empty())
- return;
- // Basic legacy Qt3 support, write out translatable text items, ignore pixmaps
- const QString varName = m_driver->findOrInsertWidget(w);
- const QString textProperty = QLatin1String("text");
-
- m_refreshOut << m_indent << varName << "->clear();\n";
- m_refreshOut << m_indent << varName << "->insertStringList(QStringList()" << '\n';
- const int itemCount = items.size();
- for (int i = 0; i< itemCount; ++i) {
- const DomItem *item = items.at(i);
- if (const DomProperty *text = propertyMap(item->elementProperty()).value(textProperty))
- m_refreshOut << m_indent << " << " << autoTrCall(text->elementString()) << "\n";
- }
- m_refreshOut << m_indent << ", 0);\n";
-}
-
void WriteInitialization::initializeComboBox(DomWidget *w)
{
const QString varName = m_driver->findOrInsertWidget(w);
@@ -2617,86 +2320,6 @@ QString WriteInitialization::trCall(const QString &str, const QString &commentHi
return result;
}
-void WriteInitialization::initializeQ3SqlDataTable(DomWidget *w)
-{
- const DomPropertyMap properties = propertyMap(w->elementProperty());
-
- const DomProperty *frameworkCode = properties.value(QLatin1String("frameworkCode"), 0);
- if (frameworkCode && toBool(frameworkCode->elementBool()) == false)
- return;
-
- QString connection;
- QString table;
- QString field;
-
- const DomProperty *db = properties.value(QLatin1String("database"), 0);
- if (db && db->elementStringList()) {
- const QStringList info = db->elementStringList()->elementString();
- connection = info.size() > 0 ? info.at(0) : QString();
- table = info.size() > 1 ? info.at(1) : QString();
- field = info.size() > 2 ? info.at(2) : QString();
- }
-
- if (table.isEmpty() || connection.isEmpty()) {
- fprintf(stderr, "%s: Warning: Invalid database connection\n", qPrintable(m_option.messagePrefix()));
- return;
- }
-
- const QString varName = m_driver->findOrInsertWidget(w);
-
- m_output << m_indent << "if (!" << varName << "->sqlCursor()) {\n";
-
- m_output << m_dindent << varName << "->setSqlCursor(";
-
- if (connection == QLatin1String("(default)")) {
- m_output << "new Q3SqlCursor(" << fixString(table, m_dindent) << "), false, true);\n";
- } else {
- m_output << "new Q3SqlCursor(" << fixString(table, m_dindent) << ", true, " << connection << "Connection" << "), false, true);\n";
- }
- m_output << m_dindent << varName << "->refresh(Q3DataTable::RefreshAll);\n";
- m_output << m_indent << "}\n";
-}
-
-void WriteInitialization::initializeQ3SqlDataBrowser(DomWidget *w)
-{
- const DomPropertyMap properties = propertyMap(w->elementProperty());
-
- const DomProperty *frameworkCode = properties.value(QLatin1String("frameworkCode"), 0);
- if (frameworkCode && toBool(frameworkCode->elementBool()) == false)
- return;
-
- QString connection;
- QString table;
- QString field;
-
- const DomProperty *db = properties.value(QLatin1String("database"), 0);
- if (db && db->elementStringList()) {
- const QStringList info = db->elementStringList()->elementString();
- connection = info.size() > 0 ? info.at(0) : QString();
- table = info.size() > 1 ? info.at(1) : QString();
- field = info.size() > 2 ? info.at(2) : QString();
- }
-
- if (table.isEmpty() || connection.isEmpty()) {
- fprintf(stderr, "%s: Warning: Invalid database connection\n", qPrintable(m_option.messagePrefix()));
- return;
- }
-
- const QString varName = m_driver->findOrInsertWidget(w);
-
- m_output << m_indent << "if (!" << varName << "->sqlCursor()) {\n";
-
- m_output << m_dindent << varName << "->setSqlCursor(";
-
- if (connection == QLatin1String("(default)")) {
- m_output << "new Q3SqlCursor(" << fixString(table, m_dindent) << "), true);\n";
- } else {
- m_output << "new Q3SqlCursor(" << fixString(table, m_dindent) << ", true, " << connection << "Connection" << "), false, true);\n";
- }
- m_output << m_dindent << varName << "->refresh();\n";
- m_output << m_indent << "}\n";
-}
-
void WriteInitialization::initializeMenu(DomWidget *w, const QString &/*parentWidget*/)
{
const QString menuName = m_driver->findOrInsertWidget(w);
diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h
index 302fbe4bc5..09983cff14 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.h
+++ b/src/tools/uic/cpp/cppwriteinitialization.h
@@ -241,7 +241,6 @@ private:
void initializeMenu(DomWidget *w, const QString &parentWidget);
void initializeComboBox(DomWidget *w);
- void initializeComboBox3(DomWidget *w);
void initializeListWidget(DomWidget *w);
void initializeTreeWidget(DomWidget *w);
QList<Item *> initializeTreeWidgetItems(const QList<DomItem *> &domItems);
@@ -250,22 +249,6 @@ private:
QString disableSorting(DomWidget *w, const QString &varName);
void enableSorting(DomWidget *w, const QString &varName, const QString &tempName);
-//
-// special initialization for the Q3 support classes
-//
- void initializeQ3ListBox(DomWidget *w);
- void initializeQ3IconView(DomWidget *w);
- void initializeQ3ListView(DomWidget *w);
- void initializeQ3ListViewItems(const QString &className, const QString &varName, const QList<DomItem*> &items);
- void initializeQ3Table(DomWidget *w);
- void initializeQ3TableItems(const QString &className, const QString &varName, const QList<DomItem*> &items);
-
-//
-// Sql
-//
- void initializeQ3SqlDataTable(DomWidget *w);
- void initializeQ3SqlDataBrowser(DomWidget *w);
-
QString findDeclaration(const QString &name);
DomWidget *findWidget(const QLatin1String &widgetClass);
DomImage *findImage(const QString &name) const;
diff --git a/src/tools/uic/uic.cpp b/src/tools/uic/uic.cpp
index f045e58d2e..b616f77b94 100644
--- a/src/tools/uic/uic.cpp
+++ b/src/tools/uic/uic.cpp
@@ -333,14 +333,12 @@ void Uic::writeHeaderProtectionEnd()
bool Uic::isMainWindow(const QString &className) const
{
- return customWidgetsInfo()->extends(className, QLatin1String("Q3MainWindow"))
- || customWidgetsInfo()->extends(className, QLatin1String("QMainWindow"));
+ return customWidgetsInfo()->extends(className, QLatin1String("QMainWindow"));
}
bool Uic::isToolBar(const QString &className) const
{
- return customWidgetsInfo()->extends(className, QLatin1String("Q3ToolBar"))
- || customWidgetsInfo()->extends(className, QLatin1String("QToolBar"));
+ return customWidgetsInfo()->extends(className, QLatin1String("QToolBar"));
}
bool Uic::isButton(const QString &className) const
diff --git a/src/uitools/quiloader.cpp b/src/uitools/quiloader.cpp
index 9d5a9d3107..6270e35d54 100644
--- a/src/uitools/quiloader.cpp
+++ b/src/uitools/quiloader.cpp
@@ -505,7 +505,7 @@ bool FormBuilderPrivate::addItem(DomWidget *ui_widget, QWidget *widget, QWidget
// Check special cases. First: Custom container
const QString className = QLatin1String(parentWidget->metaObject()->className());
- if (!QFormBuilderExtra::instance(this)->customWidgetAddPageMethod(className).isEmpty())
+ if (!d->customWidgetAddPageMethod(className).isEmpty())
return true;
const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
diff --git a/src/widgets/accessible/qaccessible.h b/src/widgets/accessible/qaccessible.h
index be3d4b5ffc..33e76a7ad2 100644
--- a/src/widgets/accessible/qaccessible.h
+++ b/src/widgets/accessible/qaccessible.h
@@ -83,6 +83,42 @@ public:
MenuCommand = 0x0018,
+ // Values from IAccessible2
+ ActionChanged = 0x0101,
+ ActiveDescendantChanged,
+ AttributeChanged,
+ DocumentContentChanged,
+ DocumentLoadComplete,
+ DocumentLoadStopped,
+ DocumentReload,
+ HyperlinkEndIndexChanged,
+ HyperlinkNumberOfAnchorsChanged,
+ HyperlinkSelectedLinkChanged,
+ HypertextLinkActivated,
+ HypertextLinkSelected,
+ HyperlinkStartIndexChanged,
+ HypertextChanged,
+ HypertextNLinksChanged,
+ ObjectAttributeChanged,
+ PageChanged,
+ SectionChanged,
+ TableCaptionChanged,
+ TableColumnDescriptionChanged,
+ TableColumnHeaderChanged,
+ TableModelChanged,
+ TableRowDescriptionChanged,
+ TableRowHeaderChanged,
+ TableSummaryChanged,
+ TextAttributeChanged,
+ TextCaretMoved,
+ TextChanged,
+ TextColumnChanged,
+ TextInserted,
+ TextRemoved,
+ TextUpdated,
+ TextSelectionChanged,
+ VisibleDataChanged,
+
ObjectCreated = 0x8000,
ObjectDestroyed = 0x8001,
ObjectShow = 0x8002,
diff --git a/src/widgets/accessible/qaccessible_win.cpp b/src/widgets/accessible/qaccessible_win.cpp
index caa21043d8..98db5293d2 100644
--- a/src/widgets/accessible/qaccessible_win.cpp
+++ b/src/widgets/accessible/qaccessible_win.cpp
@@ -47,6 +47,11 @@
#include "qt_windows.h"
#include "qwidget.h"
#include "qsettings.h"
+#include <QtCore/qmap.h>
+#include <QtCore/qpair.h>
+#include <QtGui/qgraphicsitem.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicsview.h>
#include <winuser.h>
#if !defined(WINABLEAPI)
@@ -148,6 +153,106 @@ static const char *roleString(QAccessible::Role role)
return roles[int(role)];
}
+static const char *eventString(QAccessible::Event ev)
+{
+ static const char *events[] = {
+ "null", // 0
+ "SoundPlayed" /*= 0x0001*/,
+ "Alert" /*= 0x0002*/,
+ "ForegroundChanged" /*= 0x0003*/,
+ "MenuStart" /*= 0x0004*/,
+ "MenuEnd" /*= 0x0005*/,
+ "PopupMenuStart" /*= 0x0006*/,
+ "PopupMenuEnd" /*= 0x0007*/,
+ "ContextHelpStart" /*= 0x000C*/, // 8
+ "ContextHelpEnd" /*= 0x000D*/,
+ "DragDropStart" /*= 0x000E*/,
+ "DragDropEnd" /*= 0x000F*/,
+ "DialogStart" /*= 0x0010*/,
+ "DialogEnd" /*= 0x0011*/,
+ "ScrollingStart" /*= 0x0012*/,
+ "ScrollingEnd" /*= 0x0013*/,
+ "MenuCommand" /*= 0x0018*/, // 16
+
+ // Values from IAccessible2
+ "ActionChanged" /*= 0x0101*/, // 17
+ "ActiveDescendantChanged",
+ "AttributeChanged",
+ "DocumentContentChanged",
+ "DocumentLoadComplete",
+ "DocumentLoadStopped",
+ "DocumentReload",
+ "HyperlinkEndIndexChanged",
+ "HyperlinkNumberOfAnchorsChanged",
+ "HyperlinkSelectedLinkChanged",
+ "HypertextLinkActivated",
+ "HypertextLinkSelected",
+ "HyperlinkStartIndexChanged",
+ "HypertextChanged",
+ "HypertextNLinksChanged",
+ "ObjectAttributeChanged",
+ "PageChanged",
+ "SectionChanged",
+ "TableCaptionChanged",
+ "TableColumnDescriptionChanged",
+ "TableColumnHeaderChanged",
+ "TableModelChanged",
+ "TableRowDescriptionChanged",
+ "TableRowHeaderChanged",
+ "TableSummaryChanged",
+ "TextAttributeChanged",
+ "TextCaretMoved",
+ // TextChanged, deprecated, use TextUpdated
+ //TextColumnChanged = TextCaretMoved + 2,
+ "TextInserted",
+ "TextRemoved",
+ "TextUpdated",
+ "TextSelectionChanged",
+ "VisibleDataChanged", /*= 0x0101+32*/
+ "ObjectCreated" /*= 0x8000*/, // 49
+ "ObjectDestroyed" /*= 0x8001*/,
+ "ObjectShow" /*= 0x8002*/,
+ "ObjectHide" /*= 0x8003*/,
+ "ObjectReorder" /*= 0x8004*/,
+ "Focus" /*= 0x8005*/,
+ "Selection" /*= 0x8006*/,
+ "SelectionAdd" /*= 0x8007*/,
+ "SelectionRemove" /*= 0x8008*/,
+ "SelectionWithin" /*= 0x8009*/,
+ "StateChanged" /*= 0x800A*/,
+ "LocationChanged" /*= 0x800B*/,
+ "NameChanged" /*= 0x800C*/,
+ "DescriptionChanged" /*= 0x800D*/,
+ "ValueChanged" /*= 0x800E*/,
+ "ParentChanged" /*= 0x800F*/,
+ "HelpChanged" /*= 0x80A0*/,
+ "DefaultActionChanged" /*= 0x80B0*/,
+ "AcceleratorChanged" /*= 0x80C0*/
+ };
+ int e = int(ev);
+ if (e <= 0x80c0) {
+ const int last = sizeof(events)/sizeof(char*) - 1;
+
+ if (e <= 0x07)
+ return events[e];
+ else if (e <= 0x13)
+ return events[e - 0x0c + 8];
+ else if (e == 0x18)
+ return events[16];
+ else if (e <= 0x0101 + 32)
+ return events[e - 0x101 + 17];
+ else if (e <= 0x800f)
+ return events[e - 0x8000 + 49];
+ else if (e == 0x80a0)
+ return events[last - 2];
+ else if (e == 0x80b0)
+ return events[last - 1];
+ else if (e == 0x80c0)
+ return events[last];
+ }
+ return "unknown";
+};
+
void showDebug(const char* funcName, const QAccessibleInterface *iface)
{
qDebug() << "Role:" << roleString(iface->role(0))
@@ -159,6 +264,12 @@ void showDebug(const char* funcName, const QAccessibleInterface *iface)
# define showDebug(f, iface)
#endif
+// This stuff is used for widgets/items with no window handle:
+typedef QMap<int, QPair<QObject*,int> > NotifyMap;
+Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents)
+static int eventNum = 0;
+
+
void QAccessible::initialize()
{
@@ -251,18 +362,35 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
// An event has to be associated with a window,
// so find the first parent that is a widget.
QWidget *w = 0;
- if (o->isWidgetType()) {
- w = (QWidget*)o;
- } else {
- QObject *p = o;
- while ((p = p->parent()) != 0) {
- if (p->isWidgetType()) {
- w = (QWidget*)p;
+ QObject *p = o;
+ do {
+ if (p->isWidgetType()) {
+ w = static_cast<QWidget*>(p);
+ if (w->internalWinId())
break;
+ }
+ if (QGraphicsObject *gfxObj = qobject_cast<QGraphicsObject*>(p)) {
+ QGraphicsItem *parentItem = gfxObj->parentItem();
+ if (parentItem) {
+ p = parentItem->toGraphicsObject();
+ } else {
+ QGraphicsView *view = 0;
+ if (QGraphicsScene *scene = gfxObj->scene()) {
+ QWidget *fw = QApplication::focusWidget();
+ const QList<QGraphicsView*> views = scene->views();
+ for (int i = 0 ; i < views.count() && view != fw; ++i) {
+ view = views.at(i);
+ }
+ }
+ p = view;
}
+ } else {
+ p = p->parent();
}
- }
+ } while (p);
+
+ //qDebug() << "updateAccessibility(), hwnd:" << w << ", object:" << o << "," << eventString(reason);
if (!w) {
if (reason != QAccessible::ContextHelpStart &&
reason != QAccessible::ContextHelpEnd)
@@ -282,12 +410,81 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
}
}
+ WId wid = w->internalWinId();
if (reason != MenuCommand) { // MenuCommand is faked
- ptrNotifyWinEvent(reason, w->winId(), OBJID_CLIENT, who);
+ if (w != o) {
+ // See comment "SENDING EVENTS TO OBJECTS WITH NO WINDOW HANDLE"
+ eventNum %= 50; //[0..49]
+ int eventId = - eventNum - 1;
+
+ qAccessibleRecentSentEvents()->insert(eventId, qMakePair(o,who));
+ ptrNotifyWinEvent(reason, wid, OBJID_CLIENT, eventId );
+
+ ++eventNum;
+ } else {
+ ptrNotifyWinEvent(reason, wid, OBJID_CLIENT, who);
+ }
}
#endif // Q_WS_WINCE
}
+/* == SENDING EVENTS TO OBJECTS WITH NO WINDOW HANDLE ==
+
+ If the user requested to send the event to a widget with no window,
+ we need to send an event to an object with no hwnd.
+ The way we do that is to send it to the *first* ancestor widget
+ with a window.
+ Then we'll need a way of identifying the child:
+ We'll just keep a list of the most recent events that we have sent,
+ where each entry in the list is identified by a negative value
+ between [-50,-1]. This negative value we will pass on to
+ NotifyWinEvent() as the child id. When the negative value have
+ reached -50, it will wrap around to -1. This seems to be enough
+
+ Now, when the client receives that event, he will first call
+ AccessibleObjectFromEvent() where dwChildID is the special
+ negative value. AccessibleObjectFromEvent does two steps:
+ 1. It will first sent a WM_GETOBJECT to the server, asking
+ for the IAccessible interface for the HWND.
+ 2. With the IAccessible interface it got hold of it will call
+ acc_getChild where the child id argument is the special
+ negative identifier. In our reimplementation of get_accChild
+ we check for this if the child id is negative. If it is, then
+ we'll look up in our table for the entry that is associated
+ with that value.
+ The entry will then contain a pointer to the QObject /QWidget
+ that we can use to call queryAccessibleInterface() on.
+
+
+ The following figure shows how the interaction between server and
+ client is in the case when the server is sending an event.
+
+SERVER (Qt) | CLIENT |
+--------------------------------------------+---------------------------------------+
+ |
+acc->updateAccessibility(obj, childIndex) |
+ |
+recentEvents()->insert(- 1 - eventNum, |
+ qMakePair(obj, childIndex) |
+NotifyWinEvent(hwnd, childId) => |
+ | AccessibleObjectFromEvent(event, hwnd, OBJID_CLIENT, childId )
+ | will do:
+ <=== 1. send WM_GETOBJECT(hwnd, OBJID_CLIENT)
+widget ~= hwnd
+iface = queryAccessibleInteface(widget)
+(create IAccessible interface wrapper for
+ iface)
+ return iface ===> IAccessible* iface; (for hwnd)
+ |
+ <=== call iface->get_accChild(childId)
+get_accChild() { |
+ if (varChildID.lVal < 0) {
+ QPair ref = recentEvents().value(varChildID.lVal);
+ [...]
+ }
+*/
+
+
void QAccessible::setRootObject(QObject *o)
{
if (rootObjectHandler) {
@@ -418,15 +615,18 @@ public:
delete accessible;
}
+ /* IUnknown */
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
+ /* IDispatch */
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *);
HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int, unsigned long, ITypeInfo **);
HRESULT STDMETHODCALLTYPE GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *);
HRESULT STDMETHODCALLTYPE Invoke(long, const _GUID &, unsigned long, unsigned short, tagDISPPARAMS *, tagVARIANT *, tagEXCEPINFO *, unsigned int *);
+ /* IAccessible */
HRESULT STDMETHODCALLTYPE accHitTest(long xLeft, long yTop, VARIANT *pvarID);
HRESULT STDMETHODCALLTYPE accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID);
HRESULT STDMETHODCALLTYPE accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd);
@@ -451,6 +651,7 @@ public:
HRESULT STDMETHODCALLTYPE get_accFocus(VARIANT *pvarID);
HRESULT STDMETHODCALLTYPE get_accSelection(VARIANT *pvarChildren);
+ /* IOleWindow */
HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
@@ -896,9 +1097,30 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I
if (varChildID.vt == VT_EMPTY)
return E_INVALIDARG;
+
+ int childIndex = varChildID.lVal;
QAccessibleInterface *acc = 0;
- RelationFlag rel = varChildID.lVal ? Child : Self;
- accessible->navigate(rel, varChildID.lVal, &acc);
+
+ if (childIndex < 0) {
+ const int entry = childIndex;
+ QPair<QObject*, int> ref = qAccessibleRecentSentEvents()->value(entry);
+ if (ref.first) {
+ acc = queryAccessibleInterface(ref.first);
+ if (acc && ref.second) {
+ if (ref.second) {
+ QAccessibleInterface *res;
+ int index = acc->navigate(Child, ref.second, &res);
+ delete acc;
+ if (index == -1)
+ return E_INVALIDARG;
+ acc = res;
+ }
+ }
+ }
+ } else {
+ RelationFlag rel = childIndex ? Child : Self;
+ accessible->navigate(rel, childIndex, &acc);
+ }
if (acc) {
QWindowsAccessible* wacc = new QWindowsAccessible(acc);
@@ -1203,7 +1425,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetWindow(HWND *phwnd)
if (!o || !o->isWidgetType())
return E_FAIL;
- *phwnd = static_cast<QWidget*>(o)->winId();
+ *phwnd = static_cast<QWidget*>(o)->effectiveWinId();
return S_OK;
}
diff --git a/src/widgets/accessible/qaccessibleobject.cpp b/src/widgets/accessible/qaccessibleobject.cpp
index 1d2d1da806..0cb2c08a3e 100644
--- a/src/widgets/accessible/qaccessibleobject.cpp
+++ b/src/widgets/accessible/qaccessibleobject.cpp
@@ -322,9 +322,7 @@ QString QAccessibleApplication::text(Text t, int) const
{
switch (t) {
case Name:
- if (QApplication::activeWindow())
- return QApplication::activeWindow()->windowTitle();
- break;
+ return QApplication::applicationName();
case Description:
return QApplication::applicationFilePath();
default:
diff --git a/src/widgets/dialogs/qcolordialog_mac.mm b/src/widgets/dialogs/qcolordialog_mac.mm
index ee9b19ad99..9daf595a9b 100644
--- a/src/widgets/dialogs/qcolordialog_mac.mm
+++ b/src/widgets/dialogs/qcolordialog_mac.mm
@@ -343,6 +343,7 @@ QT_USE_NAMESPACE
mDialogIsExecuting = true;
bool modalEnded = false;
while (!modalEnded) {
+#ifndef QT_NO_EXCEPTIONS
@try {
[NSApp runModalForWindow:mColorPanel];
modalEnded = true;
@@ -351,6 +352,10 @@ QT_USE_NAMESPACE
// clicking on 'SelectedMenuItemColor' from the 'Developer'
// palette (tab three).
}
+#else
+ [NSApp runModalForWindow:mColorPanel];
+ modalEnded = true;
+#endif
}
QAbstractEventDispatcher::instance()->interrupt();
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index cb8eb6ad66..ff4410db97 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -1977,13 +1977,14 @@ bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) co
const bool hideHidden = !(filters & QDir::Hidden);
const bool hideSystem = !(filters & QDir::System);
const bool hideSymlinks = (filters & QDir::NoSymLinks);
- const bool hideDotAndDotDot = (filters & QDir::NoDotAndDotDot);
+ const bool hideDot = (filters & QDir::NoDot) || (filters & QDir::NoDotAndDotDot); // ### Qt5: simplify (because NoDotAndDotDot=NoDot|NoDotDot)
+ const bool hideDotDot = (filters & QDir::NoDotDot) || (filters & QDir::NoDotAndDotDot); // ### Qt5: simplify (because NoDotAndDotDot=NoDot|NoDotDot)
// Note that we match the behavior of entryList and not QFileInfo on this and this
// incompatibility won't be fixed until Qt 5 at least
- bool isDotOrDot = ( (node->fileName == QLatin1String(".")
- || node->fileName == QLatin1String("..")));
- if ( (hideHidden && (!isDotOrDot && node->isHidden()))
+ bool isDot = (node->fileName == QLatin1String("."));
+ bool isDotDot = (node->fileName == QLatin1String(".."));
+ if ( (hideHidden && !(isDot || isDotDot) && node->isHidden())
|| (hideSystem && node->isSystem())
|| (hideDirs && node->isDir())
|| (hideFiles && node->isFile())
@@ -1991,7 +1992,8 @@ bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) co
|| (hideReadable && node->isReadable())
|| (hideWritable && node->isWritable())
|| (hideExecutable && node->isExecutable())
- || (hideDotAndDotDot && isDotOrDot))
+ || (hideDot && isDot)
+ || (hideDotDot && isDotDot))
return false;
return nameFilterDisables || passNameFilters(node);
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
index 38ddeb5ba7..5f9841ed12 100644
--- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -451,8 +451,8 @@ static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal valu
static qreal interpolate(const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> &factor,
qreal min, qreal minPref, qreal pref, qreal maxPref, qreal max)
{
- qreal lower;
- qreal upper;
+ qreal lower = 0;
+ qreal upper = 0;
switch (factor.first) {
case QGraphicsAnchorLayoutPrivate::MinimumToMinPreferred:
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index af9102f431..72ec5688f6 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -7395,15 +7395,19 @@ void QGraphicsItem::updateMicroFocus()
if (QWidget *fw = QApplication::focusWidget()) {
if (scene()) {
for (int i = 0 ; i < scene()->views().count() ; ++i) {
- if (scene()->views().at(i) == fw)
- if (QInputContext *inputContext = fw->inputContext())
+ 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);
+ // ##### is this correct
+ if (toGraphicsObject())
+ QAccessible::updateAccessibility(toGraphicsObject(), 0, QAccessible::StateChanged);
#endif
+ break;
+ }
+ }
+ }
+ }
}
#endif
}
diff --git a/src/widgets/graphicsview/qgraphicslayout.cpp b/src/widgets/graphicsview/qgraphicslayout.cpp
index 904a3deda2..5bd298061d 100644
--- a/src/widgets/graphicsview/qgraphicslayout.cpp
+++ b/src/widgets/graphicsview/qgraphicslayout.cpp
@@ -167,7 +167,7 @@ QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutItem *parent)
" neither a QGraphicsWidget nor QGraphicsLayout");
}
}
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
+ d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
setOwnedByLayout(true);
}
@@ -188,7 +188,7 @@ QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutPrivate &dd, QGraphicsLayoutItem
" neither a QGraphicsWidget nor QGraphicsLayout");
}
}
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
+ d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
setOwnedByLayout(true);
}
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index 0231dd9963..8403dfb1fb 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -245,6 +245,9 @@
#include <QtGui/qtransform.h>
#include <QtWidgets/qinputcontext.h>
#include <QtWidgets/qgraphicseffect.h>
+#ifndef QT_NO_ACCESSIBILITY
+# include <QtWidgets/qaccessible.h>
+#endif
#include <private/qapplication_p.h>
#include <private/qobject_p.h>
#ifdef Q_WS_X11
@@ -837,6 +840,14 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item,
if (item)
focusItem = item;
updateInputMethodSensitivityInViews();
+
+#ifndef QT_NO_ACCESSIBILITY
+ if (focusItem) {
+ if (QGraphicsObject *focusObj = focusItem->toGraphicsObject()) {
+ QAccessible::updateAccessibility(focusObj, 0, QAccessible::Focus);
+ }
+ }
+#endif
if (item) {
QFocusEvent event(QEvent::FocusIn, focusReason);
sendEvent(item, &event);
diff --git a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
index 92e4a55952..4688fa0b6b 100644
--- a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
+++ b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -50,14 +50,14 @@
QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning)
implementation to discover items quickly. This implementation is
- very efficient for static scene. It has a depth that you can set.
+ very efficient for static scenes. It has a depth that you can set.
The depth directly affects performance and memory usage; the latter
growing exponentially with the depth of the tree. With an optimal tree
depth, the index can instantly determine the locality of items, even
for scenes with thousands or millions of items. This also greatly improves
rendering performance.
- By default, the value is 0, in which case Qt will guess a reasonable
+ By default, the depth value is 0, in which case Qt will guess a reasonable
default depth based on the size, location and number of items in the
scene. If these parameters change frequently, however, you may experience
slowdowns as the index retunes the depth internally. You can avoid
diff --git a/src/widgets/graphicsview/qgraphicswidget_p.cpp b/src/widgets/graphicsview/qgraphicswidget_p.cpp
index cb2a2038c7..ec36c08041 100644
--- a/src/widgets/graphicsview/qgraphicswidget_p.cpp
+++ b/src/widgets/graphicsview/qgraphicswidget_p.cpp
@@ -857,8 +857,6 @@ void QGraphicsWidgetPrivate::setWidth(qreal w)
if (q->geometry().width() == w)
return;
- QRectF oldGeom = q->geometry();
-
q->setGeometry(QRectF(q->x(), q->y(), w, height()));
}
@@ -882,8 +880,6 @@ void QGraphicsWidgetPrivate::setHeight(qreal h)
if (q->geometry().height() == h)
return;
- QRectF oldGeom = q->geometry();
-
q->setGeometry(QRectF(q->x(), q->y(), width(), h));
}
diff --git a/src/widgets/itemviews/qabstractproxymodel.cpp b/src/widgets/itemviews/qabstractproxymodel.cpp
index 34ca7dff50..82b6c8d26a 100644
--- a/src/widgets/itemviews/qabstractproxymodel.cpp
+++ b/src/widgets/itemviews/qabstractproxymodel.cpp
@@ -121,15 +121,12 @@ QAbstractProxyModel::~QAbstractProxyModel()
void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
Q_D(QAbstractProxyModel);
- if (d->model) {
+ if (d->model)
disconnect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
- disconnect(d->model, SIGNAL(modelReset()), this, SLOT(resetInternalData()));
- }
if (sourceModel) {
d->model = sourceModel;
connect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
- connect(d->model, SIGNAL(modelReset()), this, SLOT(resetInternalData()));
} else {
d->model = QAbstractItemModelPrivate::staticEmptyModel();
}
@@ -383,25 +380,6 @@ Qt::DropActions QAbstractProxyModel::supportedDropActions() const
return d->model->supportedDropActions();
}
-/*
- \since 4.8
-
- This slot is called just after the internal data of a model is cleared
- while it is being reset.
-
- This slot is provided the convenience of subclasses of concrete proxy
- models, such as subclasses of QSortFilterProxyModel which maintain extra
- data.
-
- \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 10
-
- \sa modelAboutToBeReset(), modelReset()
-*/
-void QAbstractProxyModel::resetInternalData()
-{
-
-}
-
QT_END_NAMESPACE
#include "moc_qabstractproxymodel.cpp"
diff --git a/src/widgets/itemviews/qabstractproxymodel.h b/src/widgets/itemviews/qabstractproxymodel.h
index 6e485aec12..4f3bc18448 100644
--- a/src/widgets/itemviews/qabstractproxymodel.h
+++ b/src/widgets/itemviews/qabstractproxymodel.h
@@ -95,9 +95,6 @@ public:
QStringList mimeTypes() const;
Qt::DropActions supportedDropActions() const;
-protected Q_SLOTS:
- void resetInternalData();
-
protected:
QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent);
diff --git a/src/widgets/itemviews/qdatawidgetmapper.cpp b/src/widgets/itemviews/qdatawidgetmapper.cpp
index 745ef5af91..dac4613071 100644
--- a/src/widgets/itemviews/qdatawidgetmapper.cpp
+++ b/src/widgets/itemviews/qdatawidgetmapper.cpp
@@ -291,7 +291,7 @@ void QDataWidgetMapperPrivate::_q_modelDestroyed()
\snippet doc/src/snippets/code/src_gui_itemviews_qdatawidgetmapper.cpp 0
After the call to toFirst(), \c mySpinBox displays the value \c{1}, \c myLineEdit
- displays \c {Nokia Corporation and/or its subsidiary(-ies)} and \c myCountryChooser displays \c{Oslo}. The
+ displays \c{Qt Norway} and \c myCountryChooser displays \c{Oslo}. The
navigational functions toFirst(), toNext(), toPrevious(), toLast() and setCurrentIndex()
can be used to navigate in the model and update the widgets with contents from
the model.
diff --git a/src/widgets/itemviews/qitemselectionmodel.cpp b/src/widgets/itemviews/qitemselectionmodel.cpp
index 27a4a402e2..0b6445298e 100644
--- a/src/widgets/itemviews/qitemselectionmodel.cpp
+++ b/src/widgets/itemviews/qitemselectionmodel.cpp
@@ -1145,11 +1145,8 @@ void QItemSelectionModel::clearSelection()
Q_D(QItemSelectionModel);
if (d->ranges.count() == 0 && d->currentSelection.count() == 0)
return;
- QItemSelection selection = d->ranges;
- selection.merge(d->currentSelection, d->currentCommand);
- d->ranges.clear();
- d->currentSelection.clear();
- emit selectionChanged(QItemSelection(), selection);
+
+ select(QItemSelection(), Clear);
}
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index e494ee5564..e70f3569aa 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -1104,6 +1104,21 @@ void QTableView::setRootIndex(const QModelIndex &index)
/*!
\reimp
*/
+void QTableView::doItemsLayout()
+{
+ Q_D(QTableView);
+ QAbstractItemView::doItemsLayout();
+ if (verticalScrollMode() == QAbstractItemView::ScrollPerItem)
+ d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
+ else
+ d->verticalHeader->setOffset(verticalScrollBar()->value());
+ if (!d->verticalHeader->updatesEnabled())
+ d->verticalHeader->setUpdatesEnabled(true);
+}
+
+/*!
+ \reimp
+*/
void QTableView::setSelectionModel(QItemSelectionModel *selectionModel)
{
Q_D(QTableView);
@@ -1285,7 +1300,6 @@ void QTableView::paintEvent(QPaintEvent *event)
const QPen gridPen = QPen(gridColor, 0, d->gridStyle);
const QHeaderView *verticalHeader = d->verticalHeader;
const QHeaderView *horizontalHeader = d->horizontalHeader;
- const QStyle::State state = option.state;
const bool alternate = d->alternatingColors;
const bool rightToLeft = isRightToLeft();
@@ -1975,9 +1989,13 @@ QModelIndexList QTableView::selectedIndexes() const
previous number of rows is specified by \a oldCount, and the new
number of rows is specified by \a newCount.
*/
-void QTableView::rowCountChanged(int /*oldCount*/, int /*newCount*/ )
+void QTableView::rowCountChanged(int oldCount, int newCount )
{
Q_D(QTableView);
+ //when removing rows, we need to disable updates for the header until the geometries have been
+ //updated and the offset has been adjusted, or we risk calling paintSection for all the sections
+ if (newCount < oldCount)
+ d->verticalHeader->setUpdatesEnabled(false);
d->doDelayedItemsLayout();
}
diff --git a/src/widgets/itemviews/qtableview.h b/src/widgets/itemviews/qtableview.h
index 0ef5daf0ef..7dfe262b6d 100644
--- a/src/widgets/itemviews/qtableview.h
+++ b/src/widgets/itemviews/qtableview.h
@@ -71,6 +71,7 @@ public:
void setModel(QAbstractItemModel *model);
void setRootIndex(const QModelIndex &index);
void setSelectionModel(QItemSelectionModel *selectionModel);
+ void doItemsLayout();
QHeaderView *horizontalHeader() const;
QHeaderView *verticalHeader() const;
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 5359fb37e8..7aa7dffd9b 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -566,7 +566,6 @@ void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
= w->d_func()->gestureContext.find(type);
if (it != w->d_func()->gestureContext.end()) {
// i.e. 'w' listens to gesture 'type'
- Qt::GestureFlags flags = it.value();
if (!(it.value() & Qt::DontStartGestureOnChildren) && w != widget) {
// conflicting gesture!
(*conflicts)[widget].append(gestures[widget]);
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index e2969aad74..1728cfa57c 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1582,6 +1582,7 @@ QWidget::~QWidget()
// delete layout while we still are a valid widget
delete d->layout;
+ d->layout = 0;
// Remove myself from focus list
Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
@@ -11177,6 +11178,7 @@ void QWidget::setAccessibleName(const QString &name)
{
Q_D(QWidget);
d->accessibleName = name;
+ QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged);
}
QString QWidget::accessibleName() const
@@ -11198,6 +11200,7 @@ void QWidget::setAccessibleDescription(const QString &description)
{
Q_D(QWidget);
d->accessibleDescription = description;
+ QAccessible::updateAccessibility(this, 0, QAccessible::DescriptionChanged);
}
QString QWidget::accessibleDescription() const
@@ -11313,8 +11316,10 @@ void QWidget::updateMicroFocus()
}
#endif
#ifndef QT_NO_ACCESSIBILITY
- // ##### is this correct
- QAccessible::updateAccessibility(this, 0, QAccessible::StateChanged);
+ if (isVisible()) {
+ // ##### is this correct
+ QAccessible::updateAccessibility(this, 0, QAccessible::StateChanged);
+ }
#endif
}
diff --git a/src/widgets/platforms/mac/qfont_mac.cpp b/src/widgets/platforms/mac/qfont_mac.cpp
index daf68c03ea..044fd84a8b 100644
--- a/src/widgets/platforms/mac/qfont_mac.cpp
+++ b/src/widgets/platforms/mac/qfont_mac.cpp
@@ -43,6 +43,7 @@
#include "qfont_p.h"
#include "qfontengine_p.h"
#include "qfontengine_mac_p.h"
+#include "qfontengine_coretext_p.h"
#include "qfontinfo.h"
#include "qfontmetrics.h"
#include "qpaintdevice.h"
@@ -119,10 +120,10 @@ quint32 QFont::macFontID() const // ### need 64-bit version
// Returns an ATSUFonFamilyRef
Qt::HANDLE QFont::handle() const
{
-#if 0
+#ifdef QT_MAC_USE_COCOA
QFontEngine *fe = d->engineForScript(QUnicodeTables::Common);
- if (fe && fe->type() == QFontEngine::Mac)
- return (Qt::HANDLE)static_cast<QFontEngineMacMulti*>(fe)->fontFamilyRef();
+ if (fe && fe->type() == QFontEngine::Multi)
+ return (Qt::HANDLE)static_cast<QCoreTextFontEngineMulti*>(fe)->macFontID();
#endif
return 0;
}
diff --git a/src/widgets/platforms/mac/qfontengine_coretext.mm b/src/widgets/platforms/mac/qfontengine_coretext.mm
index d4df2183ed..cbf51e6ec5 100644
--- a/src/widgets/platforms/mac/qfontengine_coretext.mm
+++ b/src/widgets/platforms/mac/qfontengine_coretext.mm
@@ -871,7 +871,7 @@ QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const
newFontDef.pixelSize = pixelSize;
newFontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi();
- return new QCoreTextFontEngine(cgFont, fontDef);
+ return new QCoreTextFontEngine(cgFont, newFontDef);
}
QT_END_NAMESPACE
diff --git a/src/widgets/platforms/mac/qfontengine_coretext_p.h b/src/widgets/platforms/mac/qfontengine_coretext_p.h
index bb80a9b2f3..3775bc6002 100644
--- a/src/widgets/platforms/mac/qfontengine_coretext_p.h
+++ b/src/widgets/platforms/mac/qfontengine_coretext_p.h
@@ -124,6 +124,8 @@ public:
QScriptItem *si) const;
virtual const char *name() const { return "CoreText"; }
+ inline CTFontRef macFontID() const { return ctfont; }
+
protected:
virtual void loadEngine(int at);
diff --git a/src/widgets/platforms/mac/qpaintengine_mac.cpp b/src/widgets/platforms/mac/qpaintengine_mac.cpp
index c6d061dea8..6dcc3cc9fc 100644
--- a/src/widgets/platforms/mac/qpaintengine_mac.cpp
+++ b/src/widgets/platforms/mac/qpaintengine_mac.cpp
@@ -1546,8 +1546,9 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset)
QPointF center(radialGrad->center());
QPointF focal(radialGrad->focalPoint());
qreal radius = radialGrad->radius();
+ qreal focalRadius = radialGrad->focalRadius();
shading = CGShadingCreateRadial(colorspace, CGPointMake(focal.x(), focal.y()),
- 0.0, CGPointMake(center.x(), center.y()), radius, fill_func, false, true);
+ focalRadius, CGPointMake(center.x(), center.y()), radius, fill_func, false, true);
}
CGFunctionRelease(fill_func);
diff --git a/src/widgets/platforms/mac/qwidget_mac.mm b/src/widgets/platforms/mac/qwidget_mac.mm
index 354f05ba10..27a1bb6940 100644
--- a/src/widgets/platforms/mac/qwidget_mac.mm
+++ b/src/widgets/platforms/mac/qwidget_mac.mm
@@ -2733,7 +2733,7 @@ QWidget::macCGHandle() const
return handle();
}
-void qt_mac_repaintParentUnderAlienWidget(QWidget *alienWidget)
+void qt_mac_updateParentUnderAlienWidget(QWidget *alienWidget)
{
QWidget *nativeParent = alienWidget->nativeParentWidget();
if (!nativeParent)
@@ -2741,7 +2741,7 @@ void qt_mac_repaintParentUnderAlienWidget(QWidget *alienWidget)
QPoint globalPos = alienWidget->mapToGlobal(QPoint(0, 0));
QRect dirtyRect = QRect(nativeParent->mapFromGlobal(globalPos), alienWidget->size());
- nativeParent->repaint(dirtyRect);
+ nativeParent->update(dirtyRect);
}
void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
@@ -2752,7 +2752,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
if (!isWindow() && parentWidget())
parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
if (!internalWinId())
- qt_mac_repaintParentUnderAlienWidget(this);
+ qt_mac_updateParentUnderAlienWidget(this);
d->deactivateWidgetCleanup();
qt_mac_event_release(this);
if(testAttribute(Qt::WA_WState_Created)) {
@@ -3526,8 +3526,8 @@ void QWidgetPrivate::show_sys()
// INVARIANT: q is native. Just show the view:
[view setHidden:NO];
} else {
- // INVARIANT: q is alien. Repaint q instead:
- q->repaint();
+ // INVARIANT: q is alien. Update q instead:
+ q->update();
}
#endif
}
@@ -3683,7 +3683,7 @@ void QWidgetPrivate::hide_sys()
[view setHidden:YES];
} else {
// INVARIANT: q is alien. Repaint where q is placed instead:
- qt_mac_repaintParentUnderAlienWidget(q);
+ qt_mac_updateParentUnderAlienWidget(q);
}
#endif
}
diff --git a/src/widgets/platforms/s60/qapplication_s60.cpp b/src/widgets/platforms/s60/qapplication_s60.cpp
index 408c3b5883..222150056e 100644
--- a/src/widgets/platforms/s60/qapplication_s60.cpp
+++ b/src/widgets/platforms/s60/qapplication_s60.cpp
@@ -2703,6 +2703,9 @@ QS60ThreadLocalData::QS60ThreadLocalData()
QS60ThreadLocalData::~QS60ThreadLocalData()
{
+ for (int i = 0; i < releaseFuncs.count(); ++i)
+ releaseFuncs[i]();
+ releaseFuncs.clear();
if (!usingCONEinstances) {
delete screenDevice;
wsSession.Close();
diff --git a/src/widgets/platforms/s60/qfontdatabase_s60.cpp b/src/widgets/platforms/s60/qfontdatabase_s60.cpp
index 1db4a7d359..3ab1ac8850 100644
--- a/src/widgets/platforms/s60/qfontdatabase_s60.cpp
+++ b/src/widgets/platforms/s60/qfontdatabase_s60.cpp
@@ -152,7 +152,6 @@ public:
COpenFontRasterizer *m_rasterizer;
mutable QList<const QSymbianTypeFaceExtras *> m_extras;
- mutable QHash<QString, const QSymbianTypeFaceExtras *> m_extrasHash;
mutable QSet<QString> m_applicationFontFamilies;
};
@@ -255,8 +254,9 @@ void QSymbianFontDatabaseExtrasImplementation::clear()
static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
if (!dbExtras)
return; // initializeDb() has never been called
+ QSymbianTypeFaceExtrasHash &extrasHash = S60->fontData();
if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
- qDeleteAll(dbExtras->m_extrasHash);
+ qDeleteAll(extrasHash);
} else {
typedef QList<const QSymbianTypeFaceExtras *>::iterator iterator;
for (iterator p = dbExtras->m_extras.begin(); p != dbExtras->m_extras.end(); ++p) {
@@ -265,11 +265,16 @@ void QSymbianFontDatabaseExtrasImplementation::clear()
}
dbExtras->m_extras.clear();
}
- dbExtras->m_extrasHash.clear();
+ extrasHash.clear();
}
void qt_cleanup_symbianFontDatabase()
{
+ static bool cleanupDone = false;
+ if (cleanupDone)
+ return;
+ cleanupDone = true;
+
QFontDatabasePrivate *db = privateDb();
if (!db)
return;
@@ -320,9 +325,12 @@ COpenFont* OpenFontFromBitmapFont(const CBitmapFont* aBitmapFont)
const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &aTypeface,
bool bold, bool italic) const
{
+ QSymbianTypeFaceExtrasHash &extrasHash = S60->fontData();
+ if (extrasHash.isEmpty() && QThread::currentThread() != QApplication::instance()->thread())
+ S60->addThreadLocalReleaseFunc(clear);
const QString typeface = qt_symbian_fontNameWithAppFontMarker(aTypeface);
const QString searchKey = typeface + QString::number(int(bold)) + QString::number(int(italic));
- if (!m_extrasHash.contains(searchKey)) {
+ if (!extrasHash.contains(searchKey)) {
TFontSpec searchSpec(qt_QString2TPtrC(typeface), 1);
if (bold)
searchSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
@@ -336,7 +344,7 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c
QScopedPointer<CFont, CFontFromScreenDeviceReleaser> sFont(font);
QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font);
sFont.take();
- m_extrasHash.insert(searchKey, extras);
+ extrasHash.insert(searchKey, extras);
} else {
const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, searchSpec);
Q_ASSERT(err == KErrNone && font);
@@ -350,20 +358,20 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c
const TOpenFontFaceAttrib* const attrib = openFont->FaceAttrib();
const QString foundKey =
QString((const QChar*)attrib->FullName().Ptr(), attrib->FullName().Length());
- if (!m_extrasHash.contains(foundKey)) {
+ if (!extrasHash.contains(foundKey)) {
QScopedPointer<CFont, CFontFromFontStoreReleaser> sFont(font);
QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font, openFont);
sFont.take();
m_extras.append(extras);
- m_extrasHash.insert(searchKey, extras);
- m_extrasHash.insert(foundKey, extras);
+ extrasHash.insert(searchKey, extras);
+ extrasHash.insert(foundKey, extras);
} else {
m_store->ReleaseFont(font);
- m_extrasHash.insert(searchKey, m_extrasHash.value(foundKey));
+ extrasHash.insert(searchKey, extrasHash.value(foundKey));
}
}
}
- return m_extrasHash.value(searchKey);
+ return extrasHash.value(searchKey);
}
void QSymbianFontDatabaseExtrasImplementation::removeAppFontData(
@@ -956,7 +964,7 @@ bool QFontDatabase::removeAllApplicationFonts()
bool QFontDatabase::supportsThreadedFontRendering()
{
- return false;
+ return QSymbianTypeFaceExtras::symbianFontTableApiAvailable();
}
static
diff --git a/src/widgets/platforms/s60/qt_s60_p.h b/src/widgets/platforms/s60/qt_s60_p.h
index 8aba53a168..02977ceaf5 100644
--- a/src/widgets/platforms/s60/qt_s60_p.h
+++ b/src/widgets/platforms/s60/qt_s60_p.h
@@ -97,6 +97,10 @@ static const int qt_symbian_max_screens = 4;
//this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2
#define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13)
+class QSymbianTypeFaceExtras;
+typedef QHash<QString, const QSymbianTypeFaceExtras *> QSymbianTypeFaceExtrasHash;
+typedef void (*QThreadLocalReleaseFunc)();
+
class Q_AUTOTEST_EXPORT QS60ThreadLocalData
{
public:
@@ -105,6 +109,8 @@ public:
bool usingCONEinstances;
RWsSession wsSession;
CWsScreenDevice *screenDevice;
+ QSymbianTypeFaceExtrasHash fontData;
+ QVector<QThreadLocalReleaseFunc> releaseFuncs;
};
class QS60Data
@@ -175,6 +181,8 @@ public:
inline CWsScreenDevice* screenDevice(const QWidget *widget);
inline CWsScreenDevice* screenDevice(int screenNumber);
static inline int screenNumberForWidget(const QWidget *widget);
+ inline QSymbianTypeFaceExtrasHash& fontData();
+ inline void addThreadLocalReleaseFunc(QThreadLocalReleaseFunc func);
static inline CCoeAppUi* appUi();
static inline CEikMenuBar* menuBar();
#ifdef Q_WS_S60
@@ -470,6 +478,24 @@ inline int QS60Data::screenNumberForWidget(const QWidget *widget)
return qt_widget_private(const_cast<QWidget *>(w))->symbianScreenNumber;
}
+inline QSymbianTypeFaceExtrasHash& QS60Data::fontData()
+{
+ if (!tls.hasLocalData()) {
+ tls.setLocalData(new QS60ThreadLocalData);
+ }
+ return tls.localData()->fontData;
+}
+
+inline void QS60Data::addThreadLocalReleaseFunc(QThreadLocalReleaseFunc func)
+{
+ if (!tls.hasLocalData()) {
+ tls.setLocalData(new QS60ThreadLocalData);
+ }
+ QS60ThreadLocalData *data = tls.localData();
+ if (!data->releaseFuncs.contains(func))
+ data->releaseFuncs.append(func);
+}
+
inline CCoeAppUi* QS60Data::appUi()
{
return CCoeEnv::Static()-> AppUi();
diff --git a/src/widgets/platforms/s60/qwidget_s60.cpp b/src/widgets/platforms/s60/qwidget_s60.cpp
index e28a75a6ab..12bcc4b4cc 100644
--- a/src/widgets/platforms/s60/qwidget_s60.cpp
+++ b/src/widgets/platforms/s60/qwidget_s60.cpp
@@ -239,7 +239,16 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
if (w != oldSize.width() || h != oldSize.height())
data.window_state &= ~Qt::WindowMaximized;
- if (extra) { // any size restrictions?
+ bool checkExtra = true;
+ if (q->isWindow() && (data.window_state & Qt::WindowFullScreen)) {
+ // Do not modity window size for fullscreen windows, if requested
+ // size is already equal to clientRect.
+ TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ if (w == r.Width() && h == r.Height())
+ checkExtra = false;
+ }
+
+ if (checkExtra && extra) { // any size restrictions?
w = qMin(w,extra->maxw);
h = qMin(h,extra->maxh);
w = qMax(w,extra->minw);
diff --git a/src/widgets/platforms/win/qapplication_win.cpp b/src/widgets/platforms/win/qapplication_win.cpp
index 72a05afbd0..63e2319b3e 100644
--- a/src/widgets/platforms/win/qapplication_win.cpp
+++ b/src/widgets/platforms/win/qapplication_win.cpp
@@ -2372,8 +2372,13 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa
#ifndef QT_NO_ACCESSIBILITY
case WM_GETOBJECT:
{
+ /* On Win64, lParam can be 0x00000000fffffffc or 0xfffffffffffffffc (!),
+ but MSDN says that lParam should be converted to a DWORD
+ before its compared against OBJID_CLIENT
+ */
+ const DWORD dwObjId = (DWORD)lParam;
// Ignoring all requests while starting up
- if (QApplication::startingUp() || QApplication::closingDown() || lParam != (LPARAM)OBJID_CLIENT) {
+ if (QApplication::startingUp() || QApplication::closingDown() || dwObjId != OBJID_CLIENT) {
result = false;
break;
}
diff --git a/src/widgets/platforms/x11/qcursor_x11.cpp b/src/widgets/platforms/x11/qcursor_x11.cpp
index d0ed98e1fe..0bc725036c 100644
--- a/src/widgets/platforms/x11/qcursor_x11.cpp
+++ b/src/widgets/platforms/x11/qcursor_x11.cpp
@@ -55,6 +55,9 @@
#endif // QT_NO_XCURSOR
#ifndef QT_NO_XFIXES
+#ifndef Status
+#define Status int
+#endif
# include <X11/extensions/Xfixes.h>
#endif // QT_NO_XFIXES
diff --git a/src/widgets/platforms/x11/qpaintengine_x11.cpp b/src/widgets/platforms/x11/qpaintengine_x11.cpp
index 1256996491..d3c750a5f1 100644
--- a/src/widgets/platforms/x11/qpaintengine_x11.cpp
+++ b/src/widgets/platforms/x11/qpaintengine_x11.cpp
@@ -1611,8 +1611,6 @@ void QX11PaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int p
&& (fill.style() != Qt::NoBrush)
&& ((has_fill_texture && fill.texture().hasAlpha()) || antialias || !solid_fill || has_alpha_pen != has_alpha_brush))
{
- QRect br = tessellator->tessellate((QPointF *)clippedPoints, clippedCount,
- mode == QPaintEngine::WindingMode);
if (tessellator->size > 0) {
XRenderPictureAttributes attrs;
attrs.poly_edge = antialias ? PolyEdgeSmooth : PolyEdgeSharp;
@@ -1771,7 +1769,6 @@ void QX11PaintEngine::drawPath(const QPainterPath &path)
Q_D(QX11PaintEngine);
if (path.isEmpty())
return;
- QTransform old_matrix = d->matrix;
if (d->has_brush)
d->fillPath(path, QX11PaintEnginePrivate::BrushGC, true);
diff --git a/src/widgets/platforms/x11/qwidget_x11.cpp b/src/widgets/platforms/x11/qwidget_x11.cpp
index 5ece7d65c6..3eec5c7331 100644
--- a/src/widgets/platforms/x11/qwidget_x11.cpp
+++ b/src/widgets/platforms/x11/qwidget_x11.cpp
@@ -486,8 +486,6 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
bool topLevel = (flags & Qt::Window);
bool popup = (type == Qt::Popup);
- bool dialog = (type == Qt::Dialog
- || type == Qt::Sheet);
bool desktop = (type == Qt::Desktop);
bool tool = (type == Qt::Tool || type == Qt::SplashScreen
|| type == Qt::ToolTip || type == Qt::Drawer);
@@ -553,7 +551,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
int sh = DisplayHeight(dpy,scr);
if (desktop) { // desktop widget
- dialog = popup = false; // force these flags off
+ popup = false; // force these flags off
data.crect.setRect(0, 0, sw, sh);
} else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
QDesktopWidget *desktopWidget = qApp->desktop();
@@ -954,8 +952,13 @@ static void qt_x11_recreateWidget(QWidget *widget)
// recreate their GL context, which in turn causes them to choose
// their visual again. Now that WA_TranslucentBackground is set,
// QGLContext::chooseVisual will select an ARGB visual.
- QEvent e(QEvent::ParentChange);
- QApplication::sendEvent(widget, &e);
+
+ // QGLWidget expects a ParentAboutToChange to be sent first
+ QEvent aboutToChangeEvent(QEvent::ParentAboutToChange);
+ QApplication::sendEvent(widget, &aboutToChangeEvent);
+
+ QEvent parentChangeEvent(QEvent::ParentChange);
+ QApplication::sendEvent(widget, &parentChangeEvent);
} else {
// For regular widgets, reparent them with their parent which
// also triggers a recreation of the native window
diff --git a/src/widgets/styles/qcleanlooksstyle.cpp b/src/widgets/styles/qcleanlooksstyle.cpp
index cc5fe10692..786aab34c3 100644
--- a/src/widgets/styles/qcleanlooksstyle.cpp
+++ b/src/widgets/styles/qcleanlooksstyle.cpp
@@ -841,7 +841,6 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
case PE_PanelButtonTool:
painter->save();
if ((option->state & State_Enabled || option->state & State_On) || !(option->state & State_AutoRaise)) {
- QRect rect = option->rect;
QPen oldPen = painter->pen();
if (widget && widget->inherits("QDockWidgetTitleButton")) {
@@ -1241,7 +1240,6 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
QColor borderColor = darkOutline.lighter(110);
QColor alphaCornerColor = mergedColors(borderColor, option->palette.background().color());
- QColor innerShadow = mergedColors(borderColor, option->palette.base().color());
int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, twf, widget);
bool reverse = (twf->direction == Qt::RightToLeft);
@@ -1879,7 +1877,6 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
} else {
alphaCornerColor = mergedColors(option->palette.background().color(), borderColor);
}
- QColor alphaTextColor = mergedColors(option->palette.background().color(), option->palette.text().color());
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
painter->fillRect(menuItem->rect, menuBackground);
int w = 0;
@@ -2220,7 +2217,6 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
&& tabBarAlignment == Qt::AlignLeft);
QColor light = tab->palette.light().color();
- QColor midlight = tab->palette.midlight().color();
QColor background = tab->palette.background().color();
int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
@@ -2444,14 +2440,6 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QColor gradientStartColor = option->palette.button().color().lighter(108);
QColor gradientStopColor = mergedColors(option->palette.button().color().darker(108), dark.lighter(150), 70);
- QColor highlightedGradientStartColor = option->palette.button().color();
- QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85);
-
- QColor highlightedDarkInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 35);
- QColor highlightedLightInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 58);
-
- QColor buttonShadowAlpha = option->palette.background().color().darker(105);
-
QPalette palette = option->palette;
switch (control) {
@@ -3437,7 +3425,6 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
@@ -3539,8 +3526,6 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QRect pixmapRect(0, 0, handle.width(), handle.height());
QPainter handlePainter(&cache);
- QColor highlightedGradientStartColor = option->palette.button().color();
- QColor highlightedGradientStopColor = option->palette.light().color();
QColor gradientStartColor = mergedColors(option->palette.button().color().lighter(155),
dark.lighter(155), 50);
QColor gradientStopColor = gradientStartColor.darker(108);
@@ -3557,7 +3542,6 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
// gradient fill
- QRect innerBorder = gradRect;
QRect r = pixmapRect.adjusted(1, 1, -1, -1);
qt_cleanlooks_draw_gradient(&handlePainter, gradRect,
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 8f99d6ad26..95ebdb4662 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -223,16 +223,13 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
--yy;
}
if (!(opt->state & State_Enabled) && !(opt->state & State_On)) {
- int pnt;
- p->setPen(opt->palette.highlightedText().color());
- QPoint offset(1, 1);
- for (pnt = 0; pnt < a.size(); ++pnt)
- a[pnt].translate(offset.x(), offset.y());
+ p->save();
+ p->translate(1, 1);
+ p->setPen(opt->palette.light().color());
p->drawLines(a);
- for (pnt = 0; pnt < a.size(); ++pnt)
- a[pnt].translate(offset.x(), offset.y());
+ p->restore();
}
- p->setPen(opt->palette.text().color());
+ p->setPen((opt->state & State_On) ? opt->palette.highlightedText().color() : opt->palette.text().color());
p->drawLines(a);
break; }
case PE_Frame:
@@ -919,6 +916,7 @@ static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth)
return QSizeF(widthUsed, height);
}
+
void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewItemV4 *option, const QRect &rect) const
{
Q_Q(const QCommonStyle);
@@ -936,7 +934,7 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt
textLayout.setFont(option->font);
textLayout.setText(option->text);
- QSizeF textLayoutSize = viewItemTextLayout(textLayout, textRect.width());
+ viewItemTextLayout(textLayout, textRect.width());
QString elidedText;
qreal height = 0;
diff --git a/src/widgets/styles/qgtkpainter.cpp b/src/widgets/styles/qgtkpainter.cpp
index 0d86540974..8da3a605c6 100644
--- a/src/widgets/styles/qgtkpainter.cpp
+++ b/src/widgets/styles/qgtkpainter.cpp
@@ -586,7 +586,6 @@ void QGtkPainter::paintShadow(GtkWidget *gtkWidget, const gchar* part,
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) % pmKey;
if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
@@ -605,7 +604,6 @@ void QGtkPainter::paintFlatBox(GtkWidget *gtkWidget, const gchar* part,
{
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) % pmKey;
if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
@@ -632,7 +630,6 @@ void QGtkPainter::paintExtention(GtkWidget *gtkWidget,
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget)
% HexString<uchar>(gap_pos);
@@ -660,7 +657,6 @@ void QGtkPainter::paintOption(GtkWidget *gtkWidget, const QRect &radiorect,
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(detail, state, shadow, rect.size());
GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()};
@@ -692,7 +688,6 @@ void QGtkPainter::paintCheckbox(GtkWidget *gtkWidget, const QRect &checkrect,
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(detail, state, shadow, rect.size());
GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()};
diff --git a/src/widgets/styles/qgtkstyle.cpp b/src/widgets/styles/qgtkstyle.cpp
index 047eb97195..78a0c945a1 100644
--- a/src/widgets/styles/qgtkstyle.cpp
+++ b/src/widgets/styles/qgtkstyle.cpp
@@ -782,7 +782,6 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
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
@@ -1857,7 +1856,6 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
editArea.setRight(upRect.left());
}
if (spinBox->frame) {
- GtkShadowType shadow = GTK_SHADOW_OUT;
GtkStateType state = gtkPainter.gtkState(option);
if (!(option->state & State_Enabled))
@@ -1867,7 +1865,6 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
else if (state == GTK_STATE_PRELIGHT)
state = GTK_STATE_NORMAL;
- shadow = GTK_SHADOW_IN;
style = gtkPainter.getStyle(gtkSpinButton);
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index 2d21628488..18003ce2a2 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -4707,7 +4707,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
HIThemeFrameDrawInfo fdi;
fdi.version = qt_mac_hitheme_version;
- fdi.state = kThemeStateInactive;
+ fdi.state = tds;
fdi.kind = kHIThemeFrameTextFieldSquare;
fdi.isFocused = false;
HIRect hirect = qt_hirectForQRect(lineeditRect);
diff --git a/src/widgets/styles/qplastiquestyle.cpp b/src/widgets/styles/qplastiquestyle.cpp
index 02ce60efab..1d33212457 100644
--- a/src/widgets/styles/qplastiquestyle.cpp
+++ b/src/widgets/styles/qplastiquestyle.cpp
@@ -2007,14 +2007,10 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
} else {
alphaCornerColor = mergedColors(option->palette.background().color(), borderColor);
}
- QColor alphaTextColor = mergedColors(option->palette.background().color(), option->palette.text().color());
QColor gradientStartColor = option->palette.button().color().lighter(104);
QColor gradientStopColor = option->palette.button().color().darker(105);
- QColor shadowGradientStartColor = option->palette.button().color().darker(115);
- QColor shadowGradientStopColor = option->palette.button().color().darker(120);
-
QColor highlightedGradientStartColor = option->palette.button().color().lighter(101);
QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85);
@@ -2025,8 +2021,6 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
QColor highlightedLightInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 58);
QColor alphaInnerColor = mergedColors(highlightedDarkInnerBorderColor, option->palette.base().color());
- QColor lightShadow = lightShadowGradientStartColor;
- QColor shadow = shadowGradientStartColor;
switch (element) {
#ifndef QT_NO_TABBAR
@@ -3786,10 +3780,6 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
QColor gradientStartColor = option->palette.button().color().lighter(104);
QColor gradientStopColor = option->palette.button().color().darker(105);
- QColor highlightedGradientStartColor = option->palette.button().color().lighter(101);
- QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85);
- QColor highlightedDarkInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 35);
- QColor highlightedLightInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 58);
switch (control) {
#ifndef QT_NO_SLIDER
@@ -3797,7 +3787,6 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
QRect grooveRegion = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 44f3f92d8b..754486ee16 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -1858,8 +1858,8 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
}
QRect vCheckRect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x(), menuitem->rect.y(), checkcol, menuitem->rect.height()));
- if (checked) {
- if (act && !dis) {
+ if (!menuitem->icon.isNull() && checked) {
+ if (act) {
qDrawShadePanel(p, vCheckRect,
menuitem->palette, true, 1,
&menuitem->palette.brush(QPalette::Button));
@@ -2028,10 +2028,8 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
&& tabBarAlignment == Qt::AlignLeft);
QColor light = tab->palette.light().color();
- QColor midlight = tab->palette.midlight().color();
QColor dark = tab->palette.dark().color();
QColor shadow = tab->palette.shadow().color();
- QColor background = tab->palette.background().color();
int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
if (selected)
borderThinkness /= 2;
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index 7f1a3ab678..123741ecf7 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -969,7 +969,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
{
- if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
+ QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
+ if (anim && (btn->state & State_Enabled)) {
anim->paint(painter, option);
} else {
name = QLatin1String("BUTTON");
@@ -996,7 +997,6 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
!(state & (State_Sunken | State_On)) && !(state & State_MouseOver) &&
(state & State_Enabled) && (state & State_Active))
{
- QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
if (!anim && widget) {
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
startImage.fill(0);
@@ -1074,8 +1074,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) {
- if (((progressbar->value() > 0 && d->transitionsEnabled()) || isIndeterminate)) {
- if (!d->widgetAnimation(progressbar) && progressbar->value() < progressbar->maximum()) {
+ if (isIndeterminate || (progressbar->value() > 0 && (progressbar->value() < progressbar->maximum()) && d->transitionsEnabled())) {
+ if (!d->widgetAnimation(progressbar)) {
QWindowsVistaAnimation *a = new QWindowsVistaAnimation;
a->setWidget(const_cast<QWidget*>(widget));
a->setStartTime(QTime::currentTime());
@@ -2502,7 +2502,6 @@ void QWindowsVistaStylePrivate::timerEvent()
animations[i]->widget()->update();
if (!animations[i]->widget() ||
- !animations[i]->widget()->isEnabled() ||
!animations[i]->widget()->isVisible() ||
animations[i]->widget()->window()->isMinimized() ||
!animations[i]->running() ||
diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp
index 74a20fce29..4b2c3a59a4 100644
--- a/src/widgets/styles/qwindowsxpstyle.cpp
+++ b/src/widgets/styles/qwindowsxpstyle.cpp
@@ -1196,8 +1196,14 @@ QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option,
if (qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option))
{
rect = QWindowsStyle::subElementRect(sr, option, widget);
- if (sr == SE_TabWidgetTabContents)
- rect.adjust(0, 0, -2, -2);
+ if (sr == SE_TabWidgetTabContents) {
+ if (const QTabWidget *tabWidget = qobject_cast<const QTabWidget *>(widget)) {
+ if (tabWidget->documentMode())
+ break;
+ }
+
+ rect.adjust(0, 0, -2, -2);
+ }
}
break;
case SE_TabWidgetTabBar: {
diff --git a/src/widgets/util/qflickgesture.cpp b/src/widgets/util/qflickgesture.cpp
index fdd2a95333..f87c84ccef 100644
--- a/src/widgets/util/qflickgesture.cpp
+++ b/src/widgets/util/qflickgesture.cpp
@@ -218,10 +218,10 @@ public:
mouseTarget = 0;
} else if (mouseTarget) {
// we did send a press, so we need to fake a release now
- Qt::MouseButtons mouseButtons = QApplication::mouseButtons();
// release all pressed mouse buttons
- /*for (int i = 0; i < 32; ++i) {
+ /* Qt::MouseButtons mouseButtons = QApplication::mouseButtons();
+ for (int i = 0; i < 32; ++i) {
if (mouseButtons & (1 << i)) {
Qt::MouseButton b = static_cast<Qt::MouseButton>(1 << i);
mouseButtons &= ~b;
diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp
index db128c136a..870d56fcb7 100644
--- a/src/widgets/util/qscroller.cpp
+++ b/src/widgets/util/qscroller.cpp
@@ -1777,10 +1777,7 @@ void QScrollerPrivate::setState(QScroller::State newstate)
*/
void QScrollerPrivate::setContentPositionHelperDragging(const QPointF &deltaPos)
{
- Q_Q(QScroller);
- QPointF ppm = q->pixelPerMeter();
const QScrollerPropertiesPrivate *sp = properties.d.data();
- QPointF v = q->velocity();
if (sp->overshootDragResistanceFactor)
overshootPosition /= sp->overshootDragResistanceFactor;
diff --git a/src/widgets/util/qundogroup.cpp b/src/widgets/util/qundogroup.cpp
index 42cda7462a..a24ce8dce8 100644
--- a/src/widgets/util/qundogroup.cpp
+++ b/src/widgets/util/qundogroup.cpp
@@ -375,15 +375,18 @@ bool QUndoGroup::isClean() const
for undo, if the group is empty or if none of the stacks are active, this action will
be disabled.
- If \a prefix is empty, the default prefix "Undo" is used.
+ If \a prefix is empty, the default template "Undo %1" is used instead of prefix.
+ Before Qt 4.8, the prefix "Undo" was used by default.
\sa createRedoAction() canUndo() QUndoCommand::text()
*/
QAction *QUndoGroup::createUndoAction(QObject *parent, const QString &prefix) const
{
- QString pref = prefix.isEmpty() ? tr("Undo") : prefix;
- QUndoAction *result = new QUndoAction(pref, parent);
+ QUndoAction *result = new QUndoAction(prefix, parent);
+ if (prefix.isEmpty())
+ result->setTextFormat(tr("Undo %1"), tr("Undo", "Default text for undo action"));
+
result->setEnabled(canUndo());
result->setPrefixedText(undoText());
connect(this, SIGNAL(canUndoChanged(bool)),
@@ -403,15 +406,18 @@ QAction *QUndoGroup::createUndoAction(QObject *parent, const QString &prefix) co
for redo, if the group is empty or if none of the stacks are active, this action will
be disabled.
- If \a prefix is empty, the default prefix "Undo" is used.
+ If \a prefix is empty, the default template "Redo %1" is used instead of prefix.
+ Before Qt 4.8, the prefix "Redo" was used by default.
\sa createUndoAction() canRedo() QUndoCommand::text()
*/
QAction *QUndoGroup::createRedoAction(QObject *parent, const QString &prefix) const
{
- QString pref = prefix.isEmpty() ? tr("Redo") : prefix;
- QUndoAction *result = new QUndoAction(pref, parent);
+ QUndoAction *result = new QUndoAction(prefix, parent);
+ if (prefix.isEmpty())
+ result->setTextFormat(tr("Redo %1"), tr("Redo", "Default text for redo action"));
+
result->setEnabled(canRedo());
result->setPrefixedText(redoText());
connect(this, SIGNAL(canRedoChanged(bool)),
diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp
index 6b038ee52e..1dfab5d1ad 100644
--- a/src/widgets/util/qundostack.cpp
+++ b/src/widgets/util/qundostack.cpp
@@ -114,7 +114,7 @@ QUndoCommand::QUndoCommand(const QString &text, QUndoCommand *parent)
d = new QUndoCommandPrivate;
if (parent != 0)
parent->d->child_list.append(this);
- d->text = text;
+ setText(text);
}
/*!
@@ -230,10 +230,9 @@ void QUndoCommand::undo()
Returns a short text string describing what this command does; for example,
"insert text".
- The text is used when the text properties of the stack's undo and redo
- actions are updated.
+ The text is used for names of items in QUndoView.
- \sa setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction()
+ \sa actionText(), setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction()
*/
QString QUndoCommand::text() const
@@ -242,17 +241,47 @@ QString QUndoCommand::text() const
}
/*!
+ \since 4.8
+
+ Returns a short text string describing what this command does; for example,
+ "insert text".
+
+ The text is used when the text properties of the stack's undo and redo
+ actions are updated.
+
+ \sa text(), setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction()
+*/
+
+QString QUndoCommand::actionText() const
+{
+ return d->actionText;
+}
+
+/*!
Sets the command's text to be the \a text specified.
The specified text should be a short user-readable string describing what this
command does.
- \sa text() QUndoStack::createUndoAction() QUndoStack::createRedoAction()
+ If you need to have two different strings for text() and actionText(), separate
+ them with "\n" and pass into this function. Even if you do not use this feature
+ for English strings during development, you can still let translators use two
+ different strings in order to match specific languages' needs.
+ The described feature and the function actionText() are available since Qt 4.8.
+
+ \sa text() actionText() QUndoStack::createUndoAction() QUndoStack::createRedoAction()
*/
void QUndoCommand::setText(const QString &text)
{
- d->text = text;
+ int cdpos = text.indexOf(QLatin1Char('\n'));
+ if (cdpos > 0) {
+ d->text = text.left(cdpos);
+ d->actionText = text.mid(cdpos + 1);
+ } else {
+ d->text = text;
+ d->actionText = text;
+ }
}
/*!
@@ -374,11 +403,24 @@ QUndoAction::QUndoAction(const QString &prefix, QObject *parent)
void QUndoAction::setPrefixedText(const QString &text)
{
- QString s = m_prefix;
- if (!m_prefix.isEmpty() && !text.isEmpty())
- s.append(QLatin1Char(' '));
- s.append(text);
- setText(s);
+ if (m_defaultText.isEmpty()) {
+ QString s = m_prefix;
+ if (!m_prefix.isEmpty() && !text.isEmpty())
+ s.append(QLatin1Char(' '));
+ s.append(text);
+ setText(s);
+ } else {
+ if (text.isEmpty())
+ setText(m_defaultText);
+ else
+ setText(m_prefix.arg(text));
+ }
+}
+
+void QUndoAction::setTextFormat(const QString &textFormat, const QString &defaultText)
+{
+ m_prefix = textFormat;
+ m_defaultText = defaultText;
}
#endif // QT_NO_ACTION
@@ -783,7 +825,7 @@ bool QUndoStack::canRedo() const
/*!
Returns the text of the command which will be undone in the next call to undo().
- \sa QUndoCommand::text() redoText()
+ \sa QUndoCommand::actionText() redoText()
*/
QString QUndoStack::undoText() const
@@ -792,14 +834,14 @@ QString QUndoStack::undoText() const
if (!d->macro_stack.isEmpty())
return QString();
if (d->index > 0)
- return d->command_list.at(d->index - 1)->text();
+ return d->command_list.at(d->index - 1)->actionText();
return QString();
}
/*!
Returns the text of the command which will be redone in the next call to redo().
- \sa QUndoCommand::text() undoText()
+ \sa QUndoCommand::actionText() undoText()
*/
QString QUndoStack::redoText() const
@@ -808,7 +850,7 @@ QString QUndoStack::redoText() const
if (!d->macro_stack.isEmpty())
return QString();
if (d->index < d->command_list.size())
- return d->command_list.at(d->index)->text();
+ return d->command_list.at(d->index)->actionText();
return QString();
}
@@ -822,15 +864,18 @@ QString QUndoStack::redoText() const
prefixed by the specified \a prefix. If there is no command available for undo,
this action will be disabled.
- If \a prefix is empty, the default prefix "Undo" is used.
+ If \a prefix is empty, the default template "Undo %1" is used instead of prefix.
+ Before Qt 4.8, the prefix "Undo" was used by default.
\sa createRedoAction(), canUndo(), QUndoCommand::text()
*/
QAction *QUndoStack::createUndoAction(QObject *parent, const QString &prefix) const
{
- QString pref = prefix.isEmpty() ? tr("Undo") : prefix;
- QUndoAction *result = new QUndoAction(pref, parent);
+ QUndoAction *result = new QUndoAction(prefix, parent);
+ if (prefix.isEmpty())
+ result->setTextFormat(tr("Undo %1"), tr("Undo", "Default text for undo action"));
+
result->setEnabled(canUndo());
result->setPrefixedText(undoText());
connect(this, SIGNAL(canUndoChanged(bool)),
@@ -849,15 +894,18 @@ QAction *QUndoStack::createUndoAction(QObject *parent, const QString &prefix) co
prefixed by the specified \a prefix. If there is no command available for redo,
this action will be disabled.
- If \a prefix is empty, the default prefix "Redo" is used.
+ If \a prefix is empty, the default template "Redo %1" is used instead of prefix.
+ Before Qt 4.8, the prefix "Redo" was used by default.
\sa createUndoAction(), canRedo(), QUndoCommand::text()
*/
QAction *QUndoStack::createRedoAction(QObject *parent, const QString &prefix) const
{
- QString pref = prefix.isEmpty() ? tr("Redo") : prefix;
- QUndoAction *result = new QUndoAction(pref, parent);
+ QUndoAction *result = new QUndoAction(prefix, parent);
+ if (prefix.isEmpty())
+ result->setTextFormat(tr("Redo %1"), tr("Redo", "Default text for redo action"));
+
result->setEnabled(canRedo());
result->setPrefixedText(redoText());
connect(this, SIGNAL(canRedoChanged(bool)),
diff --git a/src/widgets/util/qundostack.h b/src/widgets/util/qundostack.h
index 65941b53c3..700996f005 100644
--- a/src/widgets/util/qundostack.h
+++ b/src/widgets/util/qundostack.h
@@ -70,6 +70,7 @@ public:
virtual void redo();
QString text() const;
+ QString actionText() const;
void setText(const QString &text);
virtual int id() const;
diff --git a/src/widgets/util/qundostack_p.h b/src/widgets/util/qundostack_p.h
index f147fc5a81..29f382587a 100644
--- a/src/widgets/util/qundostack_p.h
+++ b/src/widgets/util/qundostack_p.h
@@ -70,6 +70,7 @@ public:
QUndoCommandPrivate() : id(-1) {}
QList<QUndoCommand*> child_list;
QString text;
+ QString actionText;
int id;
};
@@ -98,10 +99,12 @@ class QUndoAction : public QAction
Q_OBJECT
public:
QUndoAction(const QString &prefix, QObject *parent = 0);
+ void setTextFormat(const QString &textFormat, const QString &defaultText);
public Q_SLOTS:
void setPrefixedText(const QString &text);
private:
QString m_prefix;
+ QString m_defaultText;
};
#endif // QT_NO_ACTION
diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp
index 63371138c7..a4739a7f69 100644
--- a/src/widgets/widgets/qdatetimeedit.cpp
+++ b/src/widgets/widgets/qdatetimeedit.cpp
@@ -2538,20 +2538,32 @@ void QDateTimeEditPrivate::syncCalendarWidget()
}
QCalendarPopup::QCalendarPopup(QWidget * parent, QCalendarWidget *cw)
- : QWidget(parent, Qt::Popup), calendar(0)
+ : QWidget(parent, Qt::Popup)
{
setAttribute(Qt::WA_WindowPropagation);
dateChanged = false;
if (!cw) {
- cw = new QCalendarWidget(this);
+ verifyCalendarInstance();
+ } else {
+ setCalendarWidget(cw);
+ }
+}
+
+QCalendarWidget *QCalendarPopup::verifyCalendarInstance()
+{
+ if (calendar.isNull()) {
+ QCalendarWidget *cw = new QCalendarWidget(this);
cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
#ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled())
cw->setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);
#endif
+ setCalendarWidget(cw);
+ return cw;
+ } else {
+ return calendar.data();
}
- setCalendarWidget(cw);
}
void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
@@ -2563,28 +2575,29 @@ void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
widgetLayout->setMargin(0);
widgetLayout->setSpacing(0);
}
- delete calendar;
- calendar = cw;
- widgetLayout->addWidget(calendar);
+ delete calendar.data();
+ calendar = QWeakPointer<QCalendarWidget>(cw);
+ widgetLayout->addWidget(cw);
- connect(calendar, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
- connect(calendar, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
- connect(calendar, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
+ connect(cw, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
+ connect(cw, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
+ connect(cw, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
- calendar->setFocus();
+ cw->setFocus();
}
void QCalendarPopup::setDate(const QDate &date)
{
oldDate = date;
- calendar->setSelectedDate(date);
+ verifyCalendarInstance()->setSelectedDate(date);
}
void QCalendarPopup::setDateRange(const QDate &min, const QDate &max)
{
- calendar->setMinimumDate(min);
- calendar->setMaximumDate(max);
+ QCalendarWidget *cw = verifyCalendarInstance();
+ cw->setMinimumDate(min);
+ cw->setMaximumDate(max);
}
void QCalendarPopup::mousePressEvent(QMouseEvent *event)
@@ -2620,7 +2633,7 @@ bool QCalendarPopup::event(QEvent *event)
void QCalendarPopup::dateSelectionChanged()
{
dateChanged = true;
- emit newDateSelected(calendar->selectedDate());
+ emit newDateSelected(verifyCalendarInstance()->selectedDate());
}
void QCalendarPopup::dateSelected(const QDate &date)
{
diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h
index 81e2afa53e..d6ff94c055 100644
--- a/src/widgets/widgets/qdatetimeedit_p.h
+++ b/src/widgets/widgets/qdatetimeedit_p.h
@@ -148,11 +148,11 @@ class QCalendarPopup : public QWidget
Q_OBJECT
public:
QCalendarPopup(QWidget *parent = 0, QCalendarWidget *cw = 0);
- QDate selectedDate() { return calendar->selectedDate(); }
+ QDate selectedDate() { return verifyCalendarInstance()->selectedDate(); }
void setDate(const QDate &date);
void setDateRange(const QDate &min, const QDate &max);
- void setFirstDayOfWeek(Qt::DayOfWeek dow) { calendar->setFirstDayOfWeek(dow); }
- QCalendarWidget *calendarWidget() const { return calendar; }
+ void setFirstDayOfWeek(Qt::DayOfWeek dow) { verifyCalendarInstance()->setFirstDayOfWeek(dow); }
+ QCalendarWidget *calendarWidget() const { return const_cast<QCalendarPopup*>(this)->verifyCalendarInstance(); }
void setCalendarWidget(QCalendarWidget *cw);
Q_SIGNALS:
void activated(const QDate &date);
@@ -171,7 +171,9 @@ protected:
bool event(QEvent *e);
private:
- QCalendarWidget *calendar;
+ QCalendarWidget *verifyCalendarInstance();
+
+ QWeakPointer<QCalendarWidget> calendar;
QDate oldDate;
bool dateChanged;
};
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index 49feb476bf..6d599fcd57 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -2100,7 +2100,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
bool gap = false;
int tab_idx = 0;
- bool changed = false;
for (int i = 0; i < item_list.count(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
@@ -2121,7 +2120,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
tabBar->setTabToolTip(tab_idx, title);
#endif
tabBar->setTabData(tab_idx, id);
- changed = true;
} else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
if (tab_idx + 1 < tabBar->count()
&& qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
@@ -2133,7 +2131,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
#endif
tabBar->setTabData(tab_idx, id);
}
- changed = true;
}
if (title != tabBar->tabText(tab_idx)) {
@@ -2141,7 +2138,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
#ifndef QT_NO_TOOLTIP
tabBar->setTabToolTip(tab_idx, title);
#endif
- changed = true;
}
++tab_idx;
@@ -2149,7 +2145,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
while (tab_idx < tabBar->count()) {
tabBar->removeTab(tab_idx);
- changed = true;
}
tabBar->blockSignals(blocked);
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 9d1a737cf1..16b60c8295 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -161,7 +161,6 @@ void QDockWidgetTitleButton::paintEvent(QPaintEvent *)
{
QPainter p(this);
- QRect r = rect();
QStyleOptionToolButton opt;
opt.init(this);
opt.state |= QStyle::State_AutoRaise;
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index b12e5c5528..b0ea00f811 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -228,6 +228,12 @@ QList<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const
void QMenuPrivate::updateActionRects() const
{
Q_Q(const QMenu);
+ updateActionRects(popupGeometry(q));
+}
+
+void QMenuPrivate::updateActionRects(const QRect &screen) const
+{
+ Q_Q(const QMenu);
if (!itemsDirty)
return;
@@ -237,20 +243,10 @@ void QMenuPrivate::updateActionRects() const
actionRects.resize(actions.count());
actionRects.fill(QRect());
- //let's try to get the last visible action
- int lastVisibleAction = actions.count() - 1;
- for(;lastVisibleAction >= 0; --lastVisibleAction) {
- const QAction *action = actions.at(lastVisibleAction);
- if (action->isVisible()) {
- //removing trailing separators
- if (action->isSeparator() && collapsibleSeparators)
- continue;
- break;
- }
- }
+ int lastVisibleAction = getLastVisibleAction();
int max_column_width = 0,
- dh = popupGeometry(q).height(),
+ dh = screen.height(),
y = 0;
QStyle *style = q->style();
QStyleOption opt;
@@ -351,7 +347,6 @@ void QMenuPrivate::updateActionRects() const
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 +
(scroll ? scroll->scrollOffset : 0) +
@@ -382,6 +377,34 @@ void QMenuPrivate::updateActionRects() const
itemsDirty = 0;
}
+QSize QMenuPrivate::adjustMenuSizeForScreen(const QRect &screen)
+{
+ Q_Q(QMenu);
+ QSize ret = screen.size();
+ itemsDirty = true;
+ updateActionRects(screen);
+ const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q);
+ ret.setWidth(actionRects.at(getLastVisibleAction()).right() + fw);
+ return ret;
+}
+
+int QMenuPrivate::getLastVisibleAction() const
+{
+ //let's try to get the last visible action
+ int lastVisibleAction = actions.count() - 1;
+ for (;lastVisibleAction >= 0; --lastVisibleAction) {
+ const QAction *action = actions.at(lastVisibleAction);
+ if (action->isVisible()) {
+ //removing trailing separators
+ if (action->isSeparator() && collapsibleSeparators)
+ continue;
+ break;
+ }
+ }
+ return lastVisibleAction;
+}
+
+
QRect QMenuPrivate::actionRect(QAction *act) const
{
int index = actions.indexOf(act);
@@ -1813,9 +1836,20 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
else
#endif
screen = d->popupGeometry(QApplication::desktop()->screenNumber(p));
-
const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this);
bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen);
+
+ // if the screens have very different geometries and the menu is too big, we have to recalculate
+ if (size.height() > screen.height() || size.width() > screen.width()) {
+ size = d->adjustMenuSizeForScreen(screen);
+ adjustToDesktop = true;
+ }
+ // Layout is not right, we might be able to save horizontal space
+ if (d->ncols >1 && size.height() < screen.height()) {
+ size = d->adjustMenuSizeForScreen(screen);
+ adjustToDesktop = true;
+ }
+
#ifdef QT_KEYPAD_NAVIGATION
if (!atAction && QApplication::keypadNavigationEnabled()) {
// Try to have one item activated
@@ -1909,6 +1943,27 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
}
}
}
+ const int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, 0, this);
+ const QSize menuSize(sizeHint());
+ QMenu *caused = qobject_cast<QMenu*>(d_func()->causedPopup.widget);
+ if (caused && caused->geometry().width() + menuSize.width() + subMenuOffset < screen.width()) {
+ QRect parentActionRect(caused->d_func()->actionRect(caused->d_func()->currentAction));
+ const QPoint actionTopLeft = caused->mapToGlobal(parentActionRect.topLeft());
+ parentActionRect.moveTopLeft(actionTopLeft);
+ if (isRightToLeft()) {
+ if ((pos.x() + menuSize.width() > parentActionRect.left() - subMenuOffset)
+ && (pos.x() < parentActionRect.right()))
+ {
+ pos.rx() = parentActionRect.right();
+ }
+ } else {
+ if ((pos.x() < parentActionRect.right() + subMenuOffset)
+ && (pos.x() + menuSize.width() > parentActionRect.left()))
+ {
+ pos.rx() = parentActionRect.left() - menuSize.width();
+ }
+ }
+ }
setGeometry(QRect(pos, size));
#ifndef QT_NO_EFFECTS
int hGuess = isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
@@ -2941,28 +2996,8 @@ void QMenu::internalDelayedPopup()
const QRect actionRect(d->actionRect(d->currentAction));
const QSize menuSize(d->activeMenu->sizeHint());
const QPoint rightPos(mapToGlobal(QPoint(actionRect.right() + subMenuOffset + 1, actionRect.top())));
- const QPoint leftPos(mapToGlobal(QPoint(actionRect.left() - subMenuOffset - menuSize.width(), actionRect.top())));
QPoint pos(rightPos);
- QMenu *caused = qobject_cast<QMenu*>(d->activeMenu->d_func()->causedPopup.widget);
-
- const QRect availGeometry(d->popupGeometry(caused));
- if (isRightToLeft()) {
- pos = leftPos;
- if ((caused && caused->x() < x()) || pos.x() < availGeometry.left()) {
- if(rightPos.x() + menuSize.width() < availGeometry.right())
- pos = rightPos;
- else
- pos.rx() = availGeometry.left();
- }
- } else {
- if ((caused && caused->x() > x()) || pos.x() + menuSize.width() > availGeometry.right()) {
- if(leftPos.x() < availGeometry.left())
- pos.rx() = availGeometry.right() - menuSize.width();
- else
- pos = leftPos;
- }
- }
//calc sloppy focus buffer
if (style()->styleHint(QStyle::SH_Menu_SloppySubMenus, 0, this)) {
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index ad8818d76e..9c777d443d 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -194,10 +194,13 @@ public:
mutable QVector<QRect> actionRects;
mutable QHash<QAction *, QWidget *> widgetItems;
void updateActionRects() const;
+ void updateActionRects(const QRect &screen) const;
QRect popupGeometry(const QWidget *widget) const;
QRect popupGeometry(int screen = -1) const;
mutable uint ncols : 4; //4 bits is probably plenty
uint collapsibleSeparators : 1;
+ QSize adjustMenuSizeForScreen(const QRect & screen);
+ int getLastVisibleAction() const;
bool activationRecursionGuard;
@@ -296,7 +299,6 @@ public:
void updateLayoutDirection();
-
//menu fading/scrolling effects
bool doChildEffects;
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 7435691bf0..51c4ccbeb7 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/